Skip to content

sailro/TrainerKit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TrainerKit

Sponsor

TrainerKit is an extract of the Feature-system developed for EscapeFromTarkov-Trainer.

TrainerKit simplifies the development of internal Unity trainers by handling:

  • UI rendering of features (everything is done automatically through reflection). Support for Color, Float, Int, String, Bool, KeyCode types.
  • Load/save of settings.
  • Runtime execution of Features.
  • Injection into target process.

Example with Unity's FPS Microgame

Starting with TrainerKit codebase, simply write the following code:

using TrainerKit.Features;
using TrainerKit.Properties;
using Unity.FPS.Game;
	
namespace TrainerKit.DemoFPS;

internal class GodMode : ToggleFeature
{
	public override string Name => Strings.FeatureGodModeName;
	public override string Description => Strings.FeatureGodModeDescription;

	protected override void UpdateWhenEnabled()
	{
		var health = FindFirstObjectByType<Health>();
		health?.Invincible = true;
	}

	protected override void UpdateWhenDisabled()
	{
		var health = FindFirstObjectByType<Health>();
		health?.Invincible = false;
	}
}

and

using TrainerKit.Configuration;
using TrainerKit.Features;
using TrainerKit.Properties;
using Unity.FPS.Game;
using UnityEngine;

namespace TrainerKit.DemoFPS;

internal class UnlimitedAmmo : ToggleFeature
{
	public override string Name => Strings.FeatureUnlimitedAmmoName;
	public override string Description => Strings.FeatureUnlimitedAmmoDescription;

	[ConfigurationProperty] public int DemoInt { get; set; } = 999;
	[ConfigurationProperty] public Color DemoColor { get; set; } = Color.red;
	[ConfigurationProperty] public string DemoText { get; set; } = "Text";
	[ConfigurationProperty] public KeyCode DemoKey { get; set; } = KeyCode.Alpha0;
	[ConfigurationProperty] public float DemoFloat { get; set; } = 3.14f;

	protected override void UpdateWhenEnabled()
	{
		var weapon = FindFirstObjectByType<WeaponController>();
		weapon?.MaxAmmo = int.MaxValue;
	}

	protected override void UpdateWhenDisabled()
	{
		var weapon = FindFirstObjectByType<WeaponController>();
		weapon?.MaxAmmo = 8;
	}
}

and the system will automatically generate the following window after injecting into the target process (use RightAlt by default to display the menu):

TrainerKit Demo

Note that the system displays names like !! [Id] !! because it couldn't find the corresponding entries in the resource file (for example PropertyDemoInt for DemoInt):

Resources

The following configuration file can be automatically generated (and reloaded on next execution):

; Be careful when updating this file :)
; For keys, use https://docs.unity3d.com/ScriptReference/KeyCode.html
; Colors are stored as an array of 'RGBA' floats

TrainerKit.DemoFPS.GodMode.Enabled=true
TrainerKit.DemoFPS.GodMode.Key="None"

TrainerKit.DemoFPS.UnlimitedAmmo.Enabled=true
TrainerKit.DemoFPS.UnlimitedAmmo.Key="None"
TrainerKit.DemoFPS.UnlimitedAmmo.DemoColor=[1.0,0.0,0.0,1.0]
TrainerKit.DemoFPS.UnlimitedAmmo.DemoFloat=3.14
TrainerKit.DemoFPS.UnlimitedAmmo.DemoInt=999
TrainerKit.DemoFPS.UnlimitedAmmo.DemoKey="Alpha0"
TrainerKit.DemoFPS.UnlimitedAmmo.DemoText="Text"

TrainerKit.Features.Commands.Key="RightAlt"
TrainerKit.Features.Commands.ConsoleColor=[1.0,1.0,1.0,1.0]
TrainerKit.Features.Commands.X=462.0
TrainerKit.Features.Commands.Y=10.0

How to Use

1- Starting from the source code, add the necessary references to the game you want to mod. You need at least:

UnityEngine
UnityEngine.CoreModule
UnityEngine.IMGUIModule
UnityEngine.InputLegacyModule
UnityEngine.TextRenderingModule

2- Write your Features, starting from:

HoldFeature
ToggleFeature
TriggerFeature

Decorate your own properties with ConfigurationPropertyAttribute. This will expose your property to rendering and persistence. You can finetune the behavior by using dedicated settings:

[AttributeUsage(AttributeTargets.Property)]
public class ConfigurationPropertyAttribute : Attribute
{
	// Skip completely (Rendering+Config), useful when overriding properties
	public bool Skip { get; set; } = false;

	// Dislay order
	public int Order { get; set; } = int.MaxValue;

    // Link a resource id for generating comment in the ini file
	public string CommentResourceId { get; set; } = string.Empty;
	
	// Enable/Disable rendering
	public bool Browsable { get; set; } = true;
}

3- Compile. If you need extra dependencies, you can either add them in the Managed folder of the target game, or il-merge everything into one unique assembly (we already use ILRepack to add a compatible Newtonsoft.Json assembly).

4- Run the executable, it will handle the injection into the target process (see Program.cs to customize the target):

public static void Main()
{
	try
	{
		var location = Assembly.GetEntryAssembly()!.Location;
		var bytes = File.ReadAllBytes(location);

		const string processName = "TODO";
		using var injector = new Injector(processName);
		var intptr = injector.Inject(bytes, typeof(Context).Namespace, nameof(Context), nameof(Context.Load));

		Console.WriteLine(
			Strings.InjectorSuccess,
			Path.GetFileName(location),
			processName,
			injector.Is64Bit ? $"0x{intptr.ToInt64():X16}" : $"0x{intptr.ToInt32):X8}");
	}
	catch (Exception e)
	{
		Console.WriteLine(Strings.InjectorFailure, e.Message);
	}
}

Here is the output, but you can still use your preferred Mono injector.

Injected TrainerKit.exe into process FPS: 0x000002B0E9099380

Indeed if we have a look at the TrainerKit.Context.Load method, we can see the registration logic:

public static void Load()
{
	var go = new GameObject(nameof(Context));
	UnityEngine.Object.DontDestroyOnLoad(go);
	FeatureFactory.RegisterAllFeatures(go);

	var commands = FeatureFactory.GetFeature<Commands>();
	if (commands == null)
		return;

	AddConsoleLog(Strings.FeatureRendererWelcome + $" ({commands.Key})");
}

If you hit any issue while injecting, make sure you are not missing any dependencies.

Trainers using TrainerKit

  • EscapeFromTarkov-Trainer for Escape From Tarkov game. Before switching to IL2CPP.

    • No ILRepacking: specific BepInEx injector, and NewtonSoft.Json types are directly provided by the game assemblies. Compiled for netfx 4.7.1
    • Using Unity 2022.3.43f1.
  • IronCast-Trainer for IronCast game.

    • No ILRepacking: standalone SharpMonoInjector, and NewtonSoft.Json types are directly provided by the game assemblies.
    • Using Unity 4.6.1f1, so compiled for netfx 3.5, requiring minor code adaptations.
  • YAZDHD-Trainer for Yet Another Zombie Defense HD game.

    • ILRepacking to provide SharpMonoInjector as a built-in injector, and NewtonSoft.Json types internalized. Compiled for netfx 4.8.1.
    • Using Unity 2019.4.13f1.
  • The demo Unity's FPS Microgame used here.

    • ILRepacking to provide SharpMonoInjector as a built-in injector, and NewtonSoft.Json types internalized. Compiled for netfx 4.8.1.
    • Using Unity 2022.3.62f3.

About

TrainerKit simplifies the development of internal Unity trainers

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Packages

No packages published

Languages