Update respect control in PlayerStatsMenu

- Added ModMenuModule::GangRespectSegment
- Updated ModMenuModule::PlayerStatsMenu to use dynamic gangs list along with their icons and names using GangRespectSegment
This commit is contained in:
izawartka 2026-07-08 23:56:44 +02:00
parent 0ebd39c8ee
commit b146035eda
7 changed files with 149 additions and 36 deletions

View File

@ -729,6 +729,7 @@ echo Created $(ProjectDir)src\git.h with commit %GIT_HASH% (dirty=%GIT_DIRTY%)
<ClInclude Include="src\modules\modmenu\segments\camera-pos-cheat-coord-segment.h" />
<ClInclude Include="src\modules\modmenu\segments\explode-all-vehicles-segment.h" />
<ClInclude Include="src\modules\modmenu\segments\fix-vehicle-segment.h" />
<ClInclude Include="src\modules\modmenu\segments\gang-respect-segment.h" />
<ClInclude Include="src\modules\modmenu\segments\get-powerup-segment.h" />
<ClInclude Include="src\modules\modmenu\segments\position-menu-segment.h" />
<ClInclude Include="src\modules\modmenu\segments\quick-action-key-segment.h" />
@ -783,6 +784,7 @@ echo Created $(ProjectDir)src\git.h with commit %GIT_HASH% (dirty=%GIT_DIRTY%)
<ClInclude Include="src\modules\ui\components\background.h" />
<ClInclude Include="src\modules\ui\components\car-sprite.h" />
<ClInclude Include="src\modules\ui\components\horcentered.h" />
<ClInclude Include="src\modules\ui\components\icon-sprite.h" />
<ClInclude Include="src\modules\ui\components\overridepos.h" />
<ClInclude Include="src\modules\ui\components\sprite.h" />
<ClInclude Include="src\modules\ui\controllers\button.h" />
@ -983,6 +985,7 @@ echo Created $(ProjectDir)src\git.h with commit %GIT_HASH% (dirty=%GIT_DIRTY%)
<ClCompile Include="src\modules\modmenu\segments\camera-pos-cheat-coord-segment.cpp" />
<ClCompile Include="src\modules\modmenu\segments\explode-all-vehicles-segment.cpp" />
<ClCompile Include="src\modules\modmenu\segments\fix-vehicle-segment.cpp" />
<ClCompile Include="src\modules\modmenu\segments\gang-respect-segment.cpp" />
<ClCompile Include="src\modules\modmenu\segments\get-powerup-segment.cpp" />
<ClCompile Include="src\modules\modmenu\segments\position-menu-segment.cpp" />
<ClCompile Include="src\modules\modmenu\segments\quick-action-key-segment.cpp" />
@ -1029,6 +1032,7 @@ echo Created $(ProjectDir)src\git.h with commit %GIT_HASH% (dirty=%GIT_DIRTY%)
<ClCompile Include="src\modules\ui\components\background.cpp" />
<ClCompile Include="src\modules\ui\components\car-sprite.cpp" />
<ClCompile Include="src\modules\ui\components\horcentered.cpp" />
<ClCompile Include="src\modules\ui\components\icon-sprite.cpp" />
<ClCompile Include="src\modules\ui\components\overridepos.cpp" />
<ClCompile Include="src\modules\ui\components\selectable.cpp" />
<ClCompile Include="src\modules\ui\components\sprite.cpp" />

View File

@ -188,6 +188,8 @@
<ClCompile Include="src\modules\modmenu\segments\position-menu-segment.cpp" />
<ClCompile Include="src\modules\modmenu\cheats\position-store.cpp" />
<ClCompile Include="src\game\utils\gang-utils.cpp" />
<ClCompile Include="src\modules\modmenu\segments\gang-respect-segment.cpp" />
<ClCompile Include="src\modules\ui\components\icon-sprite.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\converters\ammo.h" />
@ -497,6 +499,8 @@
<ClInclude Include="src\modules\modmenu\events\player-pos-rot-update.h" />
<ClInclude Include="src\game\utils\gang-utils.h" />
<ClInclude Include="src\converters\gang-name.h" />
<ClInclude Include="src\modules\modmenu\segments\gang-respect-segment.h" />
<ClInclude Include="src\modules\ui\components\icon-sprite.h" />
</ItemGroup>
<ItemGroup>
<None Include="GTA2.props" />

