Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return value support for script functions and more features #191

Merged
merged 3 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/game/features/players/teleport/TpToPlayerCamp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "game/backend/Players.hpp"
#include "game/backend/Self.hpp"
#include "game/commands/PlayerCommand.hpp"
#include "game/features/Features.hpp"
#include "game/rdr/Natives.hpp"
#include "game/rdr/ScriptGlobal.hpp"
#include "util/teleport.hpp"

namespace YimMenu::Features
{
class TpToPlayerCamp: public PlayerCommand
{
using PlayerCommand::PlayerCommand;
static constexpr auto PlayerList = ScriptGlobal(1141332);

virtual void OnCall(Player player) override
{
if (!PlayerList.CanAccess())
return;

for (int i = 0; i < 32; i++)
{
if (*PlayerList.At(i, 27).At(9).As<int*>() == player.GetId())
{
auto Camp = ScriptGlobal(1141332).At(i, 27).At(20);

if (!Camp.CanAccess())
return;

Vector3 CampCoords = *Camp.As<Vector3*>();
if (CampCoords != Vector3(0.f, 0.f, 0.f))
{
if(YimMenu::Teleport::TeleportEntity(Self::GetPed().GetHandle(), CampCoords + Vector3(1, 0, 0), true))
g_Spectating = false;
}
else
{
Notifications::Show("Camp", "Unable to find player's camp", NotificationType::Error);
}
break;
}
}
}
};

static TpToPlayerCamp _TpToPlayerCamp{"tptoplayercamp", "Teleport To Player's Camp", "Teleport to the player's camp"};
}
19 changes: 13 additions & 6 deletions src/game/features/self/TpToMoonshineShack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,24 @@ namespace YimMenu::Features
class TpToMoonshineShack : public Command
{
using Command::Command;
static constexpr auto ShackBlip = ScriptGlobal(1297441).At(128);
static constexpr auto MoonshineShack = ScriptGlobal(1297441).At(128).At(1);

virtual void OnCall() override
{
if (ShackBlip.CanAccess())
if (MoonshineShack.CanAccess())
{
Blip Shack = *ShackBlip.As<Blip*>();
if (MAP::DOES_BLIP_EXIST(Shack))
Vector3 ShackCoords;
switch (*MoonshineShack.As<int*>())
{
Vector3 ShackCoords = MAP::GET_BLIP_COORDS(Shack);
YimMenu::Teleport::TeleportEntity(Self::GetPed().GetHandle(), ShackCoords, true);
case 0: ShackCoords = Vector3(1785.3f, -813.4f, 43.f); break;
case 1: ShackCoords = Vector3(-1088.43f, 706.8f, 104.5f); break;
case 2: ShackCoords = Vector3(-2777.04, -3051.f, 11.581f); break;
case 3: ShackCoords = Vector3(1627.f, 821.f, 145.f); break;
case 4: ShackCoords = Vector3(-1859.7f, -1730.3f, 109.5f); break;
}
if (ShackCoords != Vector3(0.f, 0.f, 0.f))
{
YimMenu::Teleport::TeleportEntity(Self::GetPed().GetHandle(), ShackCoords, false);
}
else
{
Expand Down
1 change: 1 addition & 0 deletions src/game/frontend/submenus/Players.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ namespace YimMenu::Submenus
}));

teleportGroup->AddItem(std::make_shared<PlayerCommandItem>("tptoplayer"_J));
teleportGroup->AddItem(std::make_shared<PlayerCommandItem>("tptoplayercamp"_J));
teleportGroup->AddItem(std::make_shared<PlayerCommandItem>("tpbehindplayer"_J));
teleportGroup->AddItem(std::make_shared<PlayerCommandItem>("tpintovehicle"_J));
teleportGroup->AddItem(std::make_shared<PlayerCommandItem>("bring"_J));
Expand Down
44 changes: 41 additions & 3 deletions src/game/frontend/submenus/Recovery.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
#include "Recovery.hpp"

#include "core/commands/BoolCommand.hpp"
#include "core/commands/Commands.hpp"
#include "game/backend/FiberPool.hpp"
#include "game/frontend/items/Items.hpp"
#include "core/commands/Commands.hpp"
#include "core/commands/BoolCommand.hpp"
#include "game/rdr/ScriptFunction.hpp"
#include "game/rdr/Scripts.hpp"
#include "util/Rewards.hpp"

namespace YimMenu::Submenus
{

Recovery::Recovery() :
Submenu::Submenu("Recovery")
{
auto recovery = std::make_shared<Category>("Recovery");
auto spawnCollectiblesGroup = std::make_shared<Group>("Spawn Collectibles");
auto spawnHerbsGroup = std::make_shared<Group>("Spawn Herbs");
auto recoveryOptions = std::make_shared<Group>("Options");

static auto recoveryCommand = Commands::GetCommand<BoolCommand>("recoveryenabled"_J);
Expand All @@ -35,7 +40,6 @@ namespace YimMenu::Submenus
{Rewards::eRewardType::TAROTCARDS_WANDS, "Tarot Cards - Wands"},
{Rewards::eRewardType::FOSSILS, "Fossils"},
{Rewards::eRewardType::EGGS, "Eggs"},
{Rewards::eRewardType::HERBS, "Herbs"},
{Rewards::eRewardType::TREASURE, "Treasure Reward"},
{Rewards::eRewardType::CAPITALE, "Capitale"},
{Rewards::eRewardType::XP, "25K XP"},
Expand All @@ -44,6 +48,7 @@ namespace YimMenu::Submenus
{Rewards::eRewardType::COLLECTORXP, "200 Collector XP"},
{Rewards::eRewardType::NATURALISTXP, "300 Naturalist XP"},
{Rewards::eRewardType::BOUNTYHUNTERXP, "200 Bounty Hunter XP"},
{Rewards::eRewardType::TRADERGOODS, "Max Trader Goods"},
};

if (ImGui::BeginCombo("Rewards", reward_translations[selected].c_str()))
Expand Down Expand Up @@ -81,9 +86,42 @@ namespace YimMenu::Submenus
}
}
}));
spawnHerbsGroup->AddItem(std::make_shared<ImGuiItem>([=] {
if (recoveryCommand->GetState())
{
static joaat_t selectedHerb;
std::map<joaat_t, std::string> herb_translations = {{"HERB_LOOT_ALASKAN_GINSENG"_J, "Alaskan Ginseng"},{"HERB_LOOT_AMERICAN_GINSENG"_J, "American Ginseng"},{"HERB_LOOT_BAY_BOLETE"_J, "Bay Bolete"},{"HERB_LOOT_BLACK_BERRY"_J, "Black Berry"},{"HERB_LOOT_BLACK_CURRANT"_J, "Black Currant"},{"HERB_LOOT_BURDOCK_ROOT"_J, "Burdock Root"},{"HERB_LOOT_CHANTERELLES"_J, "Chanterelles"},{"HERB_LOOT_COMMON_BULRUSH"_J, "Common Bulrush"},{"HERB_LOOT_CREEPING_THYME"_J, "Creeping Thyme"},{"HERB_LOOT_DESERT_SAGE"_J, "Desert Sage"},{"HERB_LOOT_ENGLISH_MACE"_J, "English Mace"},{"HERB_LOOT_EVERGREEN_HUCKLEBERRY"_J, "Evergreen Huckleberry"},{"HERB_LOOT_GOLDEN_CURRANT"_J, "Golden Currant"},{"HERB_LOOT_HUMMINGBIRD_SAGE"_J, "Hummingbird Sage"},{"HERB_LOOT_INDIAN_TOBACCO"_J, "Indian Tobacco"},{"HERB_LOOT_MILKWEED"_J, "Milkweed"},{"HERB_LOOT_OLEANDER_SAGE"_J, "Oleander Sage"},{"HERB_LOOT_OREGANO"_J, "Oregano"},{"HERB_LOOT_PARASOL_MUSHROOM"_J, "Parasol Mushroom"},{"HERB_LOOT_PRAIRIE_POPPY"_J, "Prairie Poppy"},{"HERB_LOOT_RAMS_HEAD"_J, "Rams Head"},{"HERB_LOOT_RED_RASPBERRY"_J, "Red Raspberry"},{"HERB_LOOT_RED_SAGE"_J, "Red Sage"},{"HERB_LOOT_VANILLA_FLOWER"_J, "Vanilla Flower"},{"HERB_LOOT_VIOLET_SNOWDROP"_J, "Violet Snowdrop"},{"HERB_LOOT_WILD_CARROTS"_J, "Wild Carrots"},{"HERB_LOOT_WILD_FEVERFEW"_J, "Wild Feverfew"},{"HERB_LOOT_WILD_MINT"_J, "Wild Mint"},{"HERB_LOOT_WINTERGREEN_BERRY"_J, "Wintergreen Berry"},{"HERB_LOOT_YARROW"_J, "Yarrow"},{"HERB_LOOT_AGARITA"_J, "Agarita"},{"HERB_LOOT_BITTERWEED"_J, "Bitterweed"},{"HERB_LOOT_BLUE_BONNET"_J, "Blue Bonnet"},{"HERB_LOOT_BLOOD_FLOWER"_J, "Blood Flower"},{"HERB_LOOT_CARDINAL_FLOWER"_J, "Cardinal Flower"},{"HERB_LOOT_CHOCOLATE_DAISY"_J, "Chocolate Daisy"},{"HERB_LOOT_CREEK_PLUM"_J, "Creek Plum"},{"HERB_LOOT_RHUBARB"_J, "Rhubarb"},{"HERB_LOOT_WISTERIA"_J, "Wisteria"},{"HERB_LOOT_HARRIETUM"_J, "Harrietum"},};
if (ImGui::BeginCombo("Herbs", herb_translations[selectedHerb].c_str()))
{
for (auto& [herb, translation] : herb_translations)
{
if (ImGui::Selectable(std::string(translation).c_str(), herb == selectedHerb))
{
selectedHerb = herb;
}
}
ImGui::EndCombo();
}

static int amount = 1;
ImGui::SliderInt("Amount", &amount, 1, 10);

if (ImGui::Button("Give Selected"))
{
FiberPool::Push([] {
if (!Scripts::RequestScript("interactive_campfire"_J))
return;

for (int i = 0; i < amount; i++)
ScriptFunctions::GiveLootTableAward.StaticCall(selectedHerb, 0);
});
}
}
}));
recoveryOptions->AddItem(std::make_shared<BoolCommandItem>("unlimiteditems"_J));
recoveryOptions->AddItem(std::make_shared<BoolCommandItem>("fastmoonshine"_J));
recovery->AddItem(spawnCollectiblesGroup);
recovery->AddItem(spawnHerbsGroup);
recovery->AddItem(recoveryOptions);

AddCategory(std::move(recovery));
Expand Down
14 changes: 9 additions & 5 deletions src/game/rdr/ScriptFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,15 @@ namespace YimMenu
{
}

void ScriptFunction::RunScript(rage::scrThread* thread, rage::scrProgram* program, const std::vector<uint64_t>& args)
void ScriptFunction::RunScript(rage::scrThread* thread, rage::scrProgram* program, const std::vector<uint64_t>& args, void* returnValue, uint32_t returnSize)
{
const auto globals_initialized = std::vector<std::uint8_t>(50, true); // std::vector<bool> does weird stuff so we aren't using that

auto old_thread = *Pointers.CurrentScriptThread;
auto old_thread_running = rage::tlsContext::Get()->m_RunningScript;
auto stack = reinterpret_cast<uint64_t*>(thread->m_Stack);
auto context = thread->m_Context;
auto top = context.m_StackPointer;

for (auto& arg : args)
stack[context.m_StackPointer++] = arg;
Expand All @@ -85,9 +86,12 @@ namespace YimMenu

rage::tlsContext::Get()->m_RunningScript = old_thread_running;
*Pointers.CurrentScriptThread = old_thread;

if (returnValue)
memcpy(returnValue, stack + top, returnSize);
}

void ScriptFunction::StaticCall(const std::vector<uint64_t>& args)
void ScriptFunction::StaticCallImpl(const std::vector<uint64_t>& args, void* returnValue, uint32_t returnSize)
{
auto pc = GetPC();
auto program = Scripts::FindScriptProgram(m_Hash);
Expand All @@ -103,13 +107,13 @@ namespace YimMenu
thread->m_Context.m_StackSize = 25000;
thread->m_Context.m_StackPointer = 1;

RunScript(thread, program, args);
RunScript(thread, program, args, returnValue, returnSize);

delete[] stack;
delete[] (uint8_t*)thread;
}

void ScriptFunction::Call(const std::vector<uint64_t>& args)
void ScriptFunction::CallImpl(const std::vector<uint64_t>& args, void* returnValue, uint32_t returnSize)
{
auto pc = GetPC();
auto thread = Scripts::FindScriptThread(m_Hash);
Expand All @@ -118,6 +122,6 @@ namespace YimMenu
if (!pc || !thread || !program)
return;

RunScript(thread, program, args);
RunScript(thread, program, args, returnValue, returnSize);
}
}
44 changes: 36 additions & 8 deletions src/game/rdr/ScriptFunction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "core/memory/Pattern.hpp"
#include "util/Joaat.hpp"

#include <type_traits>

namespace rage
{
class scrThread;
Expand All @@ -19,30 +21,56 @@ namespace YimMenu

std::optional<std::int32_t> GetPC();

void RunScript(rage::scrThread* thread, rage::scrProgram* program, const std::vector<uint64_t>& args);
void RunScript(rage::scrThread* thread, rage::scrProgram* program, const std::vector<uint64_t>& args, void* returnValue, uint32_t returnSize);

void Call(const std::vector<uint64_t>& args);
void CallImpl(const std::vector<uint64_t>& args, void* returnValue = 0, uint32_t returnSize = 0);

void StaticCall(const std::vector<uint64_t>& args);
void StaticCallImpl(const std::vector<uint64_t>& args, void* returnValue = 0, uint32_t returnSize = 0);
public:
ScriptFunction(joaat_t hash, SimplePattern pattern);

// TODO: return value support
template<typename Ret = void, typename... Args>
Ret StaticCall(Args... args)
{
std::vector<uint64_t> params;
(params.push_back(static_cast<std::uint64_t>(args)), ...);

if constexpr (!std::is_same_v<Ret, void>)
{
Ret returnValue;
StaticCallImpl(params, &returnValue, sizeof(returnValue));
return returnValue;
}
else
{
StaticCallImpl(params);
}
}

template<typename... Args>
void StaticCall(Args... args)
template<typename Ret = void, typename... Args>
Ret Call(Args... args)
{
std::vector<uint64_t> params;
(params.push_back(static_cast<std::uint64_t>(args)), ...);
StaticCall(params);

if constexpr (!std::is_same_v<Ret, void>)
{
Ret returnValue;
CallImpl(params, &returnValue, sizeof(returnValue));
return returnValue;
}
else
{
CallImpl(params);
}
}

template<typename... Args>
void operator()(Args... args)
{
std::vector<uint64_t> params;
(params.push_back(static_cast<std::uint64_t>(args)), ...);
Call(params);
CallImpl(params);
}
};

