#include #include "loader/component_loader.hpp" #include "command.hpp" #include "scheduler.hpp" #include "network.hpp" #include "party.hpp" #include "game/game.hpp" #include "game/scripting/execution.hpp" #include #include #include namespace bots { namespace { bool can_add() { return party::get_client_count() < *game::mp::svs_numclients && game::SV_Loaded() && !game::VirtualLobby_Loaded(); } void bot_team_join(const int entity_num) { const game::scr_entref_t entref{static_cast(entity_num), 0}; scheduler::once([entref]() { scripting::notify(entref, "luinotifyserver", {"team_select", 2}); scheduler::once([entref]() { auto* _class = utils::string::va("class%d", utils::cryptography::random::get_integer() % 5); scripting::notify(entref, "luinotifyserver", {"class_select", _class}); }, scheduler::pipeline::server, 2s); }, scheduler::pipeline::server, 2s); } void spawn_bot(const int entity_num) { game::SV_SpawnTestClient(&game::mp::g_entities[entity_num]); if (game::Com_GetCurrentCoDPlayMode() == game::CODPLAYMODE_CORE) { bot_team_join(entity_num); } } void add_bot() { if (!can_add()) { return; } static auto first_bot = true; const auto bot_name = game::SV_BotGetRandomName(); const auto bot_ent = game::SV_AddBot(bot_name); if (bot_ent) { spawn_bot(bot_ent->s.entityNum); } else { scheduler::once([]() { add_bot(); }, scheduler::pipeline::server, 100ms); } } } class component final : public component_interface { public: void post_unpack() override { if (game::environment::is_sp()) { return; } command::add("spawnBot", [](const command::params& params) { if (!can_add()) { return; } auto num_bots = 1; if (params.size() == 2) { num_bots = atoi(params.get(1)); } num_bots = std::min(num_bots, *game::mp::svs_numclients);; for (auto i = 0; i < num_bots; i++) { scheduler::once(add_bot, scheduler::pipeline::server, 100ms * i); } }); } }; } //REGISTER_COMPONENT(bots::component)