Skip to content

Instantly share code, notes, and snippets.

@ikt32
Last active August 12, 2019 07:47
Show Gist options
  • Save ikt32/59390733b366cad4638901ae5fcfd046 to your computer and use it in GitHub Desktop.
Save ikt32/59390733b366cad4638901ae5fcfd046 to your computer and use it in GitHub Desktop.
LoadMTLib
#include "Compatibility.h"
// You should log what happens when a function isn't found, or something.
//#include "Util/Logger.h"
#include <Windows.h>
#include <string>
namespace MT {
const char* (*GetVersion )() = nullptr;
bool (*GetActive )() = nullptr;
void (*SetActive )(bool active) = nullptr;
bool (*NeutralGear )() = nullptr;
int (*GetShiftMode )() = nullptr;
void (*SetShiftMode )(int mode) = nullptr;
int (*GetShiftIndicator )() = nullptr;
void (*AddIgnoreVehicle )(int vehicle) = nullptr;
void (*DelIgnoreVehicle )(int vehicle) = nullptr;
void (*ClearIgnoredVehicles )() = nullptr;
unsigned (*NumIgnoredVehicles )() = nullptr;
const int* (*GetIgnoredVehicles )() = nullptr;
int (*GetManagedVehicle )() = nullptr;
bool (*LookingLeft )() = nullptr;
bool (*LookingRight )() = nullptr;
bool (*LookingBack )() = nullptr;
// This will be used to keep track for unloading.
HMODULE GearsModule = nullptr;
}
// This function checks if the supplied function is available in the given library.
template <typename T>
T CheckAddr(HMODULE lib, const std::string& funcName) {
FARPROC func = GetProcAddress(lib, funcName.c_str());
if (!func) {
// logger.Write(ERROR, "Couldn't get function [%s]", funcName.c_str());
return nullptr;
}
// logger.Write(DEBUG, "Found function [%s]", funcName.c_str());
return reinterpret_cast<T>(func);
}
// The available functions are checked here. You could add more libraries here if needed.
bool setupCompatibility() {
bool success = true;
//logger.Write(INFO, "Setting up Manual Transmission compatibility");
MT::GearsModule = GetModuleHandle("Gears.asi");
if (!MT::GearsModule) {
//logger.Write(ERROR, "Gears.asi not found");
return false;
}
MT::GetVersion = CheckAddr<const char* (*)()>(MT::GearsModule, "MT_GetVersion");
success &= MT::GetVersion != nullptr;
MT::GetActive = CheckAddr<bool (*)()>(MT::GearsModule, "MT_IsActive");
success &= MT::GetActive != nullptr;
MT::SetActive = CheckAddr<void (*)(bool)>(MT::GearsModule, "MT_SetActive");
success &= MT::SetActive != nullptr;
MT::NeutralGear = CheckAddr<bool (*)()>(MT::GearsModule, "MT_NeutralGear");
success &= MT::NeutralGear != nullptr;
MT::GetShiftMode = CheckAddr<int (*)()>(MT::GearsModule, "MT_GetShiftMode");
success &= MT::GetShiftMode != nullptr;
MT::SetShiftMode = CheckAddr<void (*)(int)>(MT::GearsModule, "MT_SetShiftMode");
success &= MT::SetShiftMode != nullptr;
MT::GetShiftIndicator = CheckAddr<int (*)()>(MT::GearsModule, "MT_GetShiftIndicator");
success &= MT::GetShiftIndicator != nullptr;
MT::AddIgnoreVehicle = CheckAddr<void (*)(int)>(MT::GearsModule, "MT_AddIgnoreVehicle");
success &= MT::AddIgnoreVehicle != nullptr;
MT::DelIgnoreVehicle = CheckAddr<void (*)(int)>(MT::GearsModule, "MT_DelIgnoreVehicle");
success &= MT::DelIgnoreVehicle != nullptr;
MT::ClearIgnoredVehicles = CheckAddr<void (*)()>(MT::GearsModule, "MT_ClearIgnoredVehicles");
success &= MT::ClearIgnoredVehicles != nullptr;
MT::NumIgnoredVehicles = CheckAddr<unsigned (*)()>(MT::GearsModule, "MT_NumIgnoredVehicles");
success &= MT::NumIgnoredVehicles != nullptr;
MT::GetIgnoredVehicles = CheckAddr<const int* (*)()>(MT::GearsModule, "MT_GetIgnoredVehicles");
success &= MT::GetIgnoredVehicles != nullptr;
MT::GetManagedVehicle = CheckAddr<int (*)()>(MT::GearsModule, "MT_GetManagedVehicle");
success &= MT::GetManagedVehicle != nullptr;
MT::LookingLeft = CheckAddr<bool (*)()>(MT::GearsModule, "MT_LookingLeft");
success &= MT::LookingLeft != nullptr;
MT::LookingRight = CheckAddr<bool (*)()>(MT::GearsModule, "MT_LookingRight");
success &= MT::LookingRight != nullptr;
MT::LookingBack = CheckAddr<bool (*)()>(MT::GearsModule, "MT_LookingBack");
success &= MT::LookingBack != nullptr;
return success;
}
void releaseCompatibility() {
if (MT::GearsModule) {
// In this case GearsModule is gotten with GetModuleHandle, so no FreeLibrary is needed.
// Just reset the pointer.
MT::GearsModule = nullptr;
}
}
#pragma once
// Manual Transmission functions are grouped in a namespace. If desired,
// you could make your own class or something that encapsulates this in
// a prettier way.
//
// For full function descriptions, refer to
// https://github.com/E66666666/GTAVManualTransmission/blob/master/Gears/ManualTransmission.h
namespace MT {
extern const char* (*GetVersion)();
extern bool (*GetActive)();
extern void (*SetActive)(bool active);
extern bool (*NeutralGear)();
extern int (*GetShiftMode)();
extern void (*SetShiftMode)(int mode);
extern int (*GetShiftIndicator)();
// AI Management
extern void (*AddIgnoreVehicle)(int vehicle);
extern void (*DelIgnoreVehicle)(int vehicle);
extern void (*ClearIgnoredVehicles)();
extern unsigned (*NumIgnoredVehicles)();
extern const int* (*GetIgnoredVehicles)();
extern int (*GetManagedVehicle)();
// Camera
extern bool (*LookingLeft)();
extern bool (*LookingRight)();
extern bool (*LookingBack)();
}
// The library is loaded and checked here. A boolean indicating success is returned.
// You can change this to whatever behavior is desired - for example, you could check
// each functions availability (!= nullptr), or disable integration altogether.
bool setupCompatibility();
// This should be called when your script shuts down or stops using integration,
// to release resources (the library).
void releaseCompatibility();
// Usage example - call the functions
#include "Compatibility.h"
bool setupSuccess = false;
void UpdateMTShiftMode(Vehicle v);
void setup() {
// Your setup code here
// Be sure to call this before using any functions from Gears.asi
setupSuccess = setupCompatibility();
if (setupSuccess) {
// logger.Write(INFO, "Manual Transmission [%s] integration success", MT::GetVersion());
}
else {
// logger.Write(ERROR, "Manual Transmission integration failed");
}
}
// Small example that would change shifting modes automatically.
// player/vehicle methods are pseudocode, just used as an example.
void onTick() {
if (setupSuccess) {
if (player.JustEnteredVehicle()) {
if (MT::GetActive()) {
UpdateMTShiftMode(player.CurrentVehicle());
}
}
}
}
void UpdateMTShiftMode(Vehicle v) {
if (v.GetShifter() == Shifter::Sequential) {
MT::SetShiftMode(1);
}
else if (v.GetShifter() == Shifter::HPattern) {
MT::SetShiftMode(2);
}
else {
MT::SetShiftMode(3); // Automatic
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment