diff --git a/README.md b/README.md index 9e131761..adb44e40 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ - [Cheats](#cheats) - [Accessible](#accessible) - [Patches](#patches) + - [Config](#config) - [Mapping](#mapping) - [Start & Stop Triggers](#start--stop-triggers) - [With Checkpoints](#with-checkpoints) @@ -117,7 +118,7 @@ - `sar_teleport` teleports player to a saved location - `sar_teleport_setpos` saves current location for teleportation -##### Accessible +##### Unlocked - `sv_bonus_challenge` - `sv_accelerate` - `sv_airaccelerate` @@ -135,6 +136,10 @@ - Redundant command execution has been removed for `playdemo` - Server doesn't close `+remote_view` on map load (Portal 2) +### Config +- `sar_cvars_save` saves important ConVar values to a file +- `sar_cvars_load` loads saved ConVar values + ## Mapping ### Start & Stop Triggers diff --git a/src/Injector/Program.cs b/src/Injector/Program.cs index b9392498..917c636b 100644 --- a/src/Injector/Program.cs +++ b/src/Injector/Program.cs @@ -8,19 +8,15 @@ namespace Injector // Dll injection method internal static class Program { - private const string _defaultProc = "portal2"; + private static readonly string[] _defaultProcs = new string[] { "portal2", "infra" }; private const string _defaultLib = "SourceAutoRecord.dll"; private static void Main(string[] args) { - string Inject(string processName, string dllPath) + string Inject(Process processToInject, string dllPath) { try { - var process = Array.Find(Process.GetProcesses(), p => p.ProcessName == processName); - if (process == null) - return $"Cannot find process named {processName}!"; - if (!File.Exists(dllPath)) return $"Cannot find dll named {dllPath}!"; @@ -30,7 +26,7 @@ string Inject(string processName, string dllPath) if (load == UIntPtr.Zero) return "Cannot load LoadLibraryA!"; - var handle = Kernel32.OpenProcess(ProcessAccess.AllAccess, false, process.Id); + var handle = Kernel32.OpenProcess(ProcessAccess.AllAccess, false, processToInject.Id); if (handle == IntPtr.Zero) return "Cannot open process!"; @@ -52,15 +48,14 @@ string Inject(string processName, string dllPath) return null; } - // Defaults - var proc = _defaultProc; var dll = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), _defaultLib); // Parse optional arguments + var argProc = string.Empty; if (args.Length == 2) { if (!string.IsNullOrEmpty(args[0])) - proc = args[0]; + argProc = args[0]; if (args[1].EndsWith(".dll")) dll = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), args[1]); } @@ -69,15 +64,38 @@ string Inject(string processName, string dllPath) if (args[0].EndsWith(".dll")) dll = Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), args[0]); else if (!string.IsNullOrEmpty(args[0])) - proc = args[0]; + argProc = args[0]; } - var result = Inject(proc, dll); - if (!string.IsNullOrEmpty(result)) - Console.WriteLine($"Error: {result}"); + // Find process + var proc = default(Process); + if (!string.IsNullOrEmpty(argProc)) + { + proc = Array.Find(Process.GetProcesses(), p => p.ProcessName == argProc); + } else - Console.WriteLine($"Successfully injected {dll} into process {proc}!"); + { + foreach (var supportedProc in _defaultProcs) + { + proc = Array.Find(Process.GetProcesses(), p => p.ProcessName == supportedProc); + if (proc == null) + continue; + break; + } + } + if (proc == null) + { + Console.WriteLine($"Could not find supported process!"); + } + else + { + var result = Inject(proc, dll); + if (!string.IsNullOrEmpty(result)) + Console.WriteLine($"Error: {result}"); + else + Console.WriteLine($"Successfully injected {dll} into process {proc.ProcessName}!"); + } Console.ReadKey(); } } diff --git a/src/SourceAutoRecord/Callbacks.hpp b/src/SourceAutoRecord/Callbacks.hpp index 97a4650c..81ade895 100644 --- a/src/SourceAutoRecord/Callbacks.hpp +++ b/src/SourceAutoRecord/Callbacks.hpp @@ -18,27 +18,30 @@ namespace Callbacks { - void PrintSession() + namespace { - int tick = Engine::GetTick(); - Console::Print("Session Tick: %i (%.3f)\n", tick, tick * *Engine::IntervalPerTick); - if (*DemoRecorder::Recording) { - tick = DemoRecorder::GetTick(); - Console::Print("Demo Recorder Tick: %i (%.3f)\n", tick, tick * *Engine::IntervalPerTick); + void PrintSession() + { + int tick = Engine::GetTick(); + Console::Print("Session Tick: %i (%.3f)\n", tick, tick * *Engine::IntervalPerTick); + if (*DemoRecorder::Recording) { + tick = DemoRecorder::GetTick(); + Console::Print("Demo Recorder Tick: %i (%.3f)\n", tick, tick * *Engine::IntervalPerTick); + } + if (DemoPlayer::IsPlaying()) { + tick = DemoPlayer::GetTick(); + Console::Print("Demo Player Tick: %i (%.3f)\n", tick, tick * *Engine::IntervalPerTick); + } } - if (DemoPlayer::IsPlaying()) { - tick = DemoPlayer::GetTick(); - Console::Print("Demo Player Tick: %i (%.3f)\n", tick, tick * *Engine::IntervalPerTick); + void PrintAbout() + { + Console::Print("SourceAutoRecord tells the engine to keep recording when loading a save.\n"); + Console::Print("More information at: https://nekzor.github.io/SourceAutoRecord\n"); + Console::Print("Game: %s\n", Game::GetVersion()); + Console::Print("Version: %s\n", SAR_VERSION); + Console::Print("Build: %s\n", SAR_BUILD); } } - void PrintAbout() - { - Console::Print("SourceAutoRecord tells the engine to keep recording when loading a save.\n"); - Console::Print("More information at: https://nekzor.github.io/SourceAutoRecord\n"); - Console::Print("Game: %s\n", Game::GetVersion()); - Console::Print("Version: %s\n", SAR_VERSION); - Console::Print("Build: %s\n", SAR_BUILD); - } // Demo parsing namespace { @@ -405,4 +408,41 @@ namespace Callbacks Teleporter::Save(); } } + // Config + namespace + { + void SaveCvars() + { + std::ofstream file(Engine::GetDir() + std::string("\\cfg\\_sar_cvars.cfg"), std::ios::out | std::ios::trunc); + if (!file.good()) { + Console::Print("Failed to create config file!\n"); + return; + } + + auto spacing = sar_hud_default_spacing.GetInt(); + auto xpadding = sar_hud_default_padding_x.GetInt(); + auto ypadding = sar_hud_default_padding_y.GetInt(); + auto index = sar_hud_default_font_index.GetInt(); + auto size = sar_hud_default_font_size.GetInt(); + auto color = sar_hud_default_font_color.GetString(); + + file << "sar_hud_default_spacing " << spacing << "\n"; + file << "sar_hud_default_padding_x " << xpadding << "\n"; + file << "sar_hud_default_padding_y " << ypadding << "\n"; + file << "sar_hud_default_font_index " << index << "\n"; + file << "sar_hud_default_font_size " << size << "\n"; + file << "sar_hud_default_font_color " << color; + + Console::Print("Saved important settings in /cfg/_sar_cvars.cfg!\n"); + } + void LoadCvars() + { + std::ifstream file(Engine::GetDir() + std::string("\\cfg\\_sar_cvars.cfg"), std::ios::in); + if (!file.good()) { + Console::Print("Config file not found!\n"); + return; + } + Engine::ExecuteCommand("exec _sar_cvars.cfg"); + } + } } \ No newline at end of file diff --git a/src/SourceAutoRecord/Commands.hpp b/src/SourceAutoRecord/Commands.hpp index 64dc193a..7ac8744d 100644 --- a/src/SourceAutoRecord/Commands.hpp +++ b/src/SourceAutoRecord/Commands.hpp @@ -76,6 +76,10 @@ namespace Commands ConCommand sar_teleport; ConCommand sar_teleport_setpos; + // Config + ConCommand sar_cvars_save; + ConCommand sar_cvars_load; + // Others ConCommand sar_session; ConCommand sar_about; diff --git a/src/SourceAutoRecord/SourceAutoRecord.hpp b/src/SourceAutoRecord/SourceAutoRecord.hpp index a8cc630b..7213c817 100644 --- a/src/SourceAutoRecord/SourceAutoRecord.hpp +++ b/src/SourceAutoRecord/SourceAutoRecord.hpp @@ -320,6 +320,14 @@ namespace SAR "sar_about", Callbacks::PrintAbout, "Prints info about this plugin.\n"); + sar_cvars_save = CreateCommand( + "sar_cvars_save", + Callbacks::SaveCvars, + "Saves important SAR cvars.\n"); + sar_cvars_load = CreateCommand( + "sar_cvars_load", + Callbacks::LoadCvars, + "Loads important SAR cvars.\n"); // From the game cl_showpos = ConVar("cl_showpos");