Add SpawnCharacterAction
- Added ModMenuModule::SpawnPedActionSegment - Added ModMenuModule::SpawnCharacterAction
This commit is contained in:
parent
2550ab2910
commit
ff91ccfe17
@ -458,6 +458,7 @@
|
||||
<ClInclude Include="src\modules\modmenu\quick-action-registry.h" />
|
||||
<ClInclude Include="src\modules\modmenu\quick-actions\clear-wanted-level.h" />
|
||||
<ClInclude Include="src\modules\modmenu\quick-actions\explode-vehicle.h" />
|
||||
<ClInclude Include="src\modules\modmenu\quick-actions\spawn-character.h" />
|
||||
<ClInclude Include="src\modules\modmenu\quick-actions\switch-camera-mode.h" />
|
||||
<ClInclude Include="src\modules\modmenu\quick-actions\explode-all-vehicles.h" />
|
||||
<ClInclude Include="src\modules\modmenu\quick-actions\fix-vehicle.h" />
|
||||
@ -496,6 +497,7 @@
|
||||
<ClInclude Include="src\modules\modmenu\menus\saved-vehicles-menu.h" />
|
||||
<ClInclude Include="src\modules\modmenu\segments\segments.h" />
|
||||
<ClInclude Include="src\modules\modmenu\segments\spawn-object-segment.h" />
|
||||
<ClInclude Include="src\modules\modmenu\segments\spawn-ped-action-segment.h" />
|
||||
<ClInclude Include="src\modules\modmenu\segments\spawn-ped-segment.h" />
|
||||
<ClInclude Include="src\modules\modmenu\segments\spawn-saved-vehicle-segment.h" />
|
||||
<ClInclude Include="src\modules\modmenu\segments\spawn-vehicle-segment.h" />
|
||||
@ -748,6 +750,7 @@
|
||||
<ClCompile Include="src\modules\modmenu\menus\world-menu.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\quick-action-manager.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\quick-actions\explode-vehicle.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\quick-actions\spawn-character.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\quick-actions\switch-camera-mode.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\quick-actions\clear-wanted-level.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\quick-actions\explode-all-vehicles.cpp" />
|
||||
@ -786,6 +789,7 @@
|
||||
<ClCompile Include="src\modules\modmenu\segments\position-segment.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\menus\saved-vehicles-menu.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\segments\spawn-object-segment.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\segments\spawn-ped-action-segment.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\segments\spawn-ped-segment.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\segments\spawn-saved-vehicle-segment.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\segments\spawn-vehicle-segment.cpp" />
|
||||
|
||||
@ -226,6 +226,8 @@
|
||||
<ClCompile Include="src\modules\keyboard\events\key-down.cpp" />
|
||||
<ClCompile Include="src\modules\keyboard\events\key-up.cpp" />
|
||||
<ClCompile Include="src\modules\keyboard\root.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\segments\spawn-ped-action-segment.cpp" />
|
||||
<ClCompile Include="src\modules\modmenu\quick-actions\spawn-character.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\converters\ammo.h" />
|
||||
@ -586,6 +588,8 @@
|
||||
<ClInclude Include="src\modules\keyboard\events\keyboard.h" />
|
||||
<ClInclude Include="src\modules\keyboard\keyboard.h" />
|
||||
<ClInclude Include="src\modules\keyboard\root.h" />
|
||||
<ClInclude Include="src\modules\modmenu\segments\spawn-ped-action-segment.h" />
|
||||
<ClInclude Include="src\modules\modmenu\quick-actions\spawn-character.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="GTA2.props" />
|
||||
|
||||
109
src/modules/modmenu/quick-actions/spawn-character.cpp
Normal file
109
src/modules/modmenu/quick-actions/spawn-character.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
#include "spawn-character.h"
|
||||
#include "../cheats/ped-templates.h"
|
||||
#include "../toast-manager.h"
|
||||
#include "../utils/spawn-ped-utils.h"
|
||||
#include "../quick-action-registry.h"
|
||||
|
||||
static const std::string typeId = "ModMenu_SpawnCharacter";
|
||||
static const std::wstring typeLabel = L"Spawn character";
|
||||
|
||||
ModMenuModule::SpawnCharacterAction::SpawnCharacterAction()
|
||||
{
|
||||
m_label = typeLabel;
|
||||
}
|
||||
|
||||
ModMenuModule::SpawnCharacterAction::~SpawnCharacterAction()
|
||||
{}
|
||||
|
||||
const std::string& ModMenuModule::SpawnCharacterAction::GetTypeId()
|
||||
{
|
||||
return typeId;
|
||||
}
|
||||
|
||||
const std::wstring& ModMenuModule::SpawnCharacterAction::GetTypeLabel()
|
||||
{
|
||||
return typeLabel;
|
||||
}
|
||||
|
||||
ModMenuModule::SpawnPedActionSegment* ModMenuModule::SpawnCharacterAction::CreateSegmentInstance()
|
||||
{
|
||||
return new SpawnPedActionSegment();
|
||||
}
|
||||
|
||||
void ModMenuModule::SpawnCharacterAction::Execute()
|
||||
{
|
||||
if (!m_data.has_value()) {
|
||||
spdlog::error("SpawnCharacterAction::Execute: No data to execute action.");
|
||||
return;
|
||||
}
|
||||
|
||||
PedTemplatesCheat* pedTemplatesCheat = PedTemplatesCheat::GetInstance();
|
||||
if (!pedTemplatesCheat->IsEnabled()) {
|
||||
spdlog::error("SpawnCharacterAction::Execute: PedTemplatesCheat is not enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
const SpawnPedActionSegmentData& data = m_data.value();
|
||||
|
||||
const PedTemplate* pedTemplate = pedTemplatesCheat->GetTemplate(data.pedTemplateName);
|
||||
if (!pedTemplate) {
|
||||
ToastManager::GetInstance()->Show({ L"Failed to spawn " + data.pedTemplateName + L",", ToastType::Error});
|
||||
ToastManager::GetInstance()->Show({ L"Character template not found", ToastType::Error });
|
||||
return;
|
||||
}
|
||||
|
||||
if (Utils::SpawnPed::SpawnPedAtPlayer(pedTemplate->data, data.inNearestCar)) {
|
||||
ModMenuModule::ToastManager::GetInstance()->Show({ L"Spawned " + data.pedTemplateName });
|
||||
}
|
||||
else {
|
||||
ModMenuModule::ToastManager::GetInstance()->Show({ L"Failed to spawn " + data.pedTemplateName, ToastType::Error });
|
||||
}
|
||||
}
|
||||
|
||||
const std::wstring& ModMenuModule::SpawnCharacterAction::GetLabel() const
|
||||
{
|
||||
return m_label;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ModMenuModule::SpawnCharacterAction::SerializeData() const
|
||||
{
|
||||
if (!m_data.has_value()) {
|
||||
spdlog::error("SpawnCharacterAction::SerializeData: No data to serialize.");
|
||||
return {};
|
||||
}
|
||||
|
||||
const SpawnPedActionSegmentData& data = m_data.value();
|
||||
std::vector<uint8_t> buffer;
|
||||
size_t bufferSize = data.pedTemplateName.size() * sizeof(wchar_t) + 1;
|
||||
buffer.resize(bufferSize);
|
||||
std::memcpy(buffer.data(), data.pedTemplateName.data(), bufferSize);
|
||||
buffer[buffer.size() - 1] = data.inNearestCar ? 1 : 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
bool ModMenuModule::SpawnCharacterAction::DeserializeData(const std::vector<uint8_t>& data)
|
||||
{
|
||||
if ((data.size() - 1) % sizeof(wchar_t) != 0) {
|
||||
spdlog::error("SpawnCharacterAction::DeserializeData: Invalid data size.");
|
||||
return false;
|
||||
}
|
||||
size_t wcharCount = (data.size() - 1) / sizeof(wchar_t);
|
||||
std::wstring pedTemplateName(wcharCount, L'\0');
|
||||
std::memcpy(&pedTemplateName[0], data.data(), data.size() - 1);
|
||||
bool inNearestCar = data[data.size() - 1] != 0;
|
||||
m_data = SpawnPedActionSegmentData{ pedTemplateName, inNearestCar };
|
||||
OnDataChange();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModMenuModule::SpawnCharacterAction::OnDataChange()
|
||||
{
|
||||
if (m_data.has_value()) {
|
||||
m_label = L"Spawn " + m_data->pedTemplateName;
|
||||
}
|
||||
else {
|
||||
m_label = typeLabel;
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_QUICK_ACTION(SpawnCharacterAction)
|
||||
26
src/modules/modmenu/quick-actions/spawn-character.h
Normal file
26
src/modules/modmenu/quick-actions/spawn-character.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include "../common.h"
|
||||
#include "../quick-action-base.h"
|
||||
#include "../segments/spawn-ped-action-segment.h"
|
||||
|
||||
namespace ModMenuModule {
|
||||
class SpawnCharacterAction : public QuickActionWithSegment<SpawnPedActionSegmentData> {
|
||||
public:
|
||||
SpawnCharacterAction();
|
||||
virtual ~SpawnCharacterAction();
|
||||
static const std::string& GetTypeId();
|
||||
static const std::wstring& GetTypeLabel();
|
||||
static SpawnPedActionSegment* CreateSegmentInstance();
|
||||
|
||||
void Execute() override;
|
||||
const std::wstring& GetLabel() const override;
|
||||
|
||||
std::vector<uint8_t> SerializeData() const override;
|
||||
bool DeserializeData(const std::vector<uint8_t>& data) override;
|
||||
|
||||
private:
|
||||
virtual void OnDataChange() override;
|
||||
|
||||
std::wstring m_label;
|
||||
};
|
||||
}
|
||||
134
src/modules/modmenu/segments/spawn-ped-action-segment.cpp
Normal file
134
src/modules/modmenu/segments/spawn-ped-action-segment.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include "spawn-ped-action-segment.h"
|
||||
#include "../cheats/ped-templates.h"
|
||||
#include "../root.h"
|
||||
#include "../../../converters/yes-no.h"
|
||||
#include "ped-preview-segment.h"
|
||||
#include "../toast-manager.h"
|
||||
|
||||
ModMenuModule::SpawnPedActionSegment::SpawnPedActionSegment()
|
||||
{
|
||||
m_pedPreviewSegment = SegmentSupport::CreateSegment<PedPreviewSegment>();
|
||||
}
|
||||
|
||||
ModMenuModule::SpawnPedActionSegment::~SpawnPedActionSegment()
|
||||
{
|
||||
SegmentSupport::DeleteSegment(m_pedPreviewSegment);
|
||||
}
|
||||
|
||||
bool ModMenuModule::SpawnPedActionSegment::ValidateSegment()
|
||||
{
|
||||
if (!m_pedPreviewSegment || !m_templateNameController) return false;
|
||||
|
||||
PedTemplatesCheat* pedTemplatesCheat = PedTemplatesCheat::GetInstance();
|
||||
const std::wstring& pedTemplateName = m_templateNameController->GetValue().value();
|
||||
const auto* pedTemplate = pedTemplatesCheat->GetTemplate(pedTemplateName);
|
||||
|
||||
if (!pedTemplate) {
|
||||
spdlog::warn(L"SpawnPedActionSegment: Validation failed, ped template \"{}\" not found.", pedTemplateName);
|
||||
ToastManager::GetInstance()->Show({ L"Selected template not found", ToastType::Warning });
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<ModMenuModule::SpawnPedActionSegmentData> ModMenuModule::SpawnPedActionSegment::GetSegmentData() const
|
||||
{
|
||||
if (!m_templateNameController || !m_inNearestCarController) {
|
||||
spdlog::warn("SpawnPedActionSegment: Cannot get segment data, controllers not initialized");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return SpawnPedActionSegmentData{
|
||||
m_templateNameController->GetValue().value_or(L""),
|
||||
m_inNearestCarController->GetValue().value_or(false)
|
||||
};
|
||||
}
|
||||
|
||||
bool ModMenuModule::SpawnPedActionSegment::SetSegmentData(const SpawnPedActionSegmentData& data)
|
||||
{
|
||||
if (!m_templateNameController || !m_inNearestCarController) {
|
||||
spdlog::warn("SpawnPedActionSegment: Cannot set segment data, controllers not initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_templateNameController->SetValue(data.pedTemplateName);
|
||||
m_inNearestCarController->SetValue(data.inNearestCar);
|
||||
|
||||
UpdatePreview();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ModMenuModule::SpawnPedActionSegment::Attach(ModMenuModule::MenuBase* menu, UiModule::Component* parent)
|
||||
{
|
||||
SegmentBase::CreateSegment(menu, parent);
|
||||
|
||||
UiModule::RootModule* uiRoot = UiModule::RootModule::GetInstance();
|
||||
const auto& options = ModMenuModule::RootModule::GetInstance()->GetOptions();
|
||||
PersistenceModule::PersistenceManager* persistence = PersistenceModule::PersistenceManager::GetInstance();
|
||||
|
||||
// template name
|
||||
PedTemplatesCheat* pedTemplatesCheat = PedTemplatesCheat::GetInstance();
|
||||
const auto& templateNameOptions = pedTemplatesCheat->GetTemplatesList();
|
||||
if (!templateNameOptions.size()) {
|
||||
spdlog::warn("SpawnPedActionSegment: No ped templates available");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* templateNameText = m_menuController->CreateItem<UiModule::Text>(m_vertCont, L"", options.textSize);
|
||||
m_templateNameController = m_menuController->CreateLatestItemController<UiModule::SelectController<std::wstring>>(
|
||||
templateNameText,
|
||||
templateNameOptions,
|
||||
templateNameOptions[0],
|
||||
UiModule::SelectControllerOptions{ L"Template: #", L"#" }
|
||||
);
|
||||
m_templateNameController->SetSaveCallback(std::bind(&SpawnPedActionSegment::OnTemplateControllerSave, this, std::placeholders::_1));
|
||||
|
||||
// in nearest car
|
||||
auto* inNearestCarText = m_menuController->CreateItem<UiModule::Text>(m_vertCont, L"", options.textSize);
|
||||
m_inNearestCarController = m_menuController->CreateLatestItemController<UiModule::SelectController<bool>>(
|
||||
inNearestCarText,
|
||||
std::vector<bool>{ false, true },
|
||||
false,
|
||||
UiModule::SelectControllerOptions{ L"In nearest vehicle: #", L"#" }
|
||||
);
|
||||
m_inNearestCarController->SetConverter<YesNoConverter>();
|
||||
|
||||
// sprite preview
|
||||
uiRoot->AddComponent<UiModule::Spacer>(m_vertCont, 0, options.menuSpacerHeight);
|
||||
UpdatePreview();
|
||||
SegmentSupport::AttachSegment(m_pedPreviewSegment, menu, m_vertCont);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModMenuModule::SpawnPedActionSegment::Detach()
|
||||
{
|
||||
m_templateNameController = nullptr;
|
||||
m_inNearestCarController = nullptr;
|
||||
SegmentSupport::DetachSegment(m_pedPreviewSegment);
|
||||
SegmentBase::DestroySegment();
|
||||
}
|
||||
|
||||
void ModMenuModule::SpawnPedActionSegment::OnTemplateControllerSave(const std::wstring& templateName)
|
||||
{
|
||||
UpdatePreview();
|
||||
}
|
||||
|
||||
void ModMenuModule::SpawnPedActionSegment::UpdatePreview()
|
||||
{
|
||||
if (!m_pedPreviewSegment || !m_templateNameController) return;
|
||||
|
||||
PedTemplatesCheat* pedTemplatesCheat = PedTemplatesCheat::GetInstance();
|
||||
|
||||
const std::wstring& pedTemplateName = m_templateNameController->GetValue().value();
|
||||
const auto* pedTemplate = pedTemplatesCheat->GetTemplate(pedTemplateName);
|
||||
|
||||
if (!pedTemplate) {
|
||||
spdlog::warn(L"SpawnPedActionSegment: Cannot update preview, ped template \"{}\" not found.", pedTemplateName);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pedPreviewSegment->SetPedData(pedTemplate->data);
|
||||
}
|
||||
35
src/modules/modmenu/segments/spawn-ped-action-segment.h
Normal file
35
src/modules/modmenu/segments/spawn-ped-action-segment.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
#include "../common.h"
|
||||
#include "../segment-base.h"
|
||||
#include "../segment-support.h"
|
||||
|
||||
namespace ModMenuModule {
|
||||
class PedPreviewSegment;
|
||||
|
||||
struct SpawnPedActionSegmentData {
|
||||
std::wstring pedTemplateName;
|
||||
bool inNearestCar;
|
||||
};
|
||||
|
||||
class SpawnPedActionSegment : public Segment<SpawnPedActionSegmentData>, public SegmentSupport {
|
||||
public:
|
||||
SpawnPedActionSegment();
|
||||
virtual ~SpawnPedActionSegment();
|
||||
|
||||
bool ValidateSegment();
|
||||
|
||||
virtual std::optional<SpawnPedActionSegmentData> GetSegmentData() const override;
|
||||
virtual bool SetSegmentData(const SpawnPedActionSegmentData& data) override;
|
||||
|
||||
private:
|
||||
virtual bool Attach(ModMenuModule::MenuBase* menu, UiModule::Component* parent) override;
|
||||
virtual void Detach() override;
|
||||
|
||||
void OnTemplateControllerSave(const std::wstring& templateName);
|
||||
void UpdatePreview();
|
||||
|
||||
UiModule::SelectController<std::wstring>* m_templateNameController = nullptr;
|
||||
UiModule::SelectController<bool>* m_inNearestCarController = nullptr;
|
||||
PedPreviewSegment* m_pedPreviewSegment = nullptr;
|
||||
};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user