Theater done.
This commit is contained in:
parent
519c298b0b
commit
99f5d2cd81
@ -17,7 +17,7 @@ namespace Components
|
|||||||
|
|
||||||
_time64(&time);
|
_time64(&time);
|
||||||
ltime = _localtime64(&time);
|
ltime = _localtime64(&time);
|
||||||
strftime(filename, sizeof(filename) - 1, "iw4m-" VERSION_STR "-%Y%m%d%H%M%S.dmp", ltime);
|
strftime(filename, sizeof(filename) - 1, "iw4x-" VERSION_STR "-%Y%m%d%H%M%S.dmp", ltime);
|
||||||
|
|
||||||
HANDLE hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
HANDLE hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
|
||||||
|
@ -263,14 +263,67 @@ namespace Components
|
|||||||
Dvar::Var("ui_demo_mapname").Set(info.Mapname);
|
Dvar::Var("ui_demo_mapname").Set(info.Mapname);
|
||||||
Dvar::Var("ui_demo_mapname_localized").Set(Game::UI_LocalizeMapName(info.Mapname.data()));
|
Dvar::Var("ui_demo_mapname_localized").Set(Game::UI_LocalizeMapName(info.Mapname.data()));
|
||||||
Dvar::Var("ui_demo_gametype").Set(Game::UI_LocalizeGameType(info.Gametype.data()));
|
Dvar::Var("ui_demo_gametype").Set(Game::UI_LocalizeGameType(info.Gametype.data()));
|
||||||
Dvar::Var("ui_demo_length").Set(info.Length); // TODO: Parse as readable string
|
Dvar::Var("ui_demo_length").Set(Utils::FormatTimeSpan(info.Length)); // TODO: Parse as readable string
|
||||||
Dvar::Var("ui_demo_author").Set(info.Author);
|
Dvar::Var("ui_demo_author").Set(info.Author);
|
||||||
Dvar::Var("ui_demo_date").Set(std::asctime(std::localtime(&info.TimeStamp)));
|
Dvar::Var("ui_demo_date").Set(std::asctime(std::localtime(&info.TimeStamp)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Theatre::InitCGameStub()
|
||||||
|
{
|
||||||
|
if (Dvar::Var("cl_autoRecord").Get<bool>() && !*Game::demoPlaying)
|
||||||
|
{
|
||||||
|
std::vector<std::string> files;
|
||||||
|
std::vector<std::string> demos = FileSystem::GetFileList("demos/", "dm_13");
|
||||||
|
|
||||||
|
for (auto demo : demos)
|
||||||
|
{
|
||||||
|
if (Utils::StartsWith(demo, "auto_"))
|
||||||
|
{
|
||||||
|
files.push_back(demo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int numDel = files.size() - Dvar::Var("cl_demosKeep").Get<int>();
|
||||||
|
|
||||||
|
for (int i = 0; i < numDel; i++)
|
||||||
|
{
|
||||||
|
Logger::Print("Deleting old demo %s\n", files[i].data());
|
||||||
|
FileSystem::DeleteFile("demos", files[i].data());
|
||||||
|
FileSystem::DeleteFile("demos", Utils::VA("%s.json", files[i].data()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Command::Execute(Utils::VA("record auto_%I64d", time(0)), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils::Hook::Call<DWORD()>(0x42BBB0)();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Theatre::MapChangeStub()
|
||||||
|
{
|
||||||
|
if (*Game::demoRecording)
|
||||||
|
{
|
||||||
|
Command::Execute("stoprecord", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::Hook::Call<void()>(0x464A60)();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Theatre::MapChangeSVStub(char* a1, char* a2)
|
||||||
|
{
|
||||||
|
if (*Game::demoRecording)
|
||||||
|
{
|
||||||
|
Command::Execute("stoprecord", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::Hook::Call<void(char*, char*)>(0x487C50)(a1, a2);
|
||||||
|
}
|
||||||
|
|
||||||
Theatre::Theatre()
|
Theatre::Theatre()
|
||||||
{
|
{
|
||||||
|
Dvar::Register<bool>("cl_autoRecord", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Automatically record games.");
|
||||||
|
Dvar::Register<int>("cl_demosKeep", 30, 1, 999, Game::dvar_flag::DVAR_FLAG_SAVED, "How many demos to keep with autorecord.");
|
||||||
|
|
||||||
Utils::Hook(0x5A8370, Theatre::GamestateWriteStub, HOOK_CALL).Install()->Quick();
|
Utils::Hook(0x5A8370, Theatre::GamestateWriteStub, HOOK_CALL).Install()->Quick();
|
||||||
Utils::Hook(0x5A85D2, Theatre::RecordGamestateStub, HOOK_CALL).Install()->Quick();
|
Utils::Hook(0x5A85D2, Theatre::RecordGamestateStub, HOOK_CALL).Install()->Quick();
|
||||||
Utils::Hook(0x5ABE36, Theatre::BaselineStoreStub, HOOK_JUMP).Install()->Quick();
|
Utils::Hook(0x5ABE36, Theatre::BaselineStoreStub, HOOK_JUMP).Install()->Quick();
|
||||||
@ -283,6 +336,11 @@ namespace Components
|
|||||||
Utils::Hook(0x5A82AE, Theatre::RecordStub, HOOK_CALL).Install()->Quick();
|
Utils::Hook(0x5A82AE, Theatre::RecordStub, HOOK_CALL).Install()->Quick();
|
||||||
Utils::Hook(0x5A8156, Theatre::StopRecordStub, HOOK_CALL).Install()->Quick();
|
Utils::Hook(0x5A8156, Theatre::StopRecordStub, HOOK_CALL).Install()->Quick();
|
||||||
|
|
||||||
|
// Autorecording
|
||||||
|
Utils::Hook(0x5A1D6A, Theatre::InitCGameStub, HOOK_CALL).Install()->Quick();
|
||||||
|
Utils::Hook(0x4A712A, Theatre::MapChangeStub, HOOK_CALL).Install()->Quick();
|
||||||
|
Utils::Hook(0x5AA91C, Theatre::MapChangeSVStub, HOOK_CALL).Install()->Quick();
|
||||||
|
|
||||||
// UIScripts
|
// UIScripts
|
||||||
UIScript::Add("loadDemos", Theatre::LoadDemos);
|
UIScript::Add("loadDemos", Theatre::LoadDemos);
|
||||||
UIScript::Add("launchDemo", Theatre::PlayDemo);
|
UIScript::Add("launchDemo", Theatre::PlayDemo);
|
||||||
|
@ -61,6 +61,10 @@ namespace Components
|
|||||||
static void ServerTimedOutStub();
|
static void ServerTimedOutStub();
|
||||||
static void UISetActiveMenuStub();
|
static void UISetActiveMenuStub();
|
||||||
|
|
||||||
|
static uint32_t InitCGameStub();
|
||||||
|
static void MapChangeStub();
|
||||||
|
static void MapChangeSVStub(char* a1, char* a2);
|
||||||
|
|
||||||
static void RecordStub(int channel, char* message, char* file);
|
static void RecordStub(int channel, char* message, char* file);
|
||||||
static void StopRecordStub(int channel, char* message);
|
static void StopRecordStub(int channel, char* message);
|
||||||
};
|
};
|
||||||
|
@ -154,6 +154,7 @@ namespace Game
|
|||||||
|
|
||||||
int* demoFile = (int*)0xA5EA1C;
|
int* demoFile = (int*)0xA5EA1C;
|
||||||
int* demoPlaying = (int*)0xA5EA0C;
|
int* demoPlaying = (int*)0xA5EA0C;
|
||||||
|
int* demoRecording = (int*)0xA5EA08;
|
||||||
int* serverMessageSequence = (int*)0xA3E9B4;
|
int* serverMessageSequence = (int*)0xA3E9B4;
|
||||||
|
|
||||||
void* ReallocateAssetPool(XAssetType type, unsigned int newSize)
|
void* ReallocateAssetPool(XAssetType type, unsigned int newSize)
|
||||||
|
@ -312,6 +312,7 @@ namespace Game
|
|||||||
|
|
||||||
extern int* demoFile;
|
extern int* demoFile;
|
||||||
extern int* demoPlaying;
|
extern int* demoPlaying;
|
||||||
|
extern int* demoRecording;
|
||||||
extern int* serverMessageSequence;
|
extern int* serverMessageSequence;
|
||||||
|
|
||||||
void* ReallocateAssetPool(XAssetType type, unsigned int newSize);
|
void* ReallocateAssetPool(XAssetType type, unsigned int newSize);
|
||||||
|
@ -25,9 +25,9 @@ namespace Utils
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EndsWith(const char* heystack, const char* needle)
|
bool EndsWith(const char* haystack, const char* needle)
|
||||||
{
|
{
|
||||||
return (strstr(heystack, needle) == (heystack + strlen(heystack) - strlen(needle)));
|
return (strstr(haystack, needle) == (haystack + strlen(haystack) - strlen(needle)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Explode(const std::string& str, char delim)
|
std::vector<std::string> Explode(const std::string& str, char delim)
|
||||||
@ -62,6 +62,11 @@ namespace Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StartsWith(std::string haystack, std::string needle)
|
||||||
|
{
|
||||||
|
return (haystack.size() >= needle.size() && !strncmp(needle.data(), haystack.data(), needle.size()));
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int OneAtATime(const char *key, size_t len)
|
unsigned int OneAtATime(const char *key, size_t len)
|
||||||
{
|
{
|
||||||
unsigned int hash, i;
|
unsigned int hash, i;
|
||||||
@ -97,6 +102,17 @@ namespace Utils
|
|||||||
return LTrim(RTrim(s));
|
return LTrim(RTrim(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string FormatTimeSpan(int milliseconds)
|
||||||
|
{
|
||||||
|
int secondsTotal = milliseconds / 1000;
|
||||||
|
int seconds = secondsTotal % 60;
|
||||||
|
int minutesTotal = secondsTotal / 60;
|
||||||
|
int minutes = minutesTotal % 60;
|
||||||
|
int hoursTotal = minutesTotal / 60;
|
||||||
|
|
||||||
|
return Utils::VA("%02d:%02d:%02d", hoursTotal, minutes, seconds);
|
||||||
|
}
|
||||||
|
|
||||||
std::string ParseChallenge(std::string data)
|
std::string ParseChallenge(std::string data)
|
||||||
{
|
{
|
||||||
// Ensure line break
|
// Ensure line break
|
||||||
|
@ -2,14 +2,16 @@ namespace Utils
|
|||||||
{
|
{
|
||||||
const char *VA(const char *fmt, ...);
|
const char *VA(const char *fmt, ...);
|
||||||
std::string StrToLower(std::string input);
|
std::string StrToLower(std::string input);
|
||||||
bool EndsWith(const char* heystack, const char* needle);
|
bool EndsWith(const char* haystack, const char* needle);
|
||||||
std::vector<std::string> Explode(const std::string& str, char delim);
|
std::vector<std::string> Explode(const std::string& str, char delim);
|
||||||
void Replace(std::string &string, std::string find, std::string replace);
|
void Replace(std::string &string, std::string find, std::string replace);
|
||||||
|
bool StartsWith(std::string haystack, std::string needle);
|
||||||
unsigned int OneAtATime(const char *key, size_t len);
|
unsigned int OneAtATime(const char *key, size_t len);
|
||||||
std::string <rim(std::string &s);
|
std::string <rim(std::string &s);
|
||||||
std::string &RTrim(std::string &s);
|
std::string &RTrim(std::string &s);
|
||||||
std::string &Trim(std::string &s);
|
std::string &Trim(std::string &s);
|
||||||
|
|
||||||
|
std::string FormatTimeSpan(int milliseconds);
|
||||||
std::string ParseChallenge(std::string data);
|
std::string ParseChallenge(std::string data);
|
||||||
|
|
||||||
bool FileExists(std::string file);
|
bool FileExists(std::string file);
|
||||||
|
Loading…
Reference in New Issue
Block a user