Address more
This commit is contained in:
parent
cfc540991c
commit
d7a2b1aae7
@ -3,8 +3,9 @@
|
||||
namespace Components
|
||||
{
|
||||
std::vector<std::string> Bots::BotNames;
|
||||
Game::dvar_t* Bots::SVBotWarfare;
|
||||
|
||||
struct BotMovementInfo_t
|
||||
struct BotMovementInfo
|
||||
{
|
||||
int buttons; // Actions
|
||||
int8_t forward;
|
||||
@ -12,7 +13,7 @@ namespace Components
|
||||
uint16_t weapon;
|
||||
};
|
||||
|
||||
static BotMovementInfo_t g_botai[18];
|
||||
static BotMovementInfo g_botai[18];
|
||||
|
||||
struct BotAction
|
||||
{
|
||||
@ -187,7 +188,7 @@ namespace Components
|
||||
}
|
||||
|
||||
const auto weapId = Game::G_GetWeaponIndexForName(weapon);
|
||||
g_botai[entref.entnum].weapon = static_cast<unsigned short>(weapId);
|
||||
g_botai[entref.entnum].weapon = static_cast<uint16_t>(weapId);
|
||||
});
|
||||
|
||||
Script::AddFunction("BotAction", [](Game::scr_entref_t entref) // Usage: <bot> BotAction(<str action>);
|
||||
@ -253,6 +254,57 @@ namespace Components
|
||||
});
|
||||
}
|
||||
|
||||
void Bots::BotAiAction()
|
||||
{
|
||||
for (auto i = 0; i < *Game::svs_numclients; ++i)
|
||||
{
|
||||
auto* client = &Game::svs_clients[i];
|
||||
|
||||
if (client->state < Game::CS_CONNECTED)
|
||||
continue;
|
||||
|
||||
if (!client->isBot)
|
||||
continue;
|
||||
|
||||
Game::usercmd_s ucmd = {0};
|
||||
|
||||
ucmd.serverTime = *Game::svs_time;
|
||||
|
||||
ucmd.buttons = g_botai[i].buttons;
|
||||
ucmd.forwardmove = g_botai[i].forward;
|
||||
ucmd.rightmove = g_botai[i].right;
|
||||
ucmd.weapon = g_botai[i].weapon;
|
||||
|
||||
client->deltaMessage = client->netchan.outgoingSequence - 1;
|
||||
|
||||
Game::SV_ClientThink(client, &ucmd);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto SV_UpdateBots = 0x626E50;
|
||||
__declspec(naked) void Bots::SV_UpdateBots_Hk()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
pushad
|
||||
|
||||
call SV_UpdateBots
|
||||
|
||||
// If bot warfare isn't being used let's keep
|
||||
// test clients normal functionality
|
||||
mov eax, Bots::SVBotWarfare
|
||||
cmp byte ptr [eax + 0x10], 0;
|
||||
|
||||
jz skip
|
||||
|
||||
call Bots::BotAiAction
|
||||
|
||||
skip:
|
||||
popad
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
Bots::Bots()
|
||||
{
|
||||
// Replace connect string
|
||||
@ -261,48 +313,19 @@ namespace Components
|
||||
// Intercept sprintf for the connect string
|
||||
Utils::Hook(0x48ADAB, Bots::BuildConnectString, HOOK_CALL).install()->quick();
|
||||
|
||||
// Stop default behavour of bots spinning and shooting
|
||||
Utils::Hook(0x627021, 0x4BB9B0, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x627241, 0x4BB9B0, HOOK_CALL).install()->quick();
|
||||
Bots::SVBotWarfare = Game::Dvar_RegisterBool("sv_botWarfare", false,
|
||||
Game::DVAR_FLAG_NONE, "Allow bot warfare mod to override default bot behaviour");
|
||||
|
||||
Utils::Hook(0x627021, SV_UpdateBots_Hk, HOOK_CALL).install()->quick();
|
||||
Utils::Hook(0x627241, SV_UpdateBots_Hk, HOOK_CALL).install()->quick();
|
||||
|
||||
// Zero the bot command array
|
||||
for (auto i = 0u; i < std::extent_v<decltype(g_botai)>; i++)
|
||||
{
|
||||
g_botai[i] = {0};
|
||||
g_botai[i].weapon = 1; // Prevent the bots from defaulting to the 'none' weapon
|
||||
g_botai[i].weapon = 1; // Prevent the bots from defaulting to the 'none' weapon
|
||||
}
|
||||
|
||||
// Have the bots perform the command every server frame
|
||||
Scheduler::OnFrame([]()
|
||||
{
|
||||
if (!Game::SV_Loaded())
|
||||
return;
|
||||
|
||||
for (auto i = 0; i < *Game::svs_numclients; ++i)
|
||||
{
|
||||
auto* client = &Game::svs_clients[i];
|
||||
|
||||
if (client->state < Game::CS_CONNECTED)
|
||||
continue;
|
||||
|
||||
if (!client->isBot)
|
||||
continue;
|
||||
|
||||
Game::usercmd_s ucmd = {0};
|
||||
|
||||
ucmd.serverTime = *Game::svs_time;
|
||||
|
||||
ucmd.buttons = g_botai[i].buttons;
|
||||
ucmd.forwardmove = g_botai[i].forward;
|
||||
ucmd.rightmove = g_botai[i].right;
|
||||
ucmd.weapon = g_botai[i].weapon;
|
||||
|
||||
client->deltaMessage = client->netchan.outgoingSequence - 1;
|
||||
|
||||
Game::SV_ClientThink(client, &ucmd);
|
||||
}
|
||||
});
|
||||
|
||||
Command::Add("spawnBot", [](Command::Params* params)
|
||||
{
|
||||
auto count = 1u;
|
||||
|
@ -37,16 +37,20 @@ namespace Components
|
||||
NUM_8 = 0x1000000,
|
||||
NUM_9 = 0x2000000,
|
||||
|
||||
USE = 0x28,
|
||||
USE = NUM_0 | NUM_1
|
||||
};
|
||||
|
||||
private:
|
||||
static std::vector<std::string> BotNames;
|
||||
static Game::dvar_t* SVBotWarfare;
|
||||
|
||||
static void BuildConnectString(char* buffer, const char* connectString, int num, int, int protocol, int checksum, int statVer, int statStuff, int port);
|
||||
|
||||
static void Spawn(unsigned int count);
|
||||
|
||||
static void AddMethods();
|
||||
|
||||
static void BotAiAction();
|
||||
static void SV_UpdateBots_Hk();
|
||||
};
|
||||
}
|
||||
|
@ -433,6 +433,30 @@ namespace Components
|
||||
return Game::Scr_GetNumParam();
|
||||
}
|
||||
|
||||
// Allow printing to the console even when developer is 0
|
||||
void Script::PrintStub()
|
||||
{
|
||||
const auto g_no_script_spam = Dvar::Var("g_no_script_spam").get<bool>();
|
||||
|
||||
if (!g_no_script_spam)
|
||||
return;
|
||||
|
||||
const auto developer = Dvar::Var("developer").get<int>();
|
||||
|
||||
for (auto i = 0u; i < Game::Scr_GetNumParam(); i++)
|
||||
{
|
||||
const auto str = (developer) ? Game::Scr_GetDebugString(i) : Game::Scr_GetString(i);
|
||||
|
||||
if (str == nullptr)
|
||||
{
|
||||
Game::Scr_ParamError(i, "^1PrintConsole: Illegal parameters!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::Print(*Game::level_scriptPrintChannel, "%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
const char* Script::GetCodePosForParam(int index)
|
||||
{
|
||||
if (static_cast<unsigned int>(index) >= Game::scrVmPub->outparamcount)
|
||||
@ -582,20 +606,6 @@ namespace Components
|
||||
Game::Scr_AddInt(time.wMilliseconds);
|
||||
});
|
||||
|
||||
// Print to console, even without being in 'developer 1'.
|
||||
Script::AddFunction("PrintConsole", [](Game::scr_entref_t) // gsc: PrintConsole(<string>)
|
||||
{
|
||||
const auto* str = Game::Scr_GetString(0);
|
||||
|
||||
if (str == nullptr)
|
||||
{
|
||||
Game::Scr_ParamError(0, "^1PrintConsole: Illegal parameters!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::Print(0, "%s", str);
|
||||
});
|
||||
|
||||
// Executes command to the console
|
||||
Script::AddFunction("Exec", [](Game::scr_entref_t) // gsc: Exec(<string>)
|
||||
{
|
||||
@ -610,7 +620,6 @@ namespace Components
|
||||
Command::Execute(str, false);
|
||||
});
|
||||
|
||||
|
||||
// Script Storage Funcs
|
||||
Script::AddFunction("StorageSet", [](Game::scr_entref_t) // gsc: StorageSet(<str key>, <str data>);
|
||||
{
|
||||
|
@ -73,6 +73,8 @@ namespace Components
|
||||
|
||||
static unsigned int SetExpFogStub();
|
||||
|
||||
static void PrintStub();
|
||||
|
||||
static const char* GetCodePosForParam(int index);
|
||||
static void GetReplacedPos(const char* pos);
|
||||
static void SetReplacedPos(const char* what, const char* with);
|
||||
|
@ -259,6 +259,7 @@ namespace Game
|
||||
Scr_GetFunctionHandle_t Scr_GetFunctionHandle = Scr_GetFunctionHandle_t(0x4234F0);
|
||||
|
||||
Scr_GetString_t Scr_GetString = Scr_GetString_t(0x425900);
|
||||
Scr_GetDebugString_t Scr_GetDebugString = Scr_GetDebugString_t(0x4EBF50);
|
||||
Scr_GetFloat_t Scr_GetFloat = Scr_GetFloat_t(0x443140);
|
||||
Scr_GetInt_t Scr_GetInt = Scr_GetInt_t(0x4F31D0);
|
||||
Scr_GetObject_t Scr_GetObject = Scr_GetObject_t(0x462100);
|
||||
@ -431,6 +432,8 @@ namespace Game
|
||||
|
||||
gentity_t* g_entities = reinterpret_cast<gentity_t*>(0x18835D8);
|
||||
|
||||
int* level_scriptPrintChannel = reinterpret_cast<int*>(0x1A860FC);
|
||||
|
||||
netadr_t* connectedHost = reinterpret_cast<netadr_t*>(0xA1E888);
|
||||
|
||||
SOCKET* ip_socket = reinterpret_cast<SOCKET*>(0x64A3008);
|
||||
|
@ -663,6 +663,9 @@ namespace Game
|
||||
typedef const char*(__cdecl * Scr_GetString_t)(unsigned int);
|
||||
extern Scr_GetString_t Scr_GetString;
|
||||
|
||||
typedef const char*(__cdecl * Scr_GetDebugString_t)(unsigned int index);
|
||||
extern Scr_GetDebugString_t Scr_GetDebugString;
|
||||
|
||||
typedef float(__cdecl * Scr_GetFloat_t)(unsigned int);
|
||||
extern Scr_GetFloat_t Scr_GetFloat;
|
||||
|
||||
@ -955,6 +958,8 @@ namespace Game
|
||||
constexpr auto MAX_GENTITIES = 2048u;
|
||||
extern gentity_t* g_entities;
|
||||
|
||||
extern int* level_scriptPrintChannel;
|
||||
|
||||
extern netadr_t* connectedHost;
|
||||
extern SOCKET* ip_socket;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user