Toxic update (#641)

This commit is contained in:
maybegreat48 2022-12-06 16:12:02 +00:00 committed by GitHub
parent 7f74a436d2
commit a427ccb914
80 changed files with 3258 additions and 411 deletions

View File

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

View File

@ -19,6 +19,8 @@ namespace big
looped::system_update_pointers();
looped::system_desync_kick_protection();
looped::system_force_session_host();
looped::system_mission_creator();
looped::system_auto_tp();
script::get_current()->yield();
}
@ -44,6 +46,7 @@ namespace big
looped::self_no_water_collision();
looped::self_mobile_radio();
looped::self_fast_respawn();
looped::self_dance_mode();
script::get_current()->yield();
}
@ -118,6 +121,10 @@ namespace big
looped::hud_transition_state();
looped::tunables_disable_phone();
looped::session_local_time();
looped::session_pop_multiplier_areas();
looped::session_force_thunder();
looped::session_randomize_ceo_colors();
looped::session_auto_kick_host();
script::get_current()->yield();
}

View File

@ -1,11 +1,15 @@
#include "backend/looped/looped.hpp"
#include "natives.hpp"
#include "script_global.hpp"
#include "gta/joaat.hpp"
#include "util/kick.hpp"
#include "services/players/player_service.hpp"
// Credits: QuickNET
namespace big
{
constexpr char transition_states[][48] = {
constexpr char transition_states[][48] =
{
"TRANSITION_STATE_EMPTY",
"Singleplayer Swoop Up",
"Multiplayer Swoop Up",
@ -84,6 +88,9 @@ namespace big
{
const auto state = *transition_state.as<eTransitionState*>();
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0)
return;
// When freemode script loaded remove loading screen.
if (state == eTransitionState::TRANSITION_STATE_WAIT_JOIN_FM_SESSION
&& DLC::GET_IS_LOADING_SCREEN_ACTIVE())
@ -93,7 +100,7 @@ namespace big
if (last_state == state
|| state == eTransitionState::TRANSITION_STATE_EMPTY
|| state > eTransitionState::TRANSITION_STATE_DLC_INTRO_BINK)
|| state > eTransitionState::TRANSITION_STATE_SPAWN_INTO_PERSONAL_VEHICLE)
{
return;
}
@ -103,12 +110,6 @@ namespace big
HUD::BUSYSPINNER_OFF();
}
// sometimes when going into a single player mission or transition this one remains on screen permanently
if (state == eTransitionState::TRANSITION_STATE_TERMINATE_MAINTRANSITION)
{
return;
}
if ((int)state > 0 && (int)state < std::size(transition_states))
{
HUD::BEGIN_TEXT_COMMAND_BUSYSPINNER_ON("STRING");

View File

@ -32,15 +32,22 @@ namespace big
static void self_unlimited_oxygen();
static void self_no_water_collision();
static void self_mobile_radio();
static void self_dance_mode();
static void self_fast_respawn();
static void session_local_time();
static void session_pop_multiplier_areas();
static void session_force_thunder();
static void session_randomize_ceo_colors();
static void session_auto_kick_host();
static void system_disable_sigscanner();
static void system_self_globals();
static void system_update_pointers();
static void system_desync_kick_protection();
static void system_force_session_host();
static void system_mission_creator();
static void system_auto_tp();
static void vehicle_auto_drive();
static void vehicle_boost_behavior();

View File

@ -0,0 +1,67 @@
#include "backend/looped/looped.hpp"
#include "natives.hpp"
#include "util/entity.hpp"
#include "util/scripts.hpp"
#include "script_function.hpp"
namespace big
{
bool bLastDanceMode = false;
void looped::self_dance_mode()
{
if (g->self.dance_mode && SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) > 0)
g->self.dance_mode = false;
if (g->self.dance_mode && g->self.dance_mode != bLastDanceMode)
{
scripts::request_script(RAGE_JOAAT("am_mp_nightclub"));
if (!scripts::wait_till_loaded(RAGE_JOAAT("am_mp_nightclub")))
return;
auto thread = SYSTEM::START_NEW_SCRIPT_WITH_NAME_HASH(RAGE_JOAAT("am_mp_nightclub"), 19400 /*PROPERTY_INT*/);
SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(RAGE_JOAAT("am_mp_nightclub"));
if (!thread)
return;
g->m_dance_thread = gta_util::find_script_thread(RAGE_JOAAT("am_mp_nightclub"));
g->m_dance_program = gta_util::find_script_program(RAGE_JOAAT("am_mp_nightclub"));
(*g_pointers->m_script_handler_mgr)->attach_thread(g->m_dance_thread);
g->m_dance_thread->m_context.m_state = rage::eThreadState::unk_3;
// perform initial setup
gta_util::execute_as_script(RAGE_JOAAT("am_mp_nightclub"), []
{
NETWORK::NETWORK_SET_THIS_SCRIPT_IS_NETWORK_SCRIPT(32, false, 32);
scr_functions::init_nightclub_script({});
});
scr_functions::dance_loop.populate_ip();
bLastDanceMode = true;
return;
}
if (!g->self.dance_mode && g->self.dance_mode != bLastDanceMode)
{
if (g->m_dance_thread)
g->m_dance_thread->kill();
g->m_dance_thread = nullptr;
g->m_dance_program = nullptr;
bLastDanceMode = false;
return;
}
if (g->self.dance_mode && g->m_dance_thread->m_handler)
{
*script_global(1946244).as<bool*>() = true;
misc::set_bit(scr_globals::gpbd_fm_1.at(self::id, scr_globals::size::gpbd_fm_1).at(267).at(295).at(7).as<int*>(), 0);
misc::set_bit(scr_globals::gpbd_fm_1.at(self::id, scr_globals::size::gpbd_fm_1).at(267).at(295).at(7).as<int*>(), 1);
misc::set_bit(scr_globals::gpbd_fm_1.at(self::id, scr_globals::size::gpbd_fm_1).at(267).at(295).at(7).as<int*>(), 2);
scr_functions::dance_loop.call(g->m_dance_thread, g->m_dance_program, {});
}
}
}

View File

@ -0,0 +1,22 @@
#include "backend/looped/looped.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "util/kick.hpp"
namespace big
{
static bool bLastKickHost = false;
void looped::session_auto_kick_host()
{
bool kick_host = *g_pointers->m_is_session_started && g->session.force_session_host && g->session.kick_host_when_forcing_host;
if (kick_host && !bLastKickHost)
{
g_player_service->iterate([](auto& plyr)
{
if (plyr.second->is_host())
kick::lost_connection_kick(plyr.second);
});
}
bLastKickHost = kick_host;
}
}

View File

@ -0,0 +1,36 @@
#include "backend/looped/looped.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "gta_util.hpp"
#include "util/session.hpp"
namespace big
{
static bool bLastForceThunderEnabled = false;
void looped::session_force_thunder()
{
bool used = g->session.force_thunder && *g_pointers->m_is_session_started;
if (!bLastForceThunderEnabled && used)
{
if (!STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS() && gta_util::find_script_thread(RAGE_JOAAT("freemode")) && SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0)
{
session::set_fm_event_index(9);
session::set_fm_event_index(10);
session::set_fm_event_index(11);
bLastForceThunderEnabled = true;
}
}
else if (bLastForceThunderEnabled && !used)
{
if (*g_pointers->m_is_session_started && !STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS() && gta_util::find_script_thread(RAGE_JOAAT("freemode")))
{
session::clear_fm_event_index(9);
session::clear_fm_event_index(10);
session::clear_fm_event_index(11);
}
bLastForceThunderEnabled = false;
}
}
}

View File

@ -0,0 +1,53 @@
#include "backend/looped/looped.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "gta_util.hpp"
namespace big
{
static bool bLastPopMultiplierAreasEnabled = false;
static bool bLastBlockPeds = false;
static bool bLastBlockVehs = false;
static int pop_multiplier_id = -1;
void looped::session_pop_multiplier_areas()
{
bool used = (g->session.disable_traffic || g->session.disable_peds) && *g_pointers->m_is_session_started;
if (!bLastPopMultiplierAreasEnabled && used)
{
if (!STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS() && gta_util::find_script_thread(RAGE_JOAAT("freemode")) && SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0)
{
gta_util::execute_as_script(RAGE_JOAAT("freemode"), []
{
pop_multiplier_id = MISC::ADD_POP_MULTIPLIER_SPHERE(1.1f, 1.1f, 1.1f, 15000.0f, g->session.disable_peds ? 0.0f : 1.0f, g->session.disable_traffic ? 0.0f : 1.0f, false, true);
bLastBlockPeds = g->session.disable_peds;
bLastBlockVehs = g->session.disable_traffic;
bLastPopMultiplierAreasEnabled = true;
MISC::CLEAR_AREA(1.1f, 1.1f, 1.1f, 19999.9f, true, false, false, true);
});
}
}
else if (bLastPopMultiplierAreasEnabled && (g->session.disable_traffic != bLastBlockVehs || g->session.disable_peds != bLastBlockPeds))
{
bLastBlockPeds = g->session.disable_peds;
bLastBlockVehs = g->session.disable_traffic;
used = false;
}
if (bLastPopMultiplierAreasEnabled && !used)
{
if (gta_util::find_script_thread(RAGE_JOAAT("freemode")))
{
gta_util::execute_as_script(RAGE_JOAAT("freemode"), []
{
MISC::REMOVE_POP_MULTIPLIER_SPHERE(pop_multiplier_id, false);
});
}
bLastPopMultiplierAreasEnabled = false;
pop_multiplier_id = -1;
}
}
}

View File

@ -0,0 +1,23 @@
#include "backend/looped/looped.hpp"
#include "natives.hpp"
#include "pointers.hpp"
#include "gta_util.hpp"
#include "util/session.hpp"
#include "gta/script_handler.hpp"
namespace big
{
void looped::session_randomize_ceo_colors()
{
if (g->session.randomize_ceo_colors && *g_pointers->m_is_session_started && !STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS() && SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0)
{
if (auto freemode = gta_util::find_script_thread(RAGE_JOAAT("freemode")); freemode && freemode->m_net_component && freemode->m_net_component->is_local_player_host())
{
for (int i = 0; i < *scr_globals::gsbd.at(818).at(44).as<int*>(); i++)
{
*scr_globals::gsbd.at(818).at(44).at(i, 2).at(1).as<int*>() = rand() % 15;
}
}
}
}
}

View File

@ -0,0 +1,28 @@
#include "backend/looped/looped.hpp"
#include "fiber_pool.hpp"
#include "natives.hpp"
#include "script.hpp"
#include "pointers.hpp"
namespace big
{
bool bLastAutoTP = false;
void looped::system_auto_tp()
{
bool temp_disable_tp = (!*g_pointers->m_is_session_started) && CUTSCENE::IS_CUTSCENE_ACTIVE();
if ((!g->self.auto_tp || temp_disable_tp) && bLastAutoTP)
{
MISC::USING_MISSION_CREATOR(false);
MISC::ALLOW_MISSION_CREATOR_WARP(false);
}
if (g->self.auto_tp && !temp_disable_tp)
{
MISC::USING_MISSION_CREATOR(true);
MISC::ALLOW_MISSION_CREATOR_WARP(true);
}
bLastAutoTP = g->self.auto_tp;
}
}

View File

@ -11,7 +11,13 @@ namespace big
void looped::system_desync_kick_protection()
{
memset(&gta_util::get_network()->m_game_complaint_mgr.m_host_tokens_complained, 0, 64 * sizeof(std::uint64_t));
gta_util::get_network()->m_game_complaint_mgr.m_num_tokens_complained = 0;
if (!g_player_service->m_player_to_use_complaint_kick || !g_player_service->m_player_to_use_complaint_kick->get()->get_net_data())
gta_util::get_network()->m_game_complaint_mgr.m_num_tokens_complained = 0;
else
{
gta_util::get_network()->m_game_complaint_mgr.m_num_tokens_complained = 1;
gta_util::get_network()->m_game_complaint_mgr.m_host_tokens_complained[0] = g_player_service->m_player_to_use_complaint_kick->get()->get_net_data()->m_host_token;
}
auto old = gta_util::get_network()->m_game_complaint_mgr.m_host_token;

View File

@ -0,0 +1,39 @@
#include "backend/looped/looped.hpp"
#include "fiber_pool.hpp"
#include "natives.hpp"
#include "script.hpp"
#include "gta_util.hpp"
#include "core/scr_globals.hpp"
namespace big
{
bool bLastMissionCreator = false;
void looped::system_mission_creator()
{
if (g->m_mission_creator_thread)
{
*scr_globals::terminate_creator.as<bool*>() = false;
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) > 0)
{
if (g->m_mission_creator_thread)
g->m_mission_creator_thread->kill();
g->m_mission_creator_thread = nullptr;
return;
}
bLastMissionCreator = true;
}
else if (bLastMissionCreator)
{
*scr_globals::switch_struct.at(18).as<int*>() = 0;
STREAMING::SWITCH_TO_MULTI_SECONDPART(self::ped);
HUD::DISPLAY_HUD(true);
HUD::DISPLAY_RADAR(true);
PLAYER::SET_PLAYER_CONTROL(self::id, true, 0);
ENTITY::FREEZE_ENTITY_POSITION(self::ped, false);
ENTITY::SET_ENTITY_COLLISION(self::ped, true, true);
bLastMissionCreator = false;
}
}
}

View File

@ -14,6 +14,9 @@ namespace big
rgb_controller_blue_down,
};
std::chrono::system_clock::time_point last_rgb_run_time;
std::chrono::milliseconds delay = 0s;
void looped::vehicle_rainbow_paint()
{
static int rgb_controller_v = rgb_controller_green_up;
@ -22,7 +25,7 @@ namespace big
static int green = 0;
static int blue = 0;
if (self::veh && g->vehicle.rainbow_paint.type != RainbowPaintType::Off)
if (self::veh && g->vehicle.rainbow_paint.type != RainbowPaintType::Off && last_rgb_run_time + delay < std::chrono::system_clock::now())
{
int delay_step = 100;
@ -117,8 +120,8 @@ namespace big
VEHICLE::SET_VEHICLE_TYRE_SMOKE_COLOR(vehicle, red, green, blue);
}
auto delay = std::chrono::milliseconds(((delay_step * 10) + 10) - (g->vehicle.rainbow_paint.speed * delay_step));
script::get_current()->yield(delay);
delay = std::chrono::milliseconds(((delay_step * 10) + 10) - (g->vehicle.rainbow_paint.speed * delay_step));
last_rgb_run_time = std::chrono::system_clock::now();
}
}
}

View File

@ -1,3 +1,4 @@
#pragma once
#include "services/script_patcher/script_patcher_service.hpp"
#include <script/scrProgramTable.hpp>
@ -7,9 +8,11 @@ namespace big
{
g_script_patcher_service->add_patch({ RAGE_JOAAT("freemode"), "2D 01 08 00 ? 38 00 5D ? ? ? 2A 06", 5, {0x6E, 0x2E, 0x01, 0x01}, &g->session.decloak_players });
g_script_patcher_service->add_patch({ RAGE_JOAAT("freemode"), "2D 01 04 00 ? 2C ? ? ? 5D ? ? ? 6E 57 ? ? 2C", 5, { 0x2E, 0x01, 0x00 }, &g->protections.script_host_kick });
g_script_patcher_service->add_patch({ RAGE_JOAAT("freemode"), "2D 01 08 00 00 5D ? ? ? 56 ? ? 6E ", 5, { 0x2E, 0x01, 0x00 }, &g->tunables.no_idle_kick });
g_script_patcher_service->add_patch({ RAGE_JOAAT("freemode"), "2D 01 08 00 00 5D ? ? ? 56 ? ? 6E", 5, { 0x2E, 0x01, 0x00 }, &g->tunables.no_idle_kick });
g_script_patcher_service->add_patch({ RAGE_JOAAT("freemode"), "5D ? ? ? 73 57 ? ? 5D ? ? ? 73", 0, { 0x2E, 0x00, 0x00 }, nullptr }); // end session kick protection
g_script_patcher_service->add_patch({ RAGE_JOAAT("freemode"), "2D 01 09 00 00 5D ? ? ? 56 ? ? 2E", 5, { 0x2E, 0x01, 0x00 }, nullptr }); // disable death when undermap/spectating
g_script_patcher_service->add_patch({ RAGE_JOAAT("shop_controller"), "2D 01 04 00 00 2C ? ? ? 56 ? ? 6E ", 5, { 0x6E, 0x2E, 0x01, 0x01 }, nullptr }); // despawn bypass
g_script_patcher_service->add_patch({ RAGE_JOAAT("shop_controller"), "2D 01 04 00 00 2C ? ? ? 56 ? ? 6E", 5, { 0x6E, 0x2E, 0x01, 0x01 }, nullptr }); // despawn bypass
g_script_patcher_service->add_patch({ RAGE_JOAAT("shop_controller"), "38 00 5D ? ? ? 38 00 5D ? ? ? 38 00 41", 0, std::vector<uint8_t>(12, 0x0), nullptr}); // godmode/invisibility detection bypass
for (auto& entry : *g_pointers->m_script_program_table)
{

View File

@ -0,0 +1,123 @@
#pragma once
namespace big
{
constexpr const static auto apartment_names = std::to_array({
"INVALID",
"Eclipse Towers, Apt 31",
"Eclipse Towers, Apt 9",
"Eclipse Towers, Apt 40",
"Eclipse Towers, Apt 5",
"3 Alta St, Apt 10",
"3 Alta St, Apt 57",
"Del Perro Heights, Apt 20",
"1162 Power St, Apt 3",
"0605 Spanish Ave, Apt 1",
"0604 Las Lagunas Blvd, Apt 4",
"0184 Milton Rd, Apt 13",
"The Royale, Apt 19",
"0504 S Mo Milton Dr",
"0115 Bay City Ave, Apt 45",
"0325 South Rockford Dr",
"Dream Tower, Apt 15",
"2143 Las Lagunas Blvd, Apt 9",
"1561 San Vitas St, Apt 2",
"0112 S Rockford Dr, Apt 13",
"2057 Vespucci Blvd, Apt 1",
"0069 Cougar Ave, Apt 19",
"1237 Prosperity St, Apt 21",
"1115 Blvd Del Perro, Apt 18",
"0120 Murrieta Heights",
"Unit 14 Popular St",
"Unit 2 Popular St",
"331 Supply St",
"Unit 1 Olympic Fwy",
"0754 Roy Lowenstein Blvd",
"12 Little Bighorn Ave",
"Unit 124 Popular St",
"0552 Roy Lowenstein Blvd",
"0432 Davis Ave",
"Del Perro Heights, Apt 7",
"Weazel Plaza, Apt 101",
"Weazel Plaza, Apt 70",
"Weazel Plaza, Apt 26",
"4 Integrity Way, Apt 30",
"4 Integrity Way, Apt 35",
"Richards Majestic, Apt 4",
"Richards Majestic, Apt 51",
"Tinsel Towers, Apt 45",
"Tinsel Towers, Apt 29",
"142 Paleto Blvd",
"1 Strawberry Ave",
"1932 Grapeseed Ave",
"1920 Senora Way",
"2000 Great Ocean Highway",
"197 Route 68",
"870 Route 68 Approach",
"1200 Route 68",
"8754 Route 68",
"1905 Davis Ave",
"1623 South Shambles St",
"4531 Dry Dock St",
"1337 Exceptionalists Way",
"Unit 76 Greenwich Parkway",
"Garage Innocence Blvd",
"634 Blvd Del Perro",
"0897 Mirror Park Blvd",
"Eclipse Towers, Apt 3",
"Del Perro Heights, Apt 4",
"Richards Majestic, Apt 2",
"Tinsel Towers, Apt 42",
"4 Integrity Way, Apt 28",
"4 Hangman Ave",
"12 Sustancia Rd",
"4584 Procopio Dr",
"4401 Procopio Dr",
"0232 Paleto Blvd",
"140 Zancudo Ave",
"1893 Grapeseed Ave",
"3655 Wild Oats Drive",
"2044 North Conker Avenue",
"2868 Hillcrest Avenue",
"2862 Hillcrest Avenue",
"3677 Whispymound Drive",
"2117 Milton Road",
"2866 Hillcrest Avenue",
"2874 Hillcrest Avenue",
"2113 Mad Wayne Thunder Drive",
"2045 North Conker Avenue",
"Eclipse Towers, Penthouse Suite 1",
"Eclipse Towers, Penthouse Suite 2",
"Eclipse Towers, Penthouse Suite 3",
"Private Yacht",
"Lombank West",
"Maze Bank West",
"Arcadius Business Center",
"Maze Bank Tower",
"Rancho Clubhouse",
"Del Perro Beach Clubhouse",
"Pillbox Hill Clubhouse",
"Great Chaparral Clubhouse",
"Paleto Bay Clubhouse",
"Sandy Shores Clubhouse",
"La Mesa Clubhouse",
"Downtown Vinewood Clubhouse",
"Hawick Clubhouse",
"Grapeseed Clubhouse",
"Paleto Bay Clubhouse",
"Vespucci Beach Clubhouse",
"Office Garage 1",
"Office Garage 2",
"Office Garage 3",
"Office Garage 1",
"Office Garage 2",
"Office Garage 3",
"Office Garage 1",
"Office Garage 2",
"Office Garage 3",
"Office Garage 1",
"Office Garage 2",
"Office Garage 3",
"Vehicle Warehouse"
});
}

View File

@ -13,7 +13,8 @@ namespace big
TRIGGERED_ANTICHEAT,
TRIED_CRASH_PLAYER,
TRIED_KICK_PLAYER,
BLAME_EXPLOSION_DETECTED
BLAME_EXPLOSION_DETECTED,
ATTACKING_WITH_GODMODE
};
inline std::unordered_map<Infraction, const char*> infraction_desc =
@ -25,6 +26,7 @@ namespace big
{Infraction::TRIGGERED_ANTICHEAT, "Triggered Rockstar's anticheat"},
{Infraction::TRIED_CRASH_PLAYER, "Tried to crash you"},
{Infraction::TRIED_KICK_PLAYER, "Tried to kick you"},
{Infraction::BLAME_EXPLOSION_DETECTED, "Tried to blame someone for their explosion"}
{Infraction::BLAME_EXPLOSION_DETECTED, "Tried to blame someone for their explosion"},
{Infraction::ATTACKING_WITH_GODMODE, "Attacked someone when using godmode"}
};
}

View File

@ -0,0 +1,30 @@
#pragma once
namespace big
{
constexpr const static auto warehouse_names = std::to_array({
"INVALID",
"Pacific Bait Storage",
"White Widow Garage",
"Celltowa Unit",
"Convenience Store Lockup",
"Foreclosed Garage",
"Xero Gas Factory",
"Derriere Lingerie Backlot",
"Bilgeco Warehouse",
"Pier 400 Utility Building",
"GEE Warehouse",
"LS Marine Building 3",
"Railyard Warehouse",
"Fridgit Annexe",
"Disused Factory Outlet",
"Discount Retail Unit",
"Logistics Depot",
"Darnell Bros Warehouse",
"Wholesale Furniture",
"Cypress Warehouses",
"West Vinewood Backlot",
"Old Power Station",
"Walker & Sons Warehouse"
});
}

View File

@ -164,6 +164,9 @@ namespace big
DisableRecording = 867047895, // GET_FINAL_RENDERED_CAM_COORD
MCTeleport = -555356783, // NETWORK::NETWORK_HASH_FROM_PLAYER_HANDLE(PLAYER::PLAYER_ID()) == (first one)
StartActivity = 1368055548, // (Var0.f_2, -1); first match
MarkPlayerAsBeast = -490124271, // GB_BOSSBST xref == PLAYER... global (sadly doesn't actually turn people into the beast)
KickFromInterior = -1549662639, // ENTITY::SET_ENTITY_HEALTH(PLAYER::PLAYER_PED_ID(), PED::GET_PED_MAX_HEALTH(PLAYER::PLAYER_PED_ID()), false)
InteriorControl = 111242367, // eventData.f_3 != _INVALID_PLAYER_INDEX_0()
Crash = 526822748, // SET_NO_LOADING_SCREEN, xref it
Crash2 = 1348481963,
@ -177,6 +180,20 @@ namespace big
NotificationMoneyStolen = -1640162684, // TICK_TC_STOL
};
enum class eCollectibleType
{
MovieProp = 0,
CacheShard = 1,
ChestShard = 2,
RadioTowerShard = 3,
AudioPlayerShard = 4,
ShipwreckShard = 5,
BuriedStashShard = 6,
Treat = 8,
Organics = 9,
Skydive = 10
};
enum class eActivityType
{
HeistPrep = 233,
@ -234,6 +251,7 @@ namespace big
DueDiligence = 160,
MarketManipulation = 154,
CourierService = 155,
Skydive = 267
};
enum class eSessionType

View File

@ -1,7 +1,7 @@
#pragma once
#include "rage/rlSessionInfo.hpp"
#include "weapon/CAmmoInfo.hpp"
#include "weapon/CWeaponInfo.hpp"
#include <rage/rlSessionInfo.hpp>
#include <weapon/CAmmoInfo.hpp>
#include <weapon/CWeaponInfo.hpp>
#include "enums.hpp"
#include "file_manager.hpp"
#include "imgui.h"
@ -11,6 +11,7 @@ class CNetGamePlayer;
namespace rage
{
class scrThread;
class scrProgram;
}
@ -87,6 +88,7 @@ namespace big
pair vehicle_kick{};
pair teleport_to_warehouse{};
pair start_activity{};
pair null_function_kick{};
} script_event_handler{};
pair gta_thread_kill{};
@ -188,6 +190,11 @@ namespace big
bool force_show_hud = false;
bool mobile_radio = false;
bool fast_respawn = false;
bool auto_tp = false;
// do not save below entries
bool dance_mode = false;
};
struct session
@ -206,6 +213,7 @@ namespace big
bool log_text_messages = false;
bool decloak_players = false;
bool force_session_host = false;
bool force_script_host = false;
bool player_magnet_enabled = false;
int player_magnet_count = 32;
bool is_team = false;
@ -214,10 +222,27 @@ namespace big
std::string spoofed_name = "";
bool join_in_sctv_slots = false;
bool kick_chat_spammers = false;
bool kick_host_when_forcing_host = false;
bool explosion_karma = false;
bool damage_karma = false;
bool disable_traffic = false;
bool disable_peds = false;
bool force_thunder = false;
bool block_ceo_money = false;
bool randomize_ceo_colors = false;
int send_to_apartment_idx = 1;
int send_to_warehouse_idx = 1;
// not to be saved
bool never_wanted_all = false;
bool off_radar_all = false;
bool semi_godmode_all = false;
bool wanted_level_all = false;
};
struct settings {
@ -275,6 +300,13 @@ namespace big
std::string crew_tag = "";
bool rockstar_crew = false;
bool square_crew_tag = false;
bool spoof_session_region_type = false;
int session_region_type = 0;
bool spoof_session_language = false;
int session_language = 0;
bool spoof_session_player_count = false;
int session_player_count = 25;
};
struct tunables {
@ -378,7 +410,7 @@ namespace big
struct context_menu
{
bool enabled = true;
bool enabled = false;
uint8_t allowed_entity_types =
static_cast<uint8_t>(ContextEntityType::PED) |
@ -450,6 +482,16 @@ namespace big
int m_remote_controller_vehicle = -1;
int m_remote_controlled_vehicle = -1;
int m_mod_net_id = -1;
int m_test_net_id = -1;
rage::scrThread* m_hunt_the_beast_thread = nullptr;
rage::scrThread* m_dance_thread = nullptr;
rage::scrProgram* m_dance_program = nullptr;
rage::scrThread* m_mission_creator_thread = nullptr;
debug debug{};
tunables tunables{};
notifications notifications{};
@ -577,6 +619,8 @@ namespace big
script_handler.teleport_to_warehouse.notify = script_handler_j["teleport_to_warehouse"]["notify"];
script_handler.start_activity.log = script_handler_j["start_activity"]["log"];
script_handler.start_activity.notify = script_handler_j["start_activity"]["notify"];
script_handler.null_function_kick.log = script_handler_j["null_function_kick"]["log"];
script_handler.null_function_kick.notify = script_handler_j["null_function_kick"]["notify"];
}
g->notifications.send_net_info_to_lobby.log = j["notifications"]["send_net_info_to_lobby"]["log"];
@ -651,12 +695,14 @@ namespace big
this->self.no_water_collision = j["self"]["no_water_collision"];
this->self.mobile_radio = j["self"]["mobile_radio"];
this->self.fast_respawn = j["self"]["fast_respawn"];
this->self.auto_tp = j["self"]["auto_tp"];
this->session.log_chat_messages = j["session"]["log_chat_messages"];
this->session.log_text_messages = j["session"]["log_text_messages"];
this->session.disable_chat_filter = j["session"]["disable_chat_filter"];
this->session.decloak_players = j["session"]["decloak_players"];
this->session.force_session_host = j["session"]["force_session_host"];
this->session.force_script_host = j["session"]["force_script_host"];
this->session.player_magnet_enabled = j["session"]["player_magnet_enabled"];
this->session.player_magnet_count = j["session"]["player_magnet_count"];
this->session.is_team = j["session"]["is_team"];
@ -665,6 +711,22 @@ namespace big
this->session.spoofed_name = j["session"]["spoofed_name"];
this->session.join_in_sctv_slots = j["session"]["join_in_sctv_slots"];
this->session.kick_chat_spammers = j["session"]["kick_chat_spammers"];
this->session.kick_host_when_forcing_host = j["session"]["kick_host_when_forcing_host"];
this->session.explosion_karma = j["session"]["explosion_karma"];
this->session.damage_karma = j["session"]["damage_karma"];
this->session.disable_peds = j["session"]["disable_peds"];
this->session.disable_traffic = j["session"]["disable_traffic"];
this->session.force_thunder = j["session"]["force_thunder"];
this->session.block_ceo_money = j["session"]["block_ceo_money"];
this->session.randomize_ceo_colors = j["session"]["randomize_ceo_colors"];
this->session.send_to_apartment_idx = j["session"]["send_to_apartment_idx"];
this->session.send_to_warehouse_idx = j["session"]["send_to_warehouse_idx"];
this->settings.dev_dlc = j["settings"]["dev_dlc"];
this->settings.hotkeys.menu_toggle = j["settings"]["hotkeys"]["menu_toggle"];
this->settings.hotkeys.teleport_waypoint = j["settings"]["hotkeys"]["teleport_waypoint"];
@ -704,6 +766,13 @@ namespace big
this->spoofing.spoof_hide_god = j["spoofing"]["spoof_hide_god"];
this->spoofing.spoof_hide_spectate = j["spoofing"]["spoof_hide_spectate"];
this->spoofing.spoof_session_region_type = j["spoofing"]["spoof_session_region_type"];
this->spoofing.spoof_session_language = j["spoofing"]["spoof_session_language"];
this->spoofing.spoof_session_player_count = j["spoofing"]["spoof_session_player_count"];
this->spoofing.session_region_type = j["spoofing"]["session_region_type"];
this->spoofing.session_language = j["spoofing"]["session_language"];
this->spoofing.session_player_count = j["spoofing"]["session_player_count"];
this->vehicle.speed_unit = (SpeedUnit)j["vehicle"]["speed_unit"];
this->vehicle.god_mode = j["vehicle"]["god_mode"];
this->vehicle.proof_bullet = j["vehicle"]["proof_bullet"];
@ -889,7 +958,8 @@ namespace big
{ "tse_sender_mismatch", return_notify_pair(script_handler_notifications.tse_sender_mismatch) },
{ "vehicle_kick", return_notify_pair(script_handler_notifications.vehicle_kick) },
{ "teleport_to_warehouse", return_notify_pair(script_handler_notifications.teleport_to_warehouse) },
{ "start_activity", return_notify_pair(script_handler_notifications.start_activity) }
{ "start_activity", return_notify_pair(script_handler_notifications.start_activity) },
{ "null_function_kick", return_notify_pair(script_handler_notifications.null_function_kick) }
}
},
{ "send_net_info_to_lobby", return_notify_pair(g->notifications.send_net_info_to_lobby) },
@ -927,7 +997,7 @@ namespace big
{ "transaction_error", script_handler_protections.transaction_error },
{ "vehicle_kick", script_handler_protections.vehicle_kick },
{ "teleport_to_warehouse", script_handler_protections.teleport_to_warehouse },
{ "start_activity", script_handler_protections.start_activity },
{ "start_activity", script_handler_protections.start_activity }
}
},
@ -995,6 +1065,7 @@ namespace big
{ "no_water_collision", this->self.no_water_collision },
{ "mobile_radio", this->self.mobile_radio },
{ "fast_respawn", this->self.fast_respawn },
{ "auto_tp", this->self.auto_tp }
}
},
{
@ -1004,13 +1075,25 @@ namespace big
{ "disable_chat_filter", this->session.disable_chat_filter },
{ "decloak_players", this->session.decloak_players },
{ "force_session_host", this->session.force_session_host },
{ "force_script_host", this->session.force_script_host },
{ "player_magnet_enabled", this->session.player_magnet_enabled },
{ "player_magnet_count", this->session.player_magnet_count },
{ "is_team", this->session.is_team },
{ "name_spoof_enabled", this->session.name_spoof_enabled },
{ "advertise_menu", this->session.advertise_menu },
{ "spoofed_name", this->session.spoofed_name },
{ "join_in_sctv_slots", this->session.join_in_sctv_slots }
{ "join_in_sctv_slots", this->session.join_in_sctv_slots },
{ "kick_chat_spammers", this->session.kick_chat_spammers },
{ "kick_host_when_forcing_host", this->session.kick_host_when_forcing_host },
{ "explosion_karma", this->session.explosion_karma },
{ "damage_karma", this->session.damage_karma },
{ "disable_peds", this->session.disable_peds },
{ "disable_traffic", this->session.disable_traffic },
{ "force_thunder", this->session.force_thunder },
{ "block_ceo_money", this->session.block_ceo_money },
{ "randomize_ceo_colors", this->session.randomize_ceo_colors },
{ "send_to_apartment_idx", this->session.send_to_apartment_idx },
{ "send_to_warehouse_idx", this->session.send_to_warehouse_idx }
}
},
{
@ -1070,6 +1153,12 @@ namespace big
{ "square_crew_tag", this->spoofing.square_crew_tag },
{ "spoof_hide_god", this->spoofing.spoof_hide_god },
{ "spoof_hide_spectate", this->spoofing.spoof_hide_spectate },
{ "spoof_session_region_type", this->spoofing.spoof_session_region_type},
{ "spoof_session_language", this->spoofing.spoof_session_language },
{ "spoof_session_player_count", this->spoofing.spoof_session_player_count },
{ "session_region_type", this->spoofing.session_region_type },
{ "session_language", this->spoofing.session_language },
{ "session_player_count", this->spoofing.session_player_count }
}
},
{

View File

@ -10,6 +10,14 @@ namespace big::scr_globals
constexpr int gpbd_fm_1 = 888;
}
namespace offset
{
namespace globalplayer_bd
{
constexpr int orbital_cannon_bitset = 416;
}
}
static inline script_global gsbd(2680265);
static inline script_global gsbd_fm(1835502);
static inline script_global gsbd_kicking(1883751);
@ -38,3 +46,11 @@ namespace big::scr_globals
static inline script_global spawn_global = script_global(2725439);
}
namespace big::scr_locals
{
namespace am_hunt_the_beast
{
constexpr static auto broadcast_idx = 597;
}
}

View File

@ -8,6 +8,11 @@ class NetworkGameFilterMatchmakingComponent;
namespace rage
{
class netConnectionManager;
class netConnectionPeer;
class snMsgRemoveGamersFromSessionCmd;
class snSession;
class snPlayer;
class CDynamicEntity;
}
namespace big::functions
@ -24,7 +29,7 @@ namespace big::functions
using increment_stat_event = bool(*)(uint64_t net_event_struct, int64_t sender, int64_t a3);
using ptr_to_handle = Entity(*)(void*);
using handle_to_ptr = void*(*)(Entity);
using handle_to_ptr = rage::CDynamicEntity*(*)(Entity);
using multiplayer_chat_filter = int(__int64 chat_type, const char* input, const char** output);
using write_player_game_state_data_node = bool(*)(rage::netObject* plr, CPlayerGameStateDataNode* node);
@ -87,4 +92,14 @@ namespace big::functions
using generate_uuid = bool(*)(std::uint64_t* uuid);
using send_chat_message = bool(*)(int64_t* send_chat_ptr, rage::rlGamerInfo* game_info, char* message, bool is_team);
using send_network_damage = void(*)(CEntity* source, CEntity* target, rage::fvector3* position, int hit_component, bool override_default_damage, int weapon_type, float override_damage, int tire_index, int suspension_index, int flags,
std::uint32_t action_result_hash, std::int16_t action_result_id, int action_unk, bool hit_weapon, bool hit_weapon_ammo_attachment, bool silenced, bool unk, rage::fvector3* impact_direction);
using request_ragdoll = void(*)(uint16_t object_id);
using get_connection_peer = rage::netConnectionPeer* (*)(rage::netConnectionManager* manager, int peer_id);
using send_remove_gamer_cmd = void(*)(rage::netConnectionManager* net_connection_mgr, rage::netConnectionPeer* player, int connection_id, rage::snMsgRemoveGamersFromSessionCmd* cmd, int flags);
using handle_remove_gamer_cmd = void* (*)(rage::snSession* session, rage::snPlayer* origin, rage::snMsgRemoveGamersFromSessionCmd* cmd);
using script_vm = int (*) (uint64_t* stack, int64_t** scr_globals, rage::scrProgram* program, rage::scrThreadContext* ctx);
}

218
src/gta/net_array.hpp Normal file
View File

@ -0,0 +1,218 @@
#pragma once
#include "fwddec.hpp"
class CGameArrayMgr
{
public:
char padding[0x40];
rage::netArrayHandlerBase* m_start;
};
static_assert(sizeof(CGameArrayMgr) == 0x48);
namespace rage
{
class netSyncDataUnit_Dynamic
{
public:
virtual ~netSyncDataUnit_Dynamic() = default; // 0x00
virtual void _0x08() = 0;
virtual void _0x10() = 0;
virtual void set_data_counter(int index, uint16_t counter) = 0; // 0x18
virtual void reset_data_counter(int index) = 0; // 0x20
// ...
int m_players_need_ack; // 0x08
int m_players_need_sync; // 0x0C
};
class netSyncData_Dynamic
{
public:
virtual ~netSyncData_Dynamic() = default; // 0x00
virtual rage::datBitBuffer* _0x08() = 0;
virtual rage::datBitBuffer* _0x10() = 0;
virtual int get_num_receivers() = 0; // 0x18
virtual int _0x20() = 0;
virtual void _0x28() = 0; // same as get_sync_unit_for_element
virtual netSyncDataUnit_Dynamic* get_sync_unit_for_element(uint32_t element) = 0; // 0x30
// ...
};
class netArrayHandlerBase
{
public:
virtual ~netArrayHandlerBase() = default; // 0x00
virtual void _0x08() = 0;
virtual void _0x10() = 0;
virtual void _0x18() = 0;
virtual void _0x20() = 0;
virtual void _0x28() = 0;
virtual void _0x30() = 0;
virtual void _0x38() = 0; //
virtual void _0x40() = 0; //
virtual int _0x48(CNetGamePlayer* player, int max_size, uint32_t* a3, uint32_t* a4) = 0; //
virtual int get_size(CNetGamePlayer* player, int max_size, uint32_t element) = 0; // 0x50
virtual int pack_array_data(CNetGamePlayer* player, rage::datBitBuffer* bit_buffer, uint16_t counter, uint32_t* elem_start, bool silent) = 0; // 0x58
virtual void _0x60() = 0; //
virtual bool _0x68(CNetGamePlayer* player) = 0; // is_player_out_of_scope or something like that
virtual void _0x70() = 0; //
virtual bool can_send_update(CNetGamePlayer* player) = 0; // 0x78
virtual void _0x80() = 0; //
virtual void _0x88() = 0; //
virtual void* get_identifier() = 0; // 0x90
virtual void* _0x98() = 0; // same as get_identifier
virtual void _0xA0() = 0; //
virtual bool can_verify_array_data() = 0; // 0xA8
virtual void _0xB0() = 0; //
virtual void _0xB8() = 0; //
virtual void should_sync_element(uint32_t element) = 0; // 0xC0
virtual void _0xC8() = 0; //
virtual void _0xD0() = 0; //
virtual bool are_all_elements_in_scope() = 0; // 0xD8
virtual void _0xE0() = 0; //
virtual void verify_array_data() = 0; // 0xE8
virtual void _0xF0() = 0; //
virtual char* get_name() = 0; // 0xF8
virtual bool is_local_player_owner_of_array() = 0; // 0x100
virtual CNetGamePlayer* get_owner_of_array() = 0; // 0x108
virtual void _0x110() = 0;
virtual uint32_t get_array_hash() = 0;
virtual int _0x120() = 0; // gets array size for hashing
virtual netSyncData_Dynamic* _0x128() = 0; // same as get_dynamic_sync_data
virtual netSyncData_Dynamic* get_dynamic_sync_data() = 0; // 0x130
virtual void _0x138() = 0;
virtual bool is_element_in_scope(uint32_t element, CNetGamePlayer* player) = 0; // 0x140
virtual int get_receiver_index_from_player(CNetGamePlayer*) = 0; // 0x148
virtual void _0x150() = 0;
virtual void _0x158() = 0;
// pasted from fivem
virtual bool is_element_empty(uint32_t element) = 0; // 0x160
virtual void set_element_empty(uint32_t element) = 0; // 0x168
virtual void write_element_index(rage::datBitBuffer& buffer, uint32_t) = 0; // 0x170
virtual void read_element_index(rage::datBitBuffer& buffer, uint32_t&) = 0; // 0x178
virtual bool is_valid_index(uint32_t) = 0; // 0x180
virtual void recalculate_dirty_elements() = 0; // 0x188
virtual void reset_element_sync_data(uint32_t element) = 0; // 0x190
virtual void do_post_read_processing() = 0; // 0x198
virtual void do_post_element_read_processing(uint32_t element) = 0; // 0x1A0
virtual bool can_apply_element_data(uint32_t element, const rage::netPlayer& sender, bool force) = 0; // 0x1A8
virtual void extract_data_for_serializing(uint32_t elem) = 0; // 0x1B0
virtual void write_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0; // 0x1B8
virtual void read_element(rage::datBitBuffer& buffer, uint32_t elem, void* logger) = 0; // 0x1C0
virtual void log_element(uint32_t elem, void* logger) = 0; // 0x1C8
virtual uint32_t get_current_element_size_in_bits(uint32_t elem) = 0; // 0x1D0
virtual void apply_element_data(uint32_t element, const rage::netPlayer& sender) = 0; // 0x1D8
virtual void _0x1E0() = 0;
virtual void _0x1E8(bool) = 0; // very important! changes send function to use some kind of cached buffer that prevents us from modifing array data per player
void* m_something; // 0x10
netArrayHandlerBase* m_next; // 0x18
uint8_t m_pad[100 - 0x18]; // +8
uint32_t m_hash;
uint8_t m_pad2[244 - 104]; // +8
uint16_t m_index; // 244
uint16_t m_count; // 246
uint8_t m_max_elements; // 248
uint8_t m_element_size; // 249
uint8_t m_element_size_2; // 250
uint8_t m_pad3[13]; // 251
void* m_array; // 264
#if 0
static inline netArrayHandlerBase* get_by_data(void* data)
{
if (auto array_mgr = *big::g_pointers->m_game_array_mgr)
{
if (auto handler = array_mgr->m_start)
{
do
{
if (handler->m_array == data)
return handler;
}
while (handler = handler->m_next);
}
}
return nullptr;
}
#endif
};
static_assert(sizeof(netArrayHandlerBase) == 272);
}

View File

@ -423,6 +423,24 @@ namespace rage
virtual void unk_0x38() = 0;
};
struct sEntityDamagedData
{
alignas(8) Entity m_victim_index;
alignas(8) Entity m_damager_index;
alignas(8) float m_damage;
alignas(8) float m_endurance_damage;
alignas(8) bool m_victim_incapacitated;
alignas(8) bool m_victim_destroyed;
alignas(8) int m_weapon_used;
alignas(8) float m_victim_speed;
alignas(8) float m_damager_speed;
alignas(8) bool m_is_responsible_for_collision;
alignas(8) bool m_is_headshot;
alignas(8) bool m_is_with_melee_weapon;
alignas(8) int m_hit_material;
};
static_assert(sizeof(sEntityDamagedData) == 0x68);
class netGameEvent
{
public:

View File

@ -4,6 +4,7 @@
#include "../pointers.hpp"
#include "replay.hpp"
class CNetGamePlayer;
namespace rage
{
@ -55,7 +56,6 @@ namespace rage
};
class netObject;
class CNetGamePlayer;
class netObjectMgrBase
{

View File

@ -0,0 +1,25 @@
#include "script_handler.hpp"
#include "pointers.hpp"
#include <network/CNetworkPlayerMgr.hpp>
int CGameScriptHandlerNetComponent::get_participant_index(CNetGamePlayer* player)
{
if (player == (*big::g_pointers->m_network_player_mgr)->m_local_net_player)
return m_local_participant_index;
if (m_num_participants <= 1)
return -1;
for (int i = 0; i < m_num_participants - 1; i++)
{
if (m_participants[i] && m_participants[i]->m_net_game_player == player)
return m_participants[i]->m_participant_index;
}
return -1;
}
bool CGameScriptHandlerNetComponent::is_player_a_participant(CNetGamePlayer* player)
{
return m_participant_bitset & (1 << player->m_player_id);
}

View File

@ -16,10 +16,10 @@ namespace rage
class scriptResourceEntry
{
public:
scriptResource *m_data; // 0x00
scriptResource* m_data; // 0x00
std::uint32_t m_unk; // 0x04
char m_padding[0x0C]; // 0x0C
scriptResourceEntry *m_next; // 0x18
scriptResourceEntry* m_next; // 0x18
};
class scriptHandlerNetComponent
@ -28,7 +28,7 @@ namespace rage
virtual ~scriptHandlerNetComponent() = default;
public:
scriptHandler *m_script_handler; // 0x08
scriptHandler* m_script_handler; // 0x08
};
class scriptHandler
@ -46,9 +46,9 @@ namespace rage
virtual void cleanup_objects() = 0; // 3 (0x18)
virtual scriptId *_0x20() = 0; // 4 (0x20)
virtual scriptId* _0x20() = 0; // 4 (0x20)
virtual scriptId *get_id() = 0; // 5 (0x28)
virtual scriptId* get_id() = 0; // 5 (0x28)
// Returns whether the script handler belongs to a networked script.
virtual bool is_networked() = 0; // 6 (0x30)
@ -84,14 +84,14 @@ namespace rage
virtual void _0x98() = 0; // 19 (0x98)
public:
void *m_0x08; // 0x08
void *m_0x10; // 0x10
scrThread *m_script_thread; // 0x18
void* m_0x08; // 0x08
void* m_0x10; // 0x10
scrThread* m_script_thread; // 0x18
atDList<atDScriptObjectNode> m_objects; // 0x20
scriptResource *m_resource_list_head; // 0x30
scriptResource *m_resource_list_tail; // 0x38
void *m_0x40; // 0x40
scriptHandlerNetComponent *m_net_component; // 0x48
scriptResource* m_resource_list_head; // 0x30
scriptResource* m_resource_list_tail; // 0x38
void* m_0x40; // 0x40
scriptHandlerNetComponent* m_net_component; // 0x48
std::uint32_t m_0x50; // 0x50
std::uint32_t m_0x54; // 0x54
std::uint32_t m_0x58; // 0x58
@ -120,10 +120,10 @@ namespace rage
virtual void _0x38(scrThread*) = 0; // 7 (0x38)
// Allocates and constructs a script handler.
virtual scriptHandler *create_script_handler() = 0; // 8 (0x40)
virtual scriptHandler* create_script_handler() = 0; // 8 (0x40)
// Finds the script handler for a given script id.
virtual scriptHandler *get_script_handler(scriptId*) = 0; // 9 (0x48)
virtual scriptHandler* get_script_handler(scriptId*) = 0; // 9 (0x48)
// Attaches a script thread.
virtual void attach_thread(scrThread*) = 0; // 10 (0x50)
@ -138,13 +138,13 @@ namespace rage
virtual void on_player_left(netPlayer*) = 0; // 13 (0x68)
virtual std::int32_t _0x70() = 0; // 14 (0x70)
virtual void *_0x78() = 0; // 15 (0x78)
virtual void* _0x78() = 0; // 15 (0x78)
public:
char m_padding1[0x28]; // 0x08
bool m_initialized; // 0x30
bool m_initialized2; // 0x31
char m_padding2[0x0E]; // 0x32
rage::netLoggingInterface *m_logger; // 0x40
rage::netLoggingInterface* m_logger; // 0x40
};
}
@ -179,6 +179,17 @@ class CGameScriptHandlerMgr : public rage::scriptHandlerMgr
{
};
class CScriptParticipant
{
public:
char pad_0000[16]; //0x0000
class CNetGamePlayer* m_net_game_player; //0x0010
char pad_0018[2]; //0x0018
int16_t m_participant_index; //0x001A
char pad_001C[12]; //0x001C
}; //Size: 0x0028
static_assert(sizeof(CScriptParticipant) == 0x28);
class CGameScriptHandlerNetComponent
{
public:
@ -255,9 +266,50 @@ public:
virtual bool _0x118() = 0; // related to above function
CGameScriptHandler* m_script_handler; //0x0008
char pad_0010[48]; //0x0010
std::uint32_t m_participants; //0x0040
};
char pad_0010[32]; //0x0010
class CScriptParticipant* m_host; //0x0030
int16_t m_local_participant_index; //0x0038
char pad_003A[6]; //0x003A
uint32_t m_participant_bitset; //0x0040
char pad_0044[36]; //0x0044
class CScriptParticipant* m_participants[32]; //0x0068
char pad_0168[12]; //0x0168
int16_t m_num_participants; //0x0174
char pad_0176[28]; //0x0176
uint8_t m_host_migration_flags; //0x0192
char pad_0193[29]; //0x0193
int get_participant_index(CNetGamePlayer* player);
bool is_player_a_participant(CNetGamePlayer* player);
inline bool is_local_player_host()
{
if (!m_host)
return true; // or return false?
return m_host->m_participant_index == m_local_participant_index;
}
inline CNetGamePlayer* get_host()
{
if (!m_host)
return nullptr;
return m_host->m_net_game_player;
}
// not 100% foolproof
inline void block_host_migration(bool toggle)
{
if (toggle)
m_host_migration_flags |= (1 << 7);
else
m_host_migration_flags &= ~(1 << 7);
}
}; //Size: 0x01B0
static_assert(sizeof(CGameScriptHandlerNetComponent) == 0x1B0);
static_assert(sizeof(rage::scriptHandler) == 0x60);
static_assert(sizeof(CGameScriptHandler) == 0xA0);

View File

@ -4,6 +4,8 @@
#include "joaat.hpp"
#include "tls_context.hpp"
class CGameScriptHandlerNetComponent;
namespace rage
{
enum class eThreadState : std::uint32_t
@ -47,17 +49,17 @@ namespace rage
return rage::tlsContext::get()->m_script_thread;
}
public:
scrThreadContext m_context; // 0x08
void* m_stack; // 0xB0
char m_padding[0x4]; // 0xB8
uint32_t m_arg_size; // 0xBC
uint32_t m_arg_loc; // 0xC0
char m_padding2[0x4]; // 0xC4
const char* m_exit_message; // 0xC8
std::uint32_t m_name_hash; // 0xCC
char m_name[0x40]; // 0xD4
scriptHandler* m_handler; // 0x114
scriptHandlerNetComponent* m_net_component; // 0x11C
scrThreadContext m_context; // 0x08
void* m_stack; // 0xB0
char m_padding[0x4]; // 0xB8
uint32_t m_arg_size; // 0xBC
uint32_t m_arg_loc; // 0xC0
char m_padding2[0x4]; // 0xC4
const char* m_exit_message; // 0xC8
std::uint32_t m_name_hash; // 0xCC
char m_name[0x40]; // 0xD4
scriptHandler* m_handler; // 0x114
CGameScriptHandlerNetComponent* m_net_component; // 0x11C
};
}

View File

@ -8,6 +8,10 @@ namespace rage
public:
scrVector() = default;
scrVector(rage::fvector3 vec) :
x(vec.x), y(vec.y), z(vec.z)
{}
scrVector(float x, float y, float z) :
x(x), y(y), z(z)
{}

View File

@ -2,9 +2,10 @@
#include "gta/array.hpp"
#include "gta/script_thread.hpp"
#include "gta/tls_context.hpp"
#include "ped/CPedFactory.hpp"
#include "pointers.hpp"
#include "network/CNetworkPlayerMgr.hpp"
#include <ped/CPedFactory.hpp>
#include <network/CNetworkPlayerMgr.hpp>
#include <script/scrProgramTable.hpp>
namespace big::gta_util
{
@ -91,4 +92,15 @@ namespace big::gta_util
return nullptr;
}
inline rage::scrProgram* find_script_program(rage::joaat_t hash)
{
for (auto& script : *g_pointers->m_script_program_table)
{
if (script.m_program && script.m_program->m_name_hash == hash)
return script.m_program;
}
return nullptr;
}
}

View File

@ -86,6 +86,15 @@ namespace big
detour_hook_helper::add<hooks::start_matchmaking_find_sessions>("SMFS", g_pointers->m_start_matchmaking_find_sessions);
detour_hook_helper::add<hooks::broadcast_net_array>("BNA", g_pointers->m_broadcast_net_array);
detour_hook_helper::add<hooks::send_session_matchmaking_attributes>("SSMA", g_pointers->m_send_session_matchmaking_attributes);
detour_hook_helper::add<hooks::serialize_take_off_ped_variation_task>("STOPVT", g_pointers->m_serialize_take_off_ped_variation_task);
detour_hook_helper::add<hooks::create_script_handler>("CSH", g_pointers->m_create_script_handler);
detour_hook_helper::add<hooks::set_script_as_networked>("SSAN", g_pointers->m_set_script_as_networked);
g_hooking = this;
}
@ -109,6 +118,12 @@ namespace big
detour_hook_helper->m_detour_hook->enable();
}
for (auto& thread : *g_pointers->m_script_threads)
{
if (thread->m_handler)
hook_script_handler((CGameScriptHandler*)thread->m_handler);
}
MH_ApplyQueued();
m_enabled = true;
@ -133,6 +148,7 @@ namespace big
delete detour_hook_helper;
}
m_detour_hook_helpers.clear();
m_handler_hooks.clear();
}
hooking::detour_hook_helper::~detour_hook_helper()

View File

@ -2,7 +2,6 @@
#include "common.hpp"
#include "detour_hook.hpp"
#include "gta/fwddec.hpp"
#include "gta/net_game_event.hpp"
#include "gta/script_thread.hpp"
#include "vmt_hook.hpp"
#include "MinHook.h"
@ -18,12 +17,26 @@ class SessionSortEntry;
class RemoteGamerInfoMsg;
class CMsgTextMessage;
class CNetGamePlayerDataMsg;
class MatchmakingAttributes;
class CNetworkIncrementStatEvent;
class CScriptedGameEvent;
class NetworkGameFilterMatchmakingComponent;
class ClonedTakeOffPedVariationInfo;
namespace rage
{
class rlMetric;
class snSession;
class JSONNode;
class netArrayHandlerBase;
class CEventNetwork;
class CSyncDataBase;
class netConnectionManager;
namespace netConnection
{
class InFrame;
}
}
namespace big
@ -104,6 +117,17 @@ namespace big
static bool serialize_join_request_message(RemoteGamerInfoMsg* info, void* data, int size, int* bits_serialized);
static bool start_matchmaking_find_sessions(int profile_index, int available_slots, NetworkGameFilterMatchmakingComponent* filter, unsigned int max_sessions, rage::rlSessionInfo* results, int* num_sessions_found, int* status);
static unsigned int broadcast_net_array(rage::netArrayHandlerBase* _this, CNetGamePlayer* target, rage::datBitBuffer* bit_buffer, uint16_t counter, uint32_t* elem_start, bool silent);
static bool send_session_matchmaking_attributes(void* a1, rage::rlSessionInfo* info, std::uint64_t session_id, bool use_session_id, MatchmakingAttributes* attributes);
static void serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer);
static CGameScriptHandler* create_script_handler(CGameScriptHandlerMgr* this_, void* unk);
static bool script_handler_is_networked(CGameScriptHandler* this_);
static bool script_handler_dtor(CGameScriptHandler* this_, bool free_memory);
static void set_script_as_networked(void*, rage::scrThread* thread, int instance_id);
};
class minhook_keepalive
@ -188,6 +212,9 @@ namespace big
return detour_hook_helper::hook_to_detour_hook_helper<detour_function>::m_detour_hook->get_original<decltype(detour_function)>();
}
void hook_script_handler(CGameScriptHandler* handler);
std::unordered_map<CGameScriptHandler*, std::unique_ptr<vmt_hook>> m_handler_hooks;
private:
bool m_enabled{};
minhook_keepalive m_minhook_keepalive;

View File

@ -1,17 +1,43 @@
#include "hooking.hpp"
#include "gta/net_game_event.hpp"
#include "services/players/player_service.hpp"
#include "util/session.hpp"
#include <entities/CDynamicEntity.hpp>
namespace big
{
void hooks::get_network_event_data(int64_t unk, rage::CEventNetwork* net_event)
{
switch (net_event->get_type()) {
case 161: //CEventNetworkRemovedFromSessionDueToComplaints
switch (net_event->get_type())
{
case 161: // CEventNetworkRemovedFromSessionDueToComplaints
{
g_notification_service->push_warning("Kicked", "You have been desync kicked.");
break;
}
case 186: // CEventNetworkEntityDamage
{
rage::sEntityDamagedData damage_data;
net_event->get_extra_information(&damage_data, sizeof(damage_data));
if (damage_data.m_weapon_used == RAGE_JOAAT("weapon_explosion"))
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 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 (reinterpret_cast<CPed*>(damager)->m_damage_bits & (1 << 8))
{
session::add_infraction(player, Infraction::ATTACKING_WITH_GODMODE);
}
}
}
}
break;
}
}
return g_hooking->get_original<get_network_event_data>()(unk, net_event);

View File

@ -7,10 +7,10 @@ namespace big
{
bool hooks::serialize_join_request_message(RemoteGamerInfoMsg* info, void* data, int size, int* bits_serialized)
{
if (info->m_unk == 0)
info->m_unk = 1;
if (info->unk_0xC0 == 0)
info->unk_0xC0 = 1;
info->m_required_player_count = 0;
info->m_num_handles = 0;
return g_hooking->get_original<hooks::serialize_join_request_message>()(info, data, size, bits_serialized);
}
}

View File

@ -1,8 +1,9 @@
#include "hooking.hpp"
#include "services/player_database/player_database_service.hpp"
#include "pointers.hpp"
#include <network/snSession.hpp>
#include <network/CMsgJoinResponse.hpp>
#include <network/CJoinRequestContext.hpp>
#include "services/player_database/player_database_service.hpp"
namespace big
{

View File

@ -1,4 +1,5 @@
#include "hooking.hpp"
#include "gta/net_game_event.hpp"
#include <network/CNetGamePlayer.hpp>
namespace big

View File

@ -4,6 +4,7 @@
#include "gta_util.hpp"
#include "util/session.hpp"
#include "util/spam.hpp"
#include "util/kick.hpp"
#include <network/Network.hpp>
namespace big
@ -70,6 +71,8 @@ namespace big
if (g->session.log_chat_messages)
spam::log_chat(message, player, true);
player->is_spammer = true;
if (g->session.kick_chat_spammers)
kick::breakup_kick(player);
return true;
}
else

View File

