diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 8271928a..43ce6ef7 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -27,6 +27,7 @@ namespace Components std::int8_t forward; std::int8_t right; std::uint16_t weapon; + std::uint16_t lastAltWeapon; bool active; }; @@ -316,6 +317,7 @@ namespace Components userCmd.forwardmove = g_botai[cl - Game::svs_clients].forward; userCmd.rightmove = g_botai[cl - Game::svs_clients].right; userCmd.weapon = g_botai[cl - Game::svs_clients].weapon; + userCmd.primaryWeaponForAltMode = g_botai[cl - Game::svs_clients].lastAltWeapon; userCmd.angles[0] = ANGLE2SHORT((cl->gentity->client->ps.viewangles[0] - cl->gentity->client->ps.delta_angles[0])); userCmd.angles[1] = ANGLE2SHORT((cl->gentity->client->ps.viewangles[1] - cl->gentity->client->ps.delta_angles[1])); @@ -339,11 +341,38 @@ namespace Components } } - void Bots::G_SelectWeaponIndex(int clientNum, int iWeaponIndex) + void Bots::G_SelectWeaponIndex(int clientNum, unsigned int iWeaponIndex) { if (g_botai[clientNum].active) { g_botai[clientNum].weapon = static_cast(iWeaponIndex); + g_botai[clientNum].lastAltWeapon = 0; + + auto* def = Game::BG_GetWeaponCompleteDef(iWeaponIndex); + + if (def->weapDef->inventoryType == Game::WEAPINVENTORY_ALTMODE) + { + auto* ps = &Game::g_entities[clientNum].client->ps; + auto num_weaps = Game::BG_GetNumWeapons(); + + for (auto i = 1u; i < num_weaps; i++) + { + if (!Game::BG_PlayerHasWeapon(ps, i)) + { + continue; + } + + auto* this_def = Game::BG_GetWeaponCompleteDef(i); + + if (this_def->altWeaponIndex != iWeaponIndex) + { + continue; + } + + g_botai[clientNum].lastAltWeapon = static_cast(i); + break; + } + } } } @@ -472,6 +501,11 @@ namespace Components }); } + bool Bots::Player_UpdateActivate_stub(int) + { + return false; + } + Bots::Bots() { AssertOffset(Game::client_s, bIsTestClient, 0x41AF0); @@ -489,6 +523,9 @@ namespace Components Utils::Hook(0x441B80, G_SelectWeaponIndex_Hk, HOOK_JUMP).install()->quick(); + // fix bots using objects + Utils::Hook(0x4D79C5, Player_UpdateActivate_stub, HOOK_CALL).install()->quick(); + Utils::Hook(0x459654, SV_GetClientPing_Hk, HOOK_CALL).install()->quick(); sv_randomBotNames = Game::Dvar_RegisterBool("sv_randomBotNames", false, Game::DVAR_NONE, "Randomize the bots' names"); diff --git a/src/Components/Modules/Bots.hpp b/src/Components/Modules/Bots.hpp index d2aa35f6..342007da 100644 --- a/src/Components/Modules/Bots.hpp +++ b/src/Components/Modules/Bots.hpp @@ -32,9 +32,11 @@ namespace Components static void BotAiAction(Game::client_s* cl); static void SV_BotUserMove_Hk(); - static void G_SelectWeaponIndex(int clientNum, int iWeaponIndex); + static void G_SelectWeaponIndex(int clientNum, unsigned int iWeaponIndex); static void G_SelectWeaponIndex_Hk(); + static bool Player_UpdateActivate_stub(int); + static int SV_GetClientPing_Hk(int clientNum); static bool IsFull(); diff --git a/src/Game/BothGames.cpp b/src/Game/BothGames.cpp index e3986666..023be38a 100644 --- a/src/Game/BothGames.cpp +++ b/src/Game/BothGames.cpp @@ -11,4 +11,6 @@ namespace Game BG_IsWeaponValid_t BG_IsWeaponValid = BG_IsWeaponValid_t(0x415BA0); BG_GetEquippedWeaponIndex_t BG_GetEquippedWeaponIndex = BG_GetEquippedWeaponIndex_t(0x4D8BA0); BG_GetEquippedWeaponState_t BG_GetEquippedWeaponState = BG_GetEquippedWeaponState_t(0x4E79E0); + BG_PlayerHasWeapon_t BG_PlayerHasWeapon = BG_PlayerHasWeapon_t(0x4AB530); + BG_GetWeaponCompleteDef_t BG_GetWeaponCompleteDef = BG_GetWeaponCompleteDef_t(0x44CE00); } diff --git a/src/Game/BothGames.hpp b/src/Game/BothGames.hpp index 946979b5..d8b6707d 100644 --- a/src/Game/BothGames.hpp +++ b/src/Game/BothGames.hpp @@ -28,4 +28,10 @@ namespace Game typedef PlayerEquippedWeaponState*(*BG_GetEquippedWeaponState_t)(playerState_s* ps, unsigned int weaponIndex); extern BG_GetEquippedWeaponState_t BG_GetEquippedWeaponState; + + typedef int*(*BG_PlayerHasWeapon_t)(playerState_s* ps, unsigned int weaponIndex); + extern BG_PlayerHasWeapon_t BG_PlayerHasWeapon; + + typedef Game::WeaponCompleteDef*(*BG_GetWeaponCompleteDef_t)(unsigned int weaponIndex); + extern BG_GetWeaponCompleteDef_t BG_GetWeaponCompleteDef; }