Play audio on voice chat and more (#1053)

* feat(VC): audio through voice chat
* fix(BlackHole): remove unnecessary cleanup
* fix(Formatting): fix formatting for initializer lists
* feat(LSC): reimplement LSC
* feat(Protections): add (untested) protections for vehicle kick and remote teleport
This commit is contained in:
maybegreat48 2023-03-09 12:23:01 +00:00 committed by GitHub
parent a44c74b869
commit e5aa39dd35
44 changed files with 806 additions and 322 deletions

View File

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

View File

@ -1,55 +0,0 @@
#include "backend/player_command.hpp"
#include "core/scr_globals.hpp"
#include "gta_util.hpp"
#include "natives.hpp"
#include "packet.hpp"
#include "pointers.hpp"
#include <network/Network.hpp>
namespace big
{
class lost_connection_kick : player_command
{
using player_command::player_command;
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>(hnd.unk_0009, 8);
}
}
virtual CommandAccessLevel get_access_level()
{
return CommandAccessLevel::TOXIC;
}
virtual void execute(player_ptr player, const std::vector<std::uint64_t>& _args, const std::shared_ptr<command_context> ctx)
{
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(player->get_net_data()->m_gamer_handle, msg);
for (auto& [_, plyr] : g_player_service->players())
{
if (plyr->is_host())
{
msg.send(plyr->get_session_player()->m_msg_id);
break;
}
}
}
};
lost_connection_kick g_lost_connection_kick("lckick", "Lost Connection Kick", "Can only be detected or blocked by the host. Does not work when you are the host, use Host Kick instead", 0);
}

View File

@ -15,5 +15,5 @@ namespace big
} }
}; };
bring g_bring("bring", "Bring", "Teleports the player to you if they are in a vehicle", 0); bring g_bring("bring", "Bring", "Teleports the player to you", 0, false);
} }

View File

@ -1,7 +1,6 @@
#include "backend/command.hpp" #include "backend/command.hpp"
#include "natives.hpp" #include "natives.hpp"
#include "util/mobile.hpp" #include "util/teleport.hpp"
#include "util/vehicle.hpp"
namespace big namespace big
{ {

View File

@ -1,7 +1,7 @@
#include "backend/command.hpp" #include "backend/command.hpp"
#include "natives.hpp" #include "natives.hpp"
#include "util/mobile.hpp" #include "util/mobile.hpp"
#include "util/vehicle.hpp" #include "util/teleport.hpp"
namespace big namespace big
{ {

View File

@ -0,0 +1,30 @@
#include "backend/looped_command.hpp"
#include "natives.hpp"
#include "pointers.hpp"
namespace big
{
class voice_chat_audio : looped_command
{
using looped_command::looped_command;
virtual void on_enable() override
{
*g_pointers->m_refresh_audio_input = true;
}
virtual void on_tick() override
{
NETWORK::NETWORK_OVERRIDE_SEND_RESTRICTIONS_ALL(true);
}
virtual void on_disable() override
{
*g_pointers->m_refresh_audio_input = true;
NETWORK::NETWORK_OVERRIDE_SEND_RESTRICTIONS_ALL(false);
}
};
voice_chat_audio g_voice_chat_audio("vcaudio", "Play Audio Through Voice Chat", "Plays the audio.wav file in the project folder through voice chat. The wave file must be encoded with a mono 16 bit 16kHz PCM format. You have to reset voice chat settings whenever you load the menu for the sound to play",
g.spoofing.voice_chat_audio);
}

View File

@ -1,70 +1,101 @@
#include "backend/looped/looped.hpp" #include "backend/looped/looped.hpp"
#include "gta/enums.hpp"
#include "gta_util.hpp" #include "gta_util.hpp"
#include "script_function.hpp"
#include "script_local.hpp" #include "script_local.hpp"
#include "services/script_patcher/script_patcher_service.hpp"
#include "util/math.hpp" #include "util/math.hpp"
#include "util/scripts.hpp" #include "util/scripts.hpp"
namespace big namespace big
{ {
static bool state = false; static bool bLastLsCustoms = false;
static bool busy = false; static bool bModshopReady = false;
constexpr auto CARMOD_SHOP_STRUCT = 730; // move_m@generic_idles@std -- one function below -- first local
constexpr auto CARMOD_SHOP_CUTSCENE = 2208;// "carmod_fam1" -- first boolean local below it
void looped::vehicle_ls_customs() void looped::vehicle_ls_customs()
{ {
if (busy) if (g.vehicle.ls_customs && g.vehicle.ls_customs != bLastLsCustoms)
return;
busy = true;
constexpr int hash = RAGE_JOAAT("carmod_shop");
if (g.vehicle.ls_customs && g.vehicle.ls_customs == state)
{ {
if (auto carmod_shop_thread = gta_util::find_script_thread(hash); g_fiber_pool->queue_job([] {
carmod_shop_thread && *script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).at(11).as<int*>() != 4) scripts::request_script(RAGE_JOAAT("carmod_shop"));
{ if (scripts::wait_till_loaded(RAGE_JOAAT("carmod_shop")))
g.vehicle.ls_customs = false;
*script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).as<int*>() = 1;// cleanup
}
}
if (g.vehicle.ls_customs && g.vehicle.ls_customs != state)
{
Vehicle veh = self::veh;
if (!ENTITY::DOES_ENTITY_EXIST(veh) || ENTITY::IS_ENTITY_DEAD(veh, false))
{
busy = false;
g.vehicle.ls_customs = false;
g_notification_service->push_warning("LS Customs", "You aren't in a vehicle.");
return;
}
scripts::request_script(hash);
if (scripts::wait_till_loaded(hash))
{
int args[] = {45, 0, 9};
scripts::start_script_with_args(hash, args, 3, 3600);
scripts::wait_till_running(hash);
}
if (scripts::is_running(hash))
{
if (auto carmod_shop_thread = gta_util::find_script_thread(hash); carmod_shop_thread)
{ {
*script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).at(409).as<int*>() = veh;// "HIDDEN_RADIO_09_HIPHOP_OLD" HUD::REQUEST_ADDITIONAL_TEXT("MOD_MNU", 9);
*script_local(carmod_shop_thread, CARMOD_SHOP_CUTSCENE).as<bool*>() = false;// skips cutscene that's invisible
*script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).at(11).as<int*>() = 4; while (!HUD::HAS_THIS_ADDITIONAL_TEXT_LOADED("MOD_MNU", 9))
script::get_current()->yield();
GRAPHICS::REQUEST_STREAMED_TEXTURE_DICT("CommonMenu", false);
GRAPHICS::REQUEST_STREAMED_TEXTURE_DICT("MPShopSale", false);
GRAPHICS::REQUEST_STREAMED_TEXTURE_DICT("ShopUI_Title_Los_Santos_Car_Meet", false);
// clang-format off
while (!GRAPHICS::HAS_STREAMED_TEXTURE_DICT_LOADED("CommonMenu")
|| !GRAPHICS::HAS_STREAMED_TEXTURE_DICT_LOADED("MPShopSale")
|| !GRAPHICS::HAS_STREAMED_TEXTURE_DICT_LOADED("ShopUI_Title_Los_Santos_Car_Meet"))
script::get_current()->yield();
// clang-format on
auto id = SYSTEM::START_NEW_SCRIPT_WITH_NAME_HASH(RAGE_JOAAT("carmod_shop"), 5050);
if (!id)
return;
g.m_modshop_thread = gta_util::find_script_thread_by_id(id);
if (!g.m_modshop_thread)
return;
g.m_modshop_thread->m_context.m_state = rage::eThreadState::unk_3;
scr_functions::modshop_loop.populate_ip();
scr_functions::setup_modshop.populate_ip();
g_script_patcher_service->update();
scr_functions::setup_modshop.call_latent(g.m_modshop_thread, gta_util::find_script_program(RAGE_JOAAT("carmod_shop")), {45, 0, 18, 0}, bModshopReady);
*script_local(g.m_modshop_thread->m_stack, 730).at(446).as<int*>() = 2;
*script_local(g.m_modshop_thread->m_stack, 2237).as<ControllerInputs*>() = ControllerInputs::INPUT_FRONTEND_LT;
} }
} });
bLastLsCustoms = true;
}
else if (!g.vehicle.ls_customs && g.vehicle.ls_customs != bLastLsCustoms)
{
if (g.m_modshop_thread)
g.m_modshop_thread->kill();
GRAPHICS::SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("CommonMenu");
GRAPHICS::SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("MPShopSale");
GRAPHICS::SET_STREAMED_TEXTURE_DICT_AS_NO_LONGER_NEEDED("ShopUI_Title_Los_Santos_Car_Meet");
g.m_modshop_thread = nullptr;
bLastLsCustoms = false;
bModshopReady = false;
g_script_patcher_service->update();
} }
busy = false; if (self::veh == 0 || SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) > 0 || (!g.m_modshop_thread && bModshopReady))
state = g.vehicle.ls_customs; {
g.vehicle.ls_customs = false;
return;
}
if (g.vehicle.ls_customs && g.m_modshop_thread)
{
PAD::DISABLE_CONTROL_ACTION(0, (int)ControllerInputs::INPUT_VEH_CIN_CAM, true);
if (*script_local(g.m_modshop_thread->m_stack, 2466).as<bool*>() && PAD::IS_CONTROL_JUST_PRESSED(2, (int)ControllerInputs::INPUT_FRONTEND_ACCEPT))
g.vehicle.ls_customs = false;
}
if (g.vehicle.ls_customs && bModshopReady && g.m_modshop_thread && g.m_modshop_thread->m_stack)
{
*script_local(g.m_modshop_thread->m_stack, 2418).as<bool*>() = false;
*script_local(g.m_modshop_thread->m_stack, 730).at(638).as<int*>() = -1;
*script_local(g.m_modshop_thread->m_stack, 730).at(409).as<Vehicle*>() = self::veh;
if (*script_local(g.m_modshop_thread->m_stack, 730).at(446).as<int*>() == 0)
*script_local(g.m_modshop_thread->m_stack, 730).at(446).as<int*>() = 2;
scr_functions::modshop_loop.call(g.m_modshop_thread, gta_util::find_script_program(RAGE_JOAAT("carmod_shop")), {});
}
} }
} }

View File

@ -1,5 +1,6 @@
#include "backend/looped/looped.hpp" #include "backend/looped/looped.hpp"
#include "core/enums.hpp" #include "core/enums.hpp"
#include "gta/enums.hpp"
#include "util/entity.hpp" #include "util/entity.hpp"
#include "util/vehicle.hpp" #include "util/vehicle.hpp"

View File