@ -1,10 +1,13 @@
#include "gta/enums.hpp"
#include "gta/net_game_event.hpp"
#include "hooking.hpp"
#include <network/CNetGamePlayer.hpp>
#include "gta/script_id.hpp"
#include "util/notify.hpp"
#include "util/math.hpp"
#include "util/toxic.hpp"
#include "fiber_pool.hpp"
#include <base/CObject.hpp>
#include <network/CNetGamePlayer.hpp>
namespace big
{
@ -20,6 +23,180 @@ namespace big
id.m_instance_id = buffer.Read<int32_t>(8);
}
void scan_weapon_damage_event(CNetGamePlayer* player, rage::datBitBuffer* buffer)
{
uint8_t damageType;
uint32_t weaponType; // weaponHash
bool overrideDefaultDamage;
bool hitEntityWeapon;
bool hitWeaponAmmoAttachment;
bool silenced;
uint32_t damageFlags;
bool hasActionResult;
uint32_t actionResultName;
uint16_t actionResultId;
uint32_t f104;
uint32_t weaponDamage;
bool isNetTargetPos;
rage::fvector3 localPos;
bool f112;
uint32_t damageTime;
bool willKill;
uint32_t f120;
bool hasVehicleData;
uint16_t f112_1;
uint16_t parentGlobalId; // Source entity?
uint16_t hitGlobalId; // Target entity?
uint8_t tyreIndex;
uint8_t suspensionIndex;
uint8_t hitComponent;
bool f133;
bool hasImpactDir;
rage::fvector3 impactDir;
damageType = buffer->Read<uint8_t>(2);
weaponType = buffer->Read<uint32_t>(32);
overrideDefaultDamage = buffer->Read<uint8_t>(1);
hitEntityWeapon = buffer->Read<uint8_t>(1);
hitWeaponAmmoAttachment = buffer->Read<uint8_t>(1);
silenced = buffer->Read<uint8_t>(1);
damageFlags = buffer->Read<uint32_t>(24);
// (damageFlags >> 1) & 1
hasActionResult = buffer->Read<uint8_t>(1);
if (hasActionResult)
{
actionResultName = buffer->Read<uint32_t>(32);
actionResultId = buffer->Read<uint16_t>(16);
f104 = buffer->Read<uint32_t>(32);
}
if (overrideDefaultDamage)
{
weaponDamage = buffer->Read<uint32_t>(17);
}
else
{
weaponDamage = 0;
}
bool _f92 = buffer->Read<uint8_t>(1);
if (_f92)
{
buffer->Read<uint8_t>(4);
}
isNetTargetPos = buffer->Read<uint8_t>(1);
if (isNetTargetPos)
{
localPos.x = buffer->ReadSignedFloat(16, 55.f); // divisor: 0x425C0000
localPos.y = buffer->ReadSignedFloat(16, 55.f);
localPos.z = buffer->ReadSignedFloat(16, 55.f);
}
if (damageType == 3)
{
damageTime = buffer->Read<uint32_t>(32);
willKill = buffer->Read<uint8_t>(1);
if (hasActionResult)
{
hitGlobalId = buffer->Read<uint16_t>(13);
}
else
{
hitGlobalId = 0;
}
f112 = buffer->Read<uint8_t>(1);
if (!f112)
{
f112_1 = buffer->Read<uint16_t>(11);
}
else
{
f112_1 = buffer->Read<uint16_t>(16);
}
}
else
{
parentGlobalId = buffer->Read<uint16_t>(13); // +118
hitGlobalId = buffer->Read<uint16_t>(13); // +120
}
if (damageType < 2)
{
localPos.x = buffer->ReadSignedFloat(16, 55.f); // divisor: 0x425C0000
localPos.y = buffer->ReadSignedFloat(16, 55.f);
localPos.z = buffer->ReadSignedFloat(16, 55.f);
if (damageType == 1)
{
hasVehicleData = buffer->Read<uint8_t>(1);
if (hasVehicleData)
{
tyreIndex = buffer->Read<uint8_t>(4); // +122
suspensionIndex = buffer->Read<uint8_t>(4); // +123
}
}
}
else
{
hitComponent = buffer->Read<uint8_t>(5); // +108
}
f133 = buffer->Read<uint8_t>(1);
hasImpactDir = buffer->Read<uint8_t>(1);
if (hasImpactDir)
{
impactDir.x = buffer->ReadSignedFloat(16, 6.2831854820251f); // divisor: 0x40C90FDB
impactDir.y = buffer->ReadSignedFloat(16, 6.2831854820251f);
impactDir.z = buffer->ReadSignedFloat(16, 6.2831854820251f);
}
buffer->Seek(0);
// LOG(INFO) << localPos.x << " " << localPos.y << " " << localPos.z << ". " << math::distance_between_vectors(localPos, *g_local_player->m_navigation->get_position()) << " " << (g_local_player->m_net_object->m_object_id == hitGlobalId ? "TRUE" : "FALSE") << " " << damageType << " " << damageFlags;
if (damageType == 3 && (damageFlags & (1 << 1)) == 0)
hitGlobalId = g_local_player ? g_local_player->m_net_object->m_object_id : 0;
if (g->session.damage_karma && g_local_player && g_local_player->m_net_object && (g_local_player->m_net_object->m_object_id == hitGlobalId || math::distance_between_vectors(localPos, *g_local_player->m_navigation->get_position()) < 1.5f))
{
int id = player->m_player_id;
g_fiber_pool->queue_job([id, hitComponent, overrideDefaultDamage, weaponType, weaponDamage, tyreIndex, suspensionIndex, damageFlags, actionResultName, actionResultId, f104, hitEntityWeapon, hitWeaponAmmoAttachment, silenced, hasImpactDir, impactDir, localPos]
{
auto player = g_player_service->get_by_id(id);
if (!player->is_valid() || !player->get_ped())
return;
g_pointers->m_send_network_damage((CEntity*)g_player_service->get_self()->get_ped(), (CEntity*)player->get_ped(), (rage::fvector3*)&localPos, hitComponent, overrideDefaultDamage, weaponType, weaponDamage,
tyreIndex, suspensionIndex, damageFlags, actionResultName, actionResultId, f104, hitEntityWeapon, hitWeaponAmmoAttachment, silenced, false, player->get_ped()->m_navigation->get_position());
});
}
}
void scan_explosion_event(CNetGamePlayer* player, rage::datBitBuffer* buffer)
{
uint16_t f186;
@ -128,10 +305,22 @@ namespace big
auto object = g_pointers->m_get_net_object(*g_pointers->m_network_object_mgr, ownerNetId, true);
auto entity = object ? object->GetGameObject() : nullptr;
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)
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)
{
g_notification_service->push_error("Warning!", std::format("{} blamed {} for explosion", player->get_name(), reinterpret_cast<CPed*>(entity)->m_player_info->m_net_player_data.m_name));
session::add_infraction(g_player_service->get_by_id(player->m_player_id), Infraction::BLAME_EXPLOSION_DETECTED);
return;
}
if (g->session.explosion_karma && g_local_player && math::distance_between_vectors({ posX, posY, posZ }, *g_local_player->m_navigation->get_position()) < 3.0f)
{
int id = player->m_player_id;
g_fiber_pool->queue_job([id, explosionType, damageScale, cameraShake, isAudible, isInvisible]
{
toxic::blame_explode_player(g_player_service->get_self(), g_player_service->get_by_id(id), explosionType, damageScale, isAudible, isInvisible, cameraShake);
});
}
}
@ -425,7 +614,7 @@ namespace big
case eNetworkEvents::NETWORK_PLAY_SOUND_EVENT:
{
auto plyr = g_player_service->get_by_id(source_player->m_player_id);
if (plyr->m_play_sound_rate_limit.process())
if (plyr && plyr->m_play_sound_rate_limit.process())
{
if (plyr->m_play_sound_rate_limit.exceeded_last_process())
{
@ -434,6 +623,35 @@ namespace big
g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset);
return;
}
bool is_entity = buffer->Read<bool>(1);
std::int16_t entity_net_id;
rage::fvector3 position;
std::uint32_t ref_hash;
if (is_entity)
entity_net_id = buffer->Read<std::int16_t>(13);
else
{
position.x = buffer->ReadSignedFloat(19, 1337.0f);
position.y = buffer->ReadSignedFloat(19, 1337.0f);
position.z = buffer->ReadFloat(19, 1337.0f);
}
bool has_ref = buffer->Read<bool>(1);
if (has_ref)
ref_hash = buffer->Read<std::uint32_t>(32);
std::uint32_t sound_hash = buffer->Read<std::uint32_t>(32);
if (sound_hash == RAGE_JOAAT("Remote_Ring") && plyr)
{
g_notification_service->push_warning("Protections", std::format("Blocked sound annoyance from {}", plyr->get_name()));
g_pointers->m_send_event_ack(event_manager, source_player, target_player, event_index, event_handled_bitset);
return;
}
buffer->Seek(0);
break;
}
case eNetworkEvents::EXPLOSION_EVENT:
@ -441,6 +659,11 @@ namespace big
scan_explosion_event(source_player, buffer);
break;
}
case eNetworkEvents::WEAPON_DAMAGE_EVENT:
{
scan_weapon_damage_event(source_player, buffer);
break;
}
default:
break;
}

View File

@ -1,6 +1,7 @@
#include "hooking.hpp"
#include "gta_util.hpp"
#include "util/session.hpp"
#include "gta/net_game_event.hpp"
#include <network/CNetGamePlayer.hpp>
namespace big
@ -292,6 +293,7 @@ namespace big
}
break;
case eRemoteEvent::StartActivity:
{
eActivityType activity = static_cast<eActivityType>(args[2]);
if (g->protections.script_events.start_activity)
{
@ -335,6 +337,19 @@ namespace big
}
break;
}
case eRemoteEvent::InteriorControl:
int interior = (int)args[2];
if (interior < 0 || interior > 158) // the upper bound will change after an update
{
if (auto plyr = g_player_service->get_by_id(player->m_player_id))
session::add_infraction(plyr, Infraction::TRIED_KICK_PLAYER);
format_string(player_name, "Null Function Kick", notify.null_function_kick.log, notify.null_function_kick.notify);
return true;
}
break;
}
if (g->debug.logs.script_event.logs && (!g->debug.logs.script_event.filter_player || g->debug.logs.script_event.player_id == player->m_player_id))
{

View File

@ -0,0 +1,19 @@
#include "hooking.hpp"
#include "util/notify.hpp"
#include <datanodes/task/ClonedTakeOffPedVariationInfo.hpp>
namespace big
{
void hooks::serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer)
{
g_hooking->get_original<hooks::serialize_take_off_ped_variation_task>()(info, serializer);
if (info->m_prop_hash != 0 &&
info->m_variation_component == 9 &&
info->m_prop_hash != RAGE_JOAAT("p_parachute_s")
)
{
notify::crash_blocked(g->m_syncing_player, "invalid parachute");
info->m_prop_hash = 0;
}
}
}

View File

@ -12,6 +12,15 @@ namespace big
if (g->notifications.gta_thread_kill.notify)
g_notification_service->push("Script Thread Termination", std::format("Script Thread '{}' terminated.", thread->m_name));
if (thread == g->m_hunt_the_beast_thread)
g->m_hunt_the_beast_thread = nullptr;
if (thread == g->m_dance_thread)
g->m_dance_thread = nullptr;
if (thread == g->m_mission_creator_thread)
g->m_mission_creator_thread = nullptr;
return result;
}
}

View File

@ -0,0 +1,72 @@
#include "hooking.hpp"
#include "gta/script_handler.hpp"
bool spoof_networked_status = true;
namespace big
{
void hooking::hook_script_handler(CGameScriptHandler* handler)
{
Hash script_hash = handler->m_script_thread->m_context.m_script_hash;
{
auto hook = std::make_unique<vmt_hook>(handler, 20);
hook->hook(0, &hooks::script_handler_dtor);
hook->hook(6, &hooks::script_handler_is_networked);
hook->enable();
g_hooking->m_handler_hooks[handler] = std::move(hook);
}
}
CGameScriptHandler* hooks::create_script_handler(CGameScriptHandlerMgr* _this, void* unk)
{
auto handler = g_hooking->get_original<hooks::create_script_handler>()(_this, unk);
if (handler == nullptr || handler->m_script_thread == nullptr)
return handler;
g_hooking->hook_script_handler(handler);
return handler;
};
bool hooks::script_handler_is_networked(CGameScriptHandler* _this)
{
if (spoof_networked_status)
return true;
return false;
}
bool hooks::script_handler_dtor(CGameScriptHandler* _this, bool free_memory)
{
vmt_hook* hook;
if (g_hooking->m_handler_hooks.count(_this))
{
hook = g_hooking->m_handler_hooks[_this].get();
if (!hook)
return false;
hook->disable();
auto og_func = hook->get_original<decltype(&script_handler_dtor)>(0);
g_hooking->m_handler_hooks.erase(_this);
return og_func(_this, free_memory);
}
else
{
return false;
}
}
void hooks::set_script_as_networked(void* mgr, rage::scrThread* thread, int instance_id)
{
if (instance_id >= 0x100)
{
LOG(INFO) << "Blocked a crash";
return;
}
spoof_networked_status = false;
g_hooking->get_original<hooks::set_script_as_networked>()(mgr, thread, instance_id);
spoof_networked_status = true;
}
};

View File

@ -0,0 +1,19 @@
#include "hooking.hpp"
#include "network/Network.hpp"
namespace big
{
bool hooks::send_session_matchmaking_attributes(void* a1, rage::rlSessionInfo* info, std::uint64_t session_id, bool use_session_id, MatchmakingAttributes* attributes)
{
if (g->spoofing.spoof_session_region_type)
attributes->m_param_values[4] = g->spoofing.session_region_type;
if (g->spoofing.spoof_session_language)
attributes->m_param_values[3] = g->spoofing.session_language;
if (g->spoofing.spoof_session_player_count)
attributes->m_param_values[7] = g->spoofing.session_player_count;
return g_hooking->get_original<hooks::send_session_matchmaking_attributes>()(a1, info, session_id, use_session_id, attributes);
}
}

View File

@ -1,4 +1,5 @@
#include "hooking.hpp"
#include <datanodes/player/CPlayerGameStateDataNode.hpp>
namespace big
{

View File

@ -0,0 +1,89 @@
#include "hooking.hpp"
#include "gta/net_array.hpp"
#include "script_global.hpp"
#include "script_local.hpp"
#include "util/system.hpp"
#include "util/scripts.hpp"
#include "services/players/player_service.hpp"
namespace big
{
unsigned int hooks::broadcast_net_array(rage::netArrayHandlerBase* _this, CNetGamePlayer* target, rage::datBitBuffer* bit_buffer, uint16_t counter, uint32_t* elem_start, bool silent)
{
int orig_gsbd;
Player orig_player;
int orig_participant;
bool need_to_use_end_session_kick = g_player_service->m_player_to_use_end_session_kick &&
target->m_player_id == g_player_service->m_player_to_use_end_session_kick->get()->id() && _this->m_array == scr_globals::gsbd.as<void*>();
bool need_to_modify_wanted_level = g->session.wanted_level_all && (_this->m_array >= scr_globals::globalplayer_bd.as<uint8_t*>() &&
_this->m_array <= scr_globals::globalplayer_bd.at(31, scr_globals::size::globalplayer_bd).as<uint8_t*>());
bool need_to_turn_player_into_beast = g->m_hunt_the_beast_thread && g->m_hunt_the_beast_thread->m_stack && g->m_hunt_the_beast_thread->m_net_component &&
_this->m_array == script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).as<void*>();
bool need_to_randomize_replay_protection = g->session.block_ceo_money && _this->m_array == scr_globals::gsbd_fm_events.as<void*>();
if (need_to_use_end_session_kick)
{
orig_gsbd = *scr_globals::gsbd.as<int*>();
*scr_globals::gsbd.as<uint32_t*>() = 5;
g_pointers->m_broadcast_patch->apply();
}
if (need_to_modify_wanted_level)
{
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(212).as<Player*>() = target->m_player_id;
g_pointers->m_broadcast_patch->apply();
}
if (need_to_turn_player_into_beast)
{
orig_player = *script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).at(1).at(7).as<Player*>();
orig_participant = *script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).at(1).at(6).as<int*>();
*script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).at(1).at(6).as<int*>() = g->m_hunt_the_beast_thread->m_net_component->get_participant_index(target); // participant idx
*script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).at(1).at(7).as<Player*>() = target->m_player_id; // beast player idx
*script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).at(1).at(2).as<int*>() = INT_MAX; // stopwatch time
*script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).at(83).as<int*>() = 0; // transformed bitset
g_pointers->m_broadcast_patch->apply();
}
if (need_to_randomize_replay_protection)
{
*scr_globals::gsbd_fm_events.at(9).as<uint32_t*>() = __rdtsc();
*scr_globals::gsbd_fm_events.at(10).as<uint32_t*>() = __rdtsc();
g_pointers->m_broadcast_patch->apply();
}
int ret = g_hooking->get_original<hooks::broadcast_net_array>()(_this, target, bit_buffer, counter, elem_start, silent);
if (need_to_use_end_session_kick)
{
g_pointers->m_broadcast_patch->restore();
*scr_globals::gsbd.as<int*>() = orig_gsbd;
}
if (need_to_modify_wanted_level)
{
g_pointers->m_broadcast_patch->restore();
}
if (need_to_turn_player_into_beast)
{
*script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).at(1).at(7).as<Player*>() = orig_player;
*script_local(g->m_hunt_the_beast_thread->m_stack, scr_locals::am_hunt_the_beast::broadcast_idx).at(1).at(6).as<int*>() = orig_participant;
g_pointers->m_broadcast_patch->restore();
}
if (need_to_randomize_replay_protection)
{
g_pointers->m_broadcast_patch->restore();
}
return ret;
}
}

View File

@ -65,7 +65,7 @@ namespace memory
const auto scan_end = module_size - length;
for (std::size_t current_idx{}; current_idx != scan_end;)
{
for (std::size_t sig_idx{ max_idx }; sig_idx >= 0; --sig_idx)
for (std::ptrdiff_t sig_idx{ (std::ptrdiff_t)max_idx }; sig_idx >= 0; --sig_idx)
{
if (sig[sig_idx] && *begin.add(current_idx + sig_idx).as<uint8_t*>() != *sig[sig_idx])
{

View File

@ -2,6 +2,8 @@
#include "native_hooks.hpp"
#include "natives.hpp"
#include "core/scr_globals.hpp"
#include "fiber_pool.hpp"
#include "util/scripts.hpp"
namespace big
{
@ -20,6 +22,16 @@ namespace big
void NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA(rage::scrNativeCallContext* src)
{
if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == RAGE_JOAAT("freemode") && g->session.force_script_host)
{
g_fiber_pool->queue_job([]
{
scripts::force_host(RAGE_JOAAT("freemode"));
if (auto script = gta_util::find_script_thread(RAGE_JOAAT("freemode")); script && script->m_net_component)
script->m_net_component->block_host_migration(true);
});
}
*scr_globals::gsbd.as<int*>() = 4;
src->set_return_value<BOOL>(TRUE);
}

View File

@ -0,0 +1,39 @@
#pragma once
#include "native_hooks.hpp"
#include "natives.hpp"
#include "core/scr_globals.hpp"
#include "fiber_pool.hpp"
#include "util/scripts.hpp"
namespace big
{
namespace creator
{
void GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(rage::scrNativeCallContext* src)
{
const auto hash = src->get_arg<rage::joaat_t>(0);
if (hash == RAGE_JOAAT("freemode") || hash == RAGE_JOAAT("main"))
{
src->set_return_value(0);
return;
}
src->set_return_value(SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(hash));
}
void GET_ENTITY_MODEL(rage::scrNativeCallContext* src)
{
Entity entity = src->get_arg<Entity>(0);
Hash model = ENTITY::GET_ENTITY_MODEL(entity);
if (entity == self::ped)
{
if (model != RAGE_JOAAT("mp_m_freemode_01") && model != RAGE_JOAAT("mp_f_freemode_01"))
model = RAGE_JOAAT("mp_m_freemode_01");
}
src->set_return_value<Hash>(std::move(model));
}
}
}

View File

@ -29,5 +29,17 @@ namespace big
else
ENTITY::SET_ENTITY_VISIBLE(entity, toggle, outfit);
}
void SET_BIGMAP_ACTIVE(rage::scrNativeCallContext* src)
{
if (!g->m_mission_creator_thread)
HUD::SET_BIGMAP_ACTIVE(src->get_arg<BOOL>(0), src->get_arg<BOOL>(1));
};
void SET_BLIP_DISPLAY(rage::scrNativeCallContext* src)
{
if ((!g->m_mission_creator_thread) || src->get_arg<Blip>(0) != HUD::GET_MAIN_PLAYER_BLIP_ID())
HUD::SET_BLIP_DISPLAY(src->get_arg<Blip>(0), src->get_arg<BOOL>(1));
};
}
}

View File

@ -6,6 +6,7 @@
#include "shop_controller.hpp"
#include "network_session_host.hpp"
#include "am_launcher.hpp"
#include "creator.hpp"
#include "crossmap.hpp"
#include <script/scrProgram.hpp>
@ -98,39 +99,51 @@ namespace big
}
}
constexpr auto ALL_SCRIPT_HASH = RAGE_JOAAT("ALL_SCRIPTS");
constexpr auto ALL_SCRIPT_HASH = RAGE_JOAAT("ALL_SCRIPTS");
native_hooks::native_hooks()
{
add_native_detour(0x812595A0644CE1DE, all_scripts::IS_DLC_PRESENT);
add_native_detour(0x5D10B3795F3FC886, all_scripts::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x06843DA7060A026B, carmod_shop::SET_ENTITY_COORDS);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x8E2530AA8ADA980E, carmod_shop::SET_ENTITY_HEADING);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x34E710FF01247C5A, carmod_shop::SET_VEHICLE_LIGHTS);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x767FBC2AC802EF3D, carmod_shop::STAT_GET_INT);
add_native_detour(RAGE_JOAAT("freemode"), 0x95914459A87EBA28, freemode::NETWORK_BAIL);
add_native_detour(RAGE_JOAAT("freemode"), 0x5E9564D8246B909A, freemode::IS_PLAYER_PLAYING);
add_native_detour(RAGE_JOAAT("freemode"), 0xEA1C610A04DB6BBB, freemode::SET_ENTITY_VISIBLE);
add_native_detour(RAGE_JOAAT("shop_controller"), 0xDC38CC1E35B6A5D7, shop_controller::SET_WARNING_MESSAGE_WITH_HEADER);
add_native_detour(RAGE_JOAAT("maintransition"), 0x6F3D4ED9BEE4E61D, network::NETWORK_SESSION_HOST);
add_native_detour(RAGE_JOAAT("am_launcher"), 0xB8BA7F44DF1575E1, am_launcher::START_NEW_SCRIPT_WITH_ARGS);
for (auto& entry : *g_pointers->m_script_program_table)
if (entry.m_program)
hook_program(entry.m_program);
g_native_hooks = this;
}
native_hooks::~native_hooks()
{
m_native_hooks.clear();
g_native_hooks = nullptr;
}
void native_hooks::add_native_detour(rage::scrNativeHash hash, rage::scrNativeHandler detour)
native_hooks::native_hooks()
{
add_native_detour(ALL_SCRIPT_HASH, hash, detour);
add_native_detour(0x812595A0644CE1DE, all_scripts::IS_DLC_PRESENT);
add_native_detour(0x5D10B3795F3FC886, all_scripts::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x06843DA7060A026B, carmod_shop::SET_ENTITY_COORDS);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x8E2530AA8ADA980E, carmod_shop::SET_ENTITY_HEADING);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x34E710FF01247C5A, carmod_shop::SET_VEHICLE_LIGHTS);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x767FBC2AC802EF3D, carmod_shop::STAT_GET_INT);
add_native_detour(RAGE_JOAAT("freemode"), 0x95914459A87EBA28, freemode::NETWORK_BAIL);
add_native_detour(RAGE_JOAAT("freemode"), 0x5E9564D8246B909A, freemode::IS_PLAYER_PLAYING);
add_native_detour(RAGE_JOAAT("freemode"), 0xEA1C610A04DB6BBB, freemode::SET_ENTITY_VISIBLE);
add_native_detour(RAGE_JOAAT("freemode"), 0x231C8F89D0539D8F, freemode::SET_BIGMAP_ACTIVE);
add_native_detour(RAGE_JOAAT("freemode"), 0x9029B2F3DA924928, freemode::SET_BLIP_DISPLAY);
add_native_detour(RAGE_JOAAT("shop_controller"), 0xDC38CC1E35B6A5D7, shop_controller::SET_WARNING_MESSAGE_WITH_HEADER);
add_native_detour(RAGE_JOAAT("maintransition"), 0x6F3D4ED9BEE4E61D, network::NETWORK_SESSION_HOST);
add_native_detour(RAGE_JOAAT("am_launcher"), 0xB8BA7F44DF1575E1, am_launcher::START_NEW_SCRIPT_WITH_ARGS);
add_native_detour(RAGE_JOAAT("fm_race_creator"), 0x2C83A9DA6BFFC4F9, creator::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH);
add_native_detour(RAGE_JOAAT("fm_capture_creator"), 0x2C83A9DA6BFFC4F9, creator::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH);
add_native_detour(RAGE_JOAAT("fm_deathmatch_creator"), 0x2C83A9DA6BFFC4F9, creator::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH);
add_native_detour(RAGE_JOAAT("fm_lts_creator"), 0x2C83A9DA6BFFC4F9, creator::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH);
add_native_detour(RAGE_JOAAT("fm_race_creator"), 0x9F47B058362C84B5, creator::GET_ENTITY_MODEL);
add_native_detour(RAGE_JOAAT("fm_capture_creator"), 0x9F47B058362C84B5, creator::GET_ENTITY_MODEL);
add_native_detour(RAGE_JOAAT("fm_deathmatch_creator"), 0x9F47B058362C84B5, creator::GET_ENTITY_MODEL);
add_native_detour(RAGE_JOAAT("fm_lts_creator"), 0x9F47B058362C84B5, creator::GET_ENTITY_MODEL);
for (auto& entry : *g_pointers->m_script_program_table)
if (entry.m_program)
hook_program(entry.m_program);
g_native_hooks = this;
}
native_hooks::~native_hooks()
{
m_native_hooks.clear();
g_native_hooks = nullptr;
}
void native_hooks::add_native_detour(rage::scrNativeHash hash, rage::scrNativeHandler detour)
{
add_native_detour(ALL_SCRIPT_HASH, hash, detour);
}
void native_hooks::add_native_detour(rage::joaat_t script_hash, rage::scrNativeHash hash, rage::scrNativeHandler detour)
@ -144,27 +157,27 @@ namespace big
m_native_registrations.emplace(script_hash, std::vector<native_detour>({ { hash, detour } }));
}
void native_hooks::hook_program(rage::scrProgram* program)
{
std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler> native_replacements;
const auto script_hash = program->m_name_hash;
void native_hooks::hook_program(rage::scrProgram* program)
{
std::unordered_map<rage::scrNativeHash, rage::scrNativeHandler> native_replacements;
const auto script_hash = program->m_name_hash;
// Functions that need to be detoured for all scripts
if (const auto& pair = m_native_registrations.find(ALL_SCRIPT_HASH); pair != m_native_registrations.end())
for (const auto& native_hook_reg : pair->second)
native_replacements.insert(native_hook_reg);
// Functions that need to be detoured for all scripts
if (const auto& pair = m_native_registrations.find(ALL_SCRIPT_HASH); pair != m_native_registrations.end())
for (const auto& native_hook_reg : pair->second)
native_replacements.insert(native_hook_reg);
// Functions that only need to be detoured for a specific script
if (const auto& pair = m_native_registrations.find(script_hash); pair != m_native_registrations.end())
for (const auto& native_hook_reg : pair->second)
native_replacements.insert(native_hook_reg);
// Functions that only need to be detoured for a specific script
if (const auto& pair = m_native_registrations.find(script_hash); pair != m_native_registrations.end())
for (const auto& native_hook_reg : pair->second)
native_replacements.insert(native_hook_reg);
if (!native_replacements.empty())
{
m_native_hooks.emplace(
if (!native_replacements.empty())
{
m_native_hooks.emplace(
program,
std::make_unique<native_hook>(program, native_replacements)
);
}
}
std::make_unique<native_hook>(program, native_replacements)
);
}
}
}

View File

@ -96,12 +96,6 @@ namespace big
m_swapchain = ptr.add(3).rip().as<IDXGISwapChain**>();
});
// Model Spawn Bypass
main_batch.add("MSB", "48 8B C8 FF 52 30 84 C0 74 05 48", [this](memory::handle ptr)
{
m_model_spawn_bypass = ptr.add(8).as<PVOID>();
});
// World Model Spawn Bypass
main_batch.add("WMSB", "48 85 C0 0F 84 ? ? ? ? 8B 48 50", [this](memory::handle ptr)
{
@ -241,7 +235,7 @@ namespace big
// Blame Explode
main_batch.add("BE", "0F 85 ? ? ? ? 48 8B 05 ? ? ? ? 48 8B 48 08 E8", [this](memory::handle ptr)
{
m_blame_explode = ptr.as<decltype(m_blame_explode)>();
m_blame_explode = memory::byte_patch::make(ptr.as<std::uint16_t*>(), 0xE990).get();
});
// Send NET Info to Lobby
@ -469,7 +463,7 @@ namespace big
// Script VM
main_batch.add("VM", "E8 ? ? ? ? 48 85 FF 48 89 1D", [this](memory::handle ptr)
{
m_script_vm = ptr.add(1).rip().as<PVOID>();
m_script_vm = ptr.add(1).rip().as<functions::script_vm>();
});
// Generate UUID
@ -586,24 +580,92 @@ namespace big
memory::byte_patch::make(ptr.add(1).rip().as<void*>(), std::to_array({ 0xB0, 0x01, 0xC3 }))->apply(); // has no observable side effects
});
// Send Network Damage
main_batch.add("SND", "E8 ? ? ? ? E9 E9 01 00 00 48 8B CB", [this](memory::handle ptr)
{
m_send_network_damage = ptr.add(1).rip().as<functions::send_network_damage>();
});
// Request Ragdoll
main_batch.add("RR", "E8 ? ? ? ? 09 B3 ? ? ? ? 48 8B 5C 24 ?", [this](memory::handle ptr)
{
m_request_ragdoll = ptr.add(1).rip().as<functions::request_ragdoll>();
});
// Get Connection Peer & Send Remove Gamer Command
main_batch.add("GCP&SRGC", "8D 42 FF 83 F8 FD 77 3D", [this](memory::handle ptr)
{
m_get_connection_peer = ptr.add(23).rip().as<functions::get_connection_peer>();
m_send_remove_gamer_cmd = ptr.add(65).rip().as<functions::send_remove_gamer_cmd>();
});
// Handle Remove Gamer Command
main_batch.add("HRGC", "41 FF C6 FF C7", [this](memory::handle ptr)
{
m_handle_remove_gamer_cmd = ptr.sub(0x6E).as<functions::handle_remove_gamer_cmd>();
});
// Broadcast Net Array
main_batch.add("BNA", "48 89 5C 24 ? 48 89 54 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 40 48 8B 05 ? ? ? ? 66 44 89 4C 24 ?", [this](memory::handle ptr)
{
m_broadcast_net_array = ptr.as<PVOID>();
});
// Broadcast Net Array Patch
main_batch.add("BP", "74 73 FF 90 ? ? ? ? 8B D5 4C 8B 00 48 8B C8 41 FF 50 30", [this](memory::handle ptr)
{
m_broadcast_patch = memory::byte_patch::make(ptr.as<uint8_t*>(), 0xEB).get();
});
// Rage Security
main_batch.add("RS", "48 8B ? ? ? ? ? 33 F6 E9 ? ? ? ? 55 48 8D ? ? ? ? ? 48 87 2C 24 C3 48 8B 45 50 0F B6 00", [this](memory::handle ptr)
{
m_security = ptr.add(3).rip().as<rage::atSingleton<rage::RageSecurity>*>();
});
// 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)
{
m_send_session_matchmaking_attributes = ptr.add(1).rip().as<PVOID>();
});
// Serialize Take Off Ped Variation Task
main_batch.add("STOPVT", "40 55 53 57 41 56 48 8B EC 48 83 EC 68", [this](memory::handle ptr)
{
m_serialize_take_off_ped_variation_task = ptr.as<PVOID>();
});
// Chat Data
main_batch.add("CD", "48 8B 05 ? ? ? ? 0F 45 DF", [this](memory::handle ptr)
{
m_chat_data = ptr.add(3).rip().as<ChatData**>();
});
// Create Script Handler
main_batch.add("CSH", "48 8D 05 ? ? ? ? 4C 8D 0D ? ? ? ? 41 83 C8 FF 48 89 03 89 53 70 88 53 74 4C 89 4B 68 48 89 93", [this](memory::handle ptr)
{
m_create_script_handler = *(ptr.add(3).rip().as<std::uint64_t**>() + 8);
});
// Set Script As Networked
main_batch.add("SSAN", "48 89 5C 24 10 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 70 FD", [this](memory::handle ptr)
{
m_set_script_as_networked = ptr.as<PVOID>();
});
// Creator Warp Cheat Triggered Patch
main_batch.add("CW", "74 44 E8 ? ? ? ? 80 65 2B F8 48 8D 0D ? ? ? ? 48 89 4D 17 48 89 7D 1F 89 7D 27 C7 45", [](memory::handle ptr)
{
memory::byte_patch::make(ptr.as<uint8_t*>(), 0xEB)->apply();
});
auto mem_region = memory::module("GTA5.exe");
main_batch.run(mem_region);
memory::batch socialclub_batch;
// Presence Data
socialclub_batch.add("PD", "48 8D 05 ? ? ? ? 48 8B F1 48 89 01 48 8D 99 88 02", [this](memory::handle ptr)
socialclub_batch.add("PD", "48 8D 05 ? ? ? ? 48 8B F1 48 89 01 48 8D 99 90 00 00 00", [this](memory::handle ptr)
{
auto presence_data_vft = ptr.add(3).rip().as<PVOID*>();
m_update_presence_attribute_int = presence_data_vft[1];

View File

@ -60,8 +60,7 @@ namespace big
memory::byte_patch* m_max_wanted_level;
memory::byte_patch* m_max_wanted_level_2;
PVOID m_blame_explode;
PVOID m_model_spawn_bypass;
memory::byte_patch* m_blame_explode;
PVOID m_world_model_spawn_bypass;
PVOID m_native_return;
PVOID m_get_label_text;
@ -154,7 +153,7 @@ namespace big
functions::send_chat_message m_send_chat_message{};
PVOID m_init_native_tables{};
PVOID m_script_vm{};
functions::script_vm m_script_vm{};
functions::generate_uuid m_generate_uuid{};
std::uint64_t* m_host_token{};
@ -182,11 +181,27 @@ namespace big
PVOID m_process_matchmaking_find_response;
PVOID m_serialize_player_data_msg;
// PVOID m_apply_join_request_data;
PVOID m_serialize_join_request_message;
functions::send_network_damage m_send_network_damage;
functions::request_ragdoll m_request_ragdoll;
functions::get_connection_peer m_get_connection_peer{};
functions::send_remove_gamer_cmd m_send_remove_gamer_cmd{};
functions::handle_remove_gamer_cmd m_handle_remove_gamer_cmd{};
PVOID m_broadcast_net_array{};
memory::byte_patch* m_broadcast_patch;
rage::atSingleton<rage::RageSecurity>* m_security;
PVOID m_send_session_matchmaking_attributes;
PVOID m_serialize_take_off_ped_variation_task;
PVOID m_create_script_handler{};
PVOID m_set_script_as_networked{};
};
inline pointers* g_pointers{};

78
src/script_function.cpp Normal file
View File

@ -0,0 +1,78 @@
#include "script_function.hpp"
#include "pointers.hpp"
#include "gta_util.hpp"
#include "util/scripts.hpp"
#include <script/scrProgram.hpp>
#include <script/scrProgramTable.hpp>
namespace big
{
script_function::script_function(const std::string& name, const rage::joaat_t script, const std::string& pattern, int32_t offset) :
m_name(name),
m_script(script),
m_pattern(pattern),
m_offset(offset),
m_ip(0)
{
}
void script_function::populate_ip()
{
if (m_ip == 0)
{
auto program = gta_util::find_script_program(m_script);
if (!program)
return;
auto location = scripts::get_code_location_by_pattern(program, m_pattern);
if (!location)
LOG(FATAL) << "Failed to find pattern " << m_name << " in script " << program->m_name;
else
LOG(DEBUG) << "Found pattern " << m_name << " in script " << program->m_name;
m_ip = location.value() + m_offset;
}
}
void script_function::call(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<std::uint64_t> args)
{
auto tls_ctx = rage::tlsContext::get();
auto stack = (uint64_t*)thread->m_stack;
auto og_thread = tls_ctx->m_script_thread;
tls_ctx->m_script_thread = thread;
tls_ctx->m_is_script_thread_active = true;
rage::scrThreadContext ctx = thread->m_context;
for (auto& arg : args)
stack[ctx.m_stack_pointer++] = arg;
stack[ctx.m_stack_pointer++] = 0;
ctx.m_instruction_pointer = m_ip;
ctx.m_state = rage::eThreadState::idle;
g_pointers->m_script_vm(stack, g_pointers->m_script_globals, program, &ctx);
tls_ctx->m_script_thread = og_thread;
tls_ctx->m_is_script_thread_active = og_thread != nullptr;
}
void script_function::operator()(std::initializer_list<std::uint64_t> args)
{
populate_ip();
if (m_ip == 0)
return;
auto thread = gta_util::find_script_thread(m_script);
auto program = gta_util::find_script_program(m_script);
if (thread && program)
{
call(thread, program, args);
}
}
}

29
src/script_function.hpp Normal file
View File

@ -0,0 +1,29 @@
#pragma once
#include "memory/pattern.hpp"
#include "gta/joaat.hpp"
namespace big
{
// a lightweight script function wrapper inspired by https://github.com/Parik27/V.Rainbomizer/blob/master/src/mission/missions_YscUtils.hh
class script_function
{
rage::joaat_t m_script;
const memory::pattern m_pattern;
int32_t m_offset;
int32_t m_ip;
std::string m_name;
public:
script_function(const std::string& name, const rage::joaat_t script, const std::string& pattern, int32_t offset);
void populate_ip();
void call(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<std::uint64_t> args);
void operator()(std::initializer_list<std::uint64_t> args);
};
namespace scr_functions
{
static inline script_function join_ceo("JC", RAGE_JOAAT("freemode"), "2D 04 1D 00 00 5D", 0);
static inline script_function dance_loop("DL", RAGE_JOAAT("am_mp_nightclub"), "2D 00 14 00 00 4F ? ? 47 ? ? 5D ? ? ? 56", 0);
static inline script_function init_nightclub_script("INS", RAGE_JOAAT("am_mp_nightclub"), "2D 00 11 00 00 4F", 0);
}
}

View File

@ -1,9 +1,15 @@
#pragma once
#include "player_service.hpp"
#include "vehicle/CVehicle.hpp"
#include "network/snSession.hpp"
#include "rate_limiter.hpp"
class CVehicle;
namespace rage
{
class snPlayer;
class snPeer;
}
namespace big
{
class player final

View File

@ -26,6 +26,8 @@ namespace big
void player_service::do_cleanup()
{
m_player_to_use_end_session_kick.reset();
m_player_to_use_complaint_kick.reset();
m_selected_player = m_dummy;
m_players.clear();
}
@ -82,12 +84,20 @@ namespace big
void player_service::player_leave(CNetGamePlayer* net_game_player)
{
if (net_game_player == nullptr) return;
if (net_game_player == nullptr)
return;
if (m_selected_player && m_selected_player->equals(net_game_player))
m_selected_player = m_dummy;
if (auto it = std::find_if(m_players.begin(), m_players.end(), [net_game_player](const auto& p) { return p.second->id() == net_game_player->m_player_id; }); it != m_players.end())
{
if (m_player_to_use_end_session_kick == it->second)
m_player_to_use_end_session_kick = std::nullopt;
if (m_player_to_use_complaint_kick == it->second)
m_player_to_use_complaint_kick = std::nullopt;
m_players.erase(it);
}
}

View File

@ -20,7 +20,6 @@ namespace big
player_ptr m_dummy = std::make_shared<player>(nullptr);
player_ptr m_selected_player;
public:
player_service();
~player_service();
@ -49,6 +48,8 @@ namespace big
void set_selected(player_ptr plyr);
std::optional<player_ptr> m_player_to_use_end_session_kick = std::nullopt;
std::optional<player_ptr> m_player_to_use_complaint_kick = std::nullopt;
};
inline player_service* g_player_service{};

View File

@ -71,8 +71,7 @@ namespace big::entity
return false;
int netHandle = NETWORK::NETWORK_GET_NETWORK_ID_FROM_ENTITY(ent);
NETWORK::SET_NETWORK_ID_CAN_MIGRATE(netHandle, false);
NETWORK::NETWORK_DISABLE_PROXIMITY_MIGRATION(netHandle);
NETWORK::SET_NETWORK_ID_CAN_MIGRATE(netHandle, true);
return true;
}

164
src/util/kick.hpp Normal file
View File

@ -0,0 +1,164 @@
#pragma once
#include "pointers.hpp"
#include "gta_util.hpp"
#include <network/Network.hpp>
#include "packet.hpp"
#include "gta/script_handler.hpp"
#include "util/scripts.hpp"
namespace
{
void gamer_handle_serialize(rage::rlGamerHandle& hnd, rage::datBitBuffer& buf)
{
buf.Write<uint8_t>(*reinterpret_cast<uint8_t*>(&hnd.m_platform), 8);
if (*reinterpret_cast<uint8_t*>(&hnd.m_platform) == 3)
{
buf.WriteInt64(*(int64_t*)&hnd.m_rockstar_id, 64);
buf.Write<uint8_t>(*reinterpret_cast<uint8_t*>(reinterpret_cast<__int64>(&hnd) + 9), 8);
}
}
}
namespace big::kick
{
inline void bail_kick(player_ptr target)
{
const size_t arg_count = 3;
int64_t args[arg_count] =
{
(int64_t)eRemoteEvent::Kick,
(int64_t)self::id,
*scr_globals::gpbd_fm_3.at(target->id(), scr_globals::size::gpbd_fm_3).at(510).as<int64_t*>()
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
inline void kick_player_script_host(player_ptr target)
{
if (!scripts::force_host(RAGE_JOAAT("freemode")))
{
g_notification_service->push_error("Kick", "Force script host failed!");
return;
}
*scr_globals::gsbd_kicking.at(target->id(), 1).as<bool*>() = true;
}
inline void end_session_kick(player_ptr target)
{
if (!scripts::force_host(RAGE_JOAAT("freemode")))
{
g_notification_service->push_error("Kick", "Force script host failed!");
return;
}
g_player_service->m_player_to_use_end_session_kick = target;
*scr_globals::gsbd.as<int*>() = (int)(__rdtsc() % 50000) + 6; // making the game trigger the broadcast is a bit difficult and requires a little bit of tampering with the value and luck
}
inline std::chrono::system_clock::time_point last_oom_kick_time{};
inline void oom_kick(player_ptr target)
{
if (std::chrono::system_clock::now() - last_oom_kick_time < 7s)
{
g_notification_service->push_error("Kick", "Don't spam this or it will backfire");
return;
}
last_oom_kick_time = std::chrono::system_clock::now();
if (auto freemode = gta_util::find_script_thread(RAGE_JOAAT("freemode")))
{
packet msg{};
msg.write_message(rage::eNetMessage::MsgScriptMigrateHost);
freemode->m_handler->get_id()->serialize(&msg.m_buffer);
msg.write<int>(0, 16);
msg.write<int>(0, 32);
auto msg_id = target->get_net_game_player()->m_msg_id;
for (int j = 0; j < 2100; j++)
{
msg.send(msg_id);
}
}
}
inline void lost_connection_kick(player_ptr target)
{
if (gta_util::get_network()->m_game_session_ptr->is_host())
{
g_notification_service->push_error("Kick", "Cannot use the lost connection kick while host");
return;
}
packet msg{};
msg.write_message(rage::eNetMessage::MsgLostConnectionToHost);
msg.write<uint64_t>(gta_util::get_network()->m_game_session_ptr->m_rline_session.m_session_id, 64);
gamer_handle_serialize((*(rage::rlGamerHandle*)(&target->get_net_data()->m_gamer_handle_2.m_rockstar_id)), msg);
for (auto& [_, plyr] : g_player_service->players())
{
if (plyr->is_host())
{
msg.send(plyr->get_session_player()->m_msg_id);
break;
}
}
}
inline void breakup_kick(player_ptr target)
{
rage::snMsgRemoveGamersFromSessionCmd cmd{};
cmd.m_session_id = gta_util::get_network()->m_game_session_ptr->m_rline_session.m_session_id;
cmd.m_num_peers = 1;
cmd.m_peer_ids[0] = target->get_session_peer()->m_peer_data.m_peer_id_2;
g_pointers->m_handle_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr, target->get_session_player(), &cmd);
for (auto& [_, plyr] : g_player_service->players())
{
if (plyr->id() != target->id())
g_pointers->m_send_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr,
g_pointers->m_get_connection_peer(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr, (int)plyr->get_session_player()->m_player_data.m_peer_id_2),
gta_util::get_network()->m_game_session_ptr->m_connection_identifier, &cmd, 0x1000000);
}
}
inline void host_kick(player_ptr target)
{
if (!g_player_service->get_self()->is_host())
{
g_notification_service->push_error("Kick", "You have to be the session host");
return;
}
rage::snMsgRemoveGamersFromSessionCmd cmd{};
cmd.m_session_id = gta_util::get_network()->m_game_session_ptr->m_rline_session.m_session_id;
cmd.m_num_peers = 1;
cmd.m_peer_ids[0] = target->get_session_peer()->m_peer_data.m_peer_id_2;
g_pointers->m_handle_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr, target->get_session_player(), &cmd);
}
inline void complaint_kick(player_ptr target)
{
if (gta_util::get_network()->m_game_session_ptr->is_host())
{
g_notification_service->push_error("Kick", "Cannot use the complaint kick while host");
return;
}
g_player_service->m_player_to_use_complaint_kick = target;
}
inline void null_function_kick(player_ptr target)
{
const size_t arg_count = 15;
int64_t args[arg_count] =
{
(int64_t)eRemoteEvent::InteriorControl,
(int64_t)self::id,
(int64_t)(int)-1
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
}

View File

@ -71,9 +71,7 @@ namespace big::ped
return 0;
}
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x9090;
auto ped = PED::CREATE_PED(pedType, hash, location.x, location.y, location.z, heading, is_networked, false);
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x0574;
script::get_current()->yield();

View File

@ -7,6 +7,8 @@
#include "gta/script_handler.hpp"
#include "script_local.hpp"
#include "core/scr_globals.hpp"
#include "services/players/player_service.hpp"
#include <memory/pattern.hpp>
namespace big::scripts
{
@ -50,6 +52,26 @@ namespace big::scripts
return false;
}
inline bool force_host(rage::joaat_t hash)
{
if (auto launcher = gta_util::find_script_thread(hash); launcher && launcher->m_net_component)
{
for (int i = 0; !launcher->m_net_component->is_local_player_host(); i++)
{
if (i > 200)
return false;
((CGameScriptHandlerNetComponent*)launcher->m_net_component)->send_host_migration_event(g_player_service->get_self()->get_net_game_player());
script::get_current()->yield(10ms);
if (!launcher->m_stack || !launcher->m_net_component)
return false;
}
}
return true;
}
// force launcher script over the lobby, take two
// try to get am_launcher in a consistent state before trying to start the script taking account of all participants
inline void start_launcher_script(int script_id)
@ -58,20 +80,20 @@ namespace big::scripts
{
bool set = false;
gta_util::execute_as_script(RAGE_JOAAT("am_launcher"), [launcher, state, &set]
if (!launcher->m_net_component)
return false;
for (auto& [_, plyr] : g_player_service->players())
{
for (auto& [_, plyr] : g_player_service->players())
if (launcher->m_net_component->is_player_a_participant(plyr->get_net_game_player()))
{
if (NETWORK::NETWORK_IS_PLAYER_A_PARTICIPANT(plyr->id()))
if (*script_local(launcher->m_stack, 230).at(plyr->id(), 3).at(2).as<int*>() == state)
{
if (*script_local(launcher->m_stack, 230).at(plyr->id(), 3).at(2).as<int*>() == state)
{
set = true;
break;
}
set = true;
break;
}
}
});
}
return set;
};
@ -80,17 +102,11 @@ namespace big::scripts
if (auto launcher = gta_util::find_script_thread(RAGE_JOAAT("am_launcher")))
{
// 2) Force host of launcher
for (int i = 0; NETWORK::NETWORK_GET_HOST_OF_SCRIPT("am_launcher", -1, 0) != self::id; i++)
if (!force_host(RAGE_JOAAT("am_launcher")))
{
if (i > 3600)
{
// 2F) Failed to force host of launcher
g_notification_service->push_error("Script", "Cannot force script host of am_launcher");
return;
}
((CGameScriptHandlerNetComponent*)launcher->m_net_component)->send_host_migration_event(g_player_service->get_self()->get_net_game_player());
script::get_current()->yield();
// 2F) Failed to force host of launcher
g_notification_service->push_error("Script", "Cannot force script host of am_launcher");
return;
}
launcher->m_context.m_state = rage::eThreadState::unk_3; // prevent bad things from happening to the thread in the meantime
@ -150,4 +166,91 @@ namespace big::scripts
g_notification_service->push_error("Script", "Cannot start script, am_launcher not running locally");
}
}
inline const std::optional<uint32_t> get_code_location_by_pattern(rage::scrProgram* program, const memory::pattern& pattern)
{
std::uint32_t code_size = program->m_code_size;
for (std::uint32_t i = 0; i < (code_size - pattern.m_bytes.size()); i++)
{
for (std::uint32_t j = 0; j < pattern.m_bytes.size(); j++)
if (pattern.m_bytes[j].has_value())
if (pattern.m_bytes[j].value() != *program->get_code_address(i + j))
goto incorrect;
return i;
incorrect:
continue;
}
return std::nullopt;
}
// we can't use the script patch service for this
inline void patch_script(rage::scrProgram* program, std::optional<std::uint32_t> location, std::vector<std::uint8_t> patch, int offset)
{
std::uint8_t* bytearray = patch.data();
if (location)
memcpy(program->get_code_address(location.value() + offset), bytearray, patch.size());
}
inline void start_creator_script(rage::joaat_t hash)
{
static auto read_uint24_t = [](uint8_t* arr)
{
return arr[0] + (arr[1] << 8) + (arr[2] << 16);
};
if (g->m_mission_creator_thread ||
SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("creator")) != 0 ||
SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) != 0 ||
STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS() ||
CUTSCENE::IS_CUTSCENE_ACTIVE())
{
g_notification_service->push_warning("Creator", "Cannot start creator now");
return;
}
if (MISC::GET_NUMBER_OF_FREE_STACKS_OF_THIS_SIZE(51000) == 0)
{
g_notification_service->push_warning("Creator", "No free stacks for MISSION stack size");
}
while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(hash))
{
SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(hash);
script::get_current()->yield();
}
*scr_globals::terminate_creator.as<bool*>() = false;
*scr_globals::mission_creator_exited.as<bool*>() = false;
*scr_globals::mission_creator_radar_follows_camera.as<bool*>() = true;
if (SYSTEM::START_NEW_SCRIPT_WITH_NAME_HASH(hash, 51000))
{
g->m_mission_creator_thread = gta_util::find_script_thread(hash);
}
if (auto program = gta_util::find_script_program(hash))
{
patch_script(program, get_code_location_by_pattern(program, "2D 02 04 00 ? 38 01 38 00 42 13"), {
0x6F, // PUSH_CONST_1
0x00 // NOP
}, 5); // place anywhere
patch_script(program, get_code_location_by_pattern(program, "6E 08 2A 56 ? ? 2C ? ? ? 1F 56 ? ? 6F"), {
0x00, 0x00, 0x00, 0x00, 0x00
}, 0xE); // don't bail on network mode
if (auto loc = get_code_location_by_pattern(program, "39 04 5D ? ? ? 6E"))
{
patch_script(program, read_uint24_t(program->get_code_address(loc.value() + 3)), {
0x70, // PUSH_CONST_2 0 = mp, 2 = creator, 999 = singleplayer
0x2E, 0x00, 0x01 // LEAVE 0 1
}, 5); // allow fast zoom in mp
}
}
SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(hash);
}
}

