feat(special_ability): add special ability features

This commit is contained in:
maybegreat48
2025-06-20 11:56:51 -04:00
parent 24a61a6fd2
commit f5dd5ece1e
9 changed files with 138 additions and 7 deletions
+4 -1
View File
@@ -69,7 +69,10 @@ namespace YimMenu
else
{
std::vector<Hook> hooks = {Hook(index, hook)};
m_RegisteredHooks.emplace(script, hooks);
if (!m_RegisteredHooks.emplace(script, hooks).second)
{
LOGF(WARNING, "NativeHooks::AddHookImpl: {:X} already registered for script {:X}", static_cast<std::uint64_t>(index), script);
}
}
for (auto& [scp, program] : m_RegisteredPrograms)
@@ -13,8 +13,11 @@ namespace YimMenu::Features
virtual void OnEnable() override
{
NativeHooks::AddHook(NativeHooks::ALL_SCRIPTS, NativeIndex::NETWORK_CASINO_CAN_BET, &NetworkCasinoCanBetHook);
NativeHooks::AddHook(NativeHooks::ALL_SCRIPTS, NativeIndex::NETWORK_CASINO_CAN_BUY_CHIPS_PVC, &NetworkCasinoCanBuyChipsPVCHook);
static auto hooked = []() {
NativeHooks::AddHook(NativeHooks::ALL_SCRIPTS, NativeIndex::NETWORK_CASINO_CAN_BET, &NetworkCasinoCanBetHook);
NativeHooks::AddHook(NativeHooks::ALL_SCRIPTS, NativeIndex::NETWORK_CASINO_CAN_BUY_CHIPS_PVC, &NetworkCasinoCanBuyChipsPVCHook);
return true;
}();
}
};
+7 -3
View File
@@ -13,9 +13,13 @@ namespace YimMenu::Features
virtual void OnEnable() override
{
NativeHooks::AddHook("freemode"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
NativeHooks::AddHook("fmmc_launcher"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
NativeHooks::AddHook("am_launcher"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
static auto hooked = []()
{
NativeHooks::AddHook("freemode"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
NativeHooks::AddHook("fmmc_launcher"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
NativeHooks::AddHook("am_launcher"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
return true;
}();
}
};
+5 -1
View File
@@ -27,7 +27,11 @@ namespace YimMenu::Features
formatIntCaller2Hook = CallSiteHook::AddHook(Pointers.FormatIntCaller2, reinterpret_cast<void*>(FormatIntHook));
}
formatIntCaller2Hook->Enable();
NativeHooks::AddHook("shop_controller"_J, NativeIndex::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT, &ScaleformAddIntHook);
static auto hooked = []()
{
NativeHooks::AddHook("shop_controller"_J, NativeIndex::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT, &ScaleformAddIntHook);
return true;
}();
}
virtual void OnDisable() override
@@ -0,0 +1,24 @@
#include "core/commands/LoopedCommand.hpp"
#include "game/backend/Self.hpp"
#include "game/gta/Natives.hpp"
namespace YimMenu::Features
{
class InfiniteSpecialAbility : public LoopedCommand
{
using LoopedCommand::LoopedCommand;
virtual void OnTick() override
{
if (!Self::GetPed())
return;
auto id = Self::GetPlayer().GetId();
if (PLAYER::IS_SPECIAL_ABILITY_UNLOCKED(Self::GetPed().GetModel()) && !PLAYER::IS_SPECIAL_ABILITY_METER_FULL(id, 0))
PLAYER::SPECIAL_ABILITY_CHARGE_ABSOLUTE(id, 200, true, 0);
}
};
static InfiniteSpecialAbility _InfiniteSpecialAbility{"infspecialability", "Infinite Special Ability", "Ensures that the special ability bar never runs out"};
}
@@ -0,0 +1,79 @@
#include "core/commands/LoopedCommand.hpp"
#include "core/commands/ListCommand.hpp"
#include "game/backend/NativeHooks.hpp"
#include "game/backend/Self.hpp"
#include "game/gta/Natives.hpp"
#include "game/pointers/Pointers.hpp"
#include "types/pad/ControllerInputs.hpp"
namespace YimMenu::Features
{
static void IsControlPressedHook(rage::scrNativeCallContext* ctx);
const std::vector<std::pair<int, const char*>> g_SpecialAbilityTypes = {
{0, "Slipstream"},
{2, "Deadeye"},
{1, "Trevor Rage"},
{3, "Snapshot (Aim at head)"},
{4, "Insult"},
};
static ListCommand _SelectedSpecialAbility{"selspecialability", "Special Ability in MP", "The special ability to enable for the MP character", g_SpecialAbilityTypes, 0};
class MpSpecialAbility : public LoopedCommand
{
using LoopedCommand::LoopedCommand;
virtual void OnEnable() override
{
static auto hooked = []() {
NativeHooks::AddHook("freemode"_J, NativeIndex::IS_CONTROL_PRESSED, &IsControlPressedHook);
return true;
}();
Pointers.AbilityBarPatch->Apply();
if (*Pointers.IsSessionStarted)
{
HUD::SET_ALLOW_ABILITY_BAR(true);
HUD::SET_ABILITY_BAR_VISIBILITY(true);
HUD::FLASH_ABILITY_BAR(2000);
}
}
virtual void OnTick() override
{
if (!Self::GetPed() || !*Pointers.IsSessionStarted)
return;
auto id = Self::GetPlayer().GetId();
if (!PLAYER::IS_SPECIAL_ABILITY_UNLOCKED(0))
PLAYER::SPECIAL_ABILITY_UNLOCK(0, true); // the second parameter enables the cut C&C ability mode
if (!PLAYER::IS_SPECIAL_ABILITY_ACTIVE(id, 0))
PLAYER::SET_SPECIAL_ABILITY_MP(id, _SelectedSpecialAbility.GetState(), 0);
HUD::SET_ALLOW_ABILITY_BAR(true);
HUD::SET_ABILITY_BAR_VISIBILITY(true);
}
virtual void OnDisable() override
{
Pointers.AbilityBarPatch->Restore();
PLAYER::SPECIAL_ABILITY_LOCK(0, true);
HUD::SET_ALLOW_ABILITY_BAR(false);
}
};
static MpSpecialAbility _MpSpecialAbility{"mpspecialability", "Enable Special Abilities in MP", "Enables special abilities in multiplayer. This repurposes cut content and may be unstable"};
void IsControlPressedHook(rage::scrNativeCallContext* ctx)
{
if (_MpSpecialAbility.GetState())
{
auto input = static_cast<ControllerInputs>(ctx->GetArg<int>(1));
if (input == ControllerInputs::INPUT_SPECIAL_ABILITY_PC || input == ControllerInputs::INPUT_SPECIAL_ABILITY || input == ControllerInputs::INPUT_SPECIAL_ABILITY_SECONDARY)
ctx->SetReturnValue(FALSE);
}
return ctx->SetReturnValue(PAD::IS_CONTROL_PRESSED(ctx->GetArg<int>(0), ctx->GetArg<int>(1)));
}
}
+8
View File
@@ -15,6 +15,7 @@ namespace YimMenu::Submenus
auto globalsGroup = std::make_shared<Group>("Globals");
auto movementGroup = std::make_shared<Group>("Movement");
auto toolsGroup = std::make_shared<Group>("Tools", 2);
auto specialAbilityGroup = std::make_shared<Group>("Special Ability");
auto wantedGroup = std::make_shared<Group>("Wanted");
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("godmode"_J));
@@ -57,8 +58,15 @@ namespace YimMenu::Submenus
movementGroup->AddItem(std::make_shared<BoolCommandItem>("freecam"_J));
movementGroup->AddItem(std::make_shared<ConditionalItem>("freecam"_J, std::make_shared<FloatCommandItem>("freecamspeed"_J)));
specialAbilityGroup->AddItem(std::make_shared<BoolCommandItem>("infspecialability"_J));
auto specialInMp = std::make_shared<Group>("", 1);
specialInMp->AddItem(std::make_shared<BoolCommandItem>("mpspecialability"_J, "Enable in MP"));
specialInMp->AddItem(std::make_shared<ConditionalItem>("mpspecialability"_J, std::make_shared<ListCommandItem>("selspecialability"_J, "##specialselect")));
specialAbilityGroup->AddItem(std::move(specialInMp));
main->AddItem(globalsGroup);
main->AddItem(toolsGroup);
main->AddItem(specialAbilityGroup);
main->AddItem(wantedGroup);
main->AddItem(movementGroup);
AddCategory(std::move(main));
+5
View File
@@ -411,6 +411,11 @@ namespace YimMenu
GetAnticheatInitializedHash2 = ptr.Add(0x9).Rip().As<PVOID>();
});
constexpr auto abilityBarPatchPtrn = Pattern<"75 39 48 85 F6 74 1A 48 89 F1 E8">("AbilityBarPatch");
scanner.Add(abilityBarPatchPtrn, [this](PointerCalculator ptr) {
AbilityBarPatch = BytePatches::Add(ptr.As<std::uint16_t*>(), 0x9090);
});
if (!scanner.Scan())
{
LOG(FATAL) << "Some patterns could not be found, unloading.";
+1
View File
@@ -162,6 +162,7 @@ namespace YimMenu
PVOID GetAnticheatInitializedHash;
PVOID GetAnticheatInitializedHash2;
CAnticheatContext** AnticheatContext;
BytePatch AbilityBarPatch;
};
struct Pointers : PointerData