@ -1,5 +1,6 @@
#include "backend/looped/looped.hpp" #include "backend/looped/looped.hpp"
#include "core/enums.hpp" #include "core/enums.hpp"
#include "gta/enums.hpp"
#include "gui.hpp" #include "gui.hpp"
#include "util/math.hpp" #include "util/math.hpp"
#include "util/vehicle.hpp" #include "util/vehicle.hpp"

View File

@ -44,6 +44,19 @@ namespace big
{0x2B, 0x2B, 0x2B, 0x00, 0x55}, {0x2B, 0x2B, 0x2B, 0x00, 0x55},
&g.self.invisibility}); &g.self.invisibility});
g_script_patcher_service->add_patch(
{RAGE_JOAAT("carmod_shop"), "2D 01 0A 00 00 4F ? ? 40 ? 41 ? 39 03", 5, {0x2E, 0x01, 0x00}, &g.vehicle.ls_customs});// disable camera
g_script_patcher_service->add_patch(
{RAGE_JOAAT("carmod_shop"), "2D 02 10 00 00 2C", 5, {0x71, 0x2E, 0x02, 0x01}, &g.vehicle.ls_customs});
g_script_patcher_service->add_patch(
{RAGE_JOAAT("carmod_shop"), "2D 00 B8 00 00", 5, {0x2E, 0x00, 0x00}, &g.vehicle.ls_customs});
g_script_patcher_service->add_patch(
{RAGE_JOAAT("carmod_shop"), "06 1F 56 ? ? 62 ? ? ? 56", 0, {0x2B, 0x2B, 0x55}, &g.vehicle.ls_customs});// buy mods for free in SP
g_script_patcher_service->add_patch(
{RAGE_JOAAT("carmod_shop"), "2D 03 16 00 00 5D", 5, {0x72, 0x2E, 0x03, 0x01}, &g.vehicle.ls_customs});// allow all vehicles
g_script_patcher_service->add_patch(
{RAGE_JOAAT("carmod_shop"), "2D 03 07 00 00 71 38 02", 5, {0x72, 0x2E, 0x03, 0x01}, &g.vehicle.ls_customs});// allow all vehicles 2
for (auto& entry : *g_pointers->m_script_program_table) for (auto& entry : *g_pointers->m_script_program_table)
{ {
if (entry.m_program) if (entry.m_program)

View File

@ -53,8 +53,9 @@ namespace big
int m_remote_controller_vehicle = -1; int m_remote_controller_vehicle = -1;
int m_remote_controlled_vehicle = -1; int m_remote_controlled_vehicle = -1;
int m_mod_net_id = -1; std::uint16_t m_tp_veh_net_id;
int m_test_net_id = -1; std::uint16_t m_tp_player_net_id;
rage::fvector3 m_tp_position;
rage::scrThread* m_hunt_the_beast_thread = nullptr; rage::scrThread* m_hunt_the_beast_thread = nullptr;
@ -63,6 +64,10 @@ namespace big
rage::scrThread* m_mission_creator_thread = nullptr; rage::scrThread* m_mission_creator_thread = nullptr;
rage::scrThread* m_modshop_thread = nullptr;
bool in_script_vm = false;
struct debug struct debug
{ {
struct logs struct logs
@ -79,7 +84,7 @@ namespace big
bool filter_player = true; bool filter_player = true;
std::int8_t player_id = -1; std::int8_t player_id = -1;
bool block_all = false;//should not save bool block_all = false; //should not save
NLOHMANN_DEFINE_TYPE_INTRUSIVE(script_event, logs, filter_player, player_id) NLOHMANN_DEFINE_TYPE_INTRUSIVE(script_event, logs, filter_player, player_id)
} script_event{}; } script_event{};
@ -145,7 +150,7 @@ namespace big
reaction fake_deposit{"Fake Deposit", "Blocked Fake Deposit from %s", "%s tried to show me a fake money notification!"}; reaction fake_deposit{"Fake Deposit", "Blocked Fake Deposit from %s", "%s tried to show me a fake money notification!"};
reaction force_mission{"Force Mission", "Blocked Force Mission from %s", "%s tried to force me into a mission!"}; reaction force_mission{"Force Mission", "Blocked Force Mission from %s", "%s tried to force me into a mission!"};
reaction force_teleport{"Force Teleport", "Blocked Force Teleport from %s", "%s tried to teleport me!"}; reaction force_teleport{"Force Teleport", "Blocked Force Teleport from %s", "%s tried to teleport me!"};
reaction gta_banner{"GTA Banner", "Blocked GTA Banner from %s", "Blocked GTA Banner from %s"};// please don't enable this reaction gta_banner{"GTA Banner", "Blocked GTA Banner from %s", "Blocked GTA Banner from %s"}; // please don't enable this
reaction kick_from_interior{"Kick From Interior", "Blocked Kick From Interior from %s", "%s tried to kick me from my interior!"}; reaction kick_from_interior{"Kick From Interior", "Blocked Kick From Interior from %s", "%s tried to kick me from my interior!"};
reaction mc_teleport{"MC Teleport", "Blocked MC Teleport from %s", "%s tried to teleport me!"}; reaction mc_teleport{"MC Teleport", "Blocked MC Teleport from %s", "%s tried to teleport me!"};
reaction network_bail{"Network Bail", "Blocked Network Bail from %s", "%s tried to kick me out!"}; reaction network_bail{"Network Bail", "Blocked Network Bail from %s", "%s tried to kick me out!"};
@ -179,7 +184,7 @@ namespace big
reaction request_control_event{"Request Control Event", "Blocked Request Control Event from %s", "%s tried to mess with my vehicle!"}; reaction request_control_event{"Request Control Event", "Blocked Request Control Event from %s", "%s tried to mess with my vehicle!"};
reaction report{"Report", "Blocked Report from %s", "%s tried to report me!"}; reaction report{"Report", "Blocked Report from %s", "%s tried to report me!"};
interloper_reaction breakup_others{"Breakup Kicks On Other Players", "%s is trying to breakup kick %s!", "%s is trying to breakup kick %s!", true, true};// blockable only when host but we have no way to specify that atm interloper_reaction breakup_others{"Breakup Kicks On Other Players", "%s is trying to breakup kick %s!", "%s is trying to breakup kick %s!", true, true}; // blockable only when host but we have no way to specify that atm
reaction lost_connection_kick{"Lost Connection Kick", "Blocked Lost Connection Kick from %s", "%s tried to kick me out!"}; reaction lost_connection_kick{"Lost Connection Kick", "Blocked Lost Connection Kick from %s", "%s tried to kick me out!"};
reaction gamer_instruction_kick{"Gamer Instruction Kick", "Blocked Gamer Instruction Kick from %s", "%s tried to kick me out!"}; reaction gamer_instruction_kick{"Gamer Instruction Kick", "Blocked Gamer Instruction Kick from %s", "%s tried to kick me out!"};
interloper_reaction lost_connection_kick_others{"Lost Connection Kick On Other Players", "%s is trying to lost connection kick %s!", "%s is trying to lost connection kick %s!", true, false}; interloper_reaction lost_connection_kick_others{"Lost Connection Kick On Other Players", "%s is trying to lost connection kick %s!", "%s is trying to lost connection kick %s!", true, false};
@ -225,7 +230,7 @@ namespace big
bool desync_kick = false; bool desync_kick = false;
bool rid_join = false; bool rid_join = false;
bool lessen_breakups = false;// disabled by default due to anticheat concerns bool lessen_breakups = false; // disabled by default due to anticheat concerns
bool receive_pickup = false; bool receive_pickup = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, lessen_breakups, desync_kick, receive_pickup) NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, lessen_breakups, desync_kick, receive_pickup)
@ -478,7 +483,7 @@ namespace big
bool hide_from_player_list = false; bool hide_from_player_list = false;
bool spoof_blip = false; bool spoof_blip = false;
int blip_type = 0;// actual blip type + 1 int blip_type = 0; // actual blip type + 1
bool spoof_rank = false; bool spoof_rank = false;
int rank = 1; int rank = 1;
@ -512,7 +517,9 @@ namespace big
bool spoof_session_player_count = false; bool spoof_session_player_count = false;
int session_player_count = 25; int session_player_count = 25;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(spoofing, hide_from_player_list, spoof_cheater, spoof_hide_god, spoof_hide_spectate, spoof_crew_data, crew_tag, rockstar_crew, square_crew_tag, spoof_session_region_type, session_region_type, spoof_session_language, session_language, spoof_session_player_count, session_player_count, spoof_blip, blip_type, spoof_rank, rank, spoof_job_points, job_points, spoof_bad_sport, badsport_type, spoof_kd_ratio, kd_ratio, spoof_player_model, player_model) bool voice_chat_audio = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(spoofing, hide_from_player_list, spoof_cheater, spoof_hide_god, spoof_hide_spectate, spoof_crew_data, crew_tag, rockstar_crew, square_crew_tag, spoof_session_region_type, session_region_type, spoof_session_language, session_language, spoof_session_player_count, session_player_count, voice_chat_audio)
} spoofing{}; } spoofing{};
struct vehicle struct vehicle
@ -564,36 +571,30 @@ namespace big
uint32_t proof_mask = 0; uint32_t proof_mask = 0;
AutoDriveDestination auto_drive_destination = AutoDriveDestination::STOPPED; AutoDriveDestination auto_drive_destination = AutoDriveDestination::STOPPED;
AutoDriveStyle auto_drive_style = AutoDriveStyle::LAW_ABIDING; AutoDriveStyle auto_drive_style = AutoDriveStyle::LAW_ABIDING;
float auto_drive_speed = 1; float auto_drive_speed = 1;
bool auto_turn_signals = false; bool auto_turn_signals = false;
eBoostBehaviors boost_behavior = eBoostBehaviors::DEFAULT; eBoostBehaviors boost_behavior = eBoostBehaviors::DEFAULT;
bool drive_on_water = false; bool drive_on_water = false;
bool horn_boost = false; bool horn_boost = false;
bool instant_brake = false; bool instant_brake = false;
bool block_homing = true; bool block_homing = true;
bool ls_customs = false; // don't save this to disk bool ls_customs = false; // don't save this to disk
bool seatbelt = false; bool seatbelt = false;
bool turn_signals = false; bool turn_signals = false;
bool vehicle_jump = false; bool vehicle_jump = false;
bool keep_vehicle_repaired = false; bool keep_vehicle_repaired = false;
bool no_water_collision = false; bool no_water_collision = false;
bool disable_engine_auto_start = false; bool disable_engine_auto_start = false;
bool change_engine_state_immediately = false; bool change_engine_state_immediately = false;
bool vehinvisibility = false; bool vehinvisibility = false;
bool localveh_visibility = false; bool localveh_visibility = false;
bool localped_visibility = true; bool localped_visibility = true;
bool keep_on_ground = false; bool keep_on_ground = false;
bool no_collision = false; bool no_collision = false;
bool unlimited_weapons = false; bool unlimited_weapons = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle, NLOHMANN_DEFINE_TYPE_INTRUSIVE(vehicle, speedo_meter, fly, rainbow_paint, speed_unit, god_mode, proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask, auto_drive_destination, auto_drive_style, auto_drive_speed, auto_turn_signals, boost_behavior, drive_on_water, horn_boost, instant_brake, block_homing, seatbelt, turn_signals, vehicle_jump, keep_vehicle_repaired, no_water_collision, disable_engine_auto_start, change_engine_state_immediately, vehinvisibility, localveh_visibility, localped_visibility, keep_on_ground, no_collision, unlimited_weapons)
speedo_meter, fly, rainbow_paint, speed_unit, god_mode,
proof_bullet, proof_fire, proof_collision, proof_melee, proof_explosion, proof_steam, proof_water, proof_mask,
auto_drive_destination, auto_drive_style, auto_drive_speed, auto_turn_signals, boost_behavior,
drive_on_water, horn_boost, instant_brake, block_homing, seatbelt, turn_signals, vehicle_jump,
keep_vehicle_repaired, no_water_collision, disable_engine_auto_start, change_engine_state_immediately,
vehinvisibility, localveh_visibility, localped_visibility, keep_on_ground, no_collision, unlimited_weapons)
} vehicle{}; } vehicle{};
struct weapons struct weapons
@ -634,7 +635,7 @@ namespace big
bool on_npc = false; bool on_npc = false;
float fov = 90.f; float fov = 90.f;
float distance = 200.f; float distance = 200.f;
std::uint32_t selected_bone = 0x796E;// Default to head std::uint32_t selected_bone = 0x796E; // Default to head
NLOHMANN_DEFINE_TYPE_INTRUSIVE(aimbot, enable, smoothing, smoothing_speed, fov, selected_bone) NLOHMANN_DEFINE_TYPE_INTRUSIVE(aimbot, enable, smoothing, smoothing_speed, fov, selected_bone)
} aimbot{}; } aimbot{};

View File

@ -6,7 +6,8 @@
namespace big namespace big
{ {
fiber_pool::fiber_pool(std::size_t num_fibers) fiber_pool::fiber_pool(std::size_t num_fibers) :
m_num_fibers(num_fibers)
{ {
for (std::size_t i = 0; i < num_fibers; ++i) for (std::size_t i = 0; i < num_fibers; ++i)
{ {
@ -51,4 +52,22 @@ namespace big
script::get_current()->yield(); script::get_current()->yield();
} }
} }
int fiber_pool::get_total_fibers()
{
return m_num_fibers;
}
int fiber_pool::get_used_fibers()
{
return m_jobs.size();
}
void fiber_pool::reset()
{
std::lock_guard lock(m_mutex);
while (!m_jobs.empty())
m_jobs.pop();
}
} }

View File

@ -14,9 +14,15 @@ namespace big
void fiber_tick(); void fiber_tick();
static void fiber_func(); static void fiber_func();
int get_total_fibers();
int get_used_fibers();
void reset();
private: private:
std::recursive_mutex m_mutex; std::recursive_mutex m_mutex;
std::stack<std::function<void()>> m_jobs; std::stack<std::function<void()>> m_jobs;
int m_num_fibers;
}; };
inline fiber_pool* g_fiber_pool{}; inline fiber_pool* g_fiber_pool{};

View File

@ -21,6 +21,7 @@ namespace rage
class snConnectToPeerTaskResult; class snConnectToPeerTaskResult;
class rlScHandle; class rlScHandle;
class rlQueryPresenceAttributesContext; class rlQueryPresenceAttributesContext;
enum class eThreadState : uint32_t;
} }
namespace datafile_commands namespace datafile_commands
@ -91,9 +92,9 @@ namespace big::functions
using fipackfile_unmount = bool (*)(const char* mount_point); using fipackfile_unmount = bool (*)(const char* mount_point);
using start_get_session_by_gamer_handle = bool (*)(int profile_index, rage::rlGamerHandle* handles, int count, rage::rlSessionByGamerTaskResult* result, int unk, bool* success, rage::rlTaskStatus* state); using start_get_session_by_gamer_handle = bool (*)(int profile_index, rage::rlGamerHandle* handles, int count, rage::rlSessionByGamerTaskResult* result, int unk, bool* success, rage::rlTaskStatus* state);
using start_matchmaking_find_sessions = bool (*)(int profile_index, int available_slots, NetworkGameFilterMatchmakingComponent* m_filter, unsigned int max_sessions, rage::rlSessionInfo* result_sessions, int* result_session_count, rage::rlTaskStatus* state); using start_matchmaking_find_sessions = bool (*)(int profile_index, int available_slots, NetworkGameFilterMatchmakingComponent* m_filter, unsigned int max_sessions, rage::rlSessionInfo* result_sessions, int* result_session_count, rage::rlTaskStatus* state);
using start_get_presence_attributes = bool (*)(int profile_index, rage::rlScHandle* handle, rage::rlQueryPresenceAttributesContext* contexts, int count, rage::rlTaskStatus* state); using start_get_presence_attributes = bool (*)(int profile_index, rage::rlScHandle* handle, rage::rlQueryPresenceAttributesContext* contexts, int count, rage::rlTaskStatus* state);
using join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount); using join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount);
using generate_uuid = bool (*)(std::uint64_t* uuid); using generate_uuid = bool (*)(std::uint64_t* uuid);
@ -108,14 +109,14 @@ namespace big::functions
using send_chat_message = bool (*)(int64_t* send_chat_ptr, rage::rlGamerInfo* gamer_info, char* message, bool is_team); using send_chat_message = bool (*)(int64_t* send_chat_ptr, rage::rlGamerInfo* gamer_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 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 request_ragdoll = void (*)(uint16_t object_id);
using request_control = void (*)(rage::netObject* net_object); using request_control = void (*)(rage::netObject* net_object);
using get_connection_peer = rage::netConnectionPeer* (*)(rage::netConnectionManager* manager, int peer_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 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 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); using script_vm = rage::eThreadState (*)(uint64_t* stack, int64_t** scr_globals, rage::scrProgram* program, rage::scrThreadContext* ctx);
using encode_session_info = bool (*)(rage::rlSessionInfo* info, char* buffer, int buffer_size, int* bytes_written); using encode_session_info = bool (*)(rage::rlSessionInfo* info, char* buffer, int buffer_size, int* bytes_written);
using decode_session_info = bool (*)(rage::rlSessionInfo* out_info, char* buffer, int* bytes_read); using decode_session_info = bool (*)(rage::rlSessionInfo* out_info, char* buffer, int* bytes_read);
@ -126,11 +127,13 @@ namespace big::functions
using save_json_data = char* (*)(datafile_commands::SveFileObject* object, int* out_length, const char* reason); using save_json_data = char* (*)(datafile_commands::SveFileObject* object, int* out_length, const char* reason);
using sync_network_time = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, rage::netTimeSyncMsg* msg, int flags); using sync_network_time = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, rage::netTimeSyncMsg* msg, int flags);
using send_packet = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, void* data, int size, int flags); using send_packet = bool (*)(rage::netConnectionManager* mgr, rage::netConnectionPeer* peer, int connection_id, void* data, int size, int flags);
using connect_to_peer = bool (*)(rage::netConnectionManager* mgr, rage::rlGamerInfoBase* gamer_info, rage::snConnectToPeerTaskData* data, rage::snConnectToPeerTaskResult* result, rage::rlTaskStatus* status); using connect_to_peer = bool (*)(rage::netConnectionManager* mgr, rage::rlGamerInfoBase* gamer_info, rage::snConnectToPeerTaskData* data, rage::snConnectToPeerTaskResult* result, rage::rlTaskStatus* status);
using clear_ped_tasks_network = void (*)(CPed* ped, bool immediately); using clear_ped_tasks_network = void (*)(CPed* ped, bool immediately);
using get_next_carriage = void* (*)(void* carriage); using get_next_carriage = void* (*)(void* carriage);
using get_entity_attached_to = rage::CDynamicEntity* (*)(rage::CDynamicEntity* entity); using get_entity_attached_to = rage::CDynamicEntity* (*)(rage::CDynamicEntity* entity);
using migrate_object = void (*)(CNetGamePlayer* player, rage::netObject* object, int type);
} }

203
src/gta/sound.hpp Normal file
View File

@ -0,0 +1,203 @@
#pragma once
#include "file_manager.hpp"
#include "thread_pool.hpp"
using namespace std::chrono_literals;
// {DCB7EF33-CD8A-4231-8051-66E3F683180B}
static const GUID g_yim_device = {0xdcb7ef33, 0xcd8a, 0x4231, {0x80, 0x51, 0x66, 0xe3, 0xf6, 0x83, 0x18, 0xb}};
class IDirectSoundCaptureBuffer
{
inline int GetActualReadPos()
{
return read_position + (audio_page * 32000);
}
virtual void QueryInterface(){};
virtual int AddRef()
{
return 0;
};
virtual int Release()
{
return 0;
}
virtual HRESULT GetCaps(void* caps)
{
return (HRESULT)0L;// DS_OK
}
virtual HRESULT GetCurrentPosition(int* capture, int* read)
{
if (capture)
*capture = 0;
if (read)
*read = read_position;
return (HRESULT)0L;// DS_OK
}
virtual HRESULT GetFormat(void* out, int length, int* out_length)
{
return (HRESULT)0L;// DS_OK
}
virtual HRESULT GetStatus(int* status)
{
*status = 1; // DSCBSTATUS_CAPTURING
return (HRESULT)0L;// DS_OK
}
virtual HRESULT Initialize(void*, void*)
{
return (HRESULT)0L;// DS_OK
}
virtual HRESULT Lock(DWORD dwOffset, DWORD dwBytes, char** ppvAudioPtr1, LPDWORD pdwAudioBytes1, char** ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags)
{
if (dwOffset > read_position && audio_page != 0)
{
dwOffset -= 32000;// fix page offset if we have to read back
}
dwOffset += (audio_page * 32000);// add our page offset to get the actual position
// fix artifacts after audio ends
if (dwBytes > 1280)
dwOffset = 0;
if (dwOffset + dwBytes <= audio_size)
{
*ppvAudioPtr1 = &audio_buffer[dwOffset];
*pdwAudioBytes1 = dwBytes;
*ppvAudioPtr2 = NULL;
*pdwAudioBytes2 = 0;
}
else
{
*ppvAudioPtr1 = &audio_buffer[dwOffset];
*pdwAudioBytes1 = audio_size - dwOffset;
*ppvAudioPtr2 = &audio_buffer[0];
*pdwAudioBytes2 = dwBytes - *pdwAudioBytes1;
}
return (HRESULT)0L;// DS_OK
}
virtual HRESULT Start(int flags)
{
if (big::g_file_manager->get_project_file("./audio.wav").exists())
{
std::ifstream wave_stream(big::g_file_manager->get_project_file("./audio.wav").get_path(), std::ios::in | std::ios::binary);
// https://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
int header_size = 0;
int data_size = 0;
wave_stream.seekg(4, std::ios_base::cur); // RIFF
wave_stream.seekg(4, std::ios_base::cur); // chunk size
wave_stream.seekg(4, std::ios_base::cur); // Wave ID
wave_stream.seekg(4, std::ios_base::cur); // ckID "fmt "
wave_stream.read((char*)&header_size, 4); // cksize "fmt "
wave_stream.seekg(header_size, std::ios_base::cur);// format
wave_stream.seekg(4, std::ios_base::cur); // ckID "data"
wave_stream.read((char*)&data_size, 4); // cksize "data"
audio_buffer = new char[data_size];
memset(audio_buffer, 0, data_size);
audio_size = data_size;
wave_stream.read(audio_buffer, audio_size);
wave_stream.close();
}
else
{
audio_buffer = new char[0xFFFF];
audio_size = 0xFFFF;
}
running = true;
big::g_thread_pool->push([this] {
last_read = std::chrono::high_resolution_clock::now();
while (!big::g_running)
std::this_thread::yield();
while (big::g_running && running)
{
std::this_thread::yield();
// the buffer can only support up to 32000 bytes of data at once, so we have to page it instead
if (std::chrono::high_resolution_clock::now() - last_read >= 1ms)
{
last_read = std::chrono::high_resolution_clock::now();
read_position += ((2 * 16000) / 1000);// F*M*Nc/1000
// reset page idx after audio playback completes
if (GetActualReadPos() > audio_size)
{
read_position = 0;
audio_page = 0;
}
// use next page if we go beyond 32000
if (read_position > 32000)
{
read_position = read_position % 32000;
audio_page++;
}
}
}
});
return (HRESULT)0L;// DS_OK
}
virtual HRESULT Stop()
{
running = false;
delete[] audio_buffer;
return (HRESULT)0L;// DS_OK
}
virtual HRESULT Unlock(LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2)
{
return (HRESULT)0L;// DS_OK
}
char* audio_buffer = nullptr;
int audio_size = 0;
int audio_page = 0;
int read_position = 0;
bool running = false;
std::chrono::high_resolution_clock::time_point last_read = std::chrono::high_resolution_clock::time_point();
};
inline IDirectSoundCaptureBuffer g_direct_sound_capture_buffer{};
class IDirectSoundCapture
{
virtual void QueryInterface(){};
virtual int AddRef()
{
return 0;
};
virtual int Release()
{
return 0;
}
virtual HRESULT CreateSoundBuffer(void* desc, IDirectSoundCaptureBuffer** buffer, void* unknown)
{
*buffer = &g_direct_sound_capture_buffer;
return (HRESULT)0L;// DS_OK
}
// we shouldn't need the rest
};
inline IDirectSoundCapture g_direct_sound_capture{};

View File

@ -13,20 +13,20 @@ namespace big
gui::gui() : gui::gui() :
m_is_open(false) m_is_open(false)
{ {
g_renderer->add_dx_callback(view::gta_data, -1); // -1 highest priority of drawing g_renderer->add_dx_callback(view::gta_data, -1); // -1 highest priority of drawing
g_renderer->add_dx_callback(view::notifications, -2); // second highest priority g_renderer->add_dx_callback(view::notifications, -2);// second highest priority
g_renderer->add_dx_callback(view::overlay, -3); // 3rd highest priority g_renderer->add_dx_callback(view::overlay, -3); // 3rd highest priority
g_renderer->add_dx_callback( g_renderer->add_dx_callback(
[this] { [this] {
dx_on_tick(); dx_on_tick();
}, },
-4); // 4th highest priority -4);// 4th highest priority
g_renderer->add_wndproc_callback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { g_renderer->add_wndproc_callback([this](HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
wndproc(hwnd, msg, wparam, lparam); wndproc(hwnd, msg, wparam, lparam);
}); });
g_renderer->add_dx_callback(esp::draw, 2); // TODO: move to ESP service g_renderer->add_dx_callback(esp::draw, 2);// TODO: move to ESP service
g_renderer->add_dx_callback(view::context_menu, 1); g_renderer->add_dx_callback(view::context_menu, 1);
dx_init(); dx_init();

View File

@ -11,6 +11,7 @@
#include "script_mgr.hpp" #include "script_mgr.hpp"
#include <MinHook.h> #include <MinHook.h>
#include <vehicle/CVehicle.hpp>
namespace big namespace big
{ {
@ -113,6 +114,11 @@ namespace big
detour_hook_helper::add<hooks::get_model_info>("GMI", g_pointers->m_get_model_info); detour_hook_helper::add<hooks::get_model_info>("GMI", g_pointers->m_get_model_info);
detour_hook_helper::add<hooks::enumerate_audio_devices>("EAD", g_pointers->m_enumerate_audio_devices);
detour_hook_helper::add<hooks::direct_sound_capture_create>("DSCC", g_pointers->m_direct_sound_capture_create);
detour_hook_helper::add<hooks::write_vehicle_proximity_migration_data_node>("WVPMDN", g_pointers->m_write_vehicle_proximity_migration_data_node);
g_hooking = this; g_hooking = this;
} }

View File

@ -27,6 +27,9 @@ class CPlayerCardStats;
class CStatsSerializationContext; class CStatsSerializationContext;
class CPlayerCreationDataNode; class CPlayerCreationDataNode;
class CPlayerAppearanceDataNode; class CPlayerAppearanceDataNode;
class CFoundDevice;
class IDirectSoundCapture;
class CVehicleProximityMigrationDataNode;
namespace rage namespace rage
{ {
@ -153,6 +156,11 @@ namespace big
static void write_player_appearance_data_node(rage::netObject* player, CPlayerAppearanceDataNode* node); static void write_player_appearance_data_node(rage::netObject* player, CPlayerAppearanceDataNode* node);
static CBaseModelInfo* get_model_info(rage::joaat_t hash, uint32_t* a2); static CBaseModelInfo* get_model_info(rage::joaat_t hash, uint32_t* a2);
static int enumerate_audio_devices(CFoundDevice* found_devices, int count, int flags);
static HRESULT direct_sound_capture_create(GUID* guid, IDirectSoundCapture** sound, void* unknown);
static void write_vehicle_proximity_migration_data_node(rage::netObject* veh, CVehicleProximityMigrationDataNode* node);
}; };
class minhook_keepalive class minhook_keepalive

View File

@ -10,7 +10,7 @@ namespace big
g_hooking->get_original<hooks::serialize_take_off_ped_variation_task>()(info, serializer); g_hooking->get_original<hooks::serialize_take_off_ped_variation_task>()(info, serializer);
if (info->m_prop_hash != 0 && info->m_variation_component == 5 && info->m_prop_hash != RAGE_JOAAT("p_parachute_s")) if (info->m_prop_hash != 0 && info->m_variation_component == 5 && info->m_prop_hash != RAGE_JOAAT("p_parachute_s"))
{ {
notify::crash_blocked(g.m_syncing_player, "invalid parachute"); // notify::crash_blocked(g.m_syncing_player, "invalid parachute"); false positives
info->m_prop_hash = 0; info->m_prop_hash = 0;
} }
} }

View File

@ -8,7 +8,8 @@ namespace big
const auto result = g_hooking->get_original<gta_thread_kill>()(thread); const auto result = g_hooking->get_original<gta_thread_kill>()(thread);
if (g.notifications.gta_thread_kill.log) if (g.notifications.gta_thread_kill.log)
LOG(INFO) << "Script Thread '" << thread->m_name << "' terminated."; LOG(INFO) << "Script Thread '" << thread->m_name << "' terminated (" << thread->m_exit_message << ").";
if (g.notifications.gta_thread_kill.notify) if (g.notifications.gta_thread_kill.notify)
g_notification_service->push("Script Thread Termination", g_notification_service->push("Script Thread Termination",
std::format("Script Thread '{}' terminated.", thread->m_name)); std::format("Script Thread '{}' terminated.", thread->m_name));
@ -22,6 +23,9 @@ namespace big
if (thread == g.m_mission_creator_thread) if (thread == g.m_mission_creator_thread)
g.m_mission_creator_thread = nullptr; g.m_mission_creator_thread = nullptr;
if (thread == g.m_modshop_thread)
g.m_modshop_thread = nullptr;
return result; return result;
} }
} }

View File

@ -30,6 +30,8 @@ namespace big
scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[self::id].CurrentShopIndex = old_shop_index; scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[self::id].CurrentShopIndex = old_shop_index;
scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[self::id].CayoPericoFlags = old_cayo_flags; scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[self::id].CayoPericoFlags = old_cayo_flags;
} }
g.in_script_vm = true;
} }
~script_vm_guard() ~script_vm_guard()
@ -47,6 +49,8 @@ namespace big
scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[self::id].CayoPericoFlags = 1; scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[self::id].CayoPericoFlags = 1;
} }
} }
g.in_script_vm = false;
} }
}; };

View File

@ -0,0 +1,24 @@
#include "gta/net_array.hpp"
#include "hooking.hpp"
#include "script_global.hpp"
#include "script_local.hpp"
#include <netsync/nodes/vehicle/CVehicleProximityMigrationDataNode.hpp>
namespace big
{
void hooks::write_vehicle_proximity_migration_data_node(rage::netObject* veh, CVehicleProximityMigrationDataNode* node)
{
CVehicle* vehicle = *(CVehicle**)(((__int64)veh) - 432);
g_hooking->get_original<hooks::write_vehicle_proximity_migration_data_node>()(veh, node);
if (vehicle->m_net_object->m_object_id = g.m_tp_veh_net_id)
{
node->m_has_occupants[0] = true;
node->m_occupants[0] = g.m_tp_player_net_id;
node->m_override_position = true;
node->m_position = g.m_tp_position;
}
}
}

View File

@ -0,0 +1,18 @@
#include "gta/sound.hpp"
#include "hooking.hpp"
namespace big
{
HRESULT hooks::direct_sound_capture_create(GUID* guid, IDirectSoundCapture** sound, void* unknown)
{
if ((*guid) == g_yim_device && g.spoofing.voice_chat_audio)
{
*sound = &g_direct_sound_capture;
return (HRESULT)0L;// DS_OK
}
else
{
return g_hooking->get_original<hooks::direct_sound_capture_create>()(guid, sound, unknown);
}
}
}

View File

