feat: try to implement a kick

This commit is contained in:
maybegreat48 2025-03-29 00:33:35 -04:00
parent eb192e7b4b
commit 6e0df48ce2
11 changed files with 222 additions and 6 deletions

6
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,6 @@
# YimMenu Contribution Guide (WIP)
## Structure
- `core/` : Essential general features for the base
- `game/` : Game specific implemented things

View File

@ -2,8 +2,24 @@
Experimental menu for GTA 5: Enhanced
## Structure
## How to use
- `core/` : Essential general features for the base
- `game/` : Game specific implemented things
- `util/` : Loose functions that aren't game specific
1. Download the latest version of FSL from [here](https://www.unknowncheats.me/forum/grand-theft-auto-v/616977-fsl-local-gtao-saves.html) and place version.dll in your GTA V directory. Using FSL is now optional but highly recommended for account safety
2. Download YimMenuV2 from [GitHub Releases](https://github.com/YimMenu/YimMenuV2/releases/tag/nightly)
3. Download an injector, such as [Xenos](https://www.unknowncheats.me/forum/general-programming-and-reversing/124013-xenos-injector-v2-3-2-a.html)
4. Open Rockstar Launcher, select Grand Theft Auto V Enhanced, go to settings, and disable BattlEye. If you are using Steam or Epic Games, you may have to pass the -nobattleye command line parameter as well
5. Launch GTA V, then use your injector to inject YimMenuV2.dll at the main menu
## Common issues
### I keep getting desynced from public sessions every five minutes
We currently do not have a BattlEye bypass, and legitimate hosts will eventually remove you due to a heartbeat failure. There is currently no way to stop this other than using an actual (private) bypass
### I removed FSL and all my progress disappeared!
FSL reroutes account save data to disk, so any progress made with FSL will only show up if you have FSL enabled. If you don't want this, you can also use YimMenuV2 without FSL, but this is not recommended
### I removed FSL and the game doesn't start up anymore
This is a known issue; delete "Documents/GTAV Enhanced/Profiles" to fix

View File

@ -0,0 +1,22 @@
#include "game/commands/PlayerCommand.hpp"
#include "types/script/globals/GSBD_Kicking.hpp"
#include "game/gta/Scripts.hpp"
namespace YimMenu::Features
{
class ScriptHostKick : public PlayerCommand
{
using PlayerCommand::PlayerCommand;
virtual void OnCall(Player player) override
{
if (auto freemode = Scripts::FindScriptThread("freemode"_J); freemode && Scripts::SafeToModifyFreemodeBroadcastGlobals())
{
Scripts::ForceScriptHost(freemode);
GSBD_Kicking::Get()->KickedPlayers[player.GetId()] = true;
}
}
};
static ScriptHostKick _ScriptHostKick{"shkick", "Script Host Kick", "Kicks the player by faking a vote kick"};
}

View File

@ -3,7 +3,7 @@
namespace YimMenu::Features
{
//from https://github.com/TCRoid/YimMenu-Lua-RS-Missions/
// from https://github.com/TCRoid/YimMenu-Lua-RS-Missions/
class LSCCustomsBypass : public BoolCommand
{
using BoolCommand::BoolCommand;
@ -40,5 +40,5 @@ namespace YimMenu::Features
}
};
static LSCCustomsBypass _LSCCustomsBypass{"lsccustomsbypass", "Remove LSC Restrictions", "Removes Los Santos Customs vehicle modification restrictions", false};
static LSCCustomsBypass _LSCCustomsBypass{"lsccustomsbypass", "Remove LSC Restrictions", "Removes Los Santos Customs vehicle modification restrictions"};
}

View File

@ -0,0 +1,16 @@
#include "Toxic.hpp"
namespace YimMenu::Submenus
{
std::shared_ptr<Category> BuildKickMenu()
{
auto menu = std::make_shared<Category>("Kick");
auto kicks = std::make_shared<Group>("Kicks");
kicks->AddItem(std::make_shared<PlayerCommandItem>("shkick"_J));
menu->AddItem(kicks);
return menu;
}
}

View File

@ -0,0 +1,8 @@
#pragma once
#include "core/frontend/manager/Category.hpp"
#include "game/frontend/items/Items.hpp"
namespace YimMenu::Submenus
{
std::shared_ptr<Category> BuildKickMenu();
}

View File

@ -3,6 +3,7 @@
#include "Player/Info.hpp"
#include "Player/Toxic.hpp"
#include "Player/Troll.hpp"
#include "Player/Kick.hpp"
#include "core/frontend/widgets/imgui_colors.h"
#include "game/backend/PlayerData.hpp"
#include "game/backend/Players.hpp"
@ -118,6 +119,7 @@ namespace YimMenu::Submenus
AddCategory(std::move(BuildInfoMenu()));
AddCategory(std::move(BuildTrollMenu()));
AddCategory(std::move(BuildToxicMenu()));
AddCategory(std::move(BuildKickMenu()));
for (auto& category : m_Categories)
category->PrependItem(std::make_shared<ImGuiItem>([] {

View File

@ -4,8 +4,11 @@
#include "types/rage/tlsContext.hpp"
#include "types/script/GtaThread.hpp"
#include "types/script/CGameScriptHandler.hpp"
#include "types/script/CGameScriptHandlerNetComponent.hpp"
#include "types/script/CGameScriptId.hpp"
#include "types/script/globals/GlobalPlayerBD.hpp"
#include "game/gta/Packet.hpp"
#include "game/backend/Players.hpp"
#include "game/backend/Self.hpp"
namespace YimMenu::Scripts
@ -77,4 +80,26 @@ namespace YimMenu::Scripts
return false;
}
void ForceScriptHost(rage::scrThread* thread)
{
if (auto net_component = reinterpret_cast<GtaThread*>(thread)->m_NetComponent)
{
if (net_component->IsLocalPlayerHost())
return;
net_component->DoHostMigration(Self::GetPlayer().GetHandle(), net_component->m_HostToken + 1, false);
Packet pkt;
pkt.WriteMessageHeader(rage::netMessage::Type::ScriptVerifyHostAck);
net_component->m_ScriptHandler->GetId()->Serialize(&pkt.GetBuffer());
pkt.GetBuffer().Write<bool>(true, 1);
pkt.GetBuffer().Write<bool>(true, 1);
pkt.GetBuffer().Write<std::uint16_t>(net_component->m_HostToken, 16);
for (auto& player : Players::GetPlayers())
if (!player.second.IsLocal())
pkt.Send(player.second.GetMessageId());
}
}
}

View File

@ -13,4 +13,5 @@ namespace YimMenu::Scripts
extern void RunAsScript(rage::scrThread* thread, std::function<void()> callback);
extern void RunWithSpoofedThreadName(std::uint32_t name, std::function<void()> callback); // consider using RunAsScript if possible
extern bool SafeToModifyFreemodeBroadcastGlobals(); // TODO: find a better method for this that works for all scripts
extern void ForceScriptHost(rage::scrThread* thread); // likely unstable, beware!
}

View File

@ -0,0 +1,105 @@
#pragma once
#include "scriptHandlerNetComponent.hpp"
class CNetGamePlayer;
class MsgScriptNewHost;
struct CScriptParticipant
{
CScriptParticipant* m_Next;
CScriptParticipant* m_Prev;
CNetGamePlayer* m_Player;
std::uint16_t m_ParticipantId;
std::uint16_t m_SlotNumber;
int m_JoinTime;
char gap20[8];
};
// TODO: verify if this is correct in Enhanced
class CGameScriptHandlerNetComponent : public rage::scriptHandlerNetComponent
{
public:
virtual ~CGameScriptHandlerNetComponent() override = default;
virtual bool Update() = 0;
virtual void _0x10(CNetGamePlayer*) = 0; // creates a scriptId?
virtual void* PlayerLeft(CNetGamePlayer* player) = 0;
virtual void* SendHostMigrationEvent(CNetGamePlayer* player) = 0;
virtual void PlayerJoined(void**, void* msg_ctx) = 0;
virtual void PlayerJoinedAck(void**, void* msg_ctx) = 0;
virtual void PlayerJoinedHostAck(void*, void*) = 0;
virtual void* _0x40(void*, void*) = 0; // ...
virtual void* _0x48(void*, void*, void*) = 0;
virtual void* _0x50(void*, void*) = 0;
virtual void* _0x58(void*, void*) = 0;
virtual void* _0x60(void*, void*) = 0;
virtual void* _0x68(void*, void*) = 0;
virtual void _0x70(void*, void*) = 0;
virtual void _0x78(void*, void*) = 0;
virtual short _0x80(void*, void*) = 0;
virtual void* _0x88(void*, void*) = 0;
virtual void* _0x90(void*, void*) = 0;
virtual bool _0x98(void*, void*) = 0;
virtual void* _0xA0(void*, void*) = 0;
virtual void* _0xA8(void*, void*) = 0;
virtual short _0xB0(void*, void*) = 0;
virtual bool RegisterHostBroadcastData(void* data, int size, char* a3) = 0;
virtual bool RegisterPlayerBroadcastData(int a1, int size, bool a3) = 0;
virtual bool _0xC8() = 0;
virtual bool _0xD0() = 0;
virtual bool AddPlayerToScript(CNetGamePlayer* player, short* out_participant_id, short* out_slot_number, int* out_fail_reason) = 0;
virtual bool AddPlayerToScriptInternal(CNetGamePlayer* player, short participant_id, short slot_number) = 0;
virtual bool RemovePlayerFromScript(CNetGamePlayer* player) = 0;
virtual void* PlayerLeftImpl(CNetGamePlayer*, bool) = 0;
virtual bool DoHostMigration(CNetGamePlayer* player, short host_token, bool unk) = 0;
virtual void* LeaveFromScript() = 0;
virtual bool _0x108() = 0;
virtual void* _0x110() = 0;
virtual bool _0x118() = 0; // related to above function
int m_State;
int m_AckPendingPlayers;
CScriptParticipant* m_FirstParticipant;
char gap20[16];
CScriptParticipant* m_Host;
std::int16_t m_LocalSlotNumber;
char pad_003A[6];
unsigned int m_ParticipantBitset;
uint16_t m_HostToken;
CNetGamePlayer* m_LastHost;
CNetGamePlayer* m_NextHost;
CNetGamePlayer* m_UnkHost;
char gap60[8];
MsgScriptNewHost* m_QueuedNewHostMessage; // added b3407, queues a host message if a tunable is enabled and verifies it?
CScriptParticipant* m_Participants[32];
char pad_0168[8];
int m_NextHostVerifyTime;
char m_MaxParticipants;
char pad_0175[23];
uint8_t m_NumParticipants;
uint8_t m_NumCandidates;
uint8_t m_HostAckError;
uint8_t m_HostArrayCount;
uint8_t m_PlayerArrayCount;
uint8_t m_HostMigrationState;
std::uint8_t m_Flags;
char pad_0193[13];
char m_ScriptStatusQueried;
inline bool IsLocalPlayerHost() const
{
if (!m_Host)
return true; // or return false?
return m_Host->m_SlotNumber == m_LocalSlotNumber;
}
inline CNetGamePlayer* GetHost() const
{
if (!m_Host)
return nullptr;
return m_Host->m_Player;
}
};
static_assert(sizeof(CGameScriptHandlerNetComponent) == 0x1B0);

View File

@ -0,0 +1,15 @@
#pragma once
namespace rage
{
class scriptHandler;
class scriptHandlerNetComponent
{
public:
virtual ~scriptHandlerNetComponent() = default;
public:
scriptHandler* m_ScriptHandler; // 0x08
};
static_assert(sizeof(scriptHandlerNetComponent) == 0x10);
}