diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..3a3cce5 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "npm" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" diff --git a/github/assets/readme.md b/github/assets/readme.md deleted file mode 100644 index 0c2a9ff..0000000 --- a/github/assets/readme.md +++ /dev/null @@ -1,2 +0,0 @@ -This folder is used for files shown on the Readme section of the GitHub repository. -It will not be directly used in the Donetsk Project. \ No newline at end of file diff --git a/hook_lib/Main.cpp b/hook_lib/Main.cpp index 26bcab1..56891bd 100644 --- a/hook_lib/Main.cpp +++ b/hook_lib/Main.cpp @@ -36,8 +36,6 @@ extern "C" __declspec(dllexport) int DiscordCreate() return 1; } -char buffer[0x5000]; - BOOL WINAPI DllMain(HMODULE hModule, DWORD Reason, LPVOID lpVoid) { initAddrUtils(); @@ -65,7 +63,7 @@ BOOL WINAPI DllMain(HMODULE hModule, DWORD Reason, LPVOID lpVoid) addCustomCmds(); patchGame(); - printf("Discord: discord.gg/donetsk\n"); + printf("Website: donetsk.live\n"); cmd_args = (CmdArgs*)(0x14D20CBD0_g); diff --git a/hook_lib/functions.cpp b/hook_lib/functions.cpp index c1da09c..1c6750d 100644 --- a/hook_lib/functions.cpp +++ b/hook_lib/functions.cpp @@ -164,6 +164,11 @@ dvar_t* Dvar_RegisterBool(const char* dvarName, bool value, unsigned int flags, return func(dvarName, value, flags, description); } +dvar_t* Dvar_RegisterInt(const char* dvarName, bool value, int min, int max, unsigned int flags, const char* description) { + auto func = reinterpret_cast(0x1413E7A00_g); + return func(dvarName, value, min, max, flags, description); +} + void LUI_CoD_LuaCall_ExecNow(uintptr_t luaVM, const char* str) { lua_getfield(luaVM, -10002, "Engine"); lua_getfield(luaVM, -1, "DAGFFDGFII"); @@ -549,6 +554,9 @@ dvar_t* spawn_br_gas; dvar_t* show_watermark; dvar_t* player_sustainammo; dvar_t* print_debug; +dvar_t* weap_impactType; +dvar_t* weap_dismembermentAlwaysEnabled; +dvar_t* g_dumpScripts; cmd_function_s set_byte_f_VAR; cmd_function_s set_short_f_VAR; diff --git a/hook_lib/functions.hpp b/hook_lib/functions.hpp index e664c17..782592d 100644 --- a/hook_lib/functions.hpp +++ b/hook_lib/functions.hpp @@ -111,6 +111,9 @@ extern dvar_t* spawn_br_gas; extern dvar_t* show_watermark; extern dvar_t* player_sustainammo; extern dvar_t* print_debug; +extern dvar_t* weap_impactType; +extern dvar_t* weap_dismembermentAlwaysEnabled; +extern dvar_t* g_dumpScripts; extern cmd_function_s set_byte_f_VAR; extern cmd_function_s set_short_f_VAR; @@ -172,6 +175,7 @@ dvar_t* Dvar_FindVarByName(const char* dvarName); void CL_DrawText(const uintptr_t scrPlace, const char* text, int maxChars, uintptr_t font, float x, float y, int horzAlign, int vertAlign, float xScale, float yScale, const float* color, int style); dvar_t* Dvar_RegisterString(const char* dvarName, const char* value, unsigned int flags, const char* description); dvar_t* Dvar_RegisterBool(const char* dvarName, bool value, unsigned int flags, const char* description); +dvar_t* Dvar_RegisterInt(const char* dvarName, bool value, int min, int max, unsigned int flags, const char* description); void LUI_CoD_LuaCall_ExecNow(uintptr_t luaVM, const char* str); bool LUI_LuaCall_Game_IsEntityAlive(uintptr_t luaVM, int entityNum); diff --git a/hook_lib/hook_lib.vcxproj b/hook_lib/hook_lib.vcxproj index 8b90d17..9e22166 100644 --- a/hook_lib/hook_lib.vcxproj +++ b/hook_lib/hook_lib.vcxproj @@ -48,7 +48,7 @@ DynamicLibrary false - v142 + v143 true MultiByte false diff --git a/hook_lib/lui_cod.cpp b/hook_lib/lui_cod.cpp index 50074c0..5799064 100644 --- a/hook_lib/lui_cod.cpp +++ b/hook_lib/lui_cod.cpp @@ -13,6 +13,11 @@ void LUI_CoD_RegisterDvars_Detour() print_debug = Dvar_RegisterBool("print_debug", false, 0, "Print debug output to the external console"); + weap_impactType = Dvar_RegisterInt("weap_impactType", -1, -1, 1000, 0, "Forces an weapon impact type on every weapon. -1 = default"); + weap_dismembermentAlwaysEnabled = Dvar_RegisterBool("weap_dismembermentAlwaysEnabled", false, 0, "Enables dismemberment effect for all weapons"); + + g_dumpScripts = Dvar_RegisterBool("g_dumpScripts", false, 0, "Dump GSC scripts"); + lui_cod_registerdvars.stub(); } diff --git a/hook_lib/party.cpp b/hook_lib/party.cpp index 4f81ed2..c4377a1 100644 --- a/hook_lib/party.cpp +++ b/hook_lib/party.cpp @@ -10,6 +10,13 @@ void PartyHost_StartPrivateParty_Detour(int localClientNum, int localControllerI { Cbuf_AddText("exec autoexec.cfg"); LoadInventory(); + + // skips Tutorial stuff + Cbuf_AddText("setRankedPlayerData mpTutorialLevel -2147463171"); + Cbuf_AddText("setRankedPlayerData mpTutorialLevel2 28671"); + Cbuf_AddText("setRankedPlayerData mpTutorialLevel - 2147454979"); + Cbuf_AddText("setRankedPlayerData mpTutorialLevel2 61439"); + autoexec = true; } } \ No newline at end of file diff --git a/hook_lib/patch.cpp b/hook_lib/patch.cpp index 41e2d6a..ca5013a 100644 --- a/hook_lib/patch.cpp +++ b/hook_lib/patch.cpp @@ -103,6 +103,7 @@ bool ProfanityFilter_IsBadWord_Detour() void hooks() { process_script_file.create(0x141322350_g, ProcessScriptFile); + utils::hook::jump(0x140DFE370_g, Load_ScriptFile_Detour); //utils::hook::jump(0x141BD3360_g, sub_141BD3360_Detour); @@ -153,6 +154,9 @@ void hooks() utils::hook::jump(0x141609140_g, ProfanityFilter_IsBadWord_Detour); + cg_overrideimpacteffecttype.create(0x141733CD0_g, CG_OverrideImpactEffectType_Detour); + bg_getweapondismembermentenabled.create(0x141170C00_g, BG_GetWeaponDismembermentEnabled_Detour); + // replacing Com_GameMode_GetActiveGameMode call with CheatsEnabled for jump_height dvar utils::hook::call(0x14110195A_g, CheatsEnabled); diff --git a/hook_lib/screen.cpp b/hook_lib/screen.cpp index 1fe3bb4..e04b9ce 100644 --- a/hook_lib/screen.cpp +++ b/hook_lib/screen.cpp @@ -21,4 +21,7 @@ void CL_ScreenMP_DrawOverlay_Detour() if (show_watermark->current.enabled) { CG_DrawWaterMark(); } + + float white[4] = { 1.0f, 1.0f, 1.0f, 0.075f }; + CL_DrawText(0x14EF2DEA0_g, "Donetsk", 0x7FFFFFFF, *reinterpret_cast(0x14EEB0C68_g), 0, 480, 1, 1, 0.45000001, 0.45000001, white, 7); } \ No newline at end of file diff --git a/hook_lib/script.cpp b/hook_lib/script.cpp index 434a827..80c4db8 100644 --- a/hook_lib/script.cpp +++ b/hook_lib/script.cpp @@ -2,54 +2,203 @@ #include "script.h" #include "game_inc.h" -void ProcessScriptFile(void* scrContext, ScriptFile* scriptfile) +void Load_ScriptFile_Detour(int streamStart) { - if (scriptfile) + auto DB_PatchMem_PushAsset = reinterpret_cast(0x140D8D860_g); + auto Load_Stream = reinterpret_cast(0x1411B2A20_g); + auto DB_PushStreamPos = reinterpret_cast(0x1411B2570_g); + auto Load_XString = reinterpret_cast(0x140DD3400_g); + auto DB_PopStreamPos = reinterpret_cast(0x1411B24C0_g); + auto DB_PatchMem_PopAsset = reinterpret_cast(0x140D8D850_g); + auto DB_ReadXFile = reinterpret_cast(0x1411A85D0_g); + + ScriptFile** varScriptFile = reinterpret_cast(0x145D43670_g); + char** varXString = reinterpret_cast(0x145D417C0_g); + char** varConstChar = reinterpret_cast(0x145D417B0_g); + char** varbyte = reinterpret_cast(0x145D415D8_g); + char** g_streamPosGlob_pos = reinterpret_cast(0x14D120C00_g); + + char* backup; + ScriptFile* scriptfile; + + DB_PatchMem_PushAsset(ASSET_TYPE_SCRIPTFILE, *varScriptFile); + Load_Stream(streamStart, *varScriptFile, sizeof(ScriptFile)); + DB_PushStreamPos(5); + + char* xStringBackup = *varXString; + *varXString = reinterpret_cast(*varScriptFile); + Load_XString(1); + *varXString = xStringBackup; + DB_PushStreamPos(6); + + scriptfile = *varScriptFile; + + backup = *varConstChar; + + printf("Loading scriptfile '%s' into database\n", scriptfile->name); + std::string filepath = "script.gscbin"; + bool scriptgscbin = false; + + if (!strcmp(scriptfile->name, "1892") && file_exists("script.gscbin")) { - printf("loading gsc: %s\n", scriptfile->name); - if (!strcmp(scriptfile->name, "1892")) + scriptgscbin = true; + } + else + { + std::string scriptname = scriptfile->name; + if (isSubStr(scriptname, ".gsc")) { - printf("WAR GSC ASSET - %llX\nGSC - BYTECODE %llx\n", scriptfile, scriptfile->bytecode); - std::ifstream script; - script.open("script.gscbin", std::ios::binary | std::ios::ate); - - int size = (int)script.tellg(); - script.seekg(0, std::ios::beg); - - if (script.fail()) - { - printf("Couldn't find file to inject"); - process_script_file.stub(scrContext, scriptfile); - return; - } - - auto Load_ScriptFileAsset = reinterpret_cast(0x140F134D0_g); - - char* allocMemAddress = (char*)Load_ScriptFileAsset(size, 4, 0, 0, nullptr); - - script.read(allocMemAddress, size); - script.seekg(0, std::ios::beg); - - while (script.get() != '\0') //read past the name - { - } - - int vars[3] = { 0 }; - script.read((char*)vars, sizeof(int) * 3); //read header info - - printf("vars[0] %X\n", vars[0]); - printf("vars[1] %X\n", vars[1]); - printf("vars[2] %X\n", vars[2]); - printf("buffer 0x%llX\n", allocMemAddress + (int)script.tellg()); - printf("bytecode 0x%llX\n", allocMemAddress + vars[0] + script.tellg()); - - scriptfile->compressedLen = vars[0]; - scriptfile->len = vars[1]; - scriptfile->bytecodeLen = vars[2]; - scriptfile->buffer = allocMemAddress + (int)script.tellg(); - //scriptfile->bytecode = (unsigned char*)(allocMemAddress + vars[0] + (int)script.tellg()); - memcpy(scriptfile->bytecode, allocMemAddress + vars[0] + (int)script.tellg(), vars[2]); + filepath = "donetsk/scripts/" + scriptname + "bin"; + } + else // numbered scriptfiles like "1892" + { + filepath = "donetsk/scripts/" + scriptname + ".gscbin"; } } + + if (file_exists(filepath.c_str()) || scriptgscbin) + { + std::ifstream script; + script.open(filepath, std::ios::binary | std::ios::ate); + int size = (int)script.tellg(); + script.seekg(0, std::ios::beg); + + char* customScript = new char[size]; + script.read(customScript, size); + script.seekg(0, std::ios::beg); + + while (script.get() != '\0'); // read past the name + int vars[3] = { 0 }; + script.read((char*)vars, sizeof(int) * 3); //read header info + + if (scriptfile->buffer != NULL) + { + *varConstChar = *g_streamPosGlob_pos; + scriptfile->buffer = *varConstChar; + + char* dummyMem = new char[scriptfile->compressedLen]; + DB_ReadXFile(dummyMem, scriptfile->compressedLen); + delete[scriptfile->compressedLen] dummyMem; + + memmove(*g_streamPosGlob_pos, customScript + (int)script.tellg(), vars[0]); + + *g_streamPosGlob_pos = *g_streamPosGlob_pos + vars[0]; + scriptfile->compressedLen = vars[0]; + } + *varConstChar = backup; + scriptfile->len = vars[1]; + + DB_PopStreamPos(); + DB_PushStreamPos(6); + + scriptfile = *varScriptFile; + backup = *varbyte; + + if (scriptfile->bytecode != NULL) + { + *varbyte = *g_streamPosGlob_pos; + scriptfile->bytecode = (unsigned char*)*varbyte; + + char* dummyMem = new char[scriptfile->bytecodeLen]; + DB_ReadXFile(dummyMem, scriptfile->bytecodeLen); + delete[scriptfile->bytecodeLen] dummyMem; + + memmove(*g_streamPosGlob_pos, customScript + vars[0] + (int)script.tellg(), vars[2]); + + *g_streamPosGlob_pos = *g_streamPosGlob_pos + vars[2]; + scriptfile->bytecodeLen = vars[2]; + } + *varbyte = backup; + + delete[size] customScript; + script.close(); + } + else + { + if (scriptfile->buffer != NULL) + { + *varConstChar = *g_streamPosGlob_pos; + scriptfile->buffer = *varConstChar; + Load_Stream(0, *varConstChar, scriptfile->compressedLen); + } + *varConstChar = backup; + + DB_PopStreamPos(); + DB_PushStreamPos(6); + + scriptfile = *varScriptFile; + backup = *varbyte; + if (scriptfile->bytecode != NULL) + { + *varbyte = *g_streamPosGlob_pos; + scriptfile->bytecode = (unsigned char*)*varbyte; + Load_Stream(0, *varbyte, scriptfile->bytecodeLen); + } + *varbyte = backup; + } + + DB_PopStreamPos(); + DB_PopStreamPos(); + DB_PatchMem_PopAsset(); +} + +void dump_gsc_script(std::ofstream& stream, ScriptFile* scriptfile) +{ + std::string buffer; + buffer.append(scriptfile->name, strlen(scriptfile->name) + 1); + + buffer.append(reinterpret_cast(&scriptfile->compressedLen), 4); + buffer.append(reinterpret_cast(&scriptfile->len), 4); + buffer.append(reinterpret_cast(&scriptfile->bytecodeLen), 4); + buffer.append(scriptfile->buffer, scriptfile->compressedLen); + buffer.append((char*)scriptfile->bytecode, scriptfile->bytecodeLen); + + stream << buffer; +} + + +void ProcessScriptFile(void* scrContext, ScriptFile* scriptfile) +{ + /*if (scriptfile) + { + if (strcmp(scriptfile->name, "1892") == 0) + { + std::ofstream gscbin_file("1892.gscbin", std::ios::out | std::ios::binary); + if (gscbin_file.is_open()) + { + dump_gsc_script(gscbin_file, scriptfile); + gscbin_file.close(); + } + } + }*/ + + if (g_dumpScripts->current.enabled) + { + std::string scriptFileStr = ""; + if (isSubStr(scriptfile->name, ".gsc")) + { + scriptFileStr = "gsc_dump/" + std::string(scriptfile->name) + "bin"; + } + else + { + scriptFileStr = "gsc_dump/" + std::string(scriptfile->name) + ".gscbin"; + } + + size_t lastSlash = scriptFileStr.find_last_of("/"); + if (lastSlash != std::string::npos && isSubStr(scriptfile->name, "/")) + { + std::string directory = scriptFileStr.substr(0, lastSlash); + + std::filesystem::create_directories(directory); + } + + std::ofstream gscbin_file(scriptFileStr, std::ios::out | std::ios::binary); + if (gscbin_file.is_open()) + { + dump_gsc_script(gscbin_file, scriptfile); + gscbin_file.close(); + } + } + process_script_file.stub(scrContext, scriptfile); } \ No newline at end of file diff --git a/hook_lib/script.h b/hook_lib/script.h index da8aab4..aeb2b34 100644 --- a/hook_lib/script.h +++ b/hook_lib/script.h @@ -1,5 +1,7 @@ #pragma once #include "Main.hpp" +void Load_ScriptFile_Detour(int streamStart); + inline utils::hook::detour process_script_file; void ProcessScriptFile(void* scrContext, ScriptFile* scriptfile); \ No newline at end of file diff --git a/hook_lib/weapons.cpp b/hook_lib/weapons.cpp index 8b7af01..52e5437 100644 --- a/hook_lib/weapons.cpp +++ b/hook_lib/weapons.cpp @@ -12,11 +12,25 @@ void PM_WeaponUseAmmo_Detour(__int64 playerstate, Weapon* weapon, char a3, int a } } -void CG_OverrideImpactEffectType(uintptr_t localClientNum, unsigned int sourceEntityNum, int* fxImpactType) // 0x141733CD0_g +void CG_OverrideImpactEffectType_Detour(uintptr_t localClientNum, unsigned int sourceEntityNum, int* fxImpactType) // 0x141733CD0_g { - //33 = red, 34 = blue, 35 = pink, 36 = green - fxImpactType[2] = 34; - cg_overrideimpacteffecttype.stub<__int64>(localClientNum, sourceEntityNum, fxImpactType); + if (weap_impactType->current.integer != -1) + { + int impactType = weap_impactType->current.integer; + fxImpactType[2] = impactType; + //33 = red, 34 = blue, 35 = pink, 36 = green + } + // cg_overrideimpacteffecttype.stub<__int64>(localClientNum, sourceEntityNum, fxImpactType); + cg_overrideimpacteffecttype.stub(localClientNum, sourceEntityNum, fxImpactType); +} + +bool BG_GetWeaponDismembermentEnabled_Detour(Weapon* weapon, bool alt) +{ + if (weap_dismembermentAlwaysEnabled->current.enabled == true) + { + return true; + } + return bg_getweapondismembermentenabled.stub(weapon, alt); } TracerDef* GetTracerDef(const char* asset) { @@ -54,6 +68,14 @@ void Dump_WeaponDef() { weaponDefJson[weap->szInternalName]["damageInfo"]["damageData"][i]["damage"] = weap->weapDef->damageInfo.damageData[i].damage; } + // spread + weaponDefJson[weap->szInternalName]["playerSpread"] = weap->weapDef->playerSpread; + weaponDefJson[weap->szInternalName]["hipSpreadStandMax"] = weap->weapDef->hipSpreadStandMax; + + weaponDefJson[weap->szInternalName]["adsMoveSpeedScale"] = weap->weapDef->adsMoveSpeedScale; + weaponDefJson[weap->szInternalName]["fAdsIdleAmount"] = weap->weapDef->fAdsIdleAmount; + weaponDefJson[weap->szInternalName]["adsSpeedMs_0"] = weap->weapDef->adsSpeedMs[0]; + // WeaponDef weaponDefJson[weap->szInternalName]["ladderWeapon"] = weap->weapDef->ladderWeapon; weaponDefJson[weap->szInternalName]["canHoldBreath"] = weap->weapDef->canHoldBreath; @@ -107,6 +129,14 @@ void Load_WeaponDef() { weap->weapDef->damageInfo.damageData[i].damage = weaponDefJson[weap->szInternalName]["damageInfo"]["damageData"][i]["damage"]; } + // spread + weap->weapDef->playerSpread = weaponDefJson[weap->szInternalName]["playerSpread"]; + weap->weapDef->hipSpreadStandMax = weaponDefJson[weap->szInternalName]["hipSpreadStandMax"]; + + weap->weapDef->adsMoveSpeedScale = weaponDefJson[weap->szInternalName]["adsMoveSpeedScale"]; + weap->weapDef->fAdsIdleAmount = weaponDefJson[weap->szInternalName]["fAdsIdleAmount"]; + weap->weapDef->adsSpeedMs[0] = weaponDefJson[weap->szInternalName]["adsSpeedMs_0"]; + weap->weapDef->ladderWeapon = weaponDefJson[weap->szInternalName]["ladderWeapon"]; weap->weapDef->canHoldBreath = weaponDefJson[weap->szInternalName]["canHoldBreath"]; weap->weapDef->iFireTime = weaponDefJson[weap->szInternalName]["iFireTime"]; diff --git a/hook_lib/weapons.h b/hook_lib/weapons.h index 86134b3..94acc8c 100644 --- a/hook_lib/weapons.h +++ b/hook_lib/weapons.h @@ -5,7 +5,10 @@ inline utils::hook::detour PM_WeaponUseAmmo; void PM_WeaponUseAmmo_Detour(__int64 playerstate, Weapon* weapon, char a3, int a4, int hand); inline utils::hook::detour cg_overrideimpacteffecttype; -void CG_OverrideImpactEffectType(uintptr_t localClientNum, unsigned int sourceEntityNum, int* fxImpactType); +void CG_OverrideImpactEffectType_Detour(uintptr_t localClientNum, unsigned int sourceEntityNum, int* fxImpactType); + +inline utils::hook::detour bg_getweapondismembermentenabled; +bool BG_GetWeaponDismembermentEnabled_Detour(Weapon* weapon, bool alt); TracerDef* GetTracerDef(const char* asset); diff --git a/lib/minhook.lib b/lib/minhook.lib index b8c4c74..f482f77 100644 Binary files a/lib/minhook.lib and b/lib/minhook.lib differ