Update for 1.66 (#929)

* feat(crossmap): update thanks @Aure7138

* feat(TSE): updated most hashes

* feat(ScriptEventHandler): Remove abused TSE hashes

* feat(pointers): fix snitl

* fix(pointers): region code

* fix(pointers): handle join request

* fix(pointers): decode session info

* fix(pointers): connect to peer

* fix(pointers): decode peer info

* fix(pointers): add player to session

* fix(pointers): handle join request

* fix(pointers): Is Matchmaking Session Valid

* fix(pointers): send session matchmaking attributes

* fix(pointers): process matchmaking find response

* fix(pointers): serialize join request message

* fix(TSE): updated lost few, thanks @Rimmuru

* fix(Menu): update menu (#930)

* fix(globals): mechanic global

* feat(meta): bump version

* feat(spoofing): remove patched stuff

* fix(self): off radar timer offset

* fix(overlay): retain last position

* feat(self): commented dance mode

* feat(spoofing): add note about spoofing not working

Co-authored-by: maybegreat48 <96936658+maybegreat48@users.noreply.github.com>
This commit is contained in:
Yimura 2023-02-04 00:00:56 +01:00 committed by GitHub
parent 9cb030f502
commit c75a17256e
30 changed files with 6601 additions and 6731 deletions

View File

@ -1,6 +1,6 @@
{ {
"game": { "game": {
"online": "1.64", "online": "1.66",
"build": "2802" "build": "2824"
} }
} }

View File

@ -3,7 +3,7 @@ include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
gtav_classes gtav_classes
GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git
GIT_TAG c6eb3c8c1253b5d9822a79feda7bdc61875cd47c GIT_TAG f155790d38c131f4df0933283a577423e0ddd2da
GIT_PROGRESS TRUE GIT_PROGRESS TRUE
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
BUILD_COMMAND "" BUILD_COMMAND ""

View File

@ -11,7 +11,7 @@ namespace big
virtual void on_tick() override virtual void on_tick() override
{ {
*scr_globals::globalplayer_bd.at(PLAYER::GET_PLAYER_INDEX(), scr_globals::size::globalplayer_bd).at(210).as<int*>() = true; *scr_globals::globalplayer_bd.at(PLAYER::GET_PLAYER_INDEX(), scr_globals::size::globalplayer_bd).at(210).as<int*>() = true;
*script_global(2672505).at(56).as<int*>() = NETWORK::GET_NETWORK_TIME() + 1; *script_global(2672505).at(57).as<int*>() = NETWORK::GET_NETWORK_TIME() + 1;
} }
virtual void on_disable() override virtual void on_disable() override

View File

@ -1,5 +1,6 @@
#include "natives.hpp" #include "natives.hpp"
#include "backend/looped_command.hpp" #include "backend/looped_command.hpp"
#include <ped/CPedIntelligence.hpp>
namespace big namespace big
{ {
@ -9,8 +10,8 @@ namespace big
virtual void on_tick() override virtual void on_tick() override
{ {
if (g_local_player) //if (g_local_player)
g_local_player->m_oxygen_info->m_oxygen_time = 0; // g_local_player->m_ped_intelligence->m_oxygen_time = 0;
} }
}; };

View File

@ -29,15 +29,5 @@ namespace big
bLastForceHost = g.session.force_session_host; bLastForceHost = g.session.force_session_host;
} }
if (g.spoofing.rockstar_id != g.spoofing.applied_spoof_rockstar_id && gta_util::get_network()->m_game_session_state == 0)
{
g.spoofing.applied_spoof_rockstar_id = g.spoofing.rockstar_id;
}
if (g.spoofing.spoof_rockstar_id != g.spoofing.should_spoof_rockstar_id && gta_util::get_network()->m_game_session_state == 0)
{
g.spoofing.should_spoof_rockstar_id = g.spoofing.spoof_rockstar_id;
}
} }
} }

View File

@ -83,11 +83,6 @@ namespace big
} }
} }
if (stricmp(g_player_service->get_self()->get_name(), args[0].c_str()) == 0 || (g.spoofing.spoof_username && stricmp(g.spoofing.username.c_str(), args[0].c_str()) == 0))
{
plyr_id = g_player_service->get_self()->id();
}
if (ctx->get_access_level() != CommandAccessLevel::ADMIN && (get_access_level() == CommandAccessLevel::TOXIC || get_access_level() == CommandAccessLevel::AGGRESSIVE) && plyr_id == self::id) if (ctx->get_access_level() != CommandAccessLevel::ADMIN && (get_access_level() == CommandAccessLevel::TOXIC || get_access_level() == CommandAccessLevel::AGGRESSIVE) && plyr_id == self::id)
{ {
ctx->report_error("Permission denied, cannot call toxic commands on me"); ctx->report_error("Permission denied, cannot call toxic commands on me");

View File

@ -151,54 +151,51 @@ namespace big
enum class eRemoteEvent enum class eRemoteEvent
{ {
Bounty = 1370461707, // (137, "FM_TXT_BNTY0", iVar1, PLAYER::GET_PLAYER_NAME(Var2.f_1), "", 5000, Var2.f_6); Bounty = 1459520933, // (137, "FM_TXT_BNTY0", iVar1, PLAYER::GET_PLAYER_NAME(Var2.f_1), "", 5000, Var2.f_6);
CeoBan = 316066012, // mpply_vipgameplaydisabledtimer CeoBan = 1517094008, // mpply_vipgameplaydisabledtimer
CeoKick = 265836764, CeoKick = 1421455565,
CeoMoney = 245065909, // Goon_Paid_Large CeoMoney = 75579707, // Goon_Paid_Large
ClearWantedLevel = 2080651008, ClearWantedLevel = 1743540940,
ForceMission = 1858712297, // ), Var0.f_2, 1)) ForceMission = -2138393348, // ), Var0.f_2, 1))
GiveCollectible = 697566862, // DLC_SUM20_HIDDEN_COLLECTIBLES xref GiveCollectible = 1839167950, // DLC_SUM20_HIDDEN_COLLECTIBLES xref
GtaBanner = -795380017, // NETWORK::NETWORK_IS_SCRIPT_ACTIVE("BUSINESS_BATTLES", -1, true, 0) second one GtaBanner = 2114252738, // NETWORK::NETWORK_IS_SCRIPT_ACTIVE("BUSINESS_BATTLES", -1, true, 0) second one
NetworkBail = 915462795, // NETWORK::NETWORK_BAIL(16, 0, 0); xref func NetworkBail = 1017995959, // NETWORK::NETWORK_BAIL(16, 0, 0); xref func
PersonalVehicleDestroyed = -964882004, // PLYVEH_INS_DES1 PersonalVehicleDestroyed = -642631978, // PLYVEH_INS_DES1
RemoteOffradar = -162943635, // NETWORK::GET_TIME_DIFFERENCE(NETWORK::GET_NETWORK_TIME(), Var0.f_2) RemoteOffradar = 1141648445, // NETWORK::GET_TIME_DIFFERENCE(NETWORK::GET_NETWORK_TIME(), Var0.f_2)
SendToCutscene = 392606458, // (bVar3, bVar4, 125f, 1) SendToCutscene = 2139870214, // (bVar3, bVar4, 125f, 1)
SendToCayoPerico = -910497748, // CELL_HI_INV SendToCayoPerico = -369672308, // CELL_HI_INV
SendToLocation = -93722397, // &Var222, 11); SendToLocation = 330622597, // &Var222, 11);
SoundSpam = -1891171016, // CELL_APTINVYACHT SoundSpam = 36077543, // CELL_APTINVYACHT
Spectate = -1903870031, // SPEC_TCK1 Spectate = -2029707091, // SPEC_TCK1
Teleport = -168599209, // Mission_Pass_Notify Teleport = -702866045, // Mission_Pass_Notify
TeleportToWarehouse = 434937615, // .f_4 == 50 TeleportToWarehouse = -1796714618, // .f_4 == 50
TransactionError = -492741651, // NETWORK_RECEIVE_PLAYER_JOBSHARE_CASH TransactionError = 54323524, // NETWORK_RECEIVE_PLAYER_JOBSHARE_CASH
VehicleKick = -852914485, // PIM_RFMOC VehicleKick = -1603050746, // PIM_RFMOC
MCTeleport = 879177392, // NETWORK::NETWORK_HASH_FROM_PLAYER_HANDLE(PLAYER::PLAYER_ID()) == (first one) MCTeleport = 891653640, // NETWORK::NETWORK_HASH_FROM_PLAYER_HANDLE(PLAYER::PLAYER_ID()) == (first one)
StartActivity = 243072129, // (Var0.f_2, -1); first match StartActivity = 1104117595, // (Var0.f_2, -1); first match
MarkPlayerAsBeast = -2001677186, // GB_BOSSBST xref == PLAYER... global (sadly doesn't actually turn people into the beast) MarkPlayerAsBeast = -1721728321, // GB_BOSSBST xref == PLAYER... global (sadly doesn't actually turn people into the beast)
KickFromInterior = 1454834612, // ENTITY::SET_ENTITY_HEALTH(PLAYER::PLAYER_PED_ID(), PED::GET_PED_MAX_HEALTH(PLAYER::PLAYER_PED_ID()), false) KickFromInterior = 786522321, // ENTITY::SET_ENTITY_HEALTH(PLAYER::PLAYER_PED_ID(), PED::GET_PED_MAX_HEALTH(PLAYER::PLAYER_PED_ID()), false)
InteriorControl = 1268038438, // eventData.f_3 != _INVALID_PLAYER_INDEX_0() InteriorControl = 1727896103, // eventData.f_3 != _INVALID_PLAYER_INDEX_0()
SMS = 1519903406, SMS = 53975141,
SendTextLabelSMS = -1387723751, SendTextLabelSMS = 1075676399,
Crash = -904555865, // SET_NO_LOADING_SCREEN, xref it Crash = -992162568, // SET_NO_LOADING_SCREEN, xref it
Crash2 = 1775863255, Crash2 = 1131623211,
Crash3 = 2067191610, Crash3 = 1556360603,
TSECommand = 113023613, // CnCTG_IN_BF TSECommand = -1428749433, // CnCTG_IN_BF
TSECommandRotateCam = 0x69979fea /*joaat("pats_horse_right") in script*/, // != 29) && f TSECommandRotateCam = 448051697 /*joaat("pats_horse_right") in script*/, // != 29) && f
Notification = 548471420, Notification = 2041805809,
NotificationMoneyBanked = -1032040118, // TICK_TC_BANK NotificationMoneyBanked = 276906331, // TICK_TC_BANK
NotificationMoneyRemoved = -1197151915, // TICK_TC_REMO NotificationMoneyRemoved = 853249803, // TICK_TC_REMO
NotificationMoneyStolen = -28878294, // TICK_TC_STOL NotificationMoneyStolen = 82080686, // TICK_TC_STOL
DestroyPersonalVehicle = -513394492, // CnC_PV_THEFT DestroyPersonalVehicle = -2101545224, // CnC_PV_THEFT
TriggerCEORaid = -1322731185, TriggerCEORaid = -1388385133,
StartScriptBegin = -1127353498, StartScriptBegin = -95341040,
StartScriptProceed = -16793987, StartScriptProceed = 1742713914
BadThing1 = 1279059857,
BadThing2 = -343495611
}; };
enum class eCollectibleType enum class eCollectibleType

View File

@ -459,25 +459,11 @@ namespace big
struct spoofing struct spoofing
{ {
bool spoof_username = false;
bool spoof_local_username = false;
std::string username = "";
// enabling this by default causes confusion and many get dropped out of their sessions
bool spoof_ip = false;
std::array<int, 4> ip_address = { 42, 42, 42, 42 };
bool spoof_rockstar_id = false;
uint64_t rockstar_id = 0;
bool spoof_cheater = false; bool spoof_cheater = false;
bool spoof_hide_god = true; bool spoof_hide_god = true;
bool spoof_hide_spectate = true; bool spoof_hide_spectate = true;
bool spoof_rockstar_dev = false;
bool spoof_rockstar_qa = false;
bool spoof_crew_data = false; bool spoof_crew_data = false;
std::string crew_tag = ""; std::string crew_tag = "";
bool rockstar_crew = false; bool rockstar_crew = false;
@ -490,14 +476,9 @@ namespace big
bool spoof_session_player_count = false; bool spoof_session_player_count = false;
int session_player_count = 25; int session_player_count = 25;
// don't save
bool should_spoof_rockstar_id = false;
uint64_t applied_spoof_rockstar_id = 0;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(spoofing, NLOHMANN_DEFINE_TYPE_INTRUSIVE(spoofing,
spoof_username, spoof_local_username, username, spoof_ip, ip_address, spoof_rockstar_id, rockstar_id, spoof_cheater, spoof_hide_god, spoof_hide_spectate, spoof_crew_data, crew_tag, rockstar_crew,
spoof_cheater, spoof_hide_god, spoof_hide_spectate, spoof_rockstar_dev, spoof_rockstar_qa, spoof_crew_data, square_crew_tag, spoof_session_region_type, session_region_type, spoof_session_language,
crew_tag, rockstar_crew, square_crew_tag, spoof_session_region_type, session_region_type, spoof_session_language,
session_language, spoof_session_player_count, session_player_count) session_language, spoof_session_player_count, session_player_count)
} spoofing{}; } spoofing{};

View File

@ -35,7 +35,7 @@ namespace big::scr_globals
static inline script_global transition_state(1574993); static inline script_global transition_state(1574993);
static inline script_global vehicle_global = script_global(1586468); static inline script_global vehicle_global = script_global(1586468);
static inline script_global mechanic_global = script_global(2793044); static inline script_global mechanic_global = script_global(2793046);
static inline script_global spawn_global = script_global(2694560); static inline script_global spawn_global = script_global(2694560);
} }

File diff suppressed because it is too large Load Diff

View File

@ -403,12 +403,12 @@ namespace rage
uint32_t m_connection_identifier; //0x0044 uint32_t m_connection_identifier; //0x0044
InFrame* m_this; //0x0048 InFrame* m_this; //0x0048
uint32_t m_peer_id; //0x0050 uint32_t m_peer_id; //0x0050
char pad_0050[36]; //0x0058 char pad_0050[44]; //0x0058
uint32_t m_length; //0x0078 uint32_t m_length; //0x0080
char pad_007C[4]; //0x007C char pad_007C[4]; //0x0084
void* m_data; //0x0080 void* m_data; //0x0088
}; };
static_assert(sizeof(rage::netConnection::InFrame) == 0x88); static_assert(sizeof(rage::netConnection::InFrame) == 0x90);
} }
enum class eEventNetworkType : int64_t enum class eEventNetworkType : int64_t

View File

@ -46,8 +46,6 @@ namespace big
detour_hook_helper::add<hooks::received_event>("RE", g_pointers->m_received_event); detour_hook_helper::add<hooks::received_event>("RE", g_pointers->m_received_event);
detour_hook_helper::add<hooks::send_net_info_to_lobby>("SNITL", g_pointers->m_send_net_info_to_lobby);
detour_hook_helper::add<hooks::assign_physical_index>("API", g_pointers->m_assign_physical_index); detour_hook_helper::add<hooks::assign_physical_index>("API", g_pointers->m_assign_physical_index);
detour_hook_helper::add<hooks::receive_net_message>("RNM", g_pointers->m_receive_net_message); detour_hook_helper::add<hooks::receive_net_message>("RNM", g_pointers->m_receive_net_message);
@ -93,9 +91,6 @@ namespace big
detour_hook_helper::add<hooks::create_script_handler>("CSH", g_pointers->m_create_script_handler); detour_hook_helper::add<hooks::create_script_handler>("CSH", g_pointers->m_create_script_handler);
detour_hook_helper::add<hooks::write_bitbuffer_gamer_handle>("WBGH", g_pointers->m_write_bitbuffer_gamer_handle);
detour_hook_helper::add<hooks::read_bitbuffer_gamer_handle>("RBGH", g_pointers->m_read_bitbuffer_gamer_handle);
detour_hook_helper::add<hooks::queue_dependency>("QD", g_pointers->m_queue_dependency); detour_hook_helper::add<hooks::queue_dependency>("QD", g_pointers->m_queue_dependency);
detour_hook_helper::add<hooks::prepare_metric_for_sending>("PMFS", g_pointers->m_prepare_metric_for_sending); detour_hook_helper::add<hooks::prepare_metric_for_sending>("PMFS", g_pointers->m_prepare_metric_for_sending);

View File

@ -85,7 +85,6 @@ namespace big
static bool increment_stat_event(CNetworkIncrementStatEvent* net_event_struct, CNetGamePlayer* sender); static bool increment_stat_event(CNetworkIncrementStatEvent* net_event_struct, CNetGamePlayer* sender);
static bool scripted_game_event(CScriptedGameEvent* scripted_game_event, CNetGamePlayer* player); static bool scripted_game_event(CScriptedGameEvent* scripted_game_event, CNetGamePlayer* player);
static bool send_net_info_to_lobby(rage::rlGamerInfo *player, int64_t a2, int64_t a3, DWORD* a4);
static bool receive_net_message(void* netConnectionManager, void* a2, rage::netConnection::InFrame* frame); static bool receive_net_message(void* netConnectionManager, void* a2, rage::netConnection::InFrame* frame);
static void get_network_event_data(int64_t unk, rage::CEventNetwork* net_event); static void get_network_event_data(int64_t unk, rage::CEventNetwork* net_event);

View File

