From 79c8e9b87ebc9fe85f772bf9d3e766bfd5f2822f Mon Sep 17 00:00:00 2001 From: Me_TheCat Date: Fri, 29 Mar 2019 10:22:44 +0300 Subject: [PATCH 1/4] Added an option to output player death counter and kill counter to files. Useful for display on twitch stream. --- SekiroFpsUnlockAndMore/MainWindow.xaml.cs | 134 ++++++++++++++++++---- SekiroFpsUnlockAndMore/Offsets.cs | 12 +- 2 files changed, 119 insertions(+), 27 deletions(-) diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs index c819a9c..2db3491 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs @@ -9,7 +9,8 @@ using System.Windows.Threading; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text.RegularExpressions; - +using System.Timers; + namespace SekiroFpsUnlockAndMore { public partial class MainWindow : Window @@ -41,15 +42,24 @@ namespace SekiroFpsUnlockAndMore internal long _offset_resolution = 0x0; internal long _offset_resolution_default = 0x0; internal long _offset_widescreen_219 = 0x0; - internal long _offset_fovsetting = 0x0; - - internal readonly DispatcherTimer _dispatcherTimerCheck = new DispatcherTimer(); + internal long _offset_fovsetting = 0x0; + //game stat offsets + internal long _offset_player_deaths = 0x0; + internal long _pointer_player_deaths = 0x0; + internal long _offset_total_kills = 0x0; + internal long _pointer_total_kills = 0x0; + + internal const string deathCounterFilename = "DeathCouner.txt"; + internal const string totalKillsFilename = "TotalKillsCounter.txt"; + + internal readonly Timer _statRecordTimer = new Timer(); + internal readonly DispatcherTimer _dispatcherTimerCheck = new DispatcherTimer(); internal bool _running = false; internal string _logPath; internal bool _retryAccess = true; - internal RECT _windowRect; - - public MainWindow() + internal RECT _windowRect; + + public MainWindow() { InitializeComponent(); } @@ -73,8 +83,11 @@ namespace SekiroFpsUnlockAndMore _dispatcherTimerCheck.Tick += new EventHandler(CheckGame); _dispatcherTimerCheck.Interval = new TimeSpan(0, 0, 0, 2); - _dispatcherTimerCheck.Start(); - } + _dispatcherTimerCheck.Start(); + + _statRecordTimer.Elapsed += new ElapsedEventHandler(StatReadTimer); + _statRecordTimer.Interval = 1500; + } /// /// On window closing. @@ -86,7 +99,9 @@ namespace SekiroFpsUnlockAndMore UnregisterHotKey(hwnd, 9009); if (_gameProc != IntPtr.Zero) CloseHandle(_gameProc); - } + + _statRecordTimer.Stop(); + } /// /// Windows Message queue (Wndproc) to catch HotKeyPressed @@ -243,9 +258,32 @@ namespace SekiroFpsUnlockAndMore LogToFile("FOV not found..."); this.cbFov.IsEnabled = false; this.cbFov.IsChecked = false; - } - - _running = true; + } + + //Game stats + _offset_player_deaths = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_PLAYER_DEATHS, Offsets.PATTERN_PLAYER_DEATHS_MASK, ' '); + Debug.WriteLine("Player Deaths found at: 0x" + _offset_player_deaths.ToString("X")); + if (!IsValid(_offset_player_deaths)) + { + LogToFile("Player death counter not found..."); + } + else + { + _pointer_player_deaths = Read(_gameProc, FindOffsetToStaticPointer(_gameProc, _offset_player_deaths, 0)) + 0x90; + } + + _offset_total_kills = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_TOTAL_KILLS, Offsets.PATTERN_TOTAL_KILLS_MASK, ' ') + Offsets.PATTERN_TOTAL_KILLS_OFFSET; + Debug.WriteLine("Total kills found at: 0x" + _offset_total_kills.ToString("X")); + if (!IsValid(_offset_total_kills)) + { + LogToFile("Total kills counter not found..."); + } + else + { + _pointer_total_kills = FindOffsetToStaticPointer(_gameProc, _offset_total_kills, 0); + } + + _running = true; _dispatcherTimerCheck.Stop(); PatchGame(); } @@ -402,14 +440,35 @@ namespace SekiroFpsUnlockAndMore UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game patched!", Brushes.Green); else UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White); - } - - /// - /// Returns the hexadecimal representation of an IEEE-754 floating point number - /// - /// The floating point number. - /// The hexadecimal representation of the input. - private string getHexRepresentationFromFloat(float input) + } + + /// + /// Reads some hidden stats and outputs them to text files. Use to display counters on Twitch stream or just look at them and get disspointed + /// (_gameProc, _pointer_player_deaths); + //Debug.WriteLine("[STAT]Player deaths: " + playerDeaths); + LogStatFile(deathCounterFilename, playerDeaths.ToString()); + + if (IsValid(_pointer_total_kills)) + { + int totalKills = Read(_gameProc, _pointer_total_kills); + totalKills -= playerDeaths; //Since this value seems to track every death, including the player + //Debug.WriteLine("[STAT]Enemies killed: " + totalKills); + LogStatFile(totalKillsFilename, totalKills.ToString()); + } + } + } + + /// + /// Returns the hexadecimal representation of an IEEE-754 floating point number + /// + /// The floating point number. + /// The hexadecimal representation of the input. + private string getHexRepresentationFromFloat(float input) { uint f = BitConverter.ToUInt32(BitConverter.GetBytes(input), 0); return "0x" + f.ToString("X8"); @@ -576,9 +635,29 @@ namespace SekiroFpsUnlockAndMore { MessageBox.Show("Writing to log file failed: " + ex.Message, "Sekiro Fps Unlock And More"); } - } - - private void UpdateStatus(string text, Brush color) + } + + /// + /// Logs stat values to separate files for the use in OBS + /// + /// File name + /// Just a single stat value + private void LogStatFile(string filename, string value) + { + try + { + using (StreamWriter writer = new StreamWriter(filename, false)) + { + writer.Write(value); + } + } + catch (Exception ex) + { + MessageBox.Show("Failed writing stat file: " + ex.Message, "Sekiro Fps Unlock And More"); + } + } + + private void UpdateStatus(string text, Brush color) { this.tbStatus.Background = color; this.tbStatus.Text = text; @@ -617,7 +696,12 @@ namespace SekiroFpsUnlockAndMore PatchGame(); } - private void BPatch_Click(object sender, RoutedEventArgs e) + private void CbStatChanged(object sender, RoutedEventArgs e) + { + _statRecordTimer.Enabled = (bool)cbLogStats.IsChecked; + } + + private void BPatch_Click(object sender, RoutedEventArgs e) { PatchGame(); } diff --git a/SekiroFpsUnlockAndMore/Offsets.cs b/SekiroFpsUnlockAndMore/Offsets.cs index 9a41cc4..067af51 100644 --- a/SekiroFpsUnlockAndMore/Offsets.cs +++ b/SekiroFpsUnlockAndMore/Offsets.cs @@ -26,6 +26,14 @@ namespace SekiroFpsUnlockAndMore // credits to jackfuste for FOV findings internal const string PATTERN_FOVSETTING = "F3 0F 10 08 F3 0F 59 0D 00 00 9B 02"; // F3 0F 10 08 F3 0F 59 0D ?? ?? 9B 02 internal const string PATTERN_FOVSETTING_MASK = "xxxxxxxx??xx"; - internal const int PATTERN_FOVSETTING_OFFSET = 8; - } + internal const int PATTERN_FOVSETTING_OFFSET = 8; + + // game stat values by Me_TheCat + internal const string PATTERN_PLAYER_DEATHS = "8B 88 90 00 00 00 89 8B FC 00 00 00 48 8B"; + internal const string PATTERN_PLAYER_DEATHS_MASK = "xxxxxxxxx???xx"; + + internal const string PATTERN_TOTAL_KILLS = "48 8D 0D 00 00 00 00 89 14 81 C3"; + internal const string PATTERN_TOTAL_KILLS_MASK = "xxx????xxxx"; + internal const int PATTERN_TOTAL_KILLS_OFFSET = 7; + } } From 4d6544ad2a0d289214f91baa7bac6023c77ebf20 Mon Sep 17 00:00:00 2001 From: Me_TheCat Date: Fri, 29 Mar 2019 10:23:45 +0300 Subject: [PATCH 2/4] Added UI checkbox for stat logging. Had to move content a bit --- SekiroFpsUnlockAndMore/MainWindow.xaml | 77 +++++++++++++------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml b/SekiroFpsUnlockAndMore/MainWindow.xaml index fa0ab7b..4fc5190 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml @@ -7,44 +7,45 @@ mc:Ignorable="d" Title="Sekiro FPS Unlocker and more v1.0.2" Height="Auto" SizeToContent="WidthAndHeight" Width="Auto" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing"> - - - - - -