From 86c23c0f9e45614640537e15c5e41cb2caf1979a Mon Sep 17 00:00:00 2001 From: nullifiedcat Date: Mon, 30 Jul 2018 15:30:56 +0300 Subject: [PATCH] WIP playerlist --- include/core/netvars.hpp | 1 + include/playerresource.h | 4 + include/visual/menu/GuiInterface.hpp | 2 + .../menu/special/PlayerListController.hpp | 4 +- src/core/netvars.cpp | 2 + src/hooks/LevelInit.cpp | 5 + src/playerresource.cpp | 34 ++++++- src/visual/menu/GuiInterface.cpp | 93 ++++++++++++++++++- .../menu/special/PlayerListController.cpp | 27 +++++- 9 files changed, 164 insertions(+), 8 deletions(-) diff --git a/include/core/netvars.hpp b/include/core/netvars.hpp index cd74af59..b22de707 100755 --- a/include/core/netvars.hpp +++ b/include/core/netvars.hpp @@ -128,6 +128,7 @@ public: offset_t m_Collision; offset_t res_iTeam; offset_t res_iScore; + offset_t res_bAlive; offset_t m_nChargeResistType; offset_t m_flChargeLevel; diff --git a/include/playerresource.h b/include/playerresource.h index 0991cc04..62e25123 100755 --- a/include/playerresource.h +++ b/include/playerresource.h @@ -19,6 +19,10 @@ public: int GetTeam(int idx); int GetScore(int idx); + int getClass(int idx); + int getTeam(int idx); + bool isAlive(int idx); + int entity; }; diff --git a/include/visual/menu/GuiInterface.hpp b/include/visual/menu/GuiInterface.hpp index e6ad91fa..858be6b7 100644 --- a/include/visual/menu/GuiInterface.hpp +++ b/include/visual/menu/GuiInterface.hpp @@ -13,4 +13,6 @@ void init(); void draw(); bool handleSdlEvent(SDL_Event *event); +void onLevelLoad(); + } \ No newline at end of file diff --git a/include/visual/menu/menu/special/PlayerListController.hpp b/include/visual/menu/menu/special/PlayerListController.hpp index b05c0141..303adcb4 100644 --- a/include/visual/menu/menu/special/PlayerListController.hpp +++ b/include/visual/menu/menu/special/PlayerListController.hpp @@ -39,7 +39,9 @@ public: */ void updatePlayerName(int id, const char *name); - void updatePlayerTeamClass(int id, int team, int classId); + void updatePlayerTeam(int id, int team); + + void updatePlayerClass(int id, int classId); void updatePlayerLifeState(int id, bool dead); diff --git a/src/core/netvars.cpp b/src/core/netvars.cpp index 92f77c47..20334116 100644 --- a/src/core/netvars.cpp +++ b/src/core/netvars.cpp @@ -43,6 +43,8 @@ void NetVars::Init() { res_iTeam = gNetvars.get_offset("DT_TFPlayerResource", "baseclass", "m_iTeam"); + res_bAlive = + gNetvars.get_offset("DT_TFPlayerResource", "baseclass", "m_bAlive"); this->res_iMaxBuffedHealth = gNetvars.get_offset("DT_TFPlayerResource", "m_iMaxBuffedHealth"); m_angEyeAngles = gNetvars.get_offset("DT_TFPlayer", "tfnonlocaldata", diff --git a/src/hooks/LevelInit.cpp b/src/hooks/LevelInit.cpp index 0d7b9510..fe588767 100644 --- a/src/hooks/LevelInit.cpp +++ b/src/hooks/LevelInit.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "HookedMethods.hpp" #include "MiscTemporary.hpp" #if !LAGBOT_MODE @@ -61,6 +62,10 @@ DEFINE_HOOKED_METHOD(LevelInit, void, void *this_, const char *name) playerlist::Save(); #endif #if ENABLE_VISUALS +#if ENABLE_GUI + gui::onLevelLoad(); +#endif + typedef bool (*LoadNamedSkys_Fn)(const char *); uintptr_t addr = gSignatures.GetEngineSignature( "55 89 E5 57 31 FF 56 8D B5 ? ? ? ? 53 81 EC 6C 01 00 00"); diff --git a/src/playerresource.cpp b/src/playerresource.cpp index e2d7b695..7e7f224e 100755 --- a/src/playerresource.cpp +++ b/src/playerresource.cpp @@ -5,6 +5,8 @@ * Author: nullifiedcat */ +#include + #include "common.hpp" void TFPlayerResource::Update() @@ -91,4 +93,34 @@ int TFPlayerResource::GetClass(CachedEntity *player) return *(int *) ((unsigned) ent + netvar.res_iPlayerClass + 4 * idx); } -TFPlayerResource *g_pPlayerResource = 0; +bool TFPlayerResource::isAlive(int idx) +{ + IClientEntity *ent = g_IEntityList->GetClientEntity(entity); + if (!ent || ent->GetClientClass()->m_ClassID != RCC_PLAYERRESOURCE) + return 0; + if (idx >= 64 || idx < 0) + return false; + return *(bool *) ((unsigned) ent + netvar.res_bAlive + idx); +} + +int TFPlayerResource::getClass(int idx) +{ + IClientEntity *ent = g_IEntityList->GetClientEntity(entity); + if (!ent || ent->GetClientClass()->m_ClassID != RCC_PLAYERRESOURCE) + return 0; + if (idx >= 64 || idx < 0) + return 0; + return *(int *) ((unsigned) ent + netvar.res_iPlayerClass + 4 * idx); +} + +int TFPlayerResource::getTeam(int idx) +{ + IClientEntity *ent = g_IEntityList->GetClientEntity(entity); + if (!ent || ent->GetClientClass()->m_ClassID != RCC_PLAYERRESOURCE) + return 0; + if (idx >= 64 || idx < 0) + return 0; + return *(int *) ((unsigned) ent + netvar.res_iTeam + 4 * idx); +} + +TFPlayerResource *g_pPlayerResource{ nullptr }; diff --git a/src/visual/menu/GuiInterface.cpp b/src/visual/menu/GuiInterface.cpp index c0f98036..9fadfd91 100644 --- a/src/visual/menu/GuiInterface.cpp +++ b/src/visual/menu/GuiInterface.cpp @@ -6,11 +6,91 @@ #include #include #include +#include static settings::Button open_gui_button{ "visual.open-gui-button", "Insert" }; static bool init_done{ false }; +static std::unique_ptr controller{ nullptr }; + +static zerokernel::special::PlayerListData createPlayerListData(int userid) +{ + zerokernel::special::PlayerListData data{}; + auto idx = g_IEngine->GetPlayerForUserID(userid); + player_info_s info{}; + g_IEngine->GetPlayerInfo(idx, &info); + data.classId = g_pPlayerResource->getClass(idx); + data.teamId = g_pPlayerResource->getTeam(idx); + data.dead = !g_pPlayerResource->isAlive(idx); + data.steam = info.friendsID; + strncpy(data.name, info.name, 31); + return data; +} + +class PlayerListEventListener: public IGameEventListener +{ +public: + void FireGameEvent(KeyValues *event) override + { + if (!controller) + return; + + auto userid = event->GetInt("userid"); + if (!userid) + return; + + std::string name = event->GetName(); + if (name == "player_connect_client") + { + controller->addPlayer(userid, createPlayerListData(userid)); + } + else if (name == "player_disconnect") + { + controller->removePlayer(userid); + } + else if (name == "player_team") + { + controller->updatePlayerTeam(userid, event->GetInt("team")); + } + else if (name == "player_changeclass") + { + controller->updatePlayerClass(userid, event->GetInt("class")); + } + else if (name == "player_changename") + { + controller->updatePlayerName(userid, event->GetString("newname")); + } + else if (name == "player_death") + { + controller->updatePlayerLifeState(userid, false); + } + else if (name == "player_spawn") + { + controller->updatePlayerLifeState(userid, true); + } + } +}; + +static PlayerListEventListener listener{}; + +static void initPlayerlist() +{ + auto pl = dynamic_cast(zerokernel::Menu::instance->wm->getElementById("special-player-list")); + if (pl) + { + controller = std::make_unique(*pl); + controller->setKickButtonCallback([](int uid) { + // TODO + }); + controller->setOpenSteamCallback([](unsigned steam) { + CSteamID id{}; + id.SetFromUint64((0b1000100000000000000000001 << 32) | steam); + g_ISteamFriends->ActivateGameOverlayToUser("steamid", id); + }); + } +} + static void load() { zerokernel::Menu::instance->loadFromFile(DATA_PATH "/menu", "menu.xml"); @@ -22,7 +102,7 @@ static void load() list.construct(); printf("SV found\n"); } - // FIXME add playerlist + initPlayerlist(); zerokernel::Menu::instance->update(); zerokernel::Menu::instance->setInGame(true); @@ -32,9 +112,12 @@ static CatCommand reload("gui_reload", "Reload", []() { load(); }); + + void gui::init() { zerokernel::Menu::init(draw::width, draw::height); + g_IGameEventManager->AddListener(&listener, false); load(); @@ -66,3 +149,11 @@ bool gui::handleSdlEvent(SDL_Event *event) return zerokernel::Menu::instance->handleSdlEvent(event) && !zerokernel::Menu::instance->isInGame(); } +void gui::onLevelLoad() +{ + if (controller) + { + controller->removeAll(); + } +} + diff --git a/src/visual/menu/menu/special/PlayerListController.cpp b/src/visual/menu/menu/special/PlayerListController.cpp index 40c8924b..5d3655f0 100644 --- a/src/visual/menu/menu/special/PlayerListController.cpp +++ b/src/visual/menu/menu/special/PlayerListController.cpp @@ -6,6 +6,8 @@ #include #include #include +#include + /* Created on 26.07.18. @@ -120,11 +122,11 @@ void zerokernel::special::PlayerListController::updatePlayerLifeState(int id, }); } -void zerokernel::special::PlayerListController::updatePlayerTeamClass(int id, - int team, - int classId) + +void +zerokernel::special::PlayerListController::updatePlayerTeam(int id, int team) { - table.iterateObjects([this, id, team, classId](BaseMenuObject *a) { + table.iterateObjects([this, id, team](BaseMenuObject *a) { auto row = dynamic_cast(a); // Shouldn't happen if (row == nullptr) @@ -132,6 +134,21 @@ void zerokernel::special::PlayerListController::updatePlayerTeamClass(int id, if ((int)row->kv["player_id"] == id) { row->kv["player_team"] = team; + updateRow(row); + } + }); +} + + +void zerokernel::special::PlayerListController::updatePlayerClass(int id, int classId) +{ + table.iterateObjects([this, id, classId](BaseMenuObject *a) { + auto row = dynamic_cast(a); + // Shouldn't happen + if (row == nullptr) + return; + if ((int)row->kv["player_id"] == id) + { row->kv["player_class"] = classId; updateRow(row); } @@ -227,4 +244,4 @@ void zerokernel::special::PlayerListController::updateRow(zerokernel::TRow *row) { el->set(class_names[classId]); } -} +} \ No newline at end of file