Skip to content

Commit

Permalink
Ped Spawner Improvements (#102)
Browse files Browse the repository at this point in the history
* improvements

* vast improvement to ped spawner

* update

* updates

* update

* Necessary changes

Renamed util file.
Separated pedmodels library to secluded directory.
Added new submenu called World.
Added input completion callback.
Adjusted InputTextWithHint item.
Fixed SpawnPed logic.
Removed duplicate clang variable.

---------

Co-authored-by: DayibBaba <[email protected]>
  • Loading branch information
Rxann and DayibBaba authored Apr 4, 2024
1 parent a2e90f1 commit 5c6d224
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 106 deletions.
1 change: 0 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ AlwaysBreakTemplateDeclarations: 'Yes'
BinPackArguments: 'false'
BinPackParameters: 'true'
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Allman
BreakBeforeTernaryOperators: 'false'
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
Expand Down
3 changes: 2 additions & 1 deletion src/game/frontend/Menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include "submenus/Self.hpp"
#include "submenus/Settings.hpp"
#include "submenus/Teleport.hpp"

#include "submenus/World.hpp"

namespace YimMenu
{
Expand All @@ -24,6 +24,7 @@ namespace YimMenu
UIManager::AddSubmenu(std::make_shared<Submenus::Teleport>());
UIManager::AddSubmenu(std::make_shared<Submenus::Network>());
UIManager::AddSubmenu(std::make_shared<Submenus::Players>());
UIManager::AddSubmenu(std::make_shared<Submenus::World>());
UIManager::AddSubmenu(std::make_shared<Submenus::Settings>());
// Wierd glitch causes menu to crash when clicking debug
UIManager::AddSubmenu(std::make_shared<Submenus::Debug>());
Expand Down
10 changes: 6 additions & 4 deletions src/game/frontend/items/InputTextWithHint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@

namespace YimMenu
{
InputTextWithHint::InputTextWithHint(std::string label, std::string hint, std::string* buf, ImGuiInputTextFlags_ flag , std::function<void()> cb) :
InputTextWithHint::InputTextWithHint(std::string label, std::string hint, std::string* buf, int flags, std::function<void()> cb, ImGuiInputTextCallback inputCallback) :
m_Id(label),
m_Hint(hint),
m_Buf(buf),
m_Flag(flag),
m_Callback(cb)
m_Flags(flags),
m_Callback(cb),
m_ImGuiInputTextCallback(inputCallback)
{
}

void InputTextWithHint::Draw()
{
if(ImGui::InputTextWithHint(m_Id.data(), m_Hint.data(), m_Buf, m_Flag));
if (ImGui::InputTextWithHint(m_Id.data(), m_Hint.data(), m_Buf, m_Flags, m_ImGuiInputTextCallback))
;
{
if (m_Callback != nullptr)
{
Expand Down
5 changes: 3 additions & 2 deletions src/game/frontend/items/Items.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,15 @@ namespace YimMenu
class InputTextWithHint : public UIItem
{
public:
explicit InputTextWithHint(std::string label, std::string hint, std::string* buf, ImGuiInputTextFlags_ flag = ImGuiInputTextFlags_None, std::function<void()> cb = nullptr);
explicit InputTextWithHint(std::string label, std::string hint, std::string* buf, int flags = ImGuiInputTextFlags_None, std::function<void()> cb = nullptr, ImGuiInputTextCallback inputCallback = nullptr);
void Draw() override;

private:
std::string m_Id;
std::string m_Hint;
std::string* m_Buf;
ImGuiInputTextFlags_ m_Flag;
int m_Flags;
std::function<void()> m_Callback;
ImGuiInputTextCallback m_ImGuiInputTextCallback;
};
}
48 changes: 12 additions & 36 deletions src/game/frontend/submenus/Self.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
#include "game/features/Features.hpp"
#include "game/frontend/items/Items.hpp"
#include "game/rdr/Natives.hpp"
#include "util/PedModels.hpp"
#include "util/SpawnPed.cpp"
#include "util/Rewards.hpp"
#include "util/Ped.hpp"

#include <map>

Expand Down Expand Up @@ -79,7 +78,6 @@ namespace YimMenu::Submenus
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("keepclean"_J));
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("antilasso"_J));
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("antihogtie"_J));
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("voicechatoverride"_J)); // TODO: move this to spoofing or network
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("drunk"_J));
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("autotp"_J));
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("superjump"_J));
Expand All @@ -98,37 +96,11 @@ namespace YimMenu::Submenus
toolsGroup->AddItem(std::make_shared<CommandItem>("spawnwagon"_J));

