mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2025-01-03 16:13:36 +08:00
Toxic update (#641)
This commit is contained in:
parent
7f74a436d2
commit
a427ccb914
@ -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 ""
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
67
src/backend/looped/self/dance_mode.cpp
Normal file
67
src/backend/looped/self/dance_mode.cpp
Normal 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, {});
|
||||
}
|
||||
}
|
||||
}
|
22
src/backend/looped/session/auto_kick_host.cpp
Normal file
22
src/backend/looped/session/auto_kick_host.cpp
Normal 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;
|
||||
}
|
||||
}
|
36
src/backend/looped/session/force_thunder.cpp
Normal file
36
src/backend/looped/session/force_thunder.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
53
src/backend/looped/session/pop_multiplier_areas.cpp
Normal file
53
src/backend/looped/session/pop_multiplier_areas.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
23
src/backend/looped/session/randomize_ceo_colors.cpp
Normal file
23
src/backend/looped/session/randomize_ceo_colors.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
src/backend/looped/system/auto_tp.cpp
Normal file
28
src/backend/looped/system/auto_tp.cpp
Normal 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;
|
||||
}
|
||||
}
|
@ -11,7 +11,13 @@ namespace big
|
||||
void looped::system_desync_kick_protection()
|
||||
{
|
||||
memset(>a_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;
|
||||
|
||||
|
39
src/backend/looped/system/mission_creator.cpp
Normal file
39
src/backend/looped/system/mission_creator.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
123
src/core/data/apartment_names.hpp
Normal file
123
src/core/data/apartment_names.hpp
Normal 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"
|
||||
});
|
||||
}
|
@ -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"}
|
||||
};
|
||||
}
|
30
src/core/data/warehouse_names.hpp
Normal file
30
src/core/data/warehouse_names.hpp
Normal 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"
|
||||
});
|
||||
}
|
@ -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
|
||||
|
@ -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 }
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -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);
|
||||
@ -37,4 +45,12 @@ namespace big::scr_globals
|
||||
static inline script_global mechanic_global = script_global(2815059);
|
||||
|
||||
static inline script_global spawn_global = script_global(2725439);
|
||||
}
|
||||
|
||||
namespace big::scr_locals
|
||||
{
|
||||
namespace am_hunt_the_beast
|
||||
{
|
||||
constexpr static auto broadcast_idx = 597;
|
||||
}
|
||||
}
|
@ -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
218
src/gta/net_array.hpp
Normal 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);
|
||||
}
|
@ -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:
|
||||
|
@ -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
|
||||
{
|
||||
|
25
src/gta/script_handler.cpp
Normal file
25
src/gta/script_handler.cpp
Normal 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);
|
||||
}
|
@ -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);
|
||||
|
@ -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
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "hooking.hpp"
|
||||
#include "gta/net_game_event.hpp"
|
||||
#include <network/CNetGamePlayer.hpp>
|
||||
|
||||
namespace big
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
72
src/hooks/script/script_handler.cpp
Normal file
72
src/hooks/script/script_handler.cpp
Normal 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;
|
||||
}
|
||||
};
|
19
src/hooks/spoofing/send_session_matchmaking_attributes.cpp
Normal file
19
src/hooks/spoofing/send_session_matchmaking_attributes.cpp
Normal 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);
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
#include "hooking.hpp"
|
||||
#include <datanodes/player/CPlayerGameStateDataNode.hpp>
|
||||
|
||||
namespace big
|
||||
{
|
||||
|
89
src/hooks/toxic/broadcast_net_array.cpp
Normal file
89
src/hooks/toxic/broadcast_net_array.cpp
Normal 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;
|
||||
}
|
||||
}
|
@ -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])
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
39
src/native_hooks/creator.hpp
Normal file
39
src/native_hooks/creator.hpp
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
};
|
||||
}
|
||||
}
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
|
@ -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
78
src/script_function.cpp
Normal 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
29
src/script_function.hpp
Normal 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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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{};
|
||||
|
@ -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
164
src/util/kick.hpp
Normal 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());
|
||||
}
|
||||
}
|
@ -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();
|
||||
|
||||
|
@ -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,28 +52,48 @@ 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)
|
||||
{
|
||||
static auto check_players_in_state = [](GtaThread* launcher, int state) -> bool
|
||||
{
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
@ -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*>();
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace
|
||||
".CN",
|
||||
".TOP",
|
||||
".COM",
|
||||
".top",
|
||||
"\xE3\x80\x90",
|
||||
"/Menu",
|
||||
"Money/",
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
396
src/util/toxic.hpp
Normal 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
129
src/views/players/player/player_info.cpp
Normal file
129
src/views/players/player/player_info.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
29
src/views/players/player/player_kick.cpp
Normal file
29
src/views/players/player/player_kick.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
75
src/views/players/player/player_misc.cpp
Normal file
75
src/views/players/player/player_misc.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
117
src/views/players/player/player_toxic.cpp
Normal file
117
src/views/players/player/player_toxic.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
49
src/views/players/player/player_troll.cpp
Normal file
49
src/views/players/player/player_troll.cpp
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
|
@ -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", []
|
||||
|
@ -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");
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -39,10 +39,5 @@ namespace big
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
components::button("Force Thunder", []
|
||||
{
|
||||
session::force_thunder();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user