@ -23,11 +23,11 @@ namespace big
if (damage_data.m_weapon_used == RAGE_JOAAT("weapon_explosion")) if (damage_data.m_weapon_used == RAGE_JOAAT("weapon_explosion"))
break; break;
if (auto damager = g_pointers->m_handle_to_ptr(damage_data.m_damager_index); damager && damager->gap28 == 4 && reinterpret_cast<CPed*>(damager)->m_player_info) if (auto damager = g_pointers->m_handle_to_ptr(damage_data.m_damager_index); damager && damager->m_entity_type == 4 && reinterpret_cast<CPed*>(damager)->m_player_info)
{ {
if (auto player = g_player_service->get_by_host_token(reinterpret_cast<CPed*>(damager)->m_player_info->m_net_player_data.m_host_token)) if (auto player = g_player_service->get_by_host_token(reinterpret_cast<CPed*>(damager)->m_player_info->m_net_player_data.m_host_token))
{ {
if (auto victim = g_pointers->m_handle_to_ptr(damage_data.m_victim_index); victim && victim->gap28 == 4 && reinterpret_cast<CPed*>(victim)->m_player_info) if (auto victim = g_pointers->m_handle_to_ptr(damage_data.m_victim_index); victim && victim->m_entity_type == 4 && reinterpret_cast<CPed*>(victim)->m_player_info)
{ {
if (reinterpret_cast<CPed*>(damager)->m_damage_bits & (1 << 8)) if (reinterpret_cast<CPed*>(damager)->m_damage_bits & (1 << 8))
{ {

View File

@ -58,18 +58,21 @@ namespace big
{ {
if (auto plyr = g_player_service->get_by_id(id)) if (auto plyr = g_player_service->get_by_id(id))
{ {
if (auto entry = g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle_2.m_rockstar_id)) if (plyr->get_net_data()->m_gamer_handle_2.m_rockstar_id != 0)
{ {
plyr->is_modder = entry->is_modder; if (auto entry = g_player_database_service->get_player_by_rockstar_id(plyr->get_net_data()->m_gamer_handle_2.m_rockstar_id))
plyr->block_join = entry->block_join;
plyr->block_join_reason = plyr->block_join_reason;
if (strcmp(plyr->get_name(), entry->name.data()))
{ {
g_notification_service->push("PLAYERS"_T.data(), plyr->is_modder = entry->is_modder;
std::vformat("PLAYER_CHANGED_NAME"_T, std::make_format_args(entry->name, plyr->get_name()))); plyr->block_join = entry->block_join;
entry->name = plyr->get_name(); plyr->block_join_reason = plyr->block_join_reason;
g_player_database_service->save();
if (strcmp(plyr->get_name(), entry->name.data()))
{
g_notification_service->push("PLAYERS"_T.data(),
std::vformat("PLAYER_CHANGED_NAME"_T, std::make_format_args(entry->name, plyr->get_name())));
entry->name = plyr->get_name();
g_player_database_service->save();
}
} }
} }

View File

@ -1,13 +1,10 @@
#include "hooking.hpp" #include "hooking.hpp"
#include "memory/byte_patch.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
#include <network/CNetworkPlayerMgr.hpp> #include <network/CNetworkPlayerMgr.hpp>
namespace big namespace big
{ {
static memory::byte_patch* local_name_patch{};
void hooks::network_player_mgr_init(CNetworkPlayerMgr* _this, std::uint64_t a2, std::uint32_t a3, std::uint32_t a4[4]) void hooks::network_player_mgr_init(CNetworkPlayerMgr* _this, std::uint64_t a2, std::uint32_t a3, std::uint32_t a4[4])
{ {
if (g.notifications.network_player_mgr_init.log) if (g.notifications.network_player_mgr_init.log)
@ -15,15 +12,6 @@ namespace big
if (g.notifications.network_player_mgr_init.notify) if (g.notifications.network_player_mgr_init.notify)
g_notification_service->push("NETWORK_PLAYER_MGR"_T.data(), "NETWORK_PLAYER_MGR_INIT"_T.data()); g_notification_service->push("NETWORK_PLAYER_MGR"_T.data(), "NETWORK_PLAYER_MGR_INIT"_T.data());
// set our local spoofed name
if (g.spoofing.spoof_username && g.spoofing.spoof_local_username)
{
std::array<char, 17> local_name;
std::copy(g.spoofing.username.begin(), g.spoofing.username.end(), local_name.data());
local_name_patch = memory::byte_patch::make(g_pointers->m_chat_gamer_info->m_name, local_name).get();
local_name_patch->apply();
}
g_hooking->get_original<hooks::network_player_mgr_init>()(_this, a2, a3, a4); g_hooking->get_original<hooks::network_player_mgr_init>()(_this, a2, a3, a4);
g_player_service->player_join(_this->m_local_net_player); g_player_service->player_join(_this->m_local_net_player);
@ -34,12 +22,6 @@ namespace big
g.m_spoofed_peer_ids.clear(); g.m_spoofed_peer_ids.clear();
g_player_service->do_cleanup(); g_player_service->do_cleanup();
// restore our original name
if (strcmp(g_pointers->m_chat_gamer_info->m_name, _this->m_local_net_player->get_name()) && local_name_patch)
{
local_name_patch->remove();
}
if (g.notifications.network_player_mgr_shutdown.log) if (g.notifications.network_player_mgr_shutdown.log)
LOG(INFO) << "CNetworkPlayerMgr#shutdown got called, we're probably leaving our session."; LOG(INFO) << "CNetworkPlayerMgr#shutdown got called, we're probably leaving our session.";
if (g.notifications.network_player_mgr_shutdown.notify) if (g.notifications.network_player_mgr_shutdown.notify)

View File

@ -72,7 +72,10 @@ namespace big
if (frame->get_event_type() != rage::netConnection::InFrame::EventType::FrameReceived) if (frame->get_event_type() != rage::netConnection::InFrame::EventType::FrameReceived)
return g_hooking->get_original<hooks::receive_net_message>()(netConnectionManager, a2, frame); return g_hooking->get_original<hooks::receive_net_message>()(netConnectionManager, a2, frame);
rage::datBitBuffer buffer((uint8_t*)frame->m_data, frame->m_length); if (frame->m_data == nullptr || frame->m_length == 0)
return g_hooking->get_original<hooks::receive_net_message>()(netConnectionManager, a2, frame);
rage::datBitBuffer buffer(frame->m_data, frame->m_length);
buffer.m_flagBits = 1; buffer.m_flagBits = 1;
rage::eNetMessage msgType; rage::eNetMessage msgType;
@ -250,6 +253,7 @@ namespace big
} }
case rage::eNetMessage::MsgSessionEstablished: case rage::eNetMessage::MsgSessionEstablished:
{ {
#if 0
rage::rlGamerHandle handle{ 0 }; rage::rlGamerHandle handle{ 0 };
if (player->get_net_data()) if (player->get_net_data())
{ {
@ -264,6 +268,7 @@ namespace big
} }
} }
} }
#endif
break; break;
} }
case rage::eNetMessage::MsgNetComplaint: case rage::eNetMessage::MsgNetComplaint:

View File

@ -307,7 +307,7 @@ namespace big
auto offset_object = g_pointers->m_get_net_object(*g_pointers->m_network_object_mgr, f210, true); auto offset_object = g_pointers->m_get_net_object(*g_pointers->m_network_object_mgr, f210, true);
if (f208 == 0 && entity && entity->gap28 == 4 && reinterpret_cast<CPed*>(entity)->m_player_info && player->m_player_info->m_ped && player->m_player_info->m_ped->m_net_object && ownerNetId != player->m_player_info->m_ped->m_net_object->m_object_id && !offset_object) if (f208 == 0 && entity && entity->m_entity_type == 4 && reinterpret_cast<CPed*>(entity)->m_player_info && player->m_player_info->m_ped && player->m_player_info->m_ped->m_net_object && ownerNetId != player->m_player_info->m_ped->m_net_object->m_object_id && !offset_object)
{ {
g_notification_service->push_error("WARNING"_T.data(), g_notification_service->push_error("WARNING"_T.data(),
std::vformat("BLAMED_FOR_EXPLOSION"_T, std::make_format_args(player->get_name(), reinterpret_cast<CPed*>(entity)->m_player_info->m_net_player_data.m_name))); std::vformat("BLAMED_FOR_EXPLOSION"_T, std::make_format_args(player->get_name(), reinterpret_cast<CPed*>(entity)->m_player_info->m_net_player_data.m_name)));

View File

@ -367,9 +367,6 @@ namespace big
return true; return true;
} }
case eRemoteEvent::BadThing1:
case eRemoteEvent::BadThing2:
return true;
case eRemoteEvent::StartScriptBegin: case eRemoteEvent::StartScriptBegin:
{ {
g.reactions.start_script.process(plyr); g.reactions.start_script.process(plyr);

View File

@ -1,14 +0,0 @@
#include "hooking.hpp"
#include "network/Network.hpp"
#include "pointers.hpp"
namespace big
{
bool hooks::read_bitbuffer_gamer_handle(rage::datBitBuffer* buffer, rage::rlGamerHandle* handle)
{
bool result = g_hooking->get_original<hooks::read_bitbuffer_gamer_handle>()(buffer, handle);
if (g.spoofing.should_spoof_rockstar_id && handle->m_rockstar_id == g.spoofing.applied_spoof_rockstar_id)
handle->m_rockstar_id = g_pointers->m_profile_gamer_info->m_gamer_handle_2.m_rockstar_id;
return result;
}
}

View File

@ -1,64 +0,0 @@
#include "hooking.hpp"
#include "pointers.hpp"
constexpr static auto advertisments = std::to_array(
{
"~h~~r~YimMenu",
"~h~~g~YimMenu",
"~h~~b~YimMenu",
"~h~~y~YimMenu",
"~h~~o~YimMenu",
"~h~~p~YimMenu"
});
namespace big
{
bool hooks::send_net_info_to_lobby(rage::rlGamerInfo* player, int64_t a2, int64_t a3, DWORD* a4)
{
const bool is_local_player = g_local_player->m_player_info->m_net_player_data.m_gamer_handle_2.m_rockstar_id == player->m_gamer_handle_2.m_rockstar_id;
// check so we're 100% sure we modify data only for ourselves
if (is_local_player)
{
if (g.spoofing.spoof_username)
{
memcpy(player->m_name, g.spoofing.username.c_str(), sizeof(player->m_name));
}
if (g.spoofing.spoof_ip)
{
player->m_external_ip.m_field1 = g.spoofing.ip_address[0];
player->m_external_ip.m_field2 = g.spoofing.ip_address[1];
player->m_external_ip.m_field3 = g.spoofing.ip_address[2];
player->m_external_ip.m_field4 = g.spoofing.ip_address[3];
}
if (g.spoofing.should_spoof_rockstar_id)
{
player->m_gamer_handle.m_rockstar_id = g.spoofing.applied_spoof_rockstar_id;
player->m_gamer_handle_2.m_rockstar_id = g.spoofing.applied_spoof_rockstar_id;
}
if (g.notifications.send_net_info_to_lobby.log)
LOG(INFO) << "Sending spoofed values to session host";
if (g.notifications.send_net_info_to_lobby.notify)
g_notification_service->push("Player Info Spoofing", "Sent spoofed values to lobby host.");
}
else
{
if (g.session.name_spoof_enabled)
{
if (g.session.advertise_menu)
{
memcpy(player->m_name, advertisments[rand() % advertisments.size()], sizeof(player->m_name));
}
else
{
memcpy(player->m_name, g.session.spoofed_name.c_str(), sizeof(player->m_name));
}
}
}
return g_hooking->get_original<hooks::send_net_info_to_lobby>()(player, a2, a3, a4);
}
}

View File

@ -1,23 +0,0 @@
#include "hooking.hpp"
#include "network/Network.hpp"
#include "pointers.hpp"
namespace big
{
bool hooks::write_bitbuffer_gamer_handle(rage::datBitBuffer* buffer, rage::rlGamerHandle* handle)
{
bool restore = false;
if (g.spoofing.should_spoof_rockstar_id && handle->m_rockstar_id == g_pointers->m_profile_gamer_info->m_gamer_handle_2.m_rockstar_id)
{
handle->m_rockstar_id = g.spoofing.applied_spoof_rockstar_id;
restore = true;
}
bool result = g_hooking->get_original<hooks::write_bitbuffer_gamer_handle>()(buffer, handle);
if (restore)
handle->m_rockstar_id = g_pointers->m_profile_gamer_info->m_gamer_handle_2.m_rockstar_id;
return result;
}
}

View File

@ -29,10 +29,10 @@ namespace big
node->m_is_cheater = g.spoofing.spoof_cheater; node->m_is_cheater = g.spoofing.spoof_cheater;
// spoof r* dev and qa only when spoofing rid because every player in the session will send metrics if you join with that enabled // spoof r* dev and qa only when spoofing rid because every player in the session will send metrics if you join with that enabled
if (g.spoofing.spoof_rockstar_id) /*if (g.spoofing.spoof_rockstar_id)
{ {
node->m_is_rockstar_dev = g.spoofing.spoof_rockstar_dev; node->m_is_rockstar_dev = g.spoofing.spoof_rockstar_dev;
node->m_is_rockstar_qa = g.spoofing.spoof_rockstar_qa; node->m_is_rockstar_qa = g.spoofing.spoof_rockstar_qa;
} }*/
} }
} }

View File

@ -10,20 +10,6 @@ namespace big
{ {
namespace all_scripts namespace all_scripts
{ {
void GET_PLAYER_NAME(rage::scrNativeCallContext* src)
{
const auto playerId = src->get_arg<Player>(0);
src->set_return_value(PLAYER::GET_PLAYER_NAME(playerId));
if (g.spoofing.spoof_username && g.spoofing.spoof_local_username)
{
const auto network_player_mgr = gta_util::get_network_player_mgr();
if (network_player_mgr && network_player_mgr->m_local_net_player && playerId == network_player_mgr->m_local_net_player->m_player_id)
{
src->set_return_value(g.spoofing.username.c_str());
}
}
}
void IS_DLC_PRESENT(rage::scrNativeCallContext* src) void IS_DLC_PRESENT(rage::scrNativeCallContext* src)
{ {
const auto hash = src->get_arg<rage::joaat_t>(0); const auto hash = src->get_arg<rage::joaat_t>(0);

View File

@ -103,7 +103,6 @@ namespace big
native_hooks::native_hooks() native_hooks::native_hooks()
{ {
add_native_detour(0x6D0DE6A7B5DA71F8, all_scripts::GET_PLAYER_NAME);
add_native_detour(0x812595A0644CE1DE, all_scripts::IS_DLC_PRESENT); add_native_detour(0x812595A0644CE1DE, all_scripts::IS_DLC_PRESENT);
add_native_detour(0x1CA59E306ECB80A5, all_scripts::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT); add_native_detour(0x1CA59E306ECB80A5, all_scripts::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT);
add_native_detour(0xD1110739EEADB592, all_scripts::NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT); add_native_detour(0xD1110739EEADB592, all_scripts::NETWORK_TRY_TO_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT);

View File

@ -20,9 +20,10 @@ namespace big
m_resolution_y = ptr.add(4).rip().as<int*>(); m_resolution_y = ptr.add(4).rip().as<int*>();
}); });
main_batch.add("RC", "40 32 ED 83 25", [this](memory::handle ptr) // Region Code
main_batch.add("RC", "48 83 EC 28 83 3D ? ? ? ? ? 75 10", [this](memory::handle ptr)
{ {
m_region_code = ptr.add(5).rip().add(1).as<uint32_t*>(); m_region_code = ptr.add(16).rip().add(1).as<uint32_t*>();
}); });
// Max Wanted Level // Max Wanted Level
@ -242,12 +243,6 @@ namespace big
m_blame_explode = memory::byte_patch::make(ptr.as<std::uint16_t*>(), 0xE990).get(); m_blame_explode = memory::byte_patch::make(ptr.as<std::uint16_t*>(), 0xE990).get();
}); });
// Send NET Info to Lobby
main_batch.add("SNITL", "33 DB 48 83 C1 68 45 8B F0", [this](memory::handle ptr)
{
m_send_net_info_to_lobby = ptr.sub(0x26).as<decltype(m_send_net_info_to_lobby)>();
});
// CNetworkObjectMgr // CNetworkObjectMgr
main_batch.add("CNOM", "48 8B 0D ? ? ? ? 45 33 C0 E8 ? ? ? ? 33 FF 4C 8B F0", [this](memory::handle ptr) main_batch.add("CNOM", "48 8B 0D ? ? ? ? 45 33 C0 E8 ? ? ? ? 33 FF 4C 8B F0", [this](memory::handle ptr)
{ {
@ -519,13 +514,13 @@ namespace big
}); });
// Handle Join Request // Handle Join Request
main_batch.add("HJR", "48 8B C4 4C 89 48 20 4C 89 40 18 48 89 50 10 55 53 56 57 41 54 41 55 41 56 41 57 48 8D A8 E8 FE", [this](memory::handle ptr) main_batch.add("HJR", "48 8B C4 48 89 58 08 4C 89 48 20 4C 89 40 18 48 89 50 10 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 E8", [this](memory::handle ptr)
{ {
m_handle_join_request = ptr.as<PVOID>(); m_handle_join_request = ptr.as<PVOID>();
}); });
// Handle Join Request // Handle Join Request
main_batch.add("WJRD", "E8 ? ? ? ? 48 8D 8D 90 00 00 00 F6 D8", [this](memory::handle ptr) main_batch.add("HJR", "E8 ?? ?? ?? ?? 41 8B DF 84 C0 74 06", [this](memory::handle ptr)
{ {
m_write_join_response_data = ptr.add(1).rip().as<functions::write_join_response_data>(); m_write_join_response_data = ptr.add(1).rip().as<functions::write_join_response_data>();
}); });
@ -543,7 +538,7 @@ namespace big
}); });
// Add Player To Session // Add Player To Session
main_batch.add("APTS", "E8 ? ? ? ? 48 8D 8D A0 01 00 00 8A D8", [this](memory::handle ptr) main_batch.add("APTS", "E8 ?? ?? ?? ?? 48 8D 8D F0 01 00 00 8A D8", [this](memory::handle ptr)
{ {
m_add_player_to_session = ptr.add(1).rip().as<PVOID>(); m_add_player_to_session = ptr.add(1).rip().as<PVOID>();
}); });
@ -555,7 +550,7 @@ namespace big
}); });
// Process Matchmaking Find Response // Process Matchmaking Find Response
main_batch.add("PMFR", "48 89 5C 24 08 48 89 74 24 10 57 48 81 EC 90 00 00 00 41", [this](memory::handle ptr) main_batch.add("PMFR", "48 89 5C 24 08 48 89 74 24 10 57 48 81 EC F0 00 00 00 41 83", [this](memory::handle ptr)
{ {
m_process_matchmaking_find_response = ptr.as<PVOID>(); m_process_matchmaking_find_response = ptr.as<PVOID>();
}); });
@ -567,15 +562,15 @@ namespace big
}); });
// Serialize Join Request Message // Serialize Join Request Message
main_batch.add("SPDM", "E8 ? ? ? ? 84 C0 0F 84 99 00 00 00 49 8D 8F 78 0D 00 00", [this](memory::handle ptr) main_batch.add("SJRM", "E8 ?? ?? ?? ?? 84 C0 0F 84 9B 00 00 00 49 8D 8F 50 11 00 00", [this](memory::handle ptr)
{ {
m_serialize_join_request_message = ptr.add(1).rip().as<PVOID>(); m_serialize_join_request_message = ptr.add(1).rip().as<PVOID>();
}); });
// Is Matchmaking Session Valid // Is Matchmaking Session Valid
main_batch.add("IMSV", "E8 ? ? ? ? 48 81 C7 B8 03 00 00 88 03", [this](memory::handle ptr) main_batch.add("IMSV", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 20 45 0F", [this](memory::handle ptr)
{ {
memory::byte_patch::make(ptr.add(1).rip().as<void*>(), std::to_array({ 0xB0, 0x01, 0xC3 }))->apply(); // has no observable side effects memory::byte_patch::make(ptr.as<void*>(), std::to_array({ 0xB0, 0x01, 0xC3 }))->apply(); // has no observable side effects
}); });
// Send Network Damage // Send Network Damage
@ -622,9 +617,9 @@ namespace big
}); });
// Send Session Matchmaking Attributes // Send Session Matchmaking Attributes
main_batch.add("SPDM", "E8 ? ? ? ? 84 C0 0F 84 19 01 00 00 48 8D 4D A0", [this](memory::handle ptr) main_batch.add("SSMA", "48 8B C4 48 89 58 08 48 89 68 10 48 89 70 18 48 89 78 20 41 56 48 81 EC D0 00 00 00 49 8B", [this](memory::handle ptr)
{ {
m_send_session_matchmaking_attributes = ptr.add(1).rip().as<PVOID>(); m_send_session_matchmaking_attributes = ptr.as<PVOID>();
}); });
// Serialize Take Off Ped Variation Task // Serialize Take Off Ped Variation Task
@ -657,18 +652,6 @@ namespace big
memory::byte_patch::make(ptr.as<uint8_t*>(), 0xEB)->apply(); memory::byte_patch::make(ptr.as<uint8_t*>(), 0xEB)->apply();
}); });
// Write Bitbuffer Gamer Handle
main_batch.add("WBGH", "4C 8B DC 49 89 5B 08 57 48 83 EC 30 48 8B F9", [this](memory::handle ptr)
{
m_write_bitbuffer_gamer_handle = ptr.as<PVOID>();
});
// Read Bitbuffer Gamer Handle
main_batch.add("RBGH", "48 8B C4 48 89 58 10 48 89 68 18 48 89 70 20 57 48 83 EC 30 C6", [this](memory::handle ptr)
{
m_read_bitbuffer_gamer_handle = ptr.as<PVOID>();
});
// Constraint Attachment Crash // Constraint Attachment Crash
main_batch.add("CAC", "40 53 48 83 EC 20 48 8B D9 48 8B 49 38 48 8B 01", [this](memory::handle ptr) main_batch.add("CAC", "40 53 48 83 EC 20 48 8B D9 48 8B 49 38 48 8B 01", [this](memory::handle ptr)
{ {
@ -688,13 +671,13 @@ namespace big
}); });
// Decode Session Info // Decode Session Info
main_batch.add("DSI", "48 89 5C 24 08 48 89 6C 24 10 56 57 41 56 48 81 EC C0", [this](memory::handle ptr) main_batch.add("DSI", "E8 ?? ?? ?? ?? 84 C0 74 16 48 8B 4B 60", [this](memory::handle ptr)
{ {
m_decode_session_info = ptr.as<functions::decode_session_info>(); m_decode_session_info = ptr.add(1).rip().as<functions::decode_session_info>();
}); });
// Decode Peer Info // Decode Peer Info
main_batch.add("DPI", "48 8B C4 48 89 58 08 48 89 70 10 57 48 81 EC A0 00 00 00 48 8B DA", [this](memory::handle ptr) main_batch.add("DPI", "48 89 5C 24 08 48 89 74 24 10 57 48 81 EC C0 00 00 00 48 8B F1 49", [this](memory::handle ptr)
{ {
m_decode_peer_info = ptr.as<functions::decode_peer_info>(); m_decode_peer_info = ptr.as<functions::decode_peer_info>();
}); });
@ -765,12 +748,6 @@ namespace big
m_interval_check_func = ptr.add(3).rip().as<PVOID>(); m_interval_check_func = ptr.add(3).rip().as<PVOID>();
}); });
// Chat Gamer Info
main_batch.add("CGI", "E8 ? ? ? ? 48 8B CF E8 ? ? ? ? 8B E8", [this](memory::handle ptr)
{
m_chat_gamer_info = ptr.add(1).rip().add(6).rip().as<rage::rlGamerInfo*>();
});
// Sound Overload Detour // Sound Overload Detour
main_batch.add("SOD", "66 45 3B C1 74 38", [this](memory::handle ptr) main_batch.add("SOD", "66 45 3B C1 74 38", [this](memory::handle ptr)
{ {
@ -793,7 +770,7 @@ namespace big
}); });
// Connect To Peer // Connect To Peer
main_batch.add("CTP", "48 89 5C 24 08 4C 89 44 24 18 55 56 57 41 54 41 55 41 56 41 57 48 81 EC 80", [this](memory::handle ptr) main_batch.add("CTP", "48 89 5C 24 08 4C 89 4C 24 20 48 89 54 24 10 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 60 4D", [this](memory::handle ptr)
{ {
m_connect_to_peer = ptr.as<functions::connect_to_peer>(); m_connect_to_peer = ptr.as<functions::connect_to_peer>();
}); });

