Skip to content

Instantly share code, notes, and snippets.

@ikt32
Last active March 26, 2019 09:15
Show Gist options
  • Save ikt32/d11cdbd9800ad73efeff612374349347 to your computer and use it in GitHub Desktop.
Save ikt32/d11cdbd9800ad73efeff612374349347 to your computer and use it in GitHub Desktop.
LoadLibrary Gears.asi
using System;
using System.IO;
using System.Runtime.InteropServices;
using GTA;
using GTA.Native;
static class Dll
{
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string lpFileName);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
}
public class LoadMTLib : Script
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool FnGetBool();
// We use this for strings, conversion on call
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr FnGetIntPtr();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void FnSetInt(int arg);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void FnVoid();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U4)]
private delegate uint FnGetUint();
private FnGetBool MT_IsActive;
private FnGetIntPtr MT_GetVersion;
private FnSetInt MT_AddIgnoreVehicle;
private FnSetInt MT_DelIgnoreVehicle;
private FnVoid MT_ClearIgnoredVehicles;
private FnGetUint MT_NumIgnoredVehicles;
private bool UseMT;
private Vehicle prevVehicle;
public LoadMTLib()
{
Tick += OnTick;
IntPtr mtLib = Dll.GetModuleHandle(@"Gears.asi");
if (mtLib == IntPtr.Zero)
{
Log("Couldn't get module handle?");
}
else
{
Log("Load Gears.asi success");
}
MT_IsActive = CheckAddr<FnGetBool>(mtLib, "MT_IsActive");
MT_GetVersion = CheckAddr<FnGetIntPtr>(mtLib, "MT_GetVersion");
MT_AddIgnoreVehicle = CheckAddr<FnSetInt>(mtLib, "MT_AddIgnoreVehicle");
MT_DelIgnoreVehicle = CheckAddr<FnSetInt>(mtLib, "MT_DelIgnoreVehicle");
MT_ClearIgnoredVehicles = CheckAddr<FnVoid>(mtLib, "MT_ClearIgnoredVehicles");
MT_NumIgnoredVehicles = CheckAddr<FnGetUint>(mtLib, "MT_NumIgnoredVehicles");
if (MT_IsActive == null ||
MT_GetVersion == null ||
MT_AddIgnoreVehicle == null ||
MT_DelIgnoreVehicle == null ||
MT_ClearIgnoredVehicles == null ||
MT_NumIgnoredVehicles == null)
{
UseMT = false;
Log("Disabling MT integration");
// Disable any MT integration
}
else
{
UseMT = true;
}
}
private T CheckAddr<T>(IntPtr lib, string funcName) where T : class
{
IntPtr mtFunc = Dll.GetProcAddress(lib, funcName);
if (mtFunc == IntPtr.Zero)
{
Log("Couldn't get proc addr: " + funcName);
return null;
}
Log(funcName + " available");
return Marshal.GetDelegateForFunctionPointer(mtFunc, typeof(T)) as T;
}
private void OnTick(object source, EventArgs e)
{
if (!UseMT)
{
ShowText(0.0f, 0.00f, "MT not present");
return;
}
var strResult = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(MT_GetVersion());
ShowText(0.0f, 0.00f, "MT Ver: " + strResult);
ShowText(0.0f, 0.025f, "MT Act: " + (MT_IsActive() ? "Yes" : "No"));
ShowText(0.0f, 0.050f, "MT Ignored: " + MT_NumIgnoredVehicles());
if (Game.Player.Character.CurrentVehicle != prevVehicle)
{
if (Entity.Exists(Game.Player.Character.CurrentVehicle))
MT_AddIgnoreVehicle(Game.Player.Character.CurrentVehicle.Handle);
}
prevVehicle = Game.Player.Character.CurrentVehicle;
}
void ShowText(float x, float y, string text, float size = 0.5f)
{
Function.Call(Hash.SET_TEXT_FONT, 0);
Function.Call(Hash.SET_TEXT_SCALE, size, size);
Function.Call(Hash.SET_TEXT_COLOUR, 255, 255, 255, 255);
Function.Call(Hash.SET_TEXT_WRAP, 0.0, 1.0);
Function.Call(Hash.SET_TEXT_CENTRE, 0);
Function.Call(Hash.SET_TEXT_OUTLINE, true);
Function.Call(Hash._SET_TEXT_ENTRY, "STRING");
Function.Call(Hash._ADD_TEXT_COMPONENT_STRING, text);
Function.Call(Hash._DRAW_TEXT, x, y);
}
public void Log(string msg)
{
string path = @"Scripts/LoadMTLib.log";
if (!File.Exists(path))
{
File.Create(path);
TextWriter tw = new StreamWriter(path);
tw.WriteLine(System.String.Format(
"{0:G}: {1}.", System.DateTime.Now, msg));
tw.Close();
}
else if (File.Exists(path))
{
using (var tw = new StreamWriter(path, true))
{
tw.WriteLine(System.String.Format(
"{0:G}: {1}.", System.DateTime.Now, msg));
tw.Close();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment