Merge pull request #587 from diamante0018/refactor/script

[Script]: Add IsSprinting & more
This commit is contained in:
Edo 2022-11-24 16:14:13 +00:00 committed by GitHub
commit 82a039e3b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 157 additions and 103 deletions

View File

@ -111,9 +111,15 @@ namespace Components
} }
} }
void Bots::GScr_isTestClient(Game::scr_entref_t entref) void Bots::GScr_isTestClient(const Game::scr_entref_t entref)
{ {
const auto* ent = Game::GetPlayerEntity(entref); const auto* ent = Game::GetEntity(entref);
if (!ent->client)
{
Game::Scr_Error("isTestClient: entity must be a player entity");
return;
}
Game::Scr_AddBool(Game::SV_IsTestClient(ent->s.number) != 0); Game::Scr_AddBool(Game::SV_IsTestClient(ent->s.number) != 0);
} }

View File

@ -15,8 +15,8 @@ namespace Components
std::unordered_map<const char*, const char*> Script::ReplacedFunctions; std::unordered_map<const char*, const char*> Script::ReplacedFunctions;
const char* Script::ReplacedPos = nullptr; const char* Script::ReplacedPos = nullptr;
std::vector<int> Script::ScriptMainHandles; std::unordered_map<std::string, int> Script::ScriptMainHandles;
std::vector<int> Script::ScriptInitHandles; std::unordered_map<std::string, int> Script::ScriptInitHandles;
void Script::ShowDeprecationWarning() void Script::ShowDeprecationWarning()
{ {
@ -28,16 +28,16 @@ namespace Components
void Script::FunctionError() void Script::FunctionError()
{ {
const auto* funcName = Game::SL_ConvertToString(Script::FunctionName); const auto* funcName = Game::SL_ConvertToString(FunctionName);
Game::Scr_ShutdownAllocNode(); Game::Scr_ShutdownAllocNode();
Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "\n");
Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "******* script compile error *******\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "******* script compile error *******\n");
Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "Error: unknown function {} in {}\n", funcName, Script::ScriptName); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "Error: unknown function {} in {}\n", funcName, ScriptName);
Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "************************************\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "************************************\n");
Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\nunknown function {}\n{}\n\n", funcName, Script::ScriptName); Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\nunknown function {}\n{}\n\n", funcName, ScriptName);
} }
__declspec(naked) void Script::StoreFunctionNameStub() __declspec(naked) void Script::StoreFunctionNameStub()
@ -45,7 +45,7 @@ namespace Components
__asm __asm
{ {
mov eax, [esp - 8h] mov eax, [esp - 8h]
mov Script::FunctionName, ax mov FunctionName, ax
sub esp, 0Ch sub esp, 0Ch
push 0 push 0
@ -87,12 +87,12 @@ namespace Components
void Script::StoreScriptName(const char* name) void Script::StoreScriptName(const char* name)
{ {
Script::ScriptNameStack.push_back(Script::ScriptName); ScriptNameStack.push_back(ScriptName);
Script::ScriptName = name; ScriptName = name;
if (!Utils::String::EndsWith(Script::ScriptName, ".gsc")) if (!Utils::String::EndsWith(ScriptName, ".gsc"))
{ {
Script::ScriptName.append(".gsc"); ScriptName.append(".gsc");
} }
} }
@ -105,7 +105,7 @@ namespace Components
lea ecx, [esp + 30h] lea ecx, [esp + 30h]
push ecx push ecx
call Script::StoreScriptName call StoreScriptName
add esp, 4h add esp, 4h
popad popad
@ -120,8 +120,8 @@ namespace Components
void Script::RestoreScriptName() void Script::RestoreScriptName()
{ {
Script::ScriptName = Script::ScriptNameStack.back(); ScriptName = ScriptNameStack.back();
Script::ScriptNameStack.pop_back(); ScriptNameStack.pop_back();
} }
__declspec(naked) void Script::RestoreScriptNameStub() __declspec(naked) void Script::RestoreScriptNameStub()
@ -129,7 +129,7 @@ namespace Components
__asm __asm
{ {
pushad pushad
call Script::RestoreScriptName call RestoreScriptName
popad popad
mov ds:1CDEAA8h, ebp mov ds:1CDEAA8h, ebp
@ -205,17 +205,19 @@ namespace Components
Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "\n");
Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "******* script compile error *******\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "******* script compile error *******\n");
Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "Error: {} ", msgbuf); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "Error: {} ", msgbuf);
Script::PrintSourcePos(Script::ScriptName.data(), offset); PrintSourcePos(ScriptName.data(), offset);
Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "************************************\n\n"); Logger::Print(Game::CON_CHANNEL_PARSERSCRIPT, "************************************\n\n");
Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\n{}\n{}\n(see console for actual details)\n", msgbuf, Script::ScriptName); Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\n{}\n{}\n(see console for actual details)\n", msgbuf, ScriptName);
} }
void Script::Scr_LoadGameType_Stub() void Script::Scr_LoadGameType_Stub()
{ {
for (const auto& handle : Script::ScriptMainHandles) for (const auto& handle : ScriptMainHandles)
{ {
const auto id = Game::Scr_ExecThread(handle, 0); Logger::Print("Executing '{}::main'\n", handle.first.data());
const auto id = Game::Scr_ExecThread(handle.second, 0);
Game::Scr_FreeThread(static_cast<std::uint16_t>(id)); Game::Scr_FreeThread(static_cast<std::uint16_t>(id));
} }
@ -224,9 +226,11 @@ namespace Components
void Script::Scr_StartupGameType_Stub() void Script::Scr_StartupGameType_Stub()
{ {
for (const auto& handle : Script::ScriptInitHandles) for (const auto& handle : ScriptInitHandles)
{ {
const auto id = Game::Scr_ExecThread(handle, 0); Logger::Print("Executing '{}::init'\n", handle.first.data());
const auto id = Game::Scr_ExecThread(handle.second, 0);
Game::Scr_FreeThread(static_cast<std::uint16_t>(id)); Game::Scr_FreeThread(static_cast<std::uint16_t>(id));
} }
@ -237,8 +241,8 @@ namespace Components
void Script::GScr_LoadGameTypeScript_Stub() void Script::GScr_LoadGameTypeScript_Stub()
{ {
// Clear handles (from previous GSC loading session) // Clear handles (from previous GSC loading session)
Script::ScriptMainHandles.clear(); ScriptMainHandles.clear();
Script::ScriptInitHandles.clear(); ScriptInitHandles.clear();
char path[MAX_PATH]{}; char path[MAX_PATH]{};
@ -262,18 +266,17 @@ namespace Components
} }
Logger::Print("Script {}.gsc loaded successfully.\n", path); Logger::Print("Script {}.gsc loaded successfully.\n", path);
Logger::Debug("Finding script handle main or init...");
const auto initHandle = Game::Scr_GetFunctionHandle(path, "init"); const auto initHandle = Game::Scr_GetFunctionHandle(path, "init");
if (initHandle != 0) if (initHandle != 0)
{ {
Script::ScriptInitHandles.push_back(initHandle); ScriptInitHandles.insert_or_assign(path, initHandle);
} }
const auto mainHandle = Game::Scr_GetFunctionHandle(path, "main"); const auto mainHandle = Game::Scr_GetFunctionHandle(path, "main");
if (mainHandle != 0) if (mainHandle != 0)
{ {
Script::ScriptMainHandles.push_back(mainHandle); ScriptMainHandles.insert_or_assign(path, mainHandle);
} }
// Allow scripts with no handles // Allow scripts with no handles
@ -285,7 +288,7 @@ namespace Components
void Script::AddFunction(const std::string& name, Game::BuiltinFunction func, bool type) void Script::AddFunction(const std::string& name, Game::BuiltinFunction func, bool type)
{ {
Script::ScriptFunction toAdd; ScriptFunction toAdd;
toAdd.actionFunc = func; toAdd.actionFunc = func;
toAdd.type = type; toAdd.type = type;
@ -294,7 +297,7 @@ namespace Components
void Script::AddMethod(const std::string& name, Game::BuiltinMethod func, bool type) void Script::AddMethod(const std::string& name, Game::BuiltinMethod func, bool type)
{ {
Script::ScriptMethod toAdd; ScriptMethod toAdd;
toAdd.actionFunc = func; toAdd.actionFunc = func;
toAdd.type = type; toAdd.type = type;
@ -306,7 +309,7 @@ namespace Components
if (pName != nullptr) if (pName != nullptr)
{ {
// If no function was found let's call game's function // If no function was found let's call game's function
if (const auto itr = Script::CustomScrFunctions.find(Utils::String::ToLower(*pName)); itr != Script::CustomScrFunctions.end()) if (const auto itr = CustomScrFunctions.find(Utils::String::ToLower(*pName)); itr != CustomScrFunctions.end())
{ {
*type = itr->second.type; *type = itr->second.type;
return itr->second.actionFunc; return itr->second.actionFunc;
@ -314,7 +317,7 @@ namespace Components
} }
else else
{ {
for (const auto& [name, builtin] : Script::CustomScrFunctions) for (const auto& [name, builtin] : CustomScrFunctions)
{ {
Game::Scr_RegisterFunction(reinterpret_cast<int>(builtin.actionFunc), name.data()); Game::Scr_RegisterFunction(reinterpret_cast<int>(builtin.actionFunc), name.data());
} }
@ -328,7 +331,7 @@ namespace Components
if (pName != nullptr) if (pName != nullptr)
{ {
// If no method was found let's call game's function // If no method was found let's call game's function
if (const auto itr = Script::CustomScrMethods.find(Utils::String::ToLower(*pName)); itr != Script::CustomScrMethods.end()) if (const auto itr = CustomScrMethods.find(Utils::String::ToLower(*pName)); itr != CustomScrMethods.end())
{ {
*type = itr->second.type; *type = itr->second.type;
return itr->second.actionFunc; return itr->second.actionFunc;
@ -336,7 +339,7 @@ namespace Components
} }
else else
{ {
for (const auto& [name, builtin] : Script::CustomScrMethods) for (const auto& [name, builtin] : CustomScrMethods)
{ {
Game::Scr_RegisterFunction(reinterpret_cast<int>(builtin.actionFunc), name.data()); Game::Scr_RegisterFunction(reinterpret_cast<int>(builtin.actionFunc), name.data());
} }
@ -347,7 +350,7 @@ namespace Components
void Script::StoreScriptBaseProgramNum() void Script::StoreScriptBaseProgramNum()
{ {
Script::ScriptBaseProgramNum.insert_or_assign(Utils::Hook::Get<int>(0x1CFEEF8), Script::ScriptName); ScriptBaseProgramNum.insert_or_assign(Utils::Hook::Get<int>(0x1CFEEF8), ScriptName);
} }
void Script::Scr_PrintPrevCodePos(int scriptPos) void Script::Scr_PrintPrevCodePos(int scriptPos)
@ -355,7 +358,7 @@ namespace Components
auto bestCodePos = -1, nextCodePos = -1, offset = -1; auto bestCodePos = -1, nextCodePos = -1, offset = -1;
std::string file; std::string file;
for (const auto& [key, value] : Script::ScriptBaseProgramNum) for (const auto& [key, value] : ScriptBaseProgramNum)
{ {
const auto codePos = key; const auto codePos = key;
@ -388,7 +391,7 @@ namespace Components
__asm __asm
{ {
push esi push esi
call Script::Scr_PrintPrevCodePos call Scr_PrintPrevCodePos
add esp, 4h add esp, 4h
pop esi pop esi
@ -402,7 +405,7 @@ namespace Components
{ {
// execute our hook // execute our hook
pushad pushad
call Script::StoreScriptBaseProgramNum call StoreScriptBaseProgramNum
popad popad
// execute overwritten code caused by the jump hook // execute overwritten code caused by the jump hook
@ -452,9 +455,9 @@ namespace Components
void Script::GetReplacedPos(const char* pos) void Script::GetReplacedPos(const char* pos)
{ {
if (Script::ReplacedFunctions.contains(pos)) if (ReplacedFunctions.contains(pos))
{ {
Script::ReplacedPos = Script::ReplacedFunctions[pos]; ReplacedPos = ReplacedFunctions[pos];
} }
} }
@ -466,12 +469,12 @@ namespace Components
return; return;
} }
if (Script::ReplacedFunctions.contains(what)) if (ReplacedFunctions.contains(what))
{ {
Logger::Warning(Game::CON_CHANNEL_SCRIPT, "ReplacedFunctions already contains codePosValue for a function\n"); Logger::Warning(Game::CON_CHANNEL_SCRIPT, "ReplacedFunctions already contains codePosValue for a function\n");
} }
Script::ReplacedFunctions[what] = with; ReplacedFunctions[what] = with;
} }
__declspec(naked) void Script::VMExecuteInternalStub() __declspec(naked) void Script::VMExecuteInternalStub()
@ -481,12 +484,12 @@ namespace Components
pushad pushad
push edx push edx
call Script::GetReplacedPos call GetReplacedPos
pop edx pop edx
popad popad
cmp Script::ReplacedPos, 0 cmp ReplacedPos, 0
jne SetPos jne SetPos
movzx eax, byte ptr [edx] movzx eax, byte ptr [edx]
@ -509,8 +512,8 @@ namespace Components
retn retn
SetPos: SetPos:
mov edx, Script::ReplacedPos mov edx, ReplacedPos
mov Script::ReplacedPos, 0 mov ReplacedPos, 0
movzx eax, byte ptr [edx] movzx eax, byte ptr [edx]
inc edx inc edx
@ -521,7 +524,7 @@ namespace Components
Game::client_t* Script::GetClient(const Game::gentity_t* ent) Game::client_t* Script::GetClient(const Game::gentity_t* ent)
{ {
assert(ent != nullptr); assert(ent);
if (ent->client == nullptr) if (ent->client == nullptr)
{ {
@ -529,7 +532,7 @@ namespace Components
return nullptr; return nullptr;
} }
if (ent->s.number >= *Game::svs_clientCount) if (static_cast<std::size_t>(ent->s.number) >= Game::MAX_CLIENTS)
{ {
Game::Scr_ObjectError(Utils::String::VA("Entity %i is out of bounds", ent->s.number)); Game::Scr_ObjectError(Utils::String::VA("Entity %i is out of bounds", ent->s.number));
return nullptr; return nullptr;
@ -540,7 +543,7 @@ namespace Components
void Script::AddFunctions() void Script::AddFunctions()
{ {
Script::AddFunction("ReplaceFunc", [] // gsc: ReplaceFunc(<function>, <function>) AddFunction("ReplaceFunc", [] // gsc: ReplaceFunc(<function>, <function>)
{ {
if (Game::Scr_GetNumParam() != 2) if (Game::Scr_GetNumParam() != 2)
{ {
@ -548,14 +551,14 @@ namespace Components
return; return;
} }
const auto what = Script::GetCodePosForParam(0); const auto what = GetCodePosForParam(0);
const auto with = Script::GetCodePosForParam(1); const auto with = GetCodePosForParam(1);
Script::SetReplacedPos(what, with); SetReplacedPos(what, with);
}); });
// System time // System time
Script::AddFunction("GetSystemMilliseconds", [] // gsc: GetSystemMilliseconds() AddFunction("GetSystemMilliseconds", [] // gsc: GetSystemMilliseconds()
{ {
SYSTEMTIME time; SYSTEMTIME time;
GetSystemTime(&time); GetSystemTime(&time);
@ -564,7 +567,7 @@ namespace Components
}); });
// Executes command to the console // Executes command to the console
Script::AddFunction("Exec", [] // gsc: Exec(<string>) AddFunction("Exec", [] // gsc: Exec(<string>)
{ {
const auto str = Game::Scr_GetString(0); const auto str = Game::Scr_GetString(0);
@ -578,7 +581,7 @@ namespace Components
}); });
// Allow printing to the console even when developer is 0 // Allow printing to the console even when developer is 0
Script::AddFunction("PrintConsole", [] // gsc: PrintConsole(<string>) AddFunction("PrintConsole", [] // gsc: PrintConsole(<string>)
{ {
for (std::size_t i = 0; i < Game::Scr_GetNumParam(); ++i) for (std::size_t i = 0; i < Game::Scr_GetNumParam(); ++i)
{ {
@ -595,9 +598,9 @@ namespace Components
}); });
// PlayerCmd_AreControlsFrozen GSC function from Black Ops 2 // PlayerCmd_AreControlsFrozen GSC function from Black Ops 2
Script::AddMethod("AreControlsFrozen", [](Game::scr_entref_t entref) // Usage: self AreControlsFrozen(); AddMethod("AreControlsFrozen", [](Game::scr_entref_t entref) // Usage: self AreControlsFrozen();
{ {
const auto* ent = Game::GetPlayerEntity(entref); const auto* ent = Scr_GetPlayerEntity(entref);
Game::Scr_AddBool((ent->client->flags & Game::PLAYER_FLAG_FROZEN) != 0); Game::Scr_AddBool((ent->client->flags & Game::PLAYER_FLAG_FROZEN) != 0);
}); });
@ -605,34 +608,34 @@ namespace Components
Script::Script() Script::Script()
{ {
Utils::Hook(0x612DB0, Script::StoreFunctionNameStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x612DB0, StoreFunctionNameStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x427E71, Script::RestoreScriptNameStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x427E71, RestoreScriptNameStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x427DBC, Script::StoreScriptNameStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x427DBC, StoreScriptNameStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x426C2D, Script::StoreScriptBaseProgramNumStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x426C2D, StoreScriptBaseProgramNumStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x42281B, Script::Scr_PrintPrevCodePosStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x42281B, Scr_PrintPrevCodePosStub, HOOK_JUMP).install()->quick();
Utils::Hook(0x61E3AD, Script::RuntimeError, HOOK_CALL).install()->quick(); Utils::Hook(0x61E3AD, RuntimeError, HOOK_CALL).install()->quick();
Utils::Hook(0x621976, Script::RuntimeError, HOOK_CALL).install()->quick(); Utils::Hook(0x621976, RuntimeError, HOOK_CALL).install()->quick();
Utils::Hook(0x62246E, Script::RuntimeError, HOOK_CALL).install()->quick(); Utils::Hook(0x62246E, RuntimeError, HOOK_CALL).install()->quick();
// Skip check in GScr_CheckAllowedToSetPersistentData to prevent log spam in RuntimeError. // Skip check in GScr_CheckAllowedToSetPersistentData to prevent log spam in RuntimeError.
// On IW5 the function is entirely nullsubbed // On IW5 the function is entirely nullsubbed
Utils::Hook::Set<BYTE>(0x5F8DBF, 0xEB); Utils::Hook::Set<std::uint8_t>(0x5F8DBF, 0xEB);
Utils::Hook(0x612E8D, Script::FunctionError, HOOK_CALL).install()->quick(); Utils::Hook(0x612E8D, FunctionError, HOOK_CALL).install()->quick();
Utils::Hook(0x612EA2, Script::FunctionError, HOOK_CALL).install()->quick(); Utils::Hook(0x612EA2, FunctionError, HOOK_CALL).install()->quick();
Utils::Hook(0x434260, Script::CompileError, HOOK_JUMP).install()->quick(); Utils::Hook(0x434260, CompileError, HOOK_JUMP).install()->quick();
Utils::Hook(0x48EFFE, Script::Scr_LoadGameType_Stub, HOOK_CALL).install()->quick(); Utils::Hook(0x48EFFE, Scr_LoadGameType_Stub, HOOK_CALL).install()->quick();
Utils::Hook(0x48F008, Script::Scr_StartupGameType_Stub, HOOK_CALL).install()->quick(); Utils::Hook(0x48F008, Scr_StartupGameType_Stub, HOOK_CALL).install()->quick();
Utils::Hook(0x45D44A, Script::GScr_LoadGameTypeScript_Stub, HOOK_CALL).install()->quick(); Utils::Hook(0x45D44A, GScr_LoadGameTypeScript_Stub, HOOK_CALL).install()->quick();
// Fetch custom functions // Fetch custom functions
Utils::Hook(0x44E72E, Script::BuiltIn_GetFunctionStub, HOOK_CALL).install()->quick(); // Scr_GetFunction Utils::Hook(0x44E72E, BuiltIn_GetFunctionStub, HOOK_CALL).install()->quick(); // Scr_GetFunction
Utils::Hook(0x4EC8DD, Script::BuiltIn_GetMethodStub, HOOK_CALL).install()->quick(); // Scr_GetMethod Utils::Hook(0x4EC8DD, BuiltIn_GetMethodStub, HOOK_CALL).install()->quick(); // Scr_GetMethod
Utils::Hook(0x5F41A3, Script::SetExpFogStub, HOOK_CALL).install()->quick(); Utils::Hook(0x5F41A3, SetExpFogStub, HOOK_CALL).install()->quick();
Utils::Hook(0x61E92E, Script::VMExecuteInternalStub, HOOK_JUMP).install()->quick(); Utils::Hook(0x61E92E, VMExecuteInternalStub, HOOK_JUMP).install()->quick();
Utils::Hook::Nop(0x61E933, 1); Utils::Hook::Nop(0x61E933, 1);
Scheduler::Loop([] Scheduler::Loop([]
@ -642,9 +645,9 @@ namespace Components
const auto nowMs = Game::Sys_Milliseconds(); const auto nowMs = Game::Sys_Milliseconds();
if (Script::LastFrameTime != -1) if (LastFrameTime != -1)
{ {
const auto timeTaken = (nowMs - Script::LastFrameTime) * static_cast<int>((*Game::com_timescale)->current.value); const auto timeTaken = (nowMs - LastFrameTime) * static_cast<int>((*Game::com_timescale)->current.value);
if (timeTaken >= 500) if (timeTaken >= 500)
{ {
@ -652,11 +655,11 @@ namespace Components
} }
} }
Script::LastFrameTime = nowMs; LastFrameTime = nowMs;
}, Scheduler::Pipeline::SERVER); }, Scheduler::Pipeline::SERVER);
#ifdef _DEBUG #ifdef _DEBUG
Script::AddFunction("DebugBox", [] AddFunction("DebugBox", []
{ {
const auto* message = Game::Scr_GetString(0); const auto* message = Game::Scr_GetString(0);
@ -666,14 +669,14 @@ namespace Components
} }
MessageBoxA(nullptr, message, "DEBUG", MB_OK); MessageBoxA(nullptr, message, "DEBUG", MB_OK);
}, 1); }, true);
#endif #endif
Script::AddFunctions(); AddFunctions();
Events::OnVMShutdown([] Events::OnVMShutdown([]
{ {
Script::ReplacedFunctions.clear(); ReplacedFunctions.clear();
}); });
} }
} }

View File

@ -16,6 +16,27 @@ namespace Components
static void ShowDeprecationWarning(); static void ShowDeprecationWarning();
// Probably a macro 'originally' but this is fine
static Game::gentity_s* Scr_GetPlayerEntity(Game::scr_entref_t entref)
{
if (entref.classnum != 0)
{
Game::Scr_ObjectError("not an entity");
return nullptr;
}
assert(entref.entnum < Game::MAX_GENTITIES);
auto* ent = &Game::g_entities[entref.entnum];
if (ent->client == nullptr)
{
Game::Scr_ObjectError(Utils::String::VA("entity %i is not a player", entref.entnum));
return nullptr;
}
return ent;
}
private: private:
struct ScriptFunction struct ScriptFunction
{ {
@ -38,8 +59,8 @@ namespace Components
static std::unordered_map<int, std::string> ScriptBaseProgramNum; static std::unordered_map<int, std::string> ScriptBaseProgramNum;
static int LastFrameTime; static int LastFrameTime;
static std::vector<int> ScriptMainHandles; static std::unordered_map<std::string, int> ScriptMainHandles;
static std::vector<int> ScriptInitHandles; static std::unordered_map<std::string, int> ScriptInitHandles;
static std::unordered_map<const char*, const char*> ReplacedFunctions; static std::unordered_map<const char*, const char*> ReplacedFunctions;
static const char* ReplacedPos; static const char* ReplacedPos;

View File

@ -1,4 +1,5 @@
#include <STDInclude.hpp> #include <STDInclude.hpp>
#include "GSC/Script.hpp"
namespace Components namespace Components
{ {
@ -106,13 +107,13 @@ namespace Components
// Bounce // Bounce
push 0x4B1B34 push 0x4B1B34
retn ret
noBounce: noBounce:
// Original game code // Original game code
cmp dword ptr [esp + 0x24], 0 cmp dword ptr [esp + 0x24], 0
push 0x4B1B48 push 0x4B1B48
retn ret
} }
} }
@ -186,6 +187,18 @@ namespace Components
} }
} }
void PlayerMovement::GScr_IsSprinting(const Game::scr_entref_t entref)
{
const auto* client = Game::GetEntity(entref)->client;
if (!client)
{
Game::Scr_Error("IsSprinting can only be called on a player");
return;
}
Game::Scr_AddBool(Game::PM_IsSprinting(&client->ps));
}
const Game::dvar_t* PlayerMovement::Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, const Game::dvar_t* PlayerMovement::Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value,
float min, float max, unsigned __int16 /*flags*/, const char* description) float min, float max, unsigned __int16 /*flags*/, const char* description)
{ {
@ -233,6 +246,9 @@ namespace Components
PlayerMovement::PlayerMovement() PlayerMovement::PlayerMovement()
{ {
AssertOffset(Game::playerState_s, eFlags, 0xB0);
AssertOffset(Game::playerState_s, pm_flags, 0xC);
Scheduler::Once([] Scheduler::Once([]
{ {
static const char* bg_bouncesValues[] = static const char* bg_bouncesValues[] =
@ -273,6 +289,8 @@ namespace Components
Utils::Hook(0x45A5BF, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // SV_ClipMoveToEntity Utils::Hook(0x45A5BF, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // SV_ClipMoveToEntity
Utils::Hook(0x5A0CAD, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // CG_ClipMoveToEntity Utils::Hook(0x5A0CAD, CM_TransformedCapsuleTrace_Hk, HOOK_CALL).install()->quick(); // CG_ClipMoveToEntity
Script::AddMethod("IsSprinting", GScr_IsSprinting);
RegisterMovementDvars(); RegisterMovementDvars();
} }
} }

View File

@ -41,6 +41,8 @@ namespace Components
static int StuckInClient_Hk(Game::gentity_s* self); static int StuckInClient_Hk(Game::gentity_s* self);
static void CM_TransformedCapsuleTrace_Hk(Game::trace_t* results, const float* start, const float* end, const Game::Bounds* bounds, const Game::Bounds* capsule, int contents, const float* origin, const float* angles); static void CM_TransformedCapsuleTrace_Hk(Game::trace_t* results, const float* start, const float* end, const Game::Bounds* bounds, const Game::Bounds* capsule, int contents, const float* origin, const float* angles);
static void GScr_IsSprinting(Game::scr_entref_t entref);
static const Game::dvar_t* Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, float min, float max, unsigned __int16 flags, const char* description); static const Game::dvar_t* Dvar_RegisterSpectateSpeedScale(const char* dvarName, float value, float min, float max, unsigned __int16 flags, const char* description);
static void RegisterMovementDvars(); static void RegisterMovementDvars();

View File

@ -233,6 +233,7 @@ namespace Game
PM_Trace_t PM_Trace = PM_Trace_t(0x441F60); PM_Trace_t PM_Trace = PM_Trace_t(0x441F60);
PM_GetEffectiveStance_t PM_GetEffectiveStance = PM_GetEffectiveStance_t(0x412540); PM_GetEffectiveStance_t PM_GetEffectiveStance = PM_GetEffectiveStance_t(0x412540);
PM_UpdateLean_t PM_UpdateLean = PM_UpdateLean_t(0x43DED0); PM_UpdateLean_t PM_UpdateLean = PM_UpdateLean_t(0x43DED0);
PM_IsSprinting_t PM_IsSprinting = PM_IsSprinting_t(0x4B3830);
IN_RecenterMouse_t IN_RecenterMouse = IN_RecenterMouse_t(0x463D80); IN_RecenterMouse_t IN_RecenterMouse = IN_RecenterMouse_t(0x463D80);

View File

@ -524,6 +524,9 @@ namespace Game
typedef void(*PM_UpdateLean_t)(playerState_s* ps, float msec, usercmd_s* cmd, void(*capsuleTrace)(trace_t*, const float*, const float*, const Bounds*, int, int)); typedef void(*PM_UpdateLean_t)(playerState_s* ps, float msec, usercmd_s* cmd, void(*capsuleTrace)(trace_t*, const float*, const float*, const Bounds*, int, int));
extern PM_UpdateLean_t PM_UpdateLean; extern PM_UpdateLean_t PM_UpdateLean;
typedef bool(*PM_IsSprinting_t)(const playerState_s* ps);
extern PM_IsSprinting_t PM_IsSprinting;
typedef void(*IN_RecenterMouse_t)(); typedef void(*IN_RecenterMouse_t)();
extern IN_RecenterMouse_t IN_RecenterMouse; extern IN_RecenterMouse_t IN_RecenterMouse;

View File

@ -1679,23 +1679,23 @@ namespace Game
enum usercmdButtonBits enum usercmdButtonBits
{ {
CMD_BUTTON_ATTACK = 0x1, CMD_BUTTON_ATTACK = 1 << 0,
CMD_BUTTON_SPRINT = 0x2, CMD_BUTTON_SPRINT = 1 << 1,
CMD_BUTTON_MELEE = 0x4, CMD_BUTTON_MELEE = 1 << 2,
CMD_BUTTON_ACTIVATE = 0x8, CMD_BUTTON_ACTIVATE = 1 << 3,
CMD_BUTTON_RELOAD = 0x10, CMD_BUTTON_RELOAD = 1 << 4,
CMD_BUTTON_USE_RELOAD = 0x20, CMD_BUTTON_USE_RELOAD = 1 << 5,
CMD_BUTTON_LEAN_LEFT = 0x40, CMD_BUTTON_LEAN_LEFT = 1 << 6,
CMD_BUTTON_LEAN_RIGHT = 0x80, CMD_BUTTON_LEAN_RIGHT = 1 << 7,
CMD_BUTTON_PRONE = 0x100, CMD_BUTTON_PRONE = 1 << 8,
CMD_BUTTON_CROUCH = 0x200, CMD_BUTTON_CROUCH = 1 << 9,
CMD_BUTTON_UP = 0x400, CMD_BUTTON_UP = 1 << 10,
CMD_BUTTON_ADS = 0x800, CMD_BUTTON_ADS = 1 << 11,
CMD_BUTTON_DOWN = 0x1000, CMD_BUTTON_DOWN = 1 << 12,
CMD_BUTTON_BREATH = 0x2000, CMD_BUTTON_BREATH = 1 << 13,
CMD_BUTTON_FRAG = 0x4000, CMD_BUTTON_FRAG = 1 << 14,
CMD_BUTTON_OFFHAND_SECONDARY = 0x8000, CMD_BUTTON_OFFHAND_SECONDARY = 1 << 15,
CMD_BUTTON_THROW = 0x80000 CMD_BUTTON_THROW = 1 << 19,
}; };
#pragma pack(push, 4) #pragma pack(push, 4)