View File

@ -123,8 +123,6 @@ namespace big
functions::read_bitbuffer_into_sync_tree m_read_bitbuffer_into_sync_tree{}; functions::read_bitbuffer_into_sync_tree m_read_bitbuffer_into_sync_tree{};
//Sync Signatures END //Sync Signatures END
PVOID m_send_net_info_to_lobby{};
PVOID m_receive_net_message{}; PVOID m_receive_net_message{};
PVOID m_get_network_event_data{}; PVOID m_get_network_event_data{};
PVOID m_assign_physical_index{}; PVOID m_assign_physical_index{};
@ -213,9 +211,6 @@ namespace big
PVOID m_create_script_handler; PVOID m_create_script_handler;
PVOID m_write_bitbuffer_gamer_handle;
PVOID m_read_bitbuffer_gamer_handle;
functions::encode_session_info m_encode_session_info; functions::encode_session_info m_encode_session_info;
functions::decode_session_info m_decode_session_info; functions::decode_session_info m_decode_session_info;
functions::decode_peer_info m_decode_peer_info; functions::decode_peer_info m_decode_peer_info;
@ -228,8 +223,6 @@ namespace big
rage::netTime** m_network_time; rage::netTime** m_network_time;
functions::sync_network_time m_sync_network_time; functions::sync_network_time m_sync_network_time;
rage::rlGamerInfo* m_chat_gamer_info;
functions::send_packet m_send_packet; functions::send_packet m_send_packet;
functions::connect_to_peer m_connect_to_peer; functions::connect_to_peer m_connect_to_peer;

