Skip to content

Commit

Permalink
Fixed unclickable checkboxes. Made Dakar 18 trainer 64-bit to allow m…
Browse files Browse the repository at this point in the history
…emory access. Added Readme.
  • Loading branch information
Aldaviva committed Sep 7, 2021
1 parent 7102ce4 commit 1cdcaf0
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 151 deletions.
8 changes: 3 additions & 5 deletions Dakar18Trainer/Cheats/NoSpeedLimitCheat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@ public class NoSpeedLimitCheat: BaseCheat {

private static readonly int[] SPEED_LIMIT_OFFSETS = { 0x04194850, 0x28, 0x1A0, 0x1B0, 0xA0, 0x20, 0x20, 0x830, 0x3A8 };

public override string name { get; } = "No speed limits";
public override string name { get; } = "No speed limit";

public override Combination keyboardShortcut { get; } = Combination.TriggeredBy(Keys.L).Control().Alt();

public override void applyIfNecessary(ProcessHandle processHandle, MemoryEditor memoryEditor) {
if (!isEnabled.Value) return;

protected override void apply(ProcessHandle processHandle) {
IndirectMemoryAddress speedLimitAddress = new(processHandle, null, SPEED_LIMIT_OFFSETS);
memoryEditor.writeToProcessMemory(processHandle, speedLimitAddress, 9999);
MemoryEditor.writeToProcessMemory(processHandle, speedLimitAddress, 9999);
}

}
Expand Down
1 change: 1 addition & 0 deletions Dakar18Trainer/Dakar18Trainer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand Down
6 changes: 3 additions & 3 deletions Dakar18Trainer/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Dakar 18 v.13 +1 Trainer")]
[assembly: AssemblyDescription("Dakar 18 v.13 +1 Trainer")]
[assembly: AssemblyTitle("Dakar 18 v.13 +1 Trainer by Ben")]
[assembly: AssemblyDescription("Dakar 18 v.13 +1 Trainer by Ben")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Ben Hutchison")]
[assembly: AssemblyProduct("Dakar 18 v.13 +1 Trainer")]
[assembly: AssemblyProduct("Dakar 18 v.13 +1 Trainer by Ben")]
[assembly: AssemblyCopyright("© 2021 Ben Hutchison")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
Expand Down
38 changes: 38 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
Trainers
===

<a id="requirements"></a>
### Requirements
- [.NET Framework 4.7.2 runtime](https://dotnet.microsoft.com/download/dotnet-framework) or later (included in Windows 10 version 1803 and later)

### Games
<!-- MarkdownTOC autolink="true" bracket="round" autoanchor="true" levels="1,2" style="unordered" -->

- [Dakar 18](#dakar-18)
- [Superhot: Mind Control Delete](#superhot-mind-control-delete)

<!-- /MarkdownTOC -->

<a id="dakar-18"></a>
## Dakar 18

![trainer screenshot](https://i.imgur.com/ZMcCTAs.png)

[💾 Download](https://github.com/Aldaviva/Trainers/releases/download/1.0.1/Dakar18Trainer.exe)

- No speed limit
- All speed limit warnings and penalties are removed in all difficulty levels.
- You are still automatically limited to 30 km/h in passage control auto-driving zones.

*Supports Dakar 18 v.13, released in March 2019, which contains Desafio Ruta 40 Rally and Inca Rally*

<a id="superhot-mind-control-delete"></a>
## Superhot: Mind Control Delete

![trainer screenshot](https://i.imgur.com/yH0Msy6.png)

[💾 Download](https://github.com/Aldaviva/Trainers/releases/download/1.0.1/SuperhotMindControlDeleteTrainer.exe)

- Infinite health

*Supports `SHMCD.exe` 1.0.0, which has file version 2018.4.5.14584*
12 changes: 5 additions & 7 deletions SuperhotMindControlDeleteTrainer/Cheats/InfiniteHealthCheat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,16 @@ public class InfiniteHealthCheat: BaseCheat {

public override Combination keyboardShortcut { get; } = Combination.TriggeredBy(Keys.H).Alt().Control();

public override void applyIfNecessary(ProcessHandle processHandle, MemoryEditor memoryEditor) {
if (!isEnabled.Value) return;

FixedMemoryAddress currentHeartsAddress = new(new IndirectMemoryAddress(processHandle, MODULE_NAME, CURRENT_HEARTS_OFFSETS).address);
protected override void apply(ProcessHandle processHandle) {
FixedMemoryAddress currentHeartsAddress = new(new IndirectMemoryAddress(processHandle, MODULE_NAME, CURRENT_HEARTS_OFFSETS).address); //used twice, so don't reevaluate address
IndirectMemoryAddress maxHeartsAddress = new(processHandle, MODULE_NAME, MAX_HEARTS_OFFSETS);

int currentHearts = memoryEditor.readFromProcessMemory<int>(processHandle, currentHeartsAddress);
int maxHearts = memoryEditor.readFromProcessMemory<int>(processHandle, maxHeartsAddress);
int currentHearts = MemoryEditor.readFromProcessMemory<int>(processHandle, currentHeartsAddress);
int maxHearts = MemoryEditor.readFromProcessMemory<int>(processHandle, maxHeartsAddress);

if (currentHearts < maxHearts) {
Trace.WriteLine($"Setting health to {maxHearts:N0}...");
memoryEditor.writeToProcessMemory(processHandle, currentHeartsAddress, maxHearts);
MemoryEditor.writeToProcessMemory(processHandle, currentHeartsAddress, maxHearts);
}
}

Expand Down
10 changes: 5 additions & 5 deletions SuperhotMindControlDeleteTrainer/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Superhot: Mind Control Delete 1.0.0 +1 Trainer")]
[assembly: AssemblyDescription("Superhot: Mind Control Delete 1.0.0 +1 Trainer")]
[assembly: AssemblyTitle("Superhot: Mind Control Delete 1.0.0 +1 Trainer by Ben")]
[assembly: AssemblyDescription("Superhot: Mind Control Delete 1.0.0 +1 Trainer by Ben")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Ben Hutchison")]
[assembly: AssemblyProduct("Superhot: Mind Control Delete 1.0.0 +1 Trainer")]
[assembly: AssemblyProduct("Superhot: Mind Control Delete 1.0.0 +1 Trainer by Ben")]
[assembly: AssemblyCopyright("© 2021 Ben Hutchison")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
Expand Down Expand Up @@ -47,5 +47,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]
38 changes: 32 additions & 6 deletions TrainerCommon/App/CombinationConverter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Data;
Expand All @@ -11,22 +12,47 @@ namespace TrainerCommon.App {

public class CombinationConverter: IValueConverter {

private static readonly IComparer<Keys> HOTKEY_SORTER = new HotkeySorter();

/// <summary>
/// Like Gma.System.MouseKeyHook.Combination.ToString() but it prints Ctrl instead of Control like a normal menu hotkey
/// </summary>
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if (value is Combination combination) {
// Like Gma.System.MouseKeyHook.Combination.ToString() but it prints Ctrl instead of Control like a normal menu hotkey
return string.Join("+", combination.Chord.Select(key => key switch {
Keys.Control => "Ctrl",
_ => key.ToString()
}).Append(combination.TriggerKey.ToString()));
IEnumerable<string> modifiers = combination.Chord
.OrderBy(key => key, HOTKEY_SORTER)
.Select(key => key switch {
Keys.Control => "Ctrl",
Keys.LWin or Keys.RWin => "Win",
_ => key.ToString()
});
return string.Join("+", modifiers.Append(combination.TriggerKey.ToString()));
} else {
throw new ArgumentException("value is not an instance of Combination", nameof(value));
throw new ArgumentException($"value {value} is not an instance of Combination", nameof(value));
}
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
throw new NotImplementedException();
}

/// <summary>
/// Sort Shift after Ctrl and Alt, since this is how hotkeys appear in menus in Windows.
/// </summary>
private class HotkeySorter: IComparer<Keys> {

public int Compare(Keys x, Keys y) {
if (x is Keys.Shift && y is Keys.Alt or Keys.Control or Keys.LWin or Keys.RWin) {
return 1;
} else if (y is Keys.Shift && x is Keys.Alt or Keys.Control or Keys.LWin or Keys.RWin) {
return -1;
} else {
return x.CompareTo(y);
}
}

}

}

}
80 changes: 22 additions & 58 deletions TrainerCommon/App/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:trainerCommon="clr-namespace:TrainerCommon"
xmlns:app="clr-namespace:TrainerCommon.App"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=trainerCommon:MainWindowViewModel, IsDesignTimeCreatable=True}"
d:DataContext="{d:DesignInstance Type=app:MainWindowViewModel, IsDesignTimeCreatable=True}"
Title="{Binding windowTitle}"
Height="Auto"
Width="275"
Height="Auto"
Width="275"
ResizeMode="CanMinimize"
WindowStartupLocation="CenterScreen"
SizeToContent="Height">
Expand All @@ -29,65 +28,30 @@

<DockPanel>
<StatusBar DockPanel.Dock="Bottom" BorderBrush="#FFD7D7D7" BorderThickness="0,1,0,0" Padding="1, 0">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<!--<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />-->
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem Grid.Column="0">
<StatusBarItem>
<TextBlock Style="{StaticResource statusBarTextBlock}" Text="{Binding statusBarAttachmentMessage.Value}" />
</StatusBarItem>
<!-- <Separator Grid.Column="1" Background="#FFD7D7D7" />
<StatusBarItem Grid.Column="2" HorizontalContentAlignment="Right">
<TextBlock Style="{StaticResource statusBarTextBlock}" Text="{Binding statusBarVersionText}" />
</StatusBarItem>-->
</StatusBar>

<ListBox Margin="10,10,10,4" ItemsSource="{Binding game.cheats}" HorizontalContentAlignment="Stretch" BorderThickness="0">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<!-- Disable selection and mouseover highlighting: https://stackoverflow.com/a/8894199/979493 -->
<Setter Property="Focusable" Value="False" />
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="Padding" Value="0,0,0,5" />
</Style>
</ListBox.ItemContainerStyle>

<ListBox.ItemTemplate>
<ItemsControl Margin="10,10,10,5" ItemsSource="{Binding game.cheats}" HorizontalContentAlignment="Stretch" BorderThickness="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<DockPanel>
<CheckBox IsChecked="{Binding isEnabled.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Left" Margin="0,0,4,0" VerticalAlignment="Bottom" />

<Label Content="{Binding keyboardShortcut, Converter={StaticResource combinationConverter}}" Padding="0" DockPanel.Dock="Right">
<Label.Foreground>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.GrayTextColorKey}}" />
</Label.Foreground>
</Label>

<Label Content="{Binding name}" Padding="0" />
</DockPanel>
<!-- If the window has a 1px black line at the bottom, try setting UseLayoutRounding="True" on the CheckBox -->
<CheckBox IsChecked="{Binding isEnabled.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="0,0,4,5" HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch" Height="16">
<CheckBox.Content>
<DockPanel VerticalAlignment="Bottom">
<Label Content="{Binding keyboardShortcut, Converter={StaticResource combinationConverter}}" Padding="0" DockPanel.Dock="Right" HorizontalAlignment="Right">
<Label.Foreground>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.GrayTextColorKey}}" />
</Label.Foreground>
</Label>
<Label Content="{Binding name}" Padding="0" DockPanel.Dock="Left" />
</DockPanel>
</CheckBox.Content>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

<!--<Grid Margin="10,10,10,9" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<CheckBox x:Name="infiniteHealthCheckbox" Content="Infinite health" VerticalAlignment="Top" Checked="onInfiniteHealthChecked" IsChecked="{Binding isInfiniteHealthEnabled.Value, Mode=OneWay}" Height="15" />
<Label Grid.Column="1" Padding="0" Margin="0,-1,0,0" VerticalAlignment="Top" HorizontalAlignment="Right" Height="16" Width="58">
<Label.Foreground>
<SolidColorBrush Color="{DynamicResource {x:Static SystemColors.GrayTextColorKey}}"/>
</Label.Foreground> Ctrl+Alt+H</Label>
</Grid>-->

</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
</Window>
37 changes: 27 additions & 10 deletions TrainerCommon/App/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
using KoKo.Property;
using TrainerCommon.Cheats;
Expand All @@ -18,36 +17,54 @@ public class MainWindowViewModel {

public Game game { get; }

public string windowTitle => $"{game.name} {game.supportedVersion} +{game.cheats.Count:N0} Trainer";
public string windowTitle => $"{game.name} {game.supportedVersion} +{game.cheats.Count:N0} Trainer by Ben";

// ReSharper disable once UnusedMember.Global - used by design time DataContext DesignInstance
public MainWindowViewModel(): this(new SampleGame(), new TrainerServiceImpl()) { }

public MainWindowViewModel(Game game, TrainerService trainerService) {
this.game = game;

statusBarAttachmentMessage = DerivedProperty<string>.Create(trainerService.isAttachedToGame, attached =>
attached ? "Attached to game process" : "Detached from game process");
statusBarAttachmentMessage = DerivedProperty<string>.Create(trainerService.isAttachedToGame, attached => attached switch {
AttachmentState.TRAINER_STOPPED => "Attaching to game…",
AttachmentState.PROGRAM_NOT_RUNNING => "Waiting for game to start",
AttachmentState.MEMORY_ADDRESS_NOT_FOUND => "Attached, memory address not found",
AttachmentState.MEMORY_ADDRESS_COULD_NOT_BE_READ => "Attached, memory unreadable",
AttachmentState.ATTACHED => "Attached to game process",
_ => throw new ArgumentOutOfRangeException(nameof(attached), attached, null)
});

statusBarAttachmentMessage.EventSynchronizationContext = SynchronizationContext.Current;
foreach (Cheat cheat in game.cheats) {
cheat.isEnabled.EventSynchronizationContext = SynchronizationContext.Current;
}
}

/// <summary>
/// For design time
/// </summary>
private class SampleGame: Game {

public string name { get; } = "My Game";
public string processName { get; } = "mygame.exe";
public string supportedVersion { get; } = "1.0.0";
public IList<Cheat> cheats { get; } = Enumerable.Repeat(new SampleCheat(), 2).Cast<Cheat>().ToList();

public IList<Cheat> cheats { get; } = new List<Cheat> {
new SampleCheat("Infinite ammo", "Control+Alt+LWin+A"),
new SampleCheat("Infinite lives", "Shift+Control+Alt+L")
};

private class SampleCheat: Cheat {

public string name { get; set; } = "Infinite ammo";
public Combination keyboardShortcut { get; set; } = Combination.TriggeredBy(Keys.A).Alt().Control();
public string name { get; }
public Combination keyboardShortcut { get; }
public SettableProperty<bool> isEnabled { get; } = new StoredProperty<bool>();
public void applyIfNecessary(ProcessHandle processHandle, MemoryEditor memoryEditor) { }
public void applyIfNecessary(ProcessHandle processHandle) { }

public SampleCheat(string name, string keyBoardShortcut) {
this.name = name;
keyboardShortcut = Combination.FromString(keyBoardShortcut);
}

}

Expand Down
10 changes: 8 additions & 2 deletions TrainerCommon/Cheats/Cheat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,24 @@ public interface Cheat {

SettableProperty<bool> isEnabled { get; }

void applyIfNecessary(ProcessHandle processHandle, MemoryEditor memoryEditor);
void applyIfNecessary(ProcessHandle processHandle);

}

public abstract class BaseCheat: Cheat {

public abstract string name { get; }
public abstract Combination keyboardShortcut { get; }
public abstract void applyIfNecessary(ProcessHandle processHandle, MemoryEditor memoryEditor);
protected abstract void apply(ProcessHandle processHandle);

public SettableProperty<bool> isEnabled { get; } = new StoredProperty<bool>();

public void applyIfNecessary(ProcessHandle processHandle) {
if (isEnabled.Value) {
apply(processHandle);
}
}

}

}
Loading

0 comments on commit 1cdcaf0

Please sign in to comment.