movementGroup->AddItem(std::make_shared<BoolCommandItem>("noclip"_J));
static std::string ped_model_buf;
pedSpawnerGroup->AddItem(std::make_shared<ImGuiItem>([&]() {
ImGui::Text(std::string("Current Model: ").append(ped_model_buf).c_str());
ImGui::NewLine();

if (ImGui::BeginCombo("Ped Types", ped_model_buf.c_str()))
{
for (const auto& pedItem : pedModelInfos)
{
bool is_selected = (ped_model_buf == pedItem.model);
if (ImGui::Selectable(pedItem.model.c_str(), is_selected))
{
ped_model_buf = pedItem.model;
}
if (is_selected)
ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
}));
pedSpawnerGroup->AddItem(std::make_shared<ImGuiItem>([&] {
if (ImGui::Button("Spawn Ped"))
SpawnPed(ped_model_buf, YimMenu::Self::Id, YimMenu::Self::PlayerPed);
}));


columns->AddItem(globalsGroup);
columns->AddItem(toolsGroup);
columns->AddNextColumn();
columns->AddItem(movementGroup);
columns->AddItem(pedSpawnerGroup);
main->AddItem(columns);
AddCategory(std::move(main));

Expand Down Expand Up @@ -165,16 +137,20 @@ namespace YimMenu::Submenus
static Rewards::eRewardType selected;
std::map<Rewards::eRewardType, std::string> reward_translations = {{Rewards::eRewardType::GOLD_REWARDS, "Gold Rewards"}, {Rewards::eRewardType::HEIRLOOMS, "Heirlooms"}, {Rewards::eRewardType::COINS, "Coins"}, {Rewards::eRewardType::ALCBOTTLES, "Alcohol Bottles"}, {Rewards::eRewardType::ARROWHEADS, "Arrowheads"}, {Rewards::eRewardType::BRACELETS, "Bracelets"}, {Rewards::eRewardType::EARRINGS, "Earrings"}, {Rewards::eRewardType::NECKLACES, "Necklaces"}, {Rewards::eRewardType::RINGS, "Rings"}, {Rewards::eRewardType::TAROTCARDS_CUPS, "Tarot Cards - Cups"}, {Rewards::eRewardType::TAROTCARDS_PENTACLES, "Tarot Cards - Pentacles"}, {Rewards::eRewardType::TAROTCARDS_SWORDS, "Tarot Cards - Swords"}, {Rewards::eRewardType::TAROTCARDS_WANDS, "Tarot Cards - Wands"}};

for (auto& [type, translation] : reward_translations)
if (ImGui::BeginCombo("Rewards", reward_translations[selected].c_str()))
{
if (ImGui::Selectable(std::string(translation).c_str(), type == selected, ImGuiSelectableFlags_AllowDoubleClick))
{
selected = type;
}
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
for (auto& [type, translation] : reward_translations)
{
Rewards::SpawnRequestedRewards({selected});
if (ImGui::Selectable(std::string(translation).c_str(), type == selected, ImGuiSelectableFlags_AllowDoubleClick))
{
selected = type;
}
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
Rewards::SpawnRequestedRewards({selected});
}
}
ImGui::EndCombo();
}

if (ImGui::Button("Spawn Selected"))
Expand Down
100 changes: 100 additions & 0 deletions src/game/frontend/submenus/World.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include "World.hpp"

#include "game/frontend/items/Items.hpp"
#include "util/Ped.hpp"
#include "util/libraries/PedModels.hpp"
#include "game/backend/FiberPool.hpp"

namespace YimMenu::Submenus
{
bool is_ped_model_in_ped_model_list(std::string model)
{
for (const auto& pedModel : pedModels)
{
if (pedModel.model == model)
return true;
}

return false;
}

int PedSpawnerInputCallback(ImGuiInputTextCallbackData* data)
{
if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
{
std::string newText{};
std::string inputLower = data->Buf;
std::transform(inputLower.begin(), inputLower.end(), inputLower.begin(), ::tolower);
for (const auto& pedModel : pedModels)
{
std::string modelLower = pedModel.model;
std::transform(modelLower.begin(), modelLower.end(), modelLower.begin(), ::tolower);
if (modelLower.find(inputLower) != std::string::npos)
{
newText = pedModel.model;
}
}

if (!newText.empty())
{
data->DeleteChars(0, data->BufTextLen);
data->InsertChars(0, newText.c_str());
}
}
}

void PedSpawnerGroup()
{
static std::string pedModelBuffer;
static float scale = 1;
static bool dead, invis, godmode, freeze;
InputTextWithHint("##pedmodel", "Ped Model", &pedModelBuffer, ImGuiInputTextFlags_CallbackCompletion, nullptr, PedSpawnerInputCallback).Draw();
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Press Tab to auto fill");
if (!pedModelBuffer.empty() && !is_ped_model_in_ped_model_list(pedModelBuffer))
{
ImGui::BeginListBox("##pedmodels", ImVec2(250, 100));

std::string bufferLower = pedModelBuffer;
std::transform(bufferLower.begin(), bufferLower.end(), bufferLower.begin(), ::tolower);
for (const auto& pedModel : pedModels)
{
std::string pedModelLower = pedModel.model;
std::transform(pedModelLower.begin(), pedModelLower.end(), pedModelLower.begin(), ::tolower);
if (pedModelLower.find(bufferLower) != std::string::npos && ImGui::Selectable(pedModel.model.data()))
{
pedModelBuffer = pedModel.model;
}
}

ImGui::EndListBox();
}

ImGui::Checkbox("Spawn Dead", &dead);
ImGui::Checkbox("Invisible", &invis);
ImGui::Checkbox("GodMode", &godmode);
ImGui::Checkbox("Frozen", &freeze);
ImGui::SliderFloat("Scale", &scale, 0.1, 10);
if (ImGui::Button("Spawn"))
{
FiberPool::Push([] {
Peds::SpawnPed(pedModelBuffer, ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(Self::PlayerPed, 0, 3, 0), 0, freeze, dead, godmode, invis, scale);
});
}
}

World::World() :
Submenu::Submenu("World")
{
auto spawners = std::make_shared<Category>("Spawners");
auto pedSpawnerGroup = std::make_shared<Group>("Ped Spawner", GetListBoxDimensions());

pedSpawnerGroup->AddItem(std::make_shared<ImGuiItem>([] {
PedSpawnerGroup();
}));

spawners->AddItem(pedSpawnerGroup);

AddCategory(std::move(spawners));
}
}
11 changes: 11 additions & 0 deletions src/game/frontend/submenus/World.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include "core/frontend/manager/UIManager.hpp"

namespace YimMenu::Submenus
{
class World : public Submenu
{
public:
World();
};
}
39 changes: 39 additions & 0 deletions src/util/Ped.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "Ped.hpp"
#include "Joaat.hpp"

namespace YimMenu::Peds
{
// Returns 0 if it fails
int SpawnPed(std::string model_name, Vector3 coords, float heading, bool blockNewPedMovement, bool spawnDead, bool invincible, bool invisible, int scale)
{
Hash model = Joaat(model_name.c_str());

if (!STREAMING::IS_MODEL_IN_CDIMAGE(model) || !STREAMING::IS_MODEL_VALID(model))
{
Notifications::Show("Spawner", "Invalid ped model", NotificationType::Error);
return 0;
}

for (int i = 0; i < 30 && !STREAMING::HAS_MODEL_LOADED(model); i++)
{
STREAMING::REQUEST_MODEL(model, false);
ScriptMgr::Yield();
}

auto ped = PED::CREATE_PED(model, coords.x, coords.y, coords.z, heading, 1, 0, 0, 0);

PED::_SET_RANDOM_OUTFIT_VARIATION(ped, true);
ENTITY::PLACE_ENTITY_ON_GROUND_PROPERLY(ped, true);

ENTITY::FREEZE_ENTITY_POSITION(ped, blockNewPedMovement);
ENTITY::SET_ENTITY_INVINCIBLE(ped, invincible);
ENTITY::SET_ENTITY_VISIBLE(ped, !invisible);
PED::_SET_PED_SCALE(ped, (float)scale);

if (spawnDead)
PED::APPLY_DAMAGE_TO_PED(ped, std::numeric_limits<int>::max(), 1, 0, YimMenu::Self::PlayerPed);

STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(model);
return ped;
};
}
11 changes: 11 additions & 0 deletions src/util/Ped.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include "core/frontend/Notifications.hpp"
#include "game/backend/ScriptMgr.hpp"
#include "game/features/Features.hpp"
#include "game/rdr/Natives.hpp"


namespace YimMenu::Peds
{
extern int SpawnPed(std::string model_name, Vector3 coords, float heading = 0.0f, bool blockNewPedMovement = false, bool spawnDead = false, bool invincible = false, bool invisible = false, int scale = 1);
}
14 changes: 0 additions & 14 deletions src/util/PedModels.hpp

This file was deleted.

48 changes: 0 additions & 48 deletions src/util/SpawnPed.cpp

This file was deleted.

15 changes: 15 additions & 0 deletions src/util/libraries/PedModels.hpp

Large diffs are not rendered by default.

0 comments on commit 5c6d224

Please sign in to comment.