@ -0,0 +1,42 @@
#include "gta/sound.hpp"
#include "hooking.hpp"
class CFoundDevice
{
public:
GUID m_guid;
char16_t m_name[64];
int m_device_type;
int m_default_type;
int m_pad2;
};
static_assert(sizeof(CFoundDevice) == 0x9C);
namespace big
{
int hooks::enumerate_audio_devices(CFoundDevice* found_devices, int count, int flags)
{
auto res = g_hooking->get_original<hooks::enumerate_audio_devices>()(found_devices, count, flags);
if ((flags & 1) && g.spoofing.voice_chat_audio)
{
for (int i = 0; i < count; i++)
{
if (found_devices[i].m_device_type != 2 || found_devices[i].m_default_type != 2)
{
lstrcpyW((LPWSTR)found_devices[i].m_name, L"YimMenu Virtual Input Device");
found_devices[i].m_guid = g_yim_device;
found_devices[i].m_device_type = 1;
found_devices[i].m_default_type = 1;
if (i >= res)
res++;
break;
}
}
}
return res;
}
}

View File

@ -1,5 +1,6 @@
#include "stack_trace.hpp" #include "stack_trace.hpp"
#include "gta/script_thread.hpp"
#include "memory/module.hpp" #include "memory/module.hpp"
#include <DbgHelp.h> #include <DbgHelp.h>
@ -26,9 +27,13 @@ namespace big
m_exception_info = exception_info; m_exception_info = exception_info;
m_dump << exception_code_to_string(exception_info->ExceptionRecord->ExceptionCode) << '\n'; m_dump << exception_code_to_string(exception_info->ExceptionRecord->ExceptionCode) << '\n';
if (g.in_script_vm)
dump_script_info();
dump_module_info(); dump_module_info();
dump_registers(); dump_registers();
dump_stacktrace(); dump_stacktrace();
m_dump << "\n--------End of exception--------\n"; m_dump << "\n--------End of exception--------\n";
} }
@ -40,11 +45,11 @@ namespace big
// I'd prefer to make some sort of global instance that cache all modules once instead of doing this every time // I'd prefer to make some sort of global instance that cache all modules once instead of doing this every time
void stack_trace::dump_module_info() void stack_trace::dump_module_info()
{ {
m_dump << "Dumping modules:\n"; // modules cached already
if (m_modules.size())
return;
// modules cached already m_dump << "Dumping modules:\n";
if (m_modules.size())
return;
const auto peb = reinterpret_cast<PPEB>(NtCurrentTeb()->ProcessEnvironmentBlock); const auto peb = reinterpret_cast<PPEB>(NtCurrentTeb()->ProcessEnvironmentBlock);
if (!peb) if (!peb)
@ -138,6 +143,13 @@ namespace big
} }
} }
void stack_trace::dump_script_info()
{
m_dump << "Currently executing script: " << rage::scrThread::get()->m_name << '\n';
m_dump << "Thread program counter (could be inaccurate): "
<< m_exception_info->ContextRecord->Rdi - m_exception_info->ContextRecord->Rsi << '\n';
}
void stack_trace::grab_stacktrace() void stack_trace::grab_stacktrace()
{ {
CONTEXT context = *m_exception_info->ContextRecord; CONTEXT context = *m_exception_info->ContextRecord;

View File

@ -37,6 +37,7 @@ namespace big
void dump_module_info(); void dump_module_info();
void dump_registers(); void dump_registers();
void dump_stacktrace(); void dump_stacktrace();
void dump_script_info();
void grab_stacktrace(); void grab_stacktrace();
const module_info* get_module_by_address(uint64_t addr) const; const module_info* get_module_by_address(uint64_t addr) const;

View File

@ -66,69 +66,68 @@ namespace big
{ {
const auto action = src->get_arg<ControllerInputs>(1); const auto action = src->get_arg<ControllerInputs>(1);
if (g.weapons.interior_weapon) // Filtering from the inside of Kosatka if (g.weapons.interior_weapon) // Filtering from the inside of Kosatka
{ {
switch (action) switch (action)
{ {
// case ControllerInputs::INPUT_JUMP: TODO: add as separate feature // case ControllerInputs::INPUT_JUMP: TODO: add as separate feature
case ControllerInputs::INPUT_ATTACK: case ControllerInputs::INPUT_ATTACK:
case ControllerInputs::INPUT_AIM: case ControllerInputs::INPUT_AIM:
case ControllerInputs::INPUT_DUCK: case ControllerInputs::INPUT_DUCK:
case ControllerInputs::INPUT_SELECT_WEAPON: case ControllerInputs::INPUT_SELECT_WEAPON:
case ControllerInputs::INPUT_COVER: case ControllerInputs::INPUT_COVER:
case ControllerInputs::INPUT_TALK: case ControllerInputs::INPUT_TALK:
case ControllerInputs::INPUT_DETONATE: case ControllerInputs::INPUT_DETONATE:
case ControllerInputs::INPUT_WEAPON_SPECIAL: case ControllerInputs::INPUT_WEAPON_SPECIAL:
case ControllerInputs::INPUT_WEAPON_SPECIAL_TWO: case ControllerInputs::INPUT_WEAPON_SPECIAL_TWO:
case ControllerInputs::INPUT_VEH_AIM: case ControllerInputs::INPUT_VEH_AIM:
case ControllerInputs::INPUT_VEH_ATTACK: case ControllerInputs::INPUT_VEH_ATTACK:
case ControllerInputs::INPUT_VEH_ATTACK2: case ControllerInputs::INPUT_VEH_ATTACK2:
case ControllerInputs::INPUT_VEH_HEADLIGHT: case ControllerInputs::INPUT_VEH_HEADLIGHT:
case ControllerInputs::INPUT_VEH_NEXT_RADIO: case ControllerInputs::INPUT_VEH_NEXT_RADIO:
case ControllerInputs::INPUT_VEH_PREV_RADIO: case ControllerInputs::INPUT_VEH_PREV_RADIO:
case ControllerInputs::INPUT_VEH_NEXT_RADIO_TRACK: case ControllerInputs::INPUT_VEH_NEXT_RADIO_TRACK:
case ControllerInputs::INPUT_VEH_PREV_RADIO_TRACK: case ControllerInputs::INPUT_VEH_PREV_RADIO_TRACK:
case ControllerInputs::INPUT_VEH_RADIO_WHEEL: case ControllerInputs::INPUT_VEH_RADIO_WHEEL:
case ControllerInputs::INPUT_VEH_PASSENGER_AIM: case ControllerInputs::INPUT_VEH_PASSENGER_AIM:
case ControllerInputs::INPUT_VEH_PASSENGER_ATTACK: case ControllerInputs::INPUT_VEH_PASSENGER_ATTACK:
case ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON: case ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON:
case ControllerInputs::INPUT_VEH_SELECT_PREV_WEAPON: case ControllerInputs::INPUT_VEH_SELECT_PREV_WEAPON:
case ControllerInputs::INPUT_VEH_ROOF: case ControllerInputs::INPUT_VEH_ROOF:
case ControllerInputs::INPUT_VEH_JUMP: case ControllerInputs::INPUT_VEH_JUMP:
case ControllerInputs::INPUT_VEH_FLY_ATTACK: case ControllerInputs::INPUT_VEH_FLY_ATTACK:
case ControllerInputs::INPUT_MELEE_ATTACK_LIGHT: case ControllerInputs::INPUT_MELEE_ATTACK_LIGHT:
case ControllerInputs::INPUT_MELEE_ATTACK_HEAVY: case ControllerInputs::INPUT_MELEE_ATTACK_HEAVY:
case ControllerInputs::INPUT_MELEE_ATTACK_ALTERNATE: case ControllerInputs::INPUT_MELEE_ATTACK_ALTERNATE:
case ControllerInputs::INPUT_MELEE_BLOCK: case ControllerInputs::INPUT_MELEE_BLOCK:
case ControllerInputs::INPUT_SELECT_WEAPON_UNARMED: case ControllerInputs::INPUT_SELECT_WEAPON_UNARMED:
case ControllerInputs::INPUT_SELECT_WEAPON_MELEE: case ControllerInputs::INPUT_SELECT_WEAPON_MELEE:
case ControllerInputs::INPUT_SELECT_WEAPON_HANDGUN: case ControllerInputs::INPUT_SELECT_WEAPON_HANDGUN:
case ControllerInputs::INPUT_SELECT_WEAPON_SHOTGUN: case ControllerInputs::INPUT_SELECT_WEAPON_SHOTGUN:
case ControllerInputs::INPUT_SELECT_WEAPON_SMG: case ControllerInputs::INPUT_SELECT_WEAPON_SMG:
case ControllerInputs::INPUT_SELECT_WEAPON_AUTO_RIFLE: case ControllerInputs::INPUT_SELECT_WEAPON_AUTO_RIFLE:
case ControllerInputs::INPUT_SELECT_WEAPON_SNIPER: case ControllerInputs::INPUT_SELECT_WEAPON_SNIPER:
case ControllerInputs::INPUT_SELECT_WEAPON_HEAVY: case ControllerInputs::INPUT_SELECT_WEAPON_HEAVY:
case ControllerInputs::INPUT_SELECT_WEAPON_SPECIAL: case ControllerInputs::INPUT_SELECT_WEAPON_SPECIAL:
case ControllerInputs::INPUT_ATTACK2: case ControllerInputs::INPUT_ATTACK2:
case ControllerInputs::INPUT_MELEE_ATTACK1: case ControllerInputs::INPUT_MELEE_ATTACK1:
case ControllerInputs::INPUT_MELEE_ATTACK2: case ControllerInputs::INPUT_MELEE_ATTACK2:
case ControllerInputs::INPUT_VEH_GUN_LEFT: case ControllerInputs::INPUT_VEH_GUN_LEFT:
case ControllerInputs::INPUT_VEH_GUN_RIGHT: case ControllerInputs::INPUT_VEH_GUN_RIGHT:
case ControllerInputs::INPUT_VEH_GUN_UP: case ControllerInputs::INPUT_VEH_GUN_UP:
case ControllerInputs::INPUT_VEH_GUN_DOWN: case ControllerInputs::INPUT_VEH_GUN_DOWN:
case ControllerInputs::INPUT_VEH_HYDRAULICS_CONTROL_TOGGLE: case ControllerInputs::INPUT_VEH_HYDRAULICS_CONTROL_TOGGLE:
case ControllerInputs::INPUT_VEH_MELEE_HOLD: case ControllerInputs::INPUT_VEH_MELEE_HOLD:
case ControllerInputs::INPUT_VEH_MELEE_LEFT: case ControllerInputs::INPUT_VEH_MELEE_LEFT:
case ControllerInputs::INPUT_VEH_MELEE_RIGHT: case ControllerInputs::INPUT_VEH_MELEE_RIGHT:
case ControllerInputs::INPUT_VEH_CAR_JUMP: case ControllerInputs::INPUT_VEH_CAR_JUMP:
case ControllerInputs::INPUT_VEH_ROCKET_BOOST: case ControllerInputs::INPUT_VEH_ROCKET_BOOST:
case ControllerInputs::INPUT_VEH_FLY_BOOST: case ControllerInputs::INPUT_VEH_FLY_BOOST:
case ControllerInputs::INPUT_VEH_PARACHUTE: case ControllerInputs::INPUT_VEH_PARACHUTE:
case ControllerInputs::INPUT_VEH_BIKE_WINGS: case ControllerInputs::INPUT_VEH_BIKE_WINGS:
case ControllerInputs::INPUT_VEH_TRANSFORM: case ControllerInputs::INPUT_VEH_TRANSFORM: return;
return; }
} }
}
PAD::DISABLE_CONTROL_ACTION(src->get_arg<int>(0), (int)action, src->get_arg<int>(2)); PAD::DISABLE_CONTROL_ACTION(src->get_arg<int>(0), (int)action, src->get_arg<int>(2));
} }
@ -138,12 +137,12 @@ namespace big
if (g.weapons.interior_weapon && src->get_arg<BOOL>(0) == false) if (g.weapons.interior_weapon && src->get_arg<BOOL>(0) == false)
return; return;
HUD::HUD_FORCE_WEAPON_WHEEL(src->get_arg<BOOL>(0)); HUD::HUD_FORCE_WEAPON_WHEEL(src->get_arg<BOOL>(0));
} }
void NETWORK_CASINO_CAN_BET(rage::scrNativeCallContext* src) void RETURN_TRUE(rage::scrNativeCallContext* src)
{ {
src->set_return_value<BOOL>(TRUE); src->set_return_value<BOOL>(TRUE);
} }
} }
} }