View File

@ -50,11 +50,13 @@ namespace big::session
misc::set_bit(scr_globals::gpbd_fm_3.at(self::id, scr_globals::size::gpbd_fm_3).at(10).at(205).at(idx, 1).as<int*>(), bit);
}
inline void force_thunder()
inline void clear_fm_event_index(int index)
{
session::set_fm_event_index(9);
session::set_fm_event_index(10);
session::set_fm_event_index(11);
int idx = index / 32;
int bit = index % 32;
misc::clear_bit(scr_globals::gsbd_fm_events.at(11).at(341).at(idx, 1).as<int*>(), bit);
misc::clear_bit(scr_globals::gsbd_fm_events.at(11).at(348).at(idx, 1).as<int*>(), bit);
misc::clear_bit(scr_globals::gpbd_fm_3.at(self::id, scr_globals::size::gpbd_fm_3).at(10).at(205).at(idx, 1).as<int*>(), bit);
}
inline void join_session(const rage::rlSessionInfo& info)
@ -109,4 +111,48 @@ namespace big::session
g_player_database_service->save();
}
}
inline void give_collectible(Player target, eCollectibleType col, int index = 0, bool uncomplete = false)
{
const size_t arg_count = 7;
int64_t args[arg_count] = {
(int64_t)eRemoteEvent::GiveCollectible,
(int64_t)self::id,
(int64_t)col, // iParam0
(int64_t)index, // iParam1
!uncomplete, // bParam2
true,
0 // bParam3
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target);
}
// TODO this is really broken
inline void enter_player_interior(player_ptr player)
{
if (*scr_globals::globalplayer_bd.at(player->id(), scr_globals::size::globalplayer_bd).at(318).at(6).as<int*>() == -1)
{
g_notification_service->push_error("Enter Interior", "Player does not seem to be in an interior");
return;
}
int owner = *scr_globals::globalplayer_bd.at(player->id(), scr_globals::size::globalplayer_bd).at(318).at(9).as<int*>();
if (owner == -1)
owner = player->id();
*script_global(1946250).at(3607).as<int*>() = 0;
*script_global(1946250).at(3605).as<int*>() = 1;
*script_global(1946250).at(4703).as<int*>() = 1;
*script_global(1946250).at(3218).as<int*>() = 1;
*script_global(1946250).at(3214).as<int*>() = 1;
*script_global(1946250).at(3612).as<int*>() = 1;
// misc::set_bit(script_global(1946250).at(1).as<int*>(), 22);
misc::set_bit(script_global(1946250).as<int*>(), 6);
misc::clear_bit(script_global(1946250).at(1).as<int*>(), 9);
*script_global(1946250).at(3280).as<int*>() = owner;
*script_global(1946250).at(3606).as<int*>() = *scr_globals::globalplayer_bd.at(player->id(), scr_globals::size::globalplayer_bd).at(318).at(6).as<int*>();
}
}

View File

@ -13,6 +13,7 @@ namespace
".CN",
".TOP",
".COM",
".top",
"\xE3\x80\x90",
"/Menu",
"Money/",

View File

@ -29,9 +29,4 @@ namespace big::system
return (uintptr_t)ptr - base_address;
}
inline void patch_blame(bool toggle)
{
*(unsigned short*)g_pointers->m_blame_explode = toggle ? 0xE990 : 0x850F;
}
}

View File

