diff --git a/src/component/gsc.cpp b/src/component/gsc.cpp index 25ffa00..d01147d 100644 --- a/src/component/gsc.cpp +++ b/src/component/gsc.cpp @@ -380,6 +380,20 @@ namespace gsc return {}; }); + function::add("dropallbots", [](const function_args& args) -> scripting::script_value + { + for (auto i = 0; i < *game::svs_clientCount; i++) + { + if (game::svs_clients[i].header.state != game::CS_FREE + && game::svs_clients[i].header.netchan.remoteAddress.type == game::NA_BOT) + { + game::SV_GameDropClient(i, "GAME_GET_TO_COVER"); + } + } + + return {}; + }); + method::add("tell", [](const game::scr_entref_t ent, const function_args& args) -> scripting::script_value { if (ent.classnum != 0) diff --git a/src/game/game.cpp b/src/game/game.cpp index 931724d..3bcba57 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -2,5 +2,11 @@ namespace game { - + void SV_GameDropClient(int clientNum, const char* reason) + { + if (clientNum >= 0 && clientNum < sv_maxclients->current.integer) + { + SV_DropClient(&svs_clients[clientNum], reason, true); + } + } } diff --git a/src/game/game.hpp b/src/game/game.hpp index e52eef9..a130d5a 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -29,6 +29,8 @@ namespace game private: T* dedi_; }; + + void SV_GameDropClient(int clientNum, const char* reason); } #include "symbols.hpp" \ No newline at end of file diff --git a/src/game/structs.hpp b/src/game/structs.hpp index a67cc97..ec63303 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -328,9 +328,94 @@ namespace game char __pad2[0xEC]; }; + enum netsrc_t + { + NS_CLIENT1 = 0x0, + NS_CLIENT2 = 0x1, + NS_CLIENT3 = 0x2, + NS_CLIENT4 = 0x3, + NS_MAXCLIENTS = 0x4, + NS_SERVER = 0x4, + NS_PACKET = 0x5, + NS_INVALID_NETSRC = 0x6 + }; + + enum netadrtype_t + { + NA_BOT = 0x0, + NA_BAD = 0x1, + NA_LOOPBACK = 0x2, + NA_BROADCAST = 0x3, + NA_IP = 0x4 + }; + + struct netadr_s + { + netadrtype_t type; + unsigned char ip[4]; + unsigned __int16 port; + unsigned char ipx[10]; + unsigned int addrHandleIndex; + }; + + static_assert(sizeof(netadr_s) == 24); + + struct netchan_t + { + int outgoingSequence; + netsrc_t sock; + int dropped; + int incomingSequence; + netadr_s remoteAddress; + int qport; + int fragmentSequence; + int fragmentLength; + unsigned char* fragmentBuffer; + int fragmentBufferSize; + int unsentFragments; + int unsentFragmentStart; + int unsentLength; + unsigned char* unsentBuffer; + int unsentBufferSize; + unsigned char __pad0[0x5E0]; + }; + + static_assert(sizeof(netchan_t) == 0x630); + + enum clientState_t + { + CS_FREE = 0, + CS_ZOMBIE = 1, + CS_RECONNECTING = 2, + CS_CONNECTED = 3, + CS_CLIENTLOADING = 4, + CS_ACTIVE = 5 + }; + + struct clientHeader_t + { + clientState_t state; // 0 + int sendAsActive; // 4 + int deltaMessage; // 8 + int rateDealyed; // 12 + int hasAckedBaselineData; // 16 + int hugeSnapshotSent; // 20 + netchan_t netchan; // 24 + vec3_t predictedOrigin; + int predictedOriginServerTime; + int migrationState; + vec3_t predictedVehicleOrigin; + int predictedVehicleServerTime; + }; + + static_assert(sizeof(clientHeader_t) == 0x66C); + struct client_s { - char __pad0[0x41CB2]; + clientHeader_t header; + const char* dropReason; + char userinfo[1024]; + char __pad0[0x41242]; unsigned __int16 scriptId; // 269490 int bIsTestClient; // 269492 int serverId; // 269496 diff --git a/src/game/symbols.hpp b/src/game/symbols.hpp index 83c7ada..4f02550 100644 --- a/src/game/symbols.hpp +++ b/src/game/symbols.hpp @@ -57,6 +57,7 @@ namespace game WEAK symbol SV_GameSendServerCommand{0x573220}; WEAK symbol SV_Cmd_ArgvBuffer{0x5459F0}; + WEAK symbol SV_DropClient{0x570980}; WEAK symbol VM_Notify{0x569720}; WEAK symbol VM_Execute{0x56DFE0}; @@ -79,6 +80,8 @@ namespace game WEAK symbol g_entities{0x1A66E28}; WEAK symbol levelEntityId{0x208E1A4}; + WEAK symbol sv_maxclients{0x1BA0E4C}; + WEAK symbol svs_clientCount{0x4B5CF8C}; WEAK symbol svs_clients{0x4B5CF90}; namespace plutonium