View File

@ -11,9 +11,9 @@ namespace big
return; return;
ImGui::SetNextWindowPos(ImVec2(10.0f, 10.0f), ImGuiCond_FirstUseEver, ImVec2(0.0f, 0.0f)); ImGui::SetNextWindowPos(ImVec2(10.0f, 10.0f), ImGuiCond_FirstUseEver, ImVec2(0.0f, 0.0f));
ImGui::SetNextWindowBgAlpha(0.3f); ImGui::SetNextWindowBgAlpha(0.5f);
if (ImGui::Begin("overlay", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav)) if (ImGui::Begin("overlay", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
{ {
ImGui::Text("YimMenu"); ImGui::Text("YimMenu");

View File

@ -11,48 +11,7 @@ namespace big
{ {
components::small_text("SPOOFING_DESCRIPTION"_T); components::small_text("SPOOFING_DESCRIPTION"_T);
components::sub_title("USERNAME"_T); ImGui::Text("!!!!! Spoofing options like name and RID have become impossible to spoof with update 1.66 !!!!!");
ImGui::Checkbox("SPOOFING_USERNAME"_T.data(), &g.spoofing.spoof_username);
if (g.spoofing.spoof_username)
{
ImGui::SameLine();
ImGui::Checkbox("SPOOFING_USERNAME_LOCAL"_T.data(), &g.spoofing.spoof_local_username);
}
constexpr size_t name_size = RTL_FIELD_SIZE(rage::rlGamerInfo, m_name);
static char name[name_size];
strcpy_s(name, sizeof(name), g.spoofing.username.c_str());
ImGui::Text("USERNAME_COLON"_T.data());
components::input_text("##username_input", name, sizeof(name));
if (name != g.spoofing.username)
g.spoofing.username = std::string(name);
ImGui::Separator();
components::sub_title("IP_ADDRESS"_T);
ImGui::Checkbox("SPOOFING_IP"_T.data(), &g.spoofing.spoof_ip);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("SPOOFING_IP_DESCRIPTION"_T.data());
ImGui::Text("IP_ADDRESS_COLON"_T.data());
ImGui::DragInt4("##ip_fields", g.spoofing.ip_address.data(), 0, 255);
ImGui::Separator();
components::sub_title("ROCKSTAR_ID"_T);
ImGui::Checkbox("SPOOFING_ROCKSTAR_ID"_T.data(), &g.spoofing.spoof_rockstar_id);
ImGui::Text("ROCKSTAR_ID_COLON"_T.data());
ImGui::InputScalar("##rockstar_id_input", ImGuiDataType_U64, &g.spoofing.rockstar_id);
components::sub_title("SPOOFING_HIDE_FEATURES"_T);
ImGui::Checkbox("SPOOFING_HIDE_GOD_MODE"_T.data(), &g.spoofing.spoof_hide_god);
ImGui::Checkbox("SPOOFING_HIDE_SPECTATE"_T.data(), &g.spoofing.spoof_hide_spectate);
components::sub_title("CREW"_T); components::sub_title("CREW"_T);
@ -75,8 +34,10 @@ namespace big
components::sub_title("SPOOFING_EXTRA"_T); components::sub_title("SPOOFING_EXTRA"_T);
ImGui::Checkbox("SPOOFING_IS_CHEATER"_T.data(), &g.spoofing.spoof_cheater); ImGui::Checkbox("SPOOFING_IS_CHEATER"_T.data(), &g.spoofing.spoof_cheater);
ImGui::Checkbox("SPOOFING_IS_DEV"_T.data(), &g.spoofing.spoof_rockstar_dev);
ImGui::Checkbox("SPOOFING_IS_QA"_T.data(), &g.spoofing.spoof_rockstar_qa); // Can't spoof RID anymore
//ImGui::Checkbox("SPOOFING_IS_DEV"_T.data(), &g.spoofing.spoof_rockstar_dev);
//ImGui::Checkbox("SPOOFING_IS_QA"_T.data(), &g.spoofing.spoof_rockstar_qa);
components::sub_title("SPOOFING_SESSION_ATTRIBUTES"_T); components::sub_title("SPOOFING_SESSION_ATTRIBUTES"_T);
components::small_text("SPOOFING_ONLY_WORKS_AS_HOST"_T); components::small_text("SPOOFING_ONLY_WORKS_AS_HOST"_T);

View File

@ -57,7 +57,8 @@ namespace big
components::command_checkbox<"nocollision">(); components::command_checkbox<"nocollision">();
components::command_checkbox<"mobileradio">(); components::command_checkbox<"mobileradio">();
ImGui::Checkbox("DANCE_MODE"_T.data(), &g.self.dance_mode); // TODO: fix this, causes a crash
// ImGui::Checkbox("DANCE_MODE"_T.data(), &g.self.dance_mode);
ImGui::EndGroup(); ImGui::EndGroup();