@ -2,38 +2,41 @@
#include "blip.hpp"
#include "entity.hpp"
#include "gta/enums.hpp"
#include "services/players/player_service.hpp"
namespace big::teleport
{
inline bool bring_player(Player player)
inline bool teleport_player_to_coords(player_ptr player, Vector3 coords)
{
Entity ent = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player);
Entity ent = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id());
if (ENTITY::IS_ENTITY_DEAD(ent, true))
{
g_notification_service->push_warning("Teleport", "Target player is dead.");
return false;
}
if (!PED::IS_PED_IN_ANY_VEHICLE(ent, true))
{
g_notification_service->push_warning("Teleport", "Target player is not in a vehicle.");
return false;
}
ent = PED::GET_VEHICLE_PED_IS_IN(ent, false);
Vector3 location = self::pos;
if (entity::take_control_of(ent))
ENTITY::SET_ENTITY_COORDS(ent, location.x, location.y, location.z, 0, 0, 0, 0);
ENTITY::SET_ENTITY_COORDS(ent, coords.x, coords.y, coords.z, 0, 0, 0, 0);
else
g_notification_service->push_warning("Teleport", "Failed to take control of player vehicle.");
return true;
}
inline bool bring_player(player_ptr player)
{
return teleport_player_to_coords(player, self::pos);
}
inline bool load_ground_at_3dcoord(Vector3& location)
{
float groundZ;

396
src/util/toxic.hpp Normal file
View File

@ -0,0 +1,396 @@
#pragma once
#include "pointers.hpp"
#include "core/scr_globals.hpp"
#include "core/enums.hpp"
#include "gta/net_object_mgr.hpp"
#include "gta/PickupRewards.h"
#include "util/session.hpp"
#include "util/scripts.hpp"
#include "services/gta_data/gta_data_service.hpp"
#include "util/system.hpp"
namespace big::toxic
{
inline void blame_explode_coord(player_ptr to_blame, Vector3 pos, eExplosionTag explosion_type, float damage, bool is_audible, bool is_invisible, float camera_shake)
{
g_pointers->m_blame_explode->apply();
FIRE::ADD_OWNED_EXPLOSION(
PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(to_blame->id()),
pos.x, pos.y, pos.z,
(int)explosion_type,
damage,
is_audible,
is_invisible,
camera_shake
);
g_pointers->m_blame_explode->restore();
}
inline void blame_explode_player(player_ptr to_blame, player_ptr target, eExplosionTag explosion_type, float damage, bool is_audible, bool is_invisible, float camera_shake)
{
Vector3 coords = ENTITY::GET_ENTITY_COORDS(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(target->id()), true);
blame_explode_coord(to_blame, coords, explosion_type, damage, is_audible, is_invisible, camera_shake);
}
inline void ceo_kick(player_ptr target)
{
auto leader = *scr_globals::gpbd_fm_3.at(target->id(), scr_globals::size::gpbd_fm_3).at(10).as<int*>();
if (leader == -1)
g_notification_service->push_warning("CEO Kick", "Player is not in a CEO/MC");
else if (leader == target->id())
{
// use "normal" method to remove from CEO
const size_t arg_count = 4;
int64_t args[arg_count] = {
(int64_t)eRemoteEvent::CeoKick,
(int64_t)self::id,
FALSE,
5
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
else
{
// use a more private method to remove associate
const size_t arg_count = 3;
int64_t args[arg_count] = {
(int64_t)eRemoteEvent::MarkPlayerAsBeast,
(int64_t)self::id,
leader
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
}
inline void ceo_ban(player_ptr target)
{
const size_t arg_count = 3;
int64_t args[arg_count] = {
(int64_t)eRemoteEvent::CeoBan,
(int64_t)self::id,
TRUE
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
inline void send_player_to_island(player_ptr target)
{
const size_t arg_count = 2;
int64_t args[arg_count] = {
(int64_t)eRemoteEvent::SendToCayoPerico,
(int64_t)self::id,
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
inline void send_player_to_apartment(player_ptr target, int index)
{
const size_t arg_count = 9;
int64_t args[arg_count] = {
(int64_t)eRemoteEvent::Teleport,
self::id,
(int64_t)target->id(),
(int64_t)(int)-1, 1, (int64_t)index, 1, 1, 1
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
inline void send_player_to_warehouse(player_ptr target, int index)
{
const size_t arg_count = 6;
int64_t args[arg_count] = {
(int64_t)eRemoteEvent::TeleportToWarehouse,
self::id,
(int64_t)target->id(),
1,
index
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
inline void send_player_to_interior(player_ptr player, int interior)
{
float max = 1e+38f;
auto coords = ENTITY::GET_ENTITY_COORDS(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id()), FALSE);
const size_t arg_count = 15;
int64_t args[arg_count] =
{
(int64_t)eRemoteEvent::InteriorControl,
(int64_t)self::id,
(int64_t)(int)interior,
(int64_t)self::id,
(int64_t)false,
(int64_t)true, // true means enter sender interior
(int64_t)*(uint32_t*)&coords.x,
(int64_t)*(uint32_t*)&coords.y,
(int64_t)*(uint32_t*)&coords.z,
0,
0,
1,
(int64_t)*(uint32_t*)&max,
(int64_t)true,
-1
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << player->id());
}
inline void kick_player_from_vehicle(player_ptr target)
{
auto vehicle = target->get_current_vehicle();
if (!vehicle || !vehicle->m_net_object)
{
// vehicle hasn't synced yet, use TSE
const size_t arg_count = 9;
int64_t args[arg_count] = {
(int64_t)eRemoteEvent::VehicleKick,
self::id, 0, 0, 0, 0, 0, 0, 0
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
else
{
// use a private method to kick player from vehicle
(*g_pointers->m_network_object_mgr)->ChangeOwner(vehicle->m_net_object, g_player_service->get_self()->get_net_game_player(), 0);
}
}
inline void ragdoll_player(player_ptr target)
{
if (auto ped = target->get_ped())
if (auto net_object = ped->m_net_object)
g_pointers->m_request_ragdoll(net_object->m_object_id);
}
inline void start_activity(player_ptr target, eActivityType type)
{
const size_t arg_count = 4;
int64_t args[arg_count] =
{
(int64_t)eRemoteEvent::StartActivity,
(int64_t)self::id,
(int64_t)type,
(int64_t)true
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
inline void kick_player_from_interior(player_ptr target)
{
const size_t arg_count = 8;
int64_t args[arg_count]{
(int64_t)eRemoteEvent::KickFromInterior,
(int64_t)self::id,
*scr_globals::globalplayer_bd.at(target->id(), scr_globals::size::globalplayer_bd).at(318).at(6).as<int64_t*>(),
*scr_globals::globalplayer_bd.at(target->id(), scr_globals::size::globalplayer_bd).at(318).at(7).as<int64_t*>(),
};
g_pointers->m_trigger_script_event(1, args, arg_count, 1 << target->id());
}
inline void turn_player_into_animal(player_ptr target)
{
bool bOldPlayerControl = PLAYER::IS_PLAYER_CONTROL_ON(target->id());
for (int i = 0; i < 30; i++)
{
session::give_collectible(target->id(), eCollectibleType::Treat, 0, false);
session::give_collectible(target->id(), eCollectibleType::Treat, 0, true);
g_pointers->m_give_pickup_rewards(1 << target->id(), REWARD_HEALTH); // try to keep them alive
g_pointers->m_give_pickup_rewards(1 << target->id(), REWARD_ARMOUR);
script::get_current()->yield(400ms);
Ped playerPed = PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(target->id());
Hash model = ENTITY::GET_ENTITY_MODEL(playerPed);
if (bOldPlayerControl && !PLAYER::IS_PLAYER_CONTROL_ON(target->id()))
return;
if (model != RAGE_JOAAT("mp_m_freemode_01") && model != RAGE_JOAAT("mp_f_freemode_01"))
return;
if (ENTITY::IS_ENTITY_DEAD(playerPed, FALSE))
script::get_current()->yield(7s);
}
g_notification_service->push_warning("Turn to Animal", "Failed to turn player into an animal");
}
inline void set_wanted_level(player_ptr target, int wanted_level)
{
int id = target->id();
if (PLAYER::GET_PLAYER_WANTED_LEVEL(id) > wanted_level)
{
// clear existing wanted
globals::clear_wanted_player(id);
for (int i = 0; PLAYER::GET_PLAYER_WANTED_LEVEL(id) > wanted_level && i < 3600; i++)
script::get_current()->yield(1ms);
}
if (wanted_level > 0)
{
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(212).as<Player*>() = id;
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(213).as<int*>() = wanted_level;
for (int i = 0; PLAYER::GET_PLAYER_WANTED_LEVEL(id) < wanted_level && i < 3600; i++)
script::get_current()->yield(1ms);
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(212).as<Player*>() = -1; // reset to prevent wanted from being constantly set
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(213).as<int*>() = -1;
}
}
inline void turn_player_into_beast(player_ptr target)
{
auto id = target->id();
if (!NETWORK::NETWORK_IS_PLAYER_A_PARTICIPANT_ON_SCRIPT(id, "am_hunt_the_beast", -1))
{
if (!NETWORK::NETWORK_IS_PLAYER_A_PARTICIPANT_ON_SCRIPT(id, "am_launcher", -1))
{
g_notification_service->push_error("Turn to Beast", "Cannot start the Hunt the Beast event, player not a participant of am_launcher");
return;
}
g_notification_service->push("Turn to Beast", "Starting Hunt The Beast event. Please wait...");
scripts::start_launcher_script(47);
for (int i = 0; !NETWORK::NETWORK_IS_PLAYER_A_PARTICIPANT_ON_SCRIPT(id, "am_hunt_the_beast", -1); i++)
{
if (i >= 1000)
{
g_notification_service->push_error("Turn to Beast", "Failed to start the Hunt The Beast event");
return;
}
script::get_current()->yield(1ms);
}
}
if (!NETWORK::NETWORK_IS_PLAYER_CONNECTED(id))
return;
if (!scripts::force_host(RAGE_JOAAT("am_hunt_the_beast")))
{
g_notification_service->push_error("Turn to Beast", "Failed to take control of am_hunt_the_beast");
return;
}
auto thread = gta_util::find_script_thread(RAGE_JOAAT("am_hunt_the_beast"));
auto stack = thread->m_stack;
auto net_component = thread->m_net_component;
auto idx = scr_locals::am_hunt_the_beast::broadcast_idx;
if (!stack || !net_component || !target->is_valid())
return;
*script_local(stack, idx).as<int*>() = 1;
*script_local(stack, idx).at(1).as<int*>() = 2; // stage
*script_local(stack, idx).at(1).at(6).as<int*>() = net_component->get_participant_index(target->get_net_game_player()); // beast participant idx
*script_local(stack, idx).at(1).at(7).as<Player*>() = id; // beast player idx
*script_local(stack, idx).at(1).at(2).as<int*>() = INT_MAX; // stopwatch time
*script_local(stack, idx).at(1).at(2).at(1).as<bool*>() = true; // stopwatch initialized
*script_local(stack, idx).at(1).at(4).at(1).as<bool*>() = false; // destroy old stage 1 stopwatch
*script_local(stack, idx).at(1).at(9).as<int*>() = 2; // some distance check
*script_local(stack, idx).at(83).as<int*>() = 0; // transformed bitset
}
inline void turn_everyone_into_beast()
{
scripts::start_launcher_script(47);
for (int i = 0; !scripts::is_running(RAGE_JOAAT("am_launcher")); i++)
{
if (i >= 7000)
{
g_notification_service->push_error("Turn to Beast", "Failed to start the Hunt The Beast event");
return;
}
script::get_current()->yield(1ms);
}
script::get_current()->yield(500ms);
if (!scripts::force_host(RAGE_JOAAT("am_hunt_the_beast")))
{
g_notification_service->push_error("Turn to Beast", "Failed to take control of am_hunt_the_beast");
return;
}
script::get_current()->yield(3s);
auto thread = gta_util::find_script_thread(RAGE_JOAAT("am_hunt_the_beast"));
if (!thread)
return;
auto stack = thread->m_stack;
auto net_component = thread->m_net_component;
auto idx = scr_locals::am_hunt_the_beast::broadcast_idx;
if (!stack || !net_component)
return;
thread->m_net_component->block_host_migration(true);
thread->m_context.m_state = rage::eThreadState::unk_3;
g->m_hunt_the_beast_thread = thread;
for (int i = 0; i < 15; i++)
{
*script_local(stack, idx).as<int*>() = 1;
*script_local(stack, idx).at(1).as<int*>() = 2; // stage
*script_local(stack, idx).at(1).at(6).as<int*>() = __rdtsc(); // participant idx
*script_local(stack, idx).at(1).at(7).as<Player*>() = __rdtsc(); // beast player idx
*script_local(stack, idx).at(1).at(2).as<int*>() = INT_MAX; // stopwatch time
*script_local(stack, idx).at(1).at(2).at(1).as<bool*>() = true; // stopwatch initialized
*script_local(stack, idx).at(1).at(4).at(1).as<bool*>() = false; // destroy old stage 1 stopwatch
*script_local(stack, idx).at(1).at(9).as<int*>() = 2; // some distance check
*script_local(stack, idx).at(83).as<int*>() = 0; // transformed bitset
script::get_current()->yield(350ms);
}
// unfortunately we must also turn ourselves into the beast to prevent the script from exiting due to a "missing player"
*script_local(stack, idx).at(1).at(6).as<int*>() = net_component->m_local_participant_index; // participant idx
*script_local(stack, idx).at(1).at(7).as<Player*>() = self::id; // beast player idx
*script_local(stack, idx).at(1).at(2).as<int*>() = INT_MAX; // stopwatch time
*script_local(stack, idx).at(83).as<int*>() = 0; // transformed bitset
thread->m_context.m_state = rage::eThreadState::running;
}
// the blamed player cannot be the target itself
inline void kill_player(player_ptr player, player_ptr to_blame)
{
if (!player->get_ped() || !to_blame->get_ped())
return;
g_pointers->m_send_network_damage((CEntity*)to_blame->get_ped(), (CEntity*)player->get_ped(), player->get_ped()->m_navigation->get_position(),
0, true, RAGE_JOAAT("weapon_explosion"), 10000.0f, 2, 0, (1 << 4), 0, 0, 0, false, false, true, true, nullptr);
}
inline void give_all_weapons(player_ptr target)
{
for (auto& weapon : g_gta_data_service->weapons())
WEAPON::GIVE_WEAPON_TO_PED(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(target->id()), weapon.second.m_hash, 9999, FALSE, FALSE);
}
inline void remove_all_weapons(player_ptr target)
{
WEAPON::REMOVE_ALL_PED_WEAPONS(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(target->id()), FALSE);
}
}

View File

@ -184,7 +184,7 @@ namespace big::vehicle
return true;
}
inline Vehicle spawn(Hash hash, Vector3 location, float heading, bool is_networked = true)
inline Vehicle spawn(Hash hash, Vector3 location, float heading, bool is_networked = true, bool script_veh = false)
{
for (uint8_t i = 0; !STREAMING::HAS_MODEL_LOADED(hash) && i < 100; i++)
{
@ -197,9 +197,7 @@ namespace big::vehicle
return 0;
}
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x9090;
auto veh = VEHICLE::CREATE_VEHICLE(hash, location.x, location.y, location.z, heading, is_networked, false, false);
*(unsigned short*)g_pointers->m_model_spawn_bypass = 0x0574;
auto veh = VEHICLE::CREATE_VEHICLE(hash, location.x, location.y, location.z, heading, is_networked, script_veh, false);
STREAMING::SET_MODEL_AS_NO_LONGER_NEEDED(hash);

View File

@ -1,10 +1,13 @@
#include "gui/components/components.hpp"
#include "natives.hpp"
#include "util/system.hpp"
#include "util/misc.hpp"
#include "view_debug.hpp"
#include "network/Network.hpp"
#include "script.hpp"
#include "gta/joaat.hpp"
#include "script_global.hpp"
#include "gta_util.hpp"
namespace big
{
@ -21,6 +24,14 @@ namespace big
{
NETWORK::NETWORK_BAIL(16, 0, 0);
});
components::button("Remove from Bad Sport", []
{
STATS::STAT_SET_FLOAT(RAGE_JOAAT("mpply_overall_badsport"), 0.0f, TRUE);
STATS::STAT_SET_BOOL(RAGE_JOAAT("mpply_was_i_bad_sport"), FALSE, TRUE);
});
ImGui::EndTabItem();
}
}
}

View File

@ -5,6 +5,9 @@
#include "gta_util.hpp"
#include "util/notify.hpp"
#include "util/scripts.hpp"
#include "util/toxic.hpp"
#include "core/data/apartment_names.hpp"
#include "core/data/warehouse_names.hpp"
namespace big
{
@ -55,6 +58,7 @@ namespace big
}
components::sub_title("Chat");
ImGui::Checkbox("Auto-kick Chat Spammers", &g->session.kick_chat_spammers);
ImGui::Checkbox("Disable Filter", &g->session.disable_chat_filter);
ImGui::Checkbox("Log Chat Messages", &g->session.log_chat_messages);
ImGui::Checkbox("Log Text Messages", &g->session.log_text_messages);
@ -79,6 +83,23 @@ namespace big
ImGui::Checkbox("Force Session Host", &g->session.force_session_host);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Join another session to apply changes. The original host of the session must leave or be kicked. This feature is easily detectable by other mod menus, use with caution");
ImGui::SameLine();
if (g->session.force_session_host)
{
ImGui::SameLine();
ImGui::Checkbox("Kick Host During Join", &g->session.kick_host_when_forcing_host);
}
if (ImGui::Checkbox("Force Script Host", &g->session.force_script_host))
{
if (g->session.force_script_host)
g_fiber_pool->queue_job([]
{
scripts::force_host(RAGE_JOAAT("freemode"));
if (auto script = gta_util::find_script_thread(RAGE_JOAAT("freemode")); script && script->m_net_component)
script->m_net_component->block_host_migration(true);
});
}
components::sub_title("Remote Name Spoofing");
ImGui::Checkbox("Spoof Other Players' Names", &g->session.name_spoof_enabled);
@ -107,9 +128,129 @@ namespace big
components::sub_title("All Players");
ImGui::Checkbox("Off The Radar", &g->session.off_radar_all);
ImGui::SameLine();
ImGui::Checkbox("Never Wanted", &g->session.never_wanted_all);
ImGui::SameLine();
ImGui::Checkbox("Semi Godmode", &g->session.semi_godmode_all);
ImGui::Checkbox("Explosion Karma", &g->session.explosion_karma);
ImGui::SameLine();
ImGui::Checkbox("Damage Karma", &g->session.damage_karma);
static int global_wanted_level = 0;
if (ImGui::SliderInt("Wanted Level", &global_wanted_level, 0, 5))
{
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(213).as<int*>() = global_wanted_level;
}
ImGui::SameLine();
if (ImGui::Checkbox("Force", &g->session.wanted_level_all))
{
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(212).as<Player*>() = __rdtsc() + 32;
*scr_globals::globalplayer_bd.at(self::id, scr_globals::size::globalplayer_bd).at(213).as<int*>() = global_wanted_level;
}
components::button("Kill Everyone", [] { g_player_service->iterate([](auto& plyr) { toxic::kill_player(plyr.second, g_player_service->get_self()); }); });
ImGui::SameLine();
components::button("Turn Everyone Into Beast", [] { toxic::turn_everyone_into_beast(); });
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Including you");
components::button("Give All Weapons", [] { g_player_service->iterate([](auto& plyr) { toxic::give_all_weapons(plyr.second); script::get_current()->yield(450ms); }); });
ImGui::SameLine();
components::button("Remove All Weapons", [] { g_player_service->iterate([](auto& plyr) { toxic::remove_all_weapons(plyr.second); }); });
components::button("CEO Kick", [] {
g_player_service->iterate([](auto& plyr)
{
if (*scr_globals::gpbd_fm_3.at(plyr.second->id(), scr_globals::size::gpbd_fm_3).at(10).as<int*>() != -1)
toxic::ceo_kick(plyr.second);
});
});
components::button("CEO Ban", [] {
g_player_service->iterate([](auto& plyr)
{
if (*scr_globals::gpbd_fm_3.at(plyr.second->id(), scr_globals::size::gpbd_fm_3).at(10).as<int*>() != -1)
toxic::ceo_ban(plyr.second);
});
});
components::small_text("Teleports");
if (ImGui::BeginCombo("##apartment", apartment_names[g->session.send_to_apartment_idx]))
{
for (int i = 1; i < apartment_names.size(); i++)
{
if (ImGui::Selectable(apartment_names[i], i == g->session.send_to_apartment_idx))
{
g->session.send_to_apartment_idx = i;
}
if (i == g->session.send_to_apartment_idx)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::SameLine();
components::button("TP All To Apartment", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_apartment(plyr.second, g->session.send_to_apartment_idx); }); });
if (ImGui::BeginCombo("##warehouse", warehouse_names[g->session.send_to_warehouse_idx]))
{
for (int i = 1; i < warehouse_names.size(); i++)
{
if (ImGui::Selectable(warehouse_names[i], i == g->session.send_to_warehouse_idx))
{
g->session.send_to_warehouse_idx = i;
}
if (i == g->session.send_to_warehouse_idx)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::SameLine();
components::button("TP All To Warehouse", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_warehouse(plyr.second, g->session.send_to_warehouse_idx); }); });
components::button("TP All To Darts", [] { g_player_service->iterate([](auto& plyr) { toxic::start_activity(plyr.second, eActivityType::Darts); }); });
ImGui::SameLine();
components::button("TP All To Flight School", [] { g_player_service->iterate([](auto& plyr) { toxic::start_activity(plyr.second, eActivityType::PilotSchool); }); });
ImGui::SameLine();
components::button("TP All To Map Center", [] { g_player_service->iterate([](auto& plyr) { toxic::start_activity(plyr.second, eActivityType::ArmWresling); }); });
components::button("TP All To Skydive", [] { g_player_service->iterate([](auto& plyr) { toxic::start_activity(plyr.second, eActivityType::Skydive); }); });
ImGui::SameLine();
components::button("TP All To Cayo Perico", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_island(plyr.second); }); });
ImGui::SameLine();
components::button("TP All To MOC", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_interior(plyr.second, 81); }); });
components::button("TP All To Casino", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_interior(plyr.second, 123); }); });
ImGui::SameLine();
components::button("TP All To Penthouse", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_interior(plyr.second, 124); }); });
ImGui::SameLine();
components::button("TP All To Arcade", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_interior(plyr.second, 128); }); });
components::button("TP All To Music Locker", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_interior(plyr.second, 146); }); });
ImGui::SameLine();
components::button("TP All To Record A Studios", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_interior(plyr.second, 148); }); });
ImGui::SameLine();
components::button("TP All To Custom Auto Shop", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_interior(plyr.second, 149); }); });
components::button("TP All To Agency", [] { g_player_service->iterate([](auto& plyr) { toxic::send_player_to_interior(plyr.second, 155); }); });
components::sub_title("Event Starter");
ImGui::BeginGroup();
@ -129,5 +270,40 @@ namespace big
components::button("Hunt The Beast", [] { scripts::start_launcher_script(47); });
components::button("Business Battles", [] { scripts::start_launcher_script(114); });
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup();
components::button("One-On-One Deathmatch", [] { scripts::start_launcher_script(187); });
components::button("Impromptu Race", [] { scripts::start_launcher_script(16); });
components::button("Flight School", [] { scripts::start_launcher_script(186); });
components::button("Golf", [] { scripts::start_launcher_script(183); });
components::button("Tutorial", [] { scripts::start_launcher_script(20); });
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Only works on joining players");
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup();
components::button("Gunslinger", [] { scripts::start_launcher_script(201); });
components::button("Space Monkey", [] { scripts::start_launcher_script(206); });
components::button("Wizard", [] { scripts::start_launcher_script(202); });
components::button("QUB3D", [] { scripts::start_launcher_script(207); });
components::button("Camhedz", [] { scripts::start_launcher_script(208); });
ImGui::EndGroup();
ImGui::Checkbox("Disable Pedestrians", &g->session.disable_peds);
ImGui::SameLine();
ImGui::Checkbox("Disable Traffic", &g->session.disable_traffic);
ImGui::SameLine();
ImGui::Checkbox("Force Thunder", &g->session.force_thunder);
components::sub_title("Script Host Features");
ImGui::Checkbox("Disable CEO Money", &g->session.block_ceo_money);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Blocks CEO money drops across the entire session. This can also break other stuff, use with caution");
ImGui::SameLine();
ImGui::Checkbox("Randomize CEO Colors", &g->session.randomize_ceo_colors);
}
}

View File

@ -1,6 +1,8 @@
#include "views/view.hpp"
#include "fiber_pool.hpp"
#include "util/teleport.hpp"
#include "core/data/region_codes.hpp"
#include "core/data/language_codes.hpp"
#include <network/ClanData.hpp>
namespace big
@ -84,5 +86,49 @@ namespace big
ImGui::Checkbox("Is Cheater", &g->spoofing.spoof_cheater);
ImGui::Checkbox("Is Rockstar Dev", &g->spoofing.spoof_rockstar_dev);
ImGui::Checkbox("Is Rockstar QA", &g->spoofing.spoof_rockstar_qa);
components::sub_title("Session Attributes");
components::small_text("Only works when session host");
ImGui::Checkbox("Region", &g->spoofing.spoof_session_region_type);
if (g->spoofing.spoof_session_region_type)
{
ImGui::SameLine();
if (ImGui::BeginCombo("###region_select", regions[g->spoofing.session_region_type].name))
{
for (const auto& region : regions)
{
if (ImGui::Selectable(region.name, g->spoofing.session_region_type == region.id))
{
g->spoofing.session_region_type = region.id;
}
}
ImGui::EndCombo();
}
}
ImGui::Checkbox("Language", &g->spoofing.spoof_session_language);
if (g->spoofing.spoof_session_language)
{
ImGui::SameLine();
if (ImGui::BeginCombo("###language_select", languages[g->spoofing.session_language].name))
{
for (const auto& language : languages)
{
if (ImGui::Selectable(language.name, g->spoofing.session_language == language.id))
{
g->spoofing.session_language = language.id;
};
}
ImGui::EndCombo();
}
}
ImGui::Checkbox("Player Count", &g->spoofing.spoof_session_player_count);
if (g->spoofing.spoof_session_player_count)
{
ImGui::SameLine();
ImGui::InputInt("###player_count", &g->spoofing.session_player_count);
}
}
}

View File