Expand Down
16 changes: 16 additions & 0 deletions src/game/rdr/Scripts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <script/scriptHandlerNetComponent.hpp>
#include <network/CNetworkPlayerMgr.hpp>
#include <rage/tlsContext.hpp>
#include "game/backend/ScriptMgr.hpp"
#include "game/pointers/Pointers.hpp"
#include "game/rdr/Natives.hpp"
#include "game/rdr/data/ScriptNames.hpp"
Expand Down Expand Up @@ -84,4 +85,19 @@ namespace YimMenu::Scripts
auto handler = reinterpret_cast<rage::scriptHandlerNetComponent*>(thread->m_HandlerNetComponent);
handler->DoHostMigration(Pointers.NetworkPlayerMgr->m_LocalPlayer, 0xFFFF, true);
}

bool RequestScript(joaat_t script)
{
if (!SCRIPTS::HAS_SCRIPT_WITH_NAME_HASH_LOADED(script))
{
SCRIPTS::REQUEST_SCRIPT_WITH_NAME_HASH(script);
for (int i = 0; i < 150 && !SCRIPTS::HAS_SCRIPT_WITH_NAME_HASH_LOADED(script); i++)
ScriptMgr::Yield(10ms);
}

if (SCRIPTS::HAS_SCRIPT_WITH_NAME_HASH_LOADED(script))
return true;

return false;
}
}
1 change: 1 addition & 0 deletions src/game/rdr/Scripts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ namespace YimMenu::Scripts
extern void SendScriptEvent(uint64_t* data, int count, int metadataIndex, int bits);
extern const char* GetScriptName(joaat_t hash);
extern void ForceScriptHost(rage::scrThread* thread);
extern bool RequestScript(joaat_t script);
}
23 changes: 9 additions & 14 deletions src/util/Rewards.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include "Rewards.hpp"
#include "game/backend/ScriptMgr.hpp"
#include "game/pointers/Pointers.hpp"
#include "game/rdr/Natives.hpp"
#include "game/rdr/ScriptFunction.hpp"
#include "game/rdr/Scripts.hpp"
#include <event/CEventGroup.hpp>
#include <event/CEventInventoryItemPickedUp.hpp>

Expand All @@ -17,12 +16,8 @@ namespace YimMenu::Rewards

void GiveScriptReward(const RewardInfo& info, bool loottable)
{
if (!SCRIPTS::HAS_SCRIPT_WITH_NAME_HASH_LOADED("interactive_campfire"_J))
{
SCRIPTS::REQUEST_SCRIPT_WITH_NAME_HASH("interactive_campfire"_J);
for (int i = 0; i < 150 && !SCRIPTS::HAS_SCRIPT_WITH_NAME_HASH_LOADED("interactive_campfire"_J); i++)
ScriptMgr::Yield(10ms);
}
if (!Scripts::RequestScript("interactive_campfire"_J))
return;

if (loottable)
ScriptFunctions::GiveLootTableAward.StaticCall(info.reward_hash, 0);
Expand Down Expand Up @@ -127,12 +122,6 @@ namespace YimMenu::Rewards
GiveScriptReward(egg);
}
break;
case eRewardType::HERBS:
for (const auto& herb : Herbs)
{
GiveScriptReward(herb);
}
break;
case eRewardType::TREASURE:
for (const auto& treasure : TreasureReward)
{
Expand Down Expand Up @@ -181,6 +170,12 @@ namespace YimMenu::Rewards
GiveScriptReward(xp, false);
}
break;
case eRewardType::TRADERGOODS:
for (const auto& good : TraderGoods)
{
GiveScriptReward(good, false);
}
break;
}
}
};
Expand Down
Loading
Loading