View File

@ -1,5 +1,6 @@
#include "player-stats-menu.h"
#include "../root.h"
#include "../segments/gang-respect-segment.h"
ModMenuModule::PlayerStatsMenu::PlayerStatsMenu()
{
@ -59,47 +60,32 @@ bool ModMenuModule::PlayerStatsMenu::Attach()
UiModule::VarTextEditableControllerOptions{ L"Lives: #", L"#" }
);
// respect 1
UiModule::Text* respect1Text = m_menuController->CreateItem<UiModule::Text>(vertCont, L"", options.textSize);
m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<char>>(
respect1Text,
Core::MakeResolver(
Game::Memory::GetGangRespectContainer,
mem(&Game::GangRespectContainer::gang), idx(0),
mem(&Game::GangRespect::respectArr), idx(0)
),
UiModule::VarTextEditableControllerOptions{ L"Respect 1: #", L"#" }
);
// respect 2
UiModule::Text* respect2Text = m_menuController->CreateItem<UiModule::Text>(vertCont, L"", options.textSize);
m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<char>>(
respect2Text,
Core::MakeResolver(
Game::Memory::GetGangRespectContainer,
mem(&Game::GangRespectContainer::gang), idx(1),
mem(&Game::GangRespect::respectArr), idx(0)
),
UiModule::VarTextEditableControllerOptions{ L"Respect 2: #", L"#" }
);
// respect 3
UiModule::Text* respect3Text = m_menuController->CreateItem<UiModule::Text>(vertCont, L"", options.textSize);
m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<char>>(
respect3Text,
Core::MakeResolver(
Game::Memory::GetGangRespectContainer,
mem(&Game::GangRespectContainer::gang), idx(2),
mem(&Game::GangRespect::respectArr), idx(0)
),
UiModule::VarTextEditableControllerOptions{ L"Respect 3: #", L"#" }
);
std::vector<Game::GangRespect*> gangs = Game::Utils::GetVisibleGangs();
for (Game::GangRespect* gang : gangs) {
CreateAttachSegment<GangRespectSegment>(this, vertCont, gang);
}
SetPreviousSelectedIndex();
return true;
}
void ModMenuModule::PlayerStatsMenu::Detach()
{
ClearSegments();
DestroyMenu();
}
void ModMenuModule::PlayerStatsMenu::OnShow()
{
SetSegmentsVisible(true);
}
void ModMenuModule::PlayerStatsMenu::OnHide()
{
SetSegmentsVisible(false);
}
void ModMenuModule::PlayerStatsMenu::OnMenuAction(UiModule::Selectable* item, UiModule::MenuItemId id)
{
switch (id) {

View File

@ -1,15 +1,19 @@
#pragma once
#include "../common.h"
#include "../menu-base.h"
#include "../segment-support.h"
namespace ModMenuModule {
class PlayerStatsMenu : public MenuBase {
class PlayerStatsMenu : public MenuBase, public SegmentSupport {
public:
PlayerStatsMenu();
virtual ~PlayerStatsMenu();
private:
virtual bool Attach() override;
virtual void Detach() override;
virtual void OnShow() override;
virtual void OnHide() override;
void OnMenuAction(UiModule::Selectable* item, UiModule::MenuItemId id) override;
};

View File

@ -0,0 +1,92 @@
#include "gang-respect-segment.h"
#include "../root.h"
#include "../../../converters/gang-name.h"
static constexpr Game::SCR_f GANG_RESPECT_SEGMENT_ICON_SIZE = Game::Utils::FromFloat(16.0f);
static constexpr Game::SCR_f GANG_RESPECT_SEGMENT_ICON_MARGIN_TOP = Game::Utils::FromFloat(4.0f);
static constexpr Game::SCR_f GANG_RESPECT_SEGMENT_ICON_MARGIN_RIGHT = Game::Utils::FromFloat(4.0f);
static constexpr uint16_t GANG_RESPECT_SEGMENT_BASE_SPITE_ID = 63; // first gang logo sprite
ModMenuModule::GangRespectSegment::GangRespectSegment()
{
}
ModMenuModule::GangRespectSegment::GangRespectSegment(Game::GangRespect* gang)
{
m_gang = gang;
}
ModMenuModule::GangRespectSegment::~GangRespectSegment()
{
}
void ModMenuModule::GangRespectSegment::SetGang(Game::GangRespect* gang)
{
if (IsAttached()) {
spdlog::error("GangRespectSegment: Cannot change gang while segment is attached");
return;
}
m_gang = gang;
}
bool ModMenuModule::GangRespectSegment::Attach(ModMenuModule::MenuBase* menu, UiModule::Component* parent)
{
CreateSegment(menu, parent);
if (!m_gang) {
spdlog::error("GangRespectSegment: Cannot attach, gang not set");
return false;
}
UiModule::RootModule* uiRoot = UiModule::RootModule::GetInstance();
const auto& options = ModMenuModule::RootModule::GetInstance()->GetOptions();
// container
auto* respectCont = m_menuController->CreateItem<UiModule::HorCont>(m_vertCont);
// icon
auto* iconCont = uiRoot->AddComponent<UiModule::VertCont>(respectCont);
uiRoot->AddComponent<UiModule::Spacer>(iconCont, 0, GANG_RESPECT_SEGMENT_ICON_MARGIN_TOP);
UiModule::IconSpriteOptions iconOptions = {};
iconOptions.spriteType = Game::SPRITE_TYPE_USER;
iconOptions.spriteId = GANG_RESPECT_SEGMENT_BASE_SPITE_ID + m_gang->spritesOffset;
iconOptions.palette = Game::PALETTE_BASE::PALETTE_BASE_SPRITE;
iconOptions.width = GANG_RESPECT_SEGMENT_ICON_SIZE;
iconOptions.height = GANG_RESPECT_SEGMENT_ICON_SIZE;
iconOptions.keepAspectRatio = true;
uiRoot->AddComponent<UiModule::IconSprite>(iconCont, iconOptions);
// right margin
uiRoot->AddComponent<UiModule::Spacer>(respectCont, GANG_RESPECT_SEGMENT_ICON_MARGIN_RIGHT, 0);
// respect
std::wstring gangName = GangNameConverter::ConvertToString(m_gang);
auto* respectText = uiRoot->AddComponent<UiModule::Text>(respectCont, L"", options.textSize);
auto* respectController = m_menuController->CreateLatestItemController<UiModule::VarTextEditableController<char>>(
respectText,
std::bind(&GangRespectSegment::GetGangRespectPtr, this),
UiModule::VarTextEditableControllerOptions{ gangName + L" respect: #", L"#" }
);
return true;
}
void ModMenuModule::GangRespectSegment::Detach()
{
DestroySegment();
}
char* ModMenuModule::GangRespectSegment::GetGangRespectPtr()
{
Game::Player* player = Game::Utils::GetPlayer();
if(!player) {
spdlog::error("GangRespectSegment: Cannot get player");
return nullptr;
}
return &m_gang->respectArr[player->gangsRespectIndex];
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "../common.h"
#include "../segment-base.h"
namespace ModMenuModule {
class GangRespectSegment : public SegmentBase {
public:
GangRespectSegment();
GangRespectSegment(Game::GangRespect* gang);
virtual ~GangRespectSegment();
void SetGang(Game::GangRespect* gang);
private:
virtual bool Attach(ModMenuModule::MenuBase* menu, UiModule::Component* parent) override;
virtual void Detach() override;
char* GetGangRespectPtr();
Game::GangRespect* m_gang = nullptr;
};
}

View File

@ -3,6 +3,7 @@
#include "camera-pos-cheat-coord-segment.h"
#include "explode-all-vehicles-segment.h"
#include "fix-vehicle-segment.h"
#include "gang-respect-segment.h"
#include "get-powerup-segment.h"
#include "position-menu-segment.h"
#include "position-rotation-segment.h"