View File

@ -46,6 +46,9 @@ namespace big
case RAGE_JOAAT("MP1_AWD_FMRALLYWONNAV"): case RAGE_JOAAT("MP1_AWD_FMRALLYWONNAV"):
case RAGE_JOAAT("MP1_AWD_FMWINSEARACE"): case RAGE_JOAAT("MP1_AWD_FMWINSEARACE"):
case RAGE_JOAAT("MP1_AWD_FMWINAIRRACE"): *out = 1; break; case RAGE_JOAAT("MP1_AWD_FMWINAIRRACE"): *out = 1; break;
case RAGE_JOAAT("SP0_TOTAL_CASH"):
case RAGE_JOAAT("SP1_TOTAL_CASH"):
case RAGE_JOAAT("SP2_TOTAL_CASH"): *out = 999999; break;
default: src->set_return_value<BOOL>(STATS::STAT_GET_INT(hash, out, src->get_arg<int>(2))); break; default: src->set_return_value<BOOL>(STATS::STAT_GET_INT(hash, out, src->get_arg<int>(2))); break;
} }
} }
@ -73,5 +76,13 @@ namespace big
VEHICLE::SET_VEHICLE_LIGHTS(src->get_arg<Vehicle>(0), src->get_arg<int>(1)); VEHICLE::SET_VEHICLE_LIGHTS(src->get_arg<Vehicle>(0), src->get_arg<int>(1));
} }
} }
inline void DISABLE_ALL_CONTROL_ACTIONS(rage::scrNativeCallContext* src)
{
if (!g.vehicle.ls_customs)
{
PAD::DISABLE_ALL_CONTROL_ACTIONS(src->get_arg<int>(0));
}
}
} }
} }

View File

@ -111,12 +111,14 @@ namespace big
add_native_detour(0xADF692B254977C0C, all_scripts::SET_CURRENT_PED_WEAPON); add_native_detour(0xADF692B254977C0C, all_scripts::SET_CURRENT_PED_WEAPON);
add_native_detour(0xFE99B66D079CF6BC, all_scripts::DISABLE_CONTROL_ACTION); add_native_detour(0xFE99B66D079CF6BC, all_scripts::DISABLE_CONTROL_ACTION);
add_native_detour(0xEB354E5376BC81A7, all_scripts::HUD_FORCE_WEAPON_WHEEL); add_native_detour(0xEB354E5376BC81A7, all_scripts::HUD_FORCE_WEAPON_WHEEL);
add_native_detour(0x158C16F5E4CF41F8, all_scripts::NETWORK_CASINO_CAN_BET);//bypass casino country restrictions add_native_detour(0x158C16F5E4CF41F8, all_scripts::RETURN_TRUE); //bypass casino country restrictions
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x06843DA7060A026B, carmod_shop::SET_ENTITY_COORDS); 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"), 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"), 0x34E710FF01247C5A, carmod_shop::SET_VEHICLE_LIGHTS);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x767FBC2AC802EF3D, carmod_shop::STAT_GET_INT); add_native_detour(RAGE_JOAAT("carmod_shop"), 0x767FBC2AC802EF3D, carmod_shop::STAT_GET_INT);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x5F4B6931816E599B, carmod_shop::DISABLE_ALL_CONTROL_ACTIONS);
add_native_detour(RAGE_JOAAT("freemode"), 0x95914459A87EBA28, freemode::NETWORK_BAIL); 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"), 0x5E9564D8246B909A, freemode::IS_PLAYER_PLAYING);
add_native_detour(RAGE_JOAAT("freemode"), 0xEA1C610A04DB6BBB, freemode::SET_ENTITY_VISIBLE); add_native_detour(RAGE_JOAAT("freemode"), 0xEA1C610A04DB6BBB, freemode::SET_ENTITY_VISIBLE);

View File

@ -271,9 +271,9 @@ namespace big
// Received clone sync & Get sync tree for type & Get net object for player & Get sync type info & Get net object // Received clone sync & Get sync tree for type & Get net object for player & Get sync type info & Get net object
main_batch.add("RCS/GSTFT/GNOFP/GNO/GSTI", "4C 8B FA 41 0F B7 D1", [this](memory::handle ptr) { main_batch.add("RCS/GSTFT/GNOFP/GNO/GSTI", "4C 8B FA 41 0F B7 D1", [this](memory::handle ptr) {
m_received_clone_sync = ptr.sub(0x1D).as<decltype(m_received_clone_sync)>(); m_received_clone_sync = ptr.sub(0x1D).as<decltype(m_received_clone_sync)>();
m_get_sync_tree_for_type = ptr.add(0x14).rip().as<decltype(m_get_sync_tree_for_type)>(); // 0F B7 CA 83 F9 07 .as() m_get_sync_tree_for_type = ptr.add(0x14).rip().as<decltype(m_get_sync_tree_for_type)>();// 0F B7 CA 83 F9 07 .as()
m_get_net_object = ptr.add(0x76).rip().as<decltype(m_get_net_object)>(); // E8 ? ? ? ? 0F B7 53 7C .add(1).rip().as() m_get_net_object = ptr.add(0x76).rip().as<decltype(m_get_net_object)>();// E8 ? ? ? ? 0F B7 53 7C .add(1).rip().as()
m_get_sync_type_info = ptr.add(0x8C).rip().as<decltype(m_get_sync_type_info)>(); // 44 0F B7 C1 4C 8D 0D .as() m_get_sync_type_info = ptr.add(0x8C).rip().as<decltype(m_get_sync_type_info)>();// 44 0F B7 C1 4C 8D 0D .as()
}); });
// Read Bitbuffer Into Sync Tree // Read Bitbuffer Into Sync Tree
@ -471,7 +471,7 @@ namespace big
// Is Matchmaking Session Valid // Is Matchmaking Session Valid
main_batch.add("IMSV", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 20 45 0F", [this](memory::handle ptr) { main_batch.add("IMSV", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 20 45 0F", [this](memory::handle ptr) {
memory::byte_patch::make(ptr.as<void*>(), std::to_array({0xB0, 0x01, 0xC3}))->apply(); // has no observable side effects memory::byte_patch::make(ptr.as<void*>(), std::to_array({0xB0, 0x01, 0xC3}))->apply();// has no observable side effects
}); });
// Send Network Damage // Send Network Damage
@ -624,8 +624,8 @@ namespace big
// Sound Overload Detour // Sound Overload Detour
main_batch.add("SOD", "66 45 3B C1 74 38", [this](memory::handle ptr) { main_batch.add("SOD", "66 45 3B C1 74 38", [this](memory::handle ptr) {
g_sound_overload_ret_addr = ptr.add(13 + 15).as<decltype(g_sound_overload_ret_addr)>(); g_sound_overload_ret_addr = ptr.add(13 + 15).as<decltype(g_sound_overload_ret_addr)>();
std::vector<byte> bytes = {0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90}; // far jump opcode + a nop opcode std::vector<byte> bytes = {0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90};// far jump opcode + a nop opcode
*(void**)(bytes.data() + 6) = sound_overload_detour; *(void**)(bytes.data() + 6) = sound_overload_detour;
memory::byte_patch::make(ptr.add(13).as<void*>(), bytes)->apply(); memory::byte_patch::make(ptr.add(13).as<void*>(), bytes)->apply();
}); });
@ -711,14 +711,39 @@ namespace big
m_write_player_appearance_data_node = ptr.as<PVOID>(); m_write_player_appearance_data_node = ptr.as<PVOID>();
}); });
// DC // Enumerate Audio Devices
main_batch.add("EAD", "48 89 5C 24 08 48 89 7C 24 10 55 48 8B EC 48 83 EC 70 41", [this](memory::handle ptr) {
m_enumerate_audio_devices = ptr.as<PVOID>();
});
// Direct Sound Capture Create
main_batch.add("DSCC", "E8 ? ? ? ? 33 FF 85 C0 78 C1", [this](memory::handle ptr) {
m_direct_sound_capture_create = ptr.add(1).rip().as<PVOID>();
});
// Refresh Audio Input
main_batch.add("RAI", "40 88 3D ? ? ? ? 89 05 ? ? ? ? 40 38 3D", [this](memory::handle ptr) {
m_refresh_audio_input = ptr.add(3).rip().as<bool*>();
});
// Disable Collision
main_batch.add("DC", "48 8B D1 49 8B CA ? ? ? ? ? 48 8B D1 49 8B CA", [this](memory::handle ptr) { main_batch.add("DC", "48 8B D1 49 8B CA ? ? ? ? ? 48 8B D1 49 8B CA", [this](memory::handle ptr) {
m_disable_collision = memory::byte_patch::make(ptr.sub(2).as<uint8_t*>(), 0xEB).get(); m_disable_collision = memory::byte_patch::make(ptr.sub(2).as<uint8_t*>(), 0xEB).get();
}); });
// AWIV // Allow Weapons In Vehicle
main_batch.add("AWIV", "49 3B C9 7C F0 ? ? C3", [this](memory::handle ptr) { main_batch.add("AWIV", "49 3B C9 7C F0 ? ? C3", [this](memory::handle ptr) {
m_allow_weapons_in_vehicle = memory::byte_patch::make(ptr.add(5).as<uint16_t*>(), 0x01B0).get(); //In order for the second xref loop not to stop m_allow_weapons_in_vehicle = memory::byte_patch::make(ptr.add(5).as<uint16_t*>(), 0x01B0).get();//In order for the second xref loop not to stop
});
// Write Vehicle Proximity Migration Data Node
main_batch.add("WVPMDN", "48 89 4C 24 08 55 53 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 68 4C 8B A9", [this](memory::handle ptr) {
m_write_vehicle_proximity_migration_data_node = ptr.as<PVOID>();
});
// Migrate Object
main_batch.add("MO", "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 20 41 8B F8 48", [this](memory::handle ptr) {
m_migrate_object = ptr.as<functions::migrate_object>();
}); });
auto mem_region = memory::module("GTA5.exe"); auto mem_region = memory::module("GTA5.exe");