@ -0,0 +1,129 @@
#include "views/view.hpp"
#include "services/player_database/player_database_service.hpp"
namespace big
{
void view::player_info()
{
if (ImGui::TreeNode("Info"))
{
ImGui::Text("Player ID: %d", g_player_service->get_selected()->id());
ImGui::Text("Session Host: %s", g_player_service->get_selected()->is_host() ? "Yes" : "No");
ImGui::Separator();
if (CPlayerInfo* player_info = g_player_service->get_selected()->get_player_info(); player_info != nullptr)
{
ImGui::Text("Wanted Level: %d", player_info->m_wanted_level);
}
uint32_t ped_damage_bits = 0;
uint32_t ped_task_flag = 0;
uint32_t veh_damage_bits = 0;
std::string mode_str = "";
if (CPed* ped = g_player_service->get_selected()->get_ped(); ped != nullptr)
{
ped_damage_bits = ped->m_damage_bits;
ped_task_flag = ped->m_ped_task_flag;
}
if (ped_damage_bits & (uint32_t)eEntityProofs::GOD)
{
mode_str = "God";
}
else
{
if (ped_damage_bits & (uint32_t)eEntityProofs::BULLET)
{
mode_str += "Bullet, ";
}
if (ped_damage_bits & (uint32_t)eEntityProofs::EXPLOSION)
{
mode_str += "Explosion, ";
}
}
if (mode_str.empty())
{
mode_str = "No";
}
ImGui::Text("Player God Mode: %s", mode_str.c_str());
mode_str = "";
if (auto vehicle = g_player_service->get_selected()->get_current_vehicle(); vehicle != nullptr)
{
veh_damage_bits = vehicle->m_damage_bits;
}
if (ped_task_flag & (uint8_t)ePedTask::TASK_DRIVING)
{
if (veh_damage_bits & (uint32_t)eEntityProofs::GOD)
{
mode_str = "God";
}
else
{
if (veh_damage_bits & (uint32_t)eEntityProofs::COLLISION)
{
mode_str += "Collision, ";
}
if (veh_damage_bits & (uint32_t)eEntityProofs::EXPLOSION)
{
mode_str += "Explosion, ";
}
}
if (mode_str.empty())
{
mode_str = "No";
}
}
else
{
mode_str = "No vehicle detected";
}
ImGui::Text("Vehicle God Mode: %s", mode_str.c_str());
ImGui::Separator();
if (auto net_player_data = g_player_service->get_selected()->get_net_data(); net_player_data != nullptr)
{
ImGui::Text("Rockstar ID: %d", net_player_data->m_gamer_handle_2.m_rockstar_id);
ImGui::SameLine();
if (ImGui::Button("Copy##rid")) ImGui::SetClipboardText(std::to_string(net_player_data->m_gamer_handle_2.m_rockstar_id).data());
ImGui::Text(
"IP Address: %d.%d.%d.%d:%d",
net_player_data->m_external_ip.m_field1,
net_player_data->m_external_ip.m_field2,
net_player_data->m_external_ip.m_field3,
net_player_data->m_external_ip.m_field4,
net_player_data->m_external_port
);
ImGui::SameLine();
if (ImGui::Button("Copy##ip")) ImGui::SetClipboardText(std::format("{}.{}.{}.{}:{}", net_player_data->m_external_ip.m_field1,
net_player_data->m_external_ip.m_field2,
net_player_data->m_external_ip.m_field3,
net_player_data->m_external_ip.m_field4,
net_player_data->m_external_port).data());
}
if (ImGui::Button("Add To Database"))
{
g_player_database_service->get_or_create_player(g_player_service->get_selected());
}
ImGui::TreePop();
}
}
}

View File

@ -0,0 +1,29 @@
#include "views/view.hpp"
#include "util/teleport.hpp"
#include "util/toxic.hpp"
#include "util/kick.hpp"
namespace big
{
void view::player_kick()
{
if (ImGui::TreeNode("Kick"))
{
components::button("Breakup Kick", [] { kick::breakup_kick(g_player_service->get_selected()); });
components::button("Lost Connection Kick", [] { kick::lost_connection_kick(g_player_service->get_selected()); });
components::button("Bail Kick", [] { kick::bail_kick(g_player_service->get_selected()); });
components::button("Null Function Kick", [] { kick::null_function_kick(g_player_service->get_selected()); });
components::button("OOM Kick", [] { kick::oom_kick(g_player_service->get_selected()); });
components::button("Script Host Kick", [] { kick::kick_player_script_host(g_player_service->get_selected()); });
components::button("End Session Kick", [] { kick::end_session_kick(g_player_service->get_selected()); });
if (ImGui::IsItemHovered())
ImGui::SetTooltip("The kick can take around 10 seconds to work");
components::button("Host Kick", [] { kick::host_kick(g_player_service->get_selected()); });
components::button("Complaint Kick", [] { kick::complaint_kick(g_player_service->get_selected()); });
if (ImGui::IsItemHovered())
ImGui::SetTooltip("The kick can take around 10 seconds to work");
ImGui::TreePop();
}
}
}

View File

@ -0,0 +1,75 @@
#include "views/view.hpp"
#include "util/teleport.hpp"
#include "core/scr_globals.hpp"
#include "util/ped.hpp"
#include "util/vehicle.hpp"
#include "util/globals.hpp"
#include "services/pickups/pickup_service.hpp"
#include "gta/net_object_mgr.hpp"
#include "util/scripts.hpp"
#include "util/session.hpp"
#include "script_function.hpp"
namespace big
{
void view::player_misc()
{
if (ImGui::TreeNode("Misc"))
{
components::button("Join CEO/MC", []
{
scr_functions::join_ceo({ g_player_service->get_selected()->id(), 0, false, false });
});
components::button("Enter Interior", []
{
session::enter_player_interior(g_player_service->get_selected());
});
components::button("Steal Outfit", []
{
ped::steal_outfit(
PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(g_player_service->get_selected()->id())
);
});
ImGui::SameLine();
components::button("Steal Identity", []
{
ped::steal_identity(
PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(g_player_service->get_selected()->id())
);
});
components::button("Clear Wanted Level", []
{
globals::clear_wanted_player(g_player_service->get_selected()->id());
});
ImGui::SameLine();
components::button("Give Health", []
{
g_pickup_service->give_player_health(g_player_service->get_selected()->id());
});
ImGui::SameLine();
components::button("Give Armour", []
{
g_pickup_service->give_player_armour(g_player_service->get_selected()->id());
});
components::button("Give Ammo", []
{
g_pickup_service->give_player_ammo(g_player_service->get_selected()->id());
});
ImGui::Checkbox("Off The Radar", &g_player_service->get_selected()->off_radar);
ImGui::Checkbox("Never Wanted", &g_player_service->get_selected()->never_wanted);
ImGui::Checkbox("Semi Godmode", &g_player_service->get_selected()->semi_godmode);
ImGui::TreePop();
}
}
}

View File

@ -0,0 +1,117 @@
#include "views/view.hpp"
#include "util/teleport.hpp"
#include "util/toxic.hpp"
#include "core/data/apartment_names.hpp"
#include "core/data/warehouse_names.hpp"
namespace big
{
void view::player_toxic()
{
if (ImGui::TreeNode("Toxic"))
{
components::button("Kill Player", []
{
toxic::kill_player(g_player_service->get_selected(), g_player_service->get_self());
});
components::button("CEO Kick", [] { toxic::ceo_kick(g_player_service->get_selected()); });
ImGui::SameLine();
components::button("CEO Ban", [] { toxic::ceo_ban(g_player_service->get_selected()); });
components::button("Kick From Vehicle", [] { toxic::kick_player_from_vehicle(g_player_service->get_selected()); });
ImGui::SameLine();
components::button("Ragdoll Player", [] { toxic::ragdoll_player(g_player_service->get_selected()); });
components::button("Kick From Interior", [] { toxic::kick_player_from_interior(g_player_service->get_selected()); });
components::button("Turn Into Animal", [] { toxic::turn_player_into_animal(g_player_service->get_selected()); });
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Turns player into a random animal");
ImGui::SameLine();
components::button("Turn Into Beast", [] { toxic::turn_player_into_beast(g_player_service->get_selected()); });
static int wanted_level;
ImGui::SliderInt("Wanted Level", &wanted_level, 0, 5);
ImGui::SameLine();
components::button("Set", [] { toxic::set_wanted_level(g_player_service->get_selected(), wanted_level); });
components::small_text("Teleports");
if (ImGui::BeginCombo("##apartment", apartment_names[g->session.send_to_apartment_idx]))
{
for (int i = 1; i < apartment_names.size(); i++)
{
if (ImGui::Selectable(apartment_names[i], i == g->session.send_to_apartment_idx))
{
g->session.send_to_apartment_idx = i;
}
if (i == g->session.send_to_apartment_idx)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::SameLine();
components::button("TP To Apartment", [] { toxic::send_player_to_apartment(g_player_service->get_selected(), g->session.send_to_apartment_idx); });
if (ImGui::BeginCombo("##warehouse", warehouse_names[g->session.send_to_warehouse_idx]))
{
for (int i = 1; i < warehouse_names.size(); i++)
{
if (ImGui::Selectable(warehouse_names[i], i == g->session.send_to_warehouse_idx))
{
g->session.send_to_warehouse_idx = i;
}
if (i == g->session.send_to_warehouse_idx)
{
ImGui::SetItemDefaultFocus();
}
}
ImGui::EndCombo();
}
ImGui::SameLine();
components::button("TP To Warehouse", [] { toxic::send_player_to_warehouse(g_player_service->get_selected(), g->session.send_to_warehouse_idx); });
components::button("TP To Darts", [] { toxic::start_activity(g_player_service->get_selected(), eActivityType::Darts); });
ImGui::SameLine();
components::button("TP To Flight School", [] { toxic::start_activity(g_player_service->get_selected(), eActivityType::PilotSchool); });
ImGui::SameLine();
components::button("TP To Map Center", [] { toxic::start_activity(g_player_service->get_selected(), eActivityType::ArmWresling); });
components::button("TP To Skydive", [] { toxic::start_activity(g_player_service->get_selected(), eActivityType::Skydive); });
ImGui::SameLine();
components::button("TP To Cayo Perico", [] { toxic::send_player_to_island(g_player_service->get_selected()); });
ImGui::SameLine();
components::button("TP To MOC", [] { toxic::send_player_to_interior(g_player_service->get_selected(), 81); });
components::button("TP To Casino", [] { toxic::send_player_to_interior(g_player_service->get_selected(), 123); });
ImGui::SameLine();
components::button("TP To Penthouse", [] { toxic::send_player_to_interior(g_player_service->get_selected(), 124); });
ImGui::SameLine();
components::button("TP To Arcade", [] { toxic::send_player_to_interior(g_player_service->get_selected(), 128); });
components::button("TP To Music Locker", [] { toxic::send_player_to_interior(g_player_service->get_selected(), 146); });
ImGui::SameLine();
components::button("TP To Record A Studios", [] { toxic::send_player_to_interior(g_player_service->get_selected(), 148); });
ImGui::SameLine();
components::button("TP To Custom Auto Shop", [] { toxic::send_player_to_interior(g_player_service->get_selected(), 149); });
components::button("TP To Agency", [] { toxic::send_player_to_interior(g_player_service->get_selected(), 155); });
components::button("Give All Weapons", [] { toxic::give_all_weapons(g_player_service->get_selected()); });
ImGui::SameLine();
components::button("Remove All Weapons", [] { toxic::remove_all_weapons(g_player_service->get_selected()); });
ImGui::TreePop();
}
}
}

View File

@ -0,0 +1,49 @@
#include "views/view.hpp"
#include "util/teleport.hpp"
#include "util/vehicle.hpp"
namespace big
{
void view::player_troll()
{
if (ImGui::TreeNode("Troll"))
{
components::button("Teleport", []
{
teleport::to_player(g_player_service->get_selected()->id());
});
ImGui::SameLine();
components::button("Bring", []
{
teleport::bring_player(g_player_service->get_selected());
});
components::button("Teleport into Vehicle", []
{
Vehicle veh = PED::GET_VEHICLE_PED_IS_IN(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(g_player_service->get_selected()->id()), false);
teleport::into_vehicle(veh);
});
components::button("Remote Control Vehicle", []
{
Vehicle veh = PED::GET_VEHICLE_PED_IS_IN(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(g_player_service->get_selected()->id()), FALSE);
if (veh == 0)
{
if (g->player.spectating)
g_notification_service->push_warning("Remote Control", "Player not in a vehicle");
else
g_notification_service->push_warning("Remote Control", "Player not in a vehicle, try spectating the player");
return;
}
vehicle::remote_control_vehicle(veh);
g->player.spectating = false;
});
ImGui::TreePop();
}
}
}

View File

@ -1,13 +1,4 @@
#include "gta_util.hpp"
#include "services/pickups/pickup_service.hpp"
#include "services/players/player_service.hpp"
#include "services/player_database/player_database_service.hpp"
#include "util/globals.hpp"
#include "util/misc.hpp"
#include "util/ped.hpp"
#include "util/teleport.hpp"
#include "views/view.hpp"
#include "util/vehicle.hpp"
namespace big
{
@ -20,224 +11,11 @@ namespace big
if (g_player_service->get_selected()->is_valid())
{
if (ImGui::TreeNode("Info")) {
ImGui::Text("Player ID: %d", g_player_service->get_selected()->id());
ImGui::Text("Session Host: %s", g_player_service->get_selected()->is_host() ? "Yes" : "No");
ImGui::Separator();
if (CPlayerInfo* player_info = g_player_service->get_selected()->get_player_info(); player_info != nullptr)
{
ImGui::Text("Wanted Level: %d", player_info->m_wanted_level);
}
uint32_t ped_damage_bits = 0;
uint32_t ped_task_flag = 0;
uint32_t veh_damage_bits = 0;
std::string mode_str = "";
if (CPed* ped = g_player_service->get_selected()->get_ped(); ped != nullptr)
{
ped_damage_bits = ped->m_damage_bits;
ped_task_flag = ped->m_ped_task_flag;
}
if (ped_damage_bits & (uint32_t)eEntityProofs::GOD)
{
mode_str = "God";
}
else
{
if (ped_damage_bits & (uint32_t)eEntityProofs::BULLET)
{
mode_str += "Bullet, ";
}
if (ped_damage_bits & (uint32_t)eEntityProofs::EXPLOSION)
{
mode_str += "Explosion, ";
}
}
if (mode_str.empty())
{
mode_str = "No";
}
ImGui::Text("Player God Mode: %s", mode_str.c_str());
mode_str = "";
if (auto vehicle = g_player_service->get_selected()->get_current_vehicle(); vehicle != nullptr)
{
veh_damage_bits = vehicle->m_damage_bits;
}
if (ped_task_flag & (uint8_t)ePedTask::TASK_DRIVING)
{
if (veh_damage_bits & (uint32_t)eEntityProofs::GOD)
{
mode_str = "God";
}
else
{
if (veh_damage_bits & (uint32_t)eEntityProofs::COLLISION)
{
mode_str += "Collision, ";
}
if (veh_damage_bits & (uint32_t)eEntityProofs::EXPLOSION)
{
mode_str += "Explosion, ";
}
}
if (mode_str.empty())
{
mode_str = "No";
}
}
else
{
mode_str = "No vehicle detected";
}
ImGui::Text("Vehicle God Mode: %s", mode_str.c_str());
ImGui::Separator();
if (auto net_player_data = g_player_service->get_selected()->get_net_data(); net_player_data != nullptr)
{
ImGui::Text("Rockstar ID: %d", net_player_data->m_gamer_handle_2.m_rockstar_id);
ImGui::SameLine();
if (ImGui::Button("Copy##rid")) ImGui::SetClipboardText(std::to_string(net_player_data->m_gamer_handle_2.m_rockstar_id).data());
ImGui::Text(
"IP Address: %d.%d.%d.%d:%d",
net_player_data->m_external_ip.m_field1,
net_player_data->m_external_ip.m_field2,
net_player_data->m_external_ip.m_field3,
net_player_data->m_external_ip.m_field4,
net_player_data->m_external_port
);
ImGui::SameLine();
if (ImGui::Button("Copy##ip")) ImGui::SetClipboardText(std::format("{}.{}.{}.{}:{}", net_player_data->m_external_ip.m_field1,
net_player_data->m_external_ip.m_field2,
net_player_data->m_external_ip.m_field3,
net_player_data->m_external_ip.m_field4,
net_player_data->m_external_port).data());
}
if (ImGui::Button("Add To Database"))
{
g_player_database_service->get_or_create_player(g_player_service->get_selected());
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Teleport"))
{
components::button("Teleport", [] {
teleport::to_player(g_player_service->get_selected()->id());
});
ImGui::SameLine();
components::button("Bring", [] {
teleport::bring_player(g_player_service->get_selected()->id());
});
components::button("Teleport into Vehicle", [] {
Vehicle veh = PED::GET_VEHICLE_PED_IS_IN(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(g_player_service->get_selected()->id()), false);
teleport::into_vehicle(veh);
});
ImGui::TreePop();
}
if (ImGui::TreeNode("Misc"))
{
components::button("Join CEO/MC", []
{
*scr_globals::gpbd_fm_3.at(self::id, scr_globals::size::gpbd_fm_3).at(10).as<int*>() = g_player_service->get_selected()->id();
*scr_globals::gpbd_fm_3.at(self::id, scr_globals::size::gpbd_fm_3).at(10).at(26).as<int*>() = g_player_service->get_selected()->id();
});
components::button("Steal Outfit", []
{
ped::steal_outfit(
PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(g_player_service->get_selected()->id())
);
});
ImGui::SameLine();
components::button("Steal Identity", []
{
ped::steal_identity(
PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(g_player_service->get_selected()->id())
);
});
components::button("Clear Wanted Level", []
{
globals::clear_wanted_player(g_player_service->get_selected()->id());
});
ImGui::SameLine();
components::button("Give Health", []
{
g_pickup_service->give_player_health(g_player_service->get_selected()->id());
});
ImGui::SameLine();
components::button("Give Armour", []
{
g_pickup_service->give_player_armour(g_player_service->get_selected()->id());
});
components::button("Give Ammo", []
{
g_pickup_service->give_player_ammo(g_player_service->get_selected()->id());
});
ImGui::SameLine();
components::button("Give Weapons", []
{
g_pickup_service->give_player_weapons(g_player_service->get_selected()->id());
});
ImGui::Checkbox("Off The Radar", &g_player_service->get_selected()->off_radar);
ImGui::Checkbox("Never Wanted", &g_player_service->get_selected()->never_wanted);
ImGui::Checkbox("Semi Godmode", &g_player_service->get_selected()->semi_godmode);
components::button("Remote Control Vehicle", []
{
Vehicle veh = PED::GET_VEHICLE_PED_IS_IN(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(g_player_service->get_selected()->id()), FALSE);
if (veh == 0)
{
if (g->player.spectating)
g_notification_service->push_warning("Remote Control", "Player not in a vehicle");
else
g_notification_service->push_warning("Remote Control", "Player not in a vehicle, try spectating the player");
return;
}
vehicle::remote_control_vehicle(veh);
g->player.spectating = false;
});
ImGui::TreePop();
}
view::player_info();
view::player_troll();
view::player_kick();
view::player_toxic();
view::player_misc();
}
}
}

View File

@ -3,6 +3,7 @@
#include "util/local_player.hpp"
#include "views/view.hpp"
#include "core/data/hud_component_names.hpp"
#include "util/scripts.hpp"
namespace big
{
@ -80,6 +81,10 @@ namespace big
ImGui::Checkbox("No Collision", &g->self.no_collision);
ImGui::Checkbox("Mobile Radio", &g->self.mobile_radio);
ImGui::Checkbox("Dance Mode", &g->self.dance_mode);
if (ImGui::IsItemHovered())
ImGui::SetTooltip("Hold Right DPAD or E to enter dance mode");
ImGui::EndGroup();
ImGui::Separator();
@ -209,6 +214,14 @@ namespace big
ImGui::EndGroup();
components::sub_title("Launch Creator");
ImGui::BeginGroup();
components::button("Race", [] { scripts::start_creator_script(RAGE_JOAAT("fm_race_creator")); }); ImGui::SameLine();
components::button("Capture", [] { scripts::start_creator_script(RAGE_JOAAT("fm_capture_creator")); }); ImGui::SameLine();
components::button("Deathmatch", [] { scripts::start_creator_script(RAGE_JOAAT("fm_deathmatch_creator")); }); ImGui::SameLine();
components::button("LTS", [] { scripts::start_creator_script(RAGE_JOAAT("fm_lts_creator")); });
ImGui::EndGroup();
g->self.proof_mask = 0;
if (g->self.god_mode)
{

View File

@ -21,6 +21,8 @@ namespace big
teleport::to_objective();
});
ImGui::Checkbox("Auto-Teleport To Waypoint", &g->self.auto_tp);
ImGui::Text("Vehicles:");
components::button("Teleport to Last Vehicle", []

View File

@ -95,6 +95,7 @@ namespace big
ImGui::BeginGroup();
draw_pair_option("Teleport To Warehouse", script_event_handler.teleport_to_warehouse);
draw_pair_option("Start Activity", script_event_handler.start_activity);
draw_pair_option("Null Function Kick", script_event_handler.null_function_kick);
ImGui::EndGroup();
components::sub_title("Other");

View File

@ -47,6 +47,12 @@ namespace big
static void context_menu();
static void gta_data();
static void player_info();
static void player_troll();
static void player_kick();
static void player_toxic();
static void player_misc();
// later calls will be drawn over earlier calls
static void always()
{

View File

@ -39,10 +39,5 @@ namespace big
ImGui::TreePop();
}
components::button("Force Thunder", []
{
session::force_thunder();
});
}
}