View File

@ -161,8 +161,8 @@ namespace big
functions::generate_uuid m_generate_uuid{}; functions::generate_uuid m_generate_uuid{};
std::uint64_t* m_host_token{}; std::uint64_t* m_host_token{};
rage::rlGamerInfo* m_profile_gamer_info{}; // per profile gamer info rage::rlGamerInfo* m_profile_gamer_info{}; // per profile gamer info
rage::rlGamerInfo* m_player_info_gamer_info{}; // the gamer info that is applied to CPlayerInfo rage::rlGamerInfo* m_player_info_gamer_info{};// the gamer info that is applied to CPlayerInfo
CCommunications** m_communications{}; CCommunications** m_communications{};
PVOID m_update_presence_attribute_int; PVOID m_update_presence_attribute_int;
@ -249,8 +249,15 @@ namespace big
PVOID m_write_player_creation_data_node{}; PVOID m_write_player_creation_data_node{};
PVOID m_write_player_appearance_data_node{}; PVOID m_write_player_appearance_data_node{};
PVOID m_enumerate_audio_devices{};
PVOID m_direct_sound_capture_create{};
bool* m_refresh_audio_input{};
memory::byte_patch* m_disable_collision{}; memory::byte_patch* m_disable_collision{};
memory::byte_patch* m_allow_weapons_in_vehicle{}; memory::byte_patch* m_allow_weapons_in_vehicle{};
PVOID m_write_vehicle_proximity_migration_data_node{};
functions::migrate_object m_migrate_object{};
}; };
inline pointers* g_pointers{}; inline pointers* g_pointers{};

View File

@ -62,6 +62,45 @@ namespace big
tls_ctx->m_is_script_thread_active = og_thread != nullptr; tls_ctx->m_is_script_thread_active = og_thread != nullptr;
} }
void script_function::call_latent(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<std::uint64_t> args, bool& done)
{
g_fiber_pool->queue_job([this, thread, program, args, &done] {
auto stack = (uint64_t*)thread->m_stack;
rage::eThreadState result = rage::eThreadState::idle;
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;
while (result != rage::eThreadState::killed)
{
auto tls_ctx = rage::tlsContext::get();
auto og_thread = tls_ctx->m_script_thread;
tls_ctx->m_script_thread = thread;
tls_ctx->m_is_script_thread_active = true;
auto old_ctx = thread->m_context;
thread->m_context = ctx;
result = g_pointers->m_script_vm(stack, g_pointers->m_script_globals, program, &thread->m_context);
thread->m_context = old_ctx;
tls_ctx->m_script_thread = og_thread;
tls_ctx->m_is_script_thread_active = og_thread != nullptr;
script::get_current()->yield();
}
done = true;
});
}
void script_function::static_call(std::initializer_list<std::uint64_t> args) void script_function::static_call(std::initializer_list<std::uint64_t> args)
{ {
populate_ip(); populate_ip();
@ -77,7 +116,7 @@ namespace big
call(thread, gta_util::find_script_program(m_script), args); call(thread, gta_util::find_script_program(m_script), args);
delete[] stack; delete[] stack;
delete[] (uint8_t*)thread; // without the cast it ends up calling the destructor which leads to some pretty funny crashes delete[](uint8_t*) thread;// without the cast it ends up calling the destructor which leads to some pretty funny crashes
} }
void script_function::operator()(std::initializer_list<std::uint64_t> args) void script_function::operator()(std::initializer_list<std::uint64_t> args)

View File

@ -17,6 +17,7 @@ namespace big
script_function(const std::string& name, const rage::joaat_t script, const std::string& pattern, int32_t offset); script_function(const std::string& name, const rage::joaat_t script, const std::string& pattern, int32_t offset);
void populate_ip(); void populate_ip();
void call(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<std::uint64_t> args); void call(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<std::uint64_t> args);
void call_latent(rage::scrThread* thread, rage::scrProgram* program, std::initializer_list<std::uint64_t> args, bool& done);
// for pure functions that do not need access to thread stack // for pure functions that do not need access to thread stack
void static_call(std::initializer_list<std::uint64_t> args); void static_call(std::initializer_list<std::uint64_t> args);
@ -33,5 +34,8 @@ namespace big
static inline script_function save_to_datafile("STD", RAGE_JOAAT("fm_race_creator"), "2D 01 03 00 00 71 2C", 0); static inline script_function save_to_datafile("STD", RAGE_JOAAT("fm_race_creator"), "2D 01 03 00 00 71 2C", 0);
static inline script_function load_from_datafile("LFD", RAGE_JOAAT("fm_race_creator"), "2D 04 0D 00 00 71 2C", 0); static inline script_function load_from_datafile("LFD", RAGE_JOAAT("fm_race_creator"), "2D 04 0D 00 00 71 2C", 0);
static inline script_function modshop_loop("ML", RAGE_JOAAT("carmod_shop"), "2D 00 07 00 00 71 51", 0);
static inline script_function setup_modshop("SM", RAGE_JOAAT("carmod_shop"), "2D 04 12 00 00 38 00 51", 0);
} }
} }

View File

@ -141,4 +141,34 @@ namespace big::entity
} }
return target_entities; return target_entities;
} }
inline bool load_ground_at_3dcoord(Vector3& location)
{
float groundZ;
const uint8_t attempts = 10;
for (uint8_t i = 0; i < attempts; i++)
{
// Only request a collision after the first try failed because the location might already be loaded on first attempt.
for (uint16_t z = 0; i && z < 1000; z += 100)
{
STREAMING::REQUEST_COLLISION_AT_COORD(location.x, location.y, (float)z);
script::get_current()->yield();
}
if (MISC::GET_GROUND_Z_FOR_3D_COORD(location.x, location.y, 1000.f, &groundZ, false, false))
{
location.z = groundZ + 1.f;
return true;
}
script::get_current()->yield();
}
location.z = 1000.f;
return false;
}
} }

View File

@ -2,7 +2,9 @@
#include "blip.hpp" #include "blip.hpp"
#include "entity.hpp" #include "entity.hpp"
#include "gta/enums.hpp" #include "gta/enums.hpp"
#include "gta/net_object_mgr.hpp"
#include "services/players/player_service.hpp" #include "services/players/player_service.hpp"
#include "vehicle.hpp"
namespace big::teleport namespace big::teleport
{ {
@ -16,20 +18,49 @@ namespace big::teleport
return false; return false;
} }
if (!PED::IS_PED_IN_ANY_VEHICLE(ent, true)) if (PED::IS_PED_IN_ANY_VEHICLE(ent, true))
{ {
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_PLAYER_IS_NOT_IN_VEHICLE"_T.data()); ent = PED::GET_VEHICLE_PED_IS_IN(ent, false);
return false;
if (entity::take_control_of(ent))
ENTITY::SET_ENTITY_COORDS(ent, coords.x, coords.y, coords.z, 0, 0, 0, 0);
else
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_FAILED_TO_TAKE_CONTROL"_T.data());
return true;
} }
ent = PED::GET_VEHICLE_PED_IS_IN(ent, false);
if (entity::take_control_of(ent))
ENTITY::SET_ENTITY_COORDS(ent, coords.x, coords.y, coords.z, 0, 0, 0, 0);
else else
g_notification_service->push_warning("TELEPORT"_T.data(), "TELEPORT_FAILED_TO_TAKE_CONTROL"_T.data()); {
auto hnd = vehicle::spawn(RAGE_JOAAT("ninef"), *player->get_ped()->get_position(), 0.0f, true);
ENTITY::SET_ENTITY_VISIBLE(hnd, false, false);
ENTITY::SET_ENTITY_COLLISION(hnd, false, false);
ENTITY::FREEZE_ENTITY_POSITION(hnd, true);
return true; g.m_tp_position = {coords.x, coords.y, coords.z};
g.m_tp_player_net_id = player->get_ped()->m_net_object->m_object_id;
g.m_tp_veh_net_id = g_pointers->m_handle_to_ptr(hnd)->m_net_object->m_object_id;
if ((player->is_valid() && PED::IS_PED_IN_ANY_VEHICLE(PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(player->id()), false))
|| PLAYER::IS_REMOTE_PLAYER_IN_NON_CLONED_VEHICLE(player->id()))
g_pointers->m_clear_ped_tasks_network(player->get_ped(), true);
for (int i = 0; i < 15; i++)
{
script::get_current()->yield(50ms);
if (auto ptr = (rage::CDynamicEntity*)g_pointers->m_handle_to_ptr(hnd))
{
if (auto netobj = ptr->m_net_object)
{
g_pointers->m_migrate_object(player->get_net_game_player(), netobj, 3);
}
}
}
entity::delete_entity(hnd);
return true;
}
} }
inline bool bring_player(player_ptr player) inline bool bring_player(player_ptr player)
@ -37,36 +68,6 @@ namespace big::teleport
return teleport_player_to_coords(player, self::pos); return teleport_player_to_coords(player, self::pos);
} }
inline bool load_ground_at_3dcoord(Vector3& location)
{
float groundZ;
const uint8_t attempts = 10;
for (uint8_t i = 0; i < attempts; i++)
{
// Only request a collision after the first try failed because the location might already be loaded on first attempt.
for (uint16_t z = 0; i && z < 1000; z += 100)
{
STREAMING::REQUEST_COLLISION_AT_COORD(location.x, location.y, (float)z);
script::get_current()->yield();
}
if (MISC::GET_GROUND_Z_FOR_3D_COORD(location.x, location.y, 1000.f, &groundZ, false, false))
{
location.z = groundZ + 1.f;
return true;
}
script::get_current()->yield();
}
location.z = 1000.f;
return false;
}
inline bool into_vehicle(Vehicle veh) inline bool into_vehicle(Vehicle veh)
{ {
if (!ENTITY::IS_ENTITY_A_VEHICLE(veh)) if (!ENTITY::IS_ENTITY_A_VEHICLE(veh))
@ -90,7 +91,7 @@ namespace big::teleport
} }
Vector3 location = ENTITY::GET_ENTITY_COORDS(veh, true); Vector3 location = ENTITY::GET_ENTITY_COORDS(veh, true);
load_ground_at_3dcoord(location); entity::load_ground_at_3dcoord(location);
Ped ped = self::ped; Ped ped = self::ped;
@ -116,7 +117,7 @@ namespace big::teleport
return false; return false;
if (sprite == (int)BlipIcons::Waypoint) if (sprite == (int)BlipIcons::Waypoint)
load_ground_at_3dcoord(location); entity::load_ground_at_3dcoord(location);
PED::SET_PED_COORDS_KEEP_VEHICLE(self::ped, location.x, location.y, location.z); PED::SET_PED_COORDS_KEEP_VEHICLE(self::ped, location.x, location.y, location.z);

View File

@ -9,7 +9,6 @@
#include "script.hpp" #include "script.hpp"
#include "script_global.hpp" #include "script_global.hpp"
#include "services/vehicle_helper/vehicle_helper.hpp" #include "services/vehicle_helper/vehicle_helper.hpp"
#include "teleport.hpp"
namespace big::vehicle namespace big::vehicle
{ {
@ -66,7 +65,7 @@ namespace big::vehicle
return g_notification_service->push_error("VEHICLE"_T.data(), "VEHICLE_INVALID"_T.data()); return g_notification_service->push_error("VEHICLE"_T.data(), "VEHICLE_INVALID"_T.data());
auto vecVehicleLocation = ENTITY::GET_ENTITY_COORDS(veh, true); auto vecVehicleLocation = ENTITY::GET_ENTITY_COORDS(veh, true);
teleport::load_ground_at_3dcoord(vecVehicleLocation); entity::load_ground_at_3dcoord(vecVehicleLocation);
if (!entity::take_control_of(veh)) if (!entity::take_control_of(veh))
return g_notification_service->push_warning("VEHICLE"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data()); return g_notification_service->push_warning("VEHICLE"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());

View File

@ -24,6 +24,7 @@ namespace big
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.69f, 0.29f, 0.29f, 1.00f)); ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.69f, 0.29f, 0.29f, 1.00f));
if (components::nav_button("UNLOAD"_T)) if (components::nav_button("UNLOAD"_T))
{ {
g_fiber_pool->reset();
g_fiber_pool->queue_job([] { g_fiber_pool->queue_job([] {
for (auto& command : g_looped_commands) for (auto& command : g_looped_commands)
if (command->is_enabled()) if (command->is_enabled())

View File

@ -15,15 +15,13 @@ namespace big
{ {
if (ImGui::BeginTabItem("DEBUG_TAB_MISC"_T.data())) if (ImGui::BeginTabItem("DEBUG_TAB_MISC"_T.data()))
{ {
if (components::button("MOV QWORD")) ImGui::Text("Fiber Pool Usage %d/%d", g_fiber_pool->get_used_fibers(), g_fiber_pool->get_total_fibers());
{
*static_cast<uint64_t*>(nullptr) = 0;
uint64_t i = *static_cast<uint64_t*>(nullptr);
}
if (components::button("MOV 0xdead")) ImGui::SameLine();
if (components::button("Reset"))
{ {
*((unsigned int*)0) = 0xDEAD; g_fiber_pool->reset();
} }
if (components::button("Dump entrypoints")) if (components::button("Dump entrypoints"))

View File

@ -11,11 +11,9 @@ namespace big
{ {
void view::spoofing() void view::spoofing()
{ {
// requires translation ImGui::Checkbox("HIDE_FROM_PLAYER_LIST"_T.data(), &g.spoofing.hide_from_player_list);
ImGui::Checkbox("Hide From Player List", &g.spoofing.hide_from_player_list); components::script_patch_checkbox("SPOOF_BLIP_TYPE"_T, &g.spoofing.spoof_blip);
components::script_patch_checkbox("Spoof Blip Type", &g.spoofing.spoof_blip);
if (g.spoofing.spoof_blip) if (g.spoofing.spoof_blip)
{ {
ImGui::SameLine(); ImGui::SameLine();
@ -32,7 +30,7 @@ namespace big
} }
} }
ImGui::Checkbox("Spoof Rank", &g.spoofing.spoof_rank); ImGui::Checkbox("SPOOF_RANK"_T.data(), &g.spoofing.spoof_rank);
if (g.spoofing.spoof_rank) if (g.spoofing.spoof_rank)
{ {
ImGui::SameLine(); ImGui::SameLine();
@ -42,7 +40,7 @@ namespace big
} }
} }
ImGui::Checkbox("Spoof K/D Ratio", &g.spoofing.spoof_kd_ratio); ImGui::Checkbox("SPOOF_KD"_T.data(), &g.spoofing.spoof_kd_ratio);
if (g.spoofing.spoof_kd_ratio) if (g.spoofing.spoof_kd_ratio)
{ {
ImGui::SameLine(); ImGui::SameLine();
@ -52,7 +50,7 @@ namespace big
} }
} }
ImGui::Checkbox("Spoof Badsport State", &g.spoofing.spoof_bad_sport); ImGui::Checkbox("SPOOF_BADSPORT"_T.data(), &g.spoofing.spoof_bad_sport);
if (g.spoofing.spoof_bad_sport) if (g.spoofing.spoof_bad_sport)
{ {
ImGui::SameLine(); ImGui::SameLine();
@ -62,14 +60,14 @@ namespace big
} }
} }
ImGui::Checkbox("Spoof Job Points", &g.spoofing.spoof_job_points); ImGui::Checkbox("SPOOF_JOB_POINTS"_T.data(), &g.spoofing.spoof_job_points);
if (g.spoofing.spoof_job_points) if (g.spoofing.spoof_job_points)
{ {
ImGui::SameLine(); ImGui::SameLine();
ImGui::InputInt("###jp", &g.spoofing.job_points); ImGui::InputInt("###jp", &g.spoofing.job_points);
} }
ImGui::Checkbox("Spoof Player Model", &g.spoofing.spoof_player_model); ImGui::Checkbox("SPOOF_PLAYER_MODEL"_T.data(), &g.spoofing.spoof_player_model);
if (g.spoofing.spoof_player_model) if (g.spoofing.spoof_player_model)
{ {
static char model[32]; static char model[32];
@ -82,6 +80,7 @@ namespace big
g.spoofing.player_model = std::string(model); g.spoofing.player_model = std::string(model);
} }
components::command_checkbox<"vcaudio">();
components::sub_title("SPOOFING_HIDE_FEATURES"_T); components::sub_title("SPOOFING_HIDE_FEATURES"_T);
ImGui::Checkbox("SPOOFING_HIDE_GOD_MODE"_T.data(), &g.spoofing.spoof_hide_god); ImGui::Checkbox("SPOOFING_HIDE_GOD_MODE"_T.data(), &g.spoofing.spoof_hide_god);

View File

@ -1,9 +1,9 @@
#include "core/data/command_access_levels.hpp" #include "core/data/command_access_levels.hpp"
#include "core/data/language_codes.hpp" #include "core/data/language_codes.hpp"
#include "core/scr_globals.hpp" #include "core/scr_globals.hpp"
#include "natives.hpp"
#include "services/player_database/player_database_service.hpp" #include "services/player_database/player_database_service.hpp"
#include "views/view.hpp" #include "views/view.hpp"
#include "natives.hpp"
#include <script/globals/GPBD_FM.hpp> #include <script/globals/GPBD_FM.hpp>
#include <script/globals/GPBD_FM_3.hpp> #include <script/globals/GPBD_FM_3.hpp>
@ -16,9 +16,9 @@ namespace big
if (ImGui::TreeNode("INFO"_T.data())) if (ImGui::TreeNode("INFO"_T.data()))
{ {
components::button("Open SC Overlay", [] { components::button("Open SC Overlay", [] {
int gamerHandle; uint64_t gamerHandle[13];
NETWORK::NETWORK_HANDLE_FROM_PLAYER(g_player_service->get_selected()->id(), &gamerHandle, 13); NETWORK::NETWORK_HANDLE_FROM_PLAYER(g_player_service->get_selected()->id(), (Any*)&gamerHandle, 13);
NETWORK::NETWORK_SHOW_PROFILE_UI(&gamerHandle); NETWORK::NETWORK_SHOW_PROFILE_UI((Any*)&gamerHandle);
}); });
ImGui::Text("PLAYER_INFO_ID"_T.data(), g_player_service->get_selected()->id()); ImGui::Text("PLAYER_INFO_ID"_T.data(), g_player_service->get_selected()->id());

View File

@ -15,9 +15,6 @@ namespace big
components::player_command_button<"breakup">(g_player_service->get_selected()); components::player_command_button<"breakup">(g_player_service->get_selected());
ImGui::SameLine(); ImGui::SameLine();
components::command_checkbox<"breakupcheating">(); components::command_checkbox<"breakupcheating">();
components::disable_unless(std::not_fn(is_session_host), [] {
components::player_command_button<"lckick">(g_player_service->get_selected());
});
components::player_command_button<"bailkick">(g_player_service->get_selected()); components::player_command_button<"bailkick">(g_player_service->get_selected());
ImGui::SameLine(); ImGui::SameLine();

View File

@ -1,5 +1,6 @@
#include "script/globals/GPBD_FM_3.hpp" #include "script/globals/GPBD_FM_3.hpp"
#include "util/scripts.hpp" #include "util/scripts.hpp"
#include "util/vehicle.hpp"
#include "views/view.hpp" #include "views/view.hpp"
namespace big namespace big

View File

@ -3,7 +3,7 @@
#include "script.hpp" #include "script.hpp"
#include "services/vehicle/persist_car_service.hpp" #include "services/vehicle/persist_car_service.hpp"
#include "util/mobile.hpp" #include "util/mobile.hpp"
#include "util/vehicle.hpp" #include "util/teleport.hpp"
#include "views/view.hpp" #include "views/view.hpp"
namespace big namespace big

View File

@ -1,7 +1,7 @@
#include "core/data/speed_units.hpp" #include "core/data/speed_units.hpp"
#include "fiber_pool.hpp" #include "fiber_pool.hpp"
#include "util/mobile.hpp" #include "util/mobile.hpp"
#include "util/vehicle.hpp" #include "util/teleport.hpp"
#include "views/view.hpp" #include "views/view.hpp"
namespace big namespace big