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:
parent
2d44f14a22
commit
ad90ee3f6a
@ -3,7 +3,7 @@ include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
gtav_classes
|
||||
GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git
|
||||
GIT_TAG f71748dd1dfac7b1c678e0e8b87d2739bde314b6
|
||||
GIT_TAG 56aeddea31d677efa0e5c4f84b4f353d420a8502
|
||||
GIT_PROGRESS TRUE
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
#include "backend/command.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "util/mobile.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
#include "util/teleport.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "backend/command.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "util/mobile.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
#include "util/teleport.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
|
30
src/backend/looped/system/voice_chat_audio.cpp
Normal file
30
src/backend/looped/system/voice_chat_audio.cpp
Normal 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);
|
||||
}
|
@ -1,70 +1,101 @@
|
||||
#include "backend/looped/looped.hpp"
|
||||
#include "gta/enums.hpp"
|
||||
#include "gta_util.hpp"
|
||||
#include "script_function.hpp"
|
||||
#include "script_local.hpp"
|
||||
#include "services/script_patcher/script_patcher_service.hpp"
|
||||
#include "util/math.hpp"
|
||||
#include "util/scripts.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
static bool state = false;
|
||||
static bool busy = 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
|
||||
static bool bLastLsCustoms = false;
|
||||
static bool bModshopReady = false;
|
||||
|
||||
void looped::vehicle_ls_customs()
|
||||
{
|
||||
if (busy)
|
||||
return;
|
||||
busy = true;
|
||||
|
||||
constexpr int hash = RAGE_JOAAT("carmod_shop");
|
||||
if (g.vehicle.ls_customs && g.vehicle.ls_customs == state)
|
||||
if (g.vehicle.ls_customs && g.vehicle.ls_customs != bLastLsCustoms)
|
||||
{
|
||||
if (auto carmod_shop_thread = gta_util::find_script_thread(hash);
|
||||
carmod_shop_thread && *script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).at(11).as<int*>() != 4)
|
||||
{
|
||||
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)
|
||||
g_fiber_pool->queue_job([] {
|
||||
scripts::request_script(RAGE_JOAAT("carmod_shop"));
|
||||
if (scripts::wait_till_loaded(RAGE_JOAAT("carmod_shop")))
|
||||
{
|
||||
*script_local(carmod_shop_thread, CARMOD_SHOP_STRUCT).at(409).as<int*>() = veh;// "HIDDEN_RADIO_09_HIPHOP_OLD"
|
||||
*script_local(carmod_shop_thread, CARMOD_SHOP_CUTSCENE).as<bool*>() = false;// skips cutscene that's invisible
|
||||
HUD::REQUEST_ADDITIONAL_TEXT("MOD_MNU", 9);
|
||||
|
||||
*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;
|
||||
state = g.vehicle.ls_customs;
|
||||
if (self::veh == 0 || SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) > 0 || (!g.m_modshop_thread && bModshopReady))
|
||||
{
|
||||
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")), {});
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "backend/looped/looped.hpp"
|
||||
#include "core/enums.hpp"
|
||||
#include "gta/enums.hpp"
|
||||
#include "util/entity.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "backend/looped/looped.hpp"
|
||||
#include "core/enums.hpp"
|
||||
#include "gta/enums.hpp"
|
||||
#include "gui.hpp"
|
||||
#include "util/math.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
|
@ -44,6 +44,19 @@ namespace big
|
||||
{0x2B, 0x2B, 0x2B, 0x00, 0x55},
|
||||
&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)
|
||||
{
|
||||
if (entry.m_program)
|
||||
|
@ -53,8 +53,9 @@ 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;
|
||||
std::uint16_t m_tp_veh_net_id;
|
||||
std::uint16_t m_tp_player_net_id;
|
||||
rage::fvector3 m_tp_position;
|
||||
|
||||
rage::scrThread* m_hunt_the_beast_thread = nullptr;
|
||||
|
||||
@ -63,6 +64,10 @@ namespace big
|
||||
|
||||
rage::scrThread* m_mission_creator_thread = nullptr;
|
||||
|
||||
rage::scrThread* m_modshop_thread = nullptr;
|
||||
|
||||
bool in_script_vm = false;
|
||||
|
||||
struct debug
|
||||
{
|
||||
struct logs
|
||||
@ -79,7 +84,7 @@ namespace big
|
||||
bool filter_player = true;
|
||||
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)
|
||||
} 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 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 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 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!"};
|
||||
@ -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 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 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};
|
||||
@ -225,7 +230,7 @@ namespace big
|
||||
|
||||
bool desync_kick = 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;
|
||||
|
||||
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 spoof_blip = false;
|
||||
int blip_type = 0;// actual blip type + 1
|
||||
int blip_type = 0; // actual blip type + 1
|
||||
|
||||
bool spoof_rank = false;
|
||||
int rank = 1;
|
||||
@ -512,7 +517,9 @@ namespace big
|
||||
bool spoof_session_player_count = false;
|
||||
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{};
|
||||
|
||||
struct vehicle
|
||||
@ -564,36 +571,30 @@ namespace big
|
||||
uint32_t proof_mask = 0;
|
||||
|
||||
AutoDriveDestination auto_drive_destination = AutoDriveDestination::STOPPED;
|
||||
AutoDriveStyle auto_drive_style = AutoDriveStyle::LAW_ABIDING;
|
||||
float auto_drive_speed = 1;
|
||||
bool auto_turn_signals = false;
|
||||
eBoostBehaviors boost_behavior = eBoostBehaviors::DEFAULT;
|
||||
bool drive_on_water = false;
|
||||
bool horn_boost = false;
|
||||
bool instant_brake = false;
|
||||
bool block_homing = true;
|
||||
bool ls_customs = false; // don't save this to disk
|
||||
bool seatbelt = false;
|
||||
bool turn_signals = false;
|
||||
bool vehicle_jump = false;
|
||||
bool keep_vehicle_repaired = false;
|
||||
bool no_water_collision = false;
|
||||
bool disable_engine_auto_start = false;
|
||||
bool change_engine_state_immediately = false;
|
||||
bool vehinvisibility = false;
|
||||
bool localveh_visibility = false;
|
||||
bool localped_visibility = true;
|
||||
bool keep_on_ground = false;
|
||||
bool no_collision = false;
|
||||
bool unlimited_weapons = false;
|
||||
AutoDriveStyle auto_drive_style = AutoDriveStyle::LAW_ABIDING;
|
||||
float auto_drive_speed = 1;
|
||||
bool auto_turn_signals = false;
|
||||
eBoostBehaviors boost_behavior = eBoostBehaviors::DEFAULT;
|
||||
bool drive_on_water = false;
|
||||
bool horn_boost = false;
|
||||
bool instant_brake = false;
|
||||
bool block_homing = true;
|
||||
bool ls_customs = false; // don't save this to disk
|
||||
bool seatbelt = false;
|
||||
bool turn_signals = false;
|
||||
bool vehicle_jump = false;
|
||||
bool keep_vehicle_repaired = false;
|
||||
bool no_water_collision = false;
|
||||
bool disable_engine_auto_start = false;
|
||||
bool change_engine_state_immediately = false;
|
||||
bool vehinvisibility = false;
|
||||
bool localveh_visibility = false;
|
||||
bool localped_visibility = true;
|
||||
bool keep_on_ground = false;
|
||||
bool no_collision = false;
|
||||
bool unlimited_weapons = false;
|
||||
|
||||
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)
|
||||
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)
|
||||
} vehicle{};
|
||||
|
||||
struct weapons
|
||||
@ -634,7 +635,7 @@ namespace big
|
||||
bool on_npc = false;
|
||||
float fov = 90.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)
|
||||
} aimbot{};
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
|
||||
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)
|
||||
{
|
||||
@ -51,4 +52,22 @@ namespace big
|
||||
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();
|
||||
}
|
||||
}
|
@ -14,9 +14,15 @@ namespace big
|
||||
void fiber_tick();
|
||||
static void fiber_func();
|
||||
|
||||
int get_total_fibers();
|
||||
int get_used_fibers();
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
std::recursive_mutex m_mutex;
|
||||
std::stack<std::function<void()>> m_jobs;
|
||||
int m_num_fibers;
|
||||
};
|
||||
|
||||
inline fiber_pool* g_fiber_pool{};
|
||||
|
@ -21,6 +21,7 @@ namespace rage
|
||||
class snConnectToPeerTaskResult;
|
||||
class rlScHandle;
|
||||
class rlQueryPresenceAttributesContext;
|
||||
enum class eThreadState : uint32_t;
|
||||
}
|
||||
|
||||
namespace datafile_commands
|
||||
@ -91,9 +92,9 @@ namespace big::functions
|
||||
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_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 join_session_by_info = bool (*)(Network* network, rage::rlSessionInfo* info, int unk, int flags, rage::rlGamerHandle* handles, int handlecount);
|
||||
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 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);
|
||||
|
||||
@ -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_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_control = void (*)(rage::netObject* net_object);
|
||||
using request_ragdoll = void (*)(uint16_t object_id);
|
||||
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 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 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 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 connect_to_peer = bool (*)(rage::netConnectionManager* mgr, rage::rlGamerInfoBase* gamer_info, rage::snConnectToPeerTaskData* data, rage::snConnectToPeerTaskResult* result, rage::rlTaskStatus* status);
|
||||
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 clear_ped_tasks_network = void (*)(CPed* ped, bool immediately);
|
||||
|
||||
using get_next_carriage = void* (*)(void* carriage);
|
||||
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
203
src/gta/sound.hpp
Normal 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{};
|
10
src/gui.cpp
10
src/gui.cpp
@ -13,20 +13,20 @@ namespace big
|
||||
gui::gui() :
|
||||
m_is_open(false)
|
||||
{
|
||||
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::overlay, -3); // 3rd highest priority
|
||||
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::overlay, -3); // 3rd highest priority
|
||||
g_renderer->add_dx_callback(
|
||||
[this] {
|
||||
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) {
|
||||
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);
|
||||
|
||||
dx_init();
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "script_mgr.hpp"
|
||||
|
||||
#include <MinHook.h>
|
||||
#include <vehicle/CVehicle.hpp>
|
||||
|
||||
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::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;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,9 @@ class CPlayerCardStats;
|
||||
class CStatsSerializationContext;
|
||||
class CPlayerCreationDataNode;
|
||||
class CPlayerAppearanceDataNode;
|
||||
class CFoundDevice;
|
||||
class IDirectSoundCapture;
|
||||
class CVehicleProximityMigrationDataNode;
|
||||
|
||||
namespace rage
|
||||
{
|
||||
@ -153,6 +156,11 @@ namespace big
|
||||
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 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
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "netsync/nodes/train/CTrainGameStateDataNode.hpp"
|
||||
#include "netsync/nodes/vehicle/CVehicleCreationDataNode.hpp"
|
||||
#include "netsync/nodes/vehicle/CVehicleGadgetDataNode.hpp"
|
||||
#include "netsync/nodes/vehicle/CVehicleProximityMigrationDataNode.hpp"
|
||||
#include "network/CNetGamePlayer.hpp"
|
||||
#include "network/netObject.hpp"
|
||||
#include "util/model_info.hpp"
|
||||
@ -503,6 +504,21 @@ namespace big
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_in_vehicle(CPed* ped, CVehicle* vehicle)
|
||||
{
|
||||
if (!ped || !vehicle)
|
||||
return false;
|
||||
|
||||
if (ped == vehicle->m_driver)
|
||||
return true;
|
||||
|
||||
for (int i = 0; i < 15; i++)
|
||||
if (vehicle->m_passengers[i] == ped)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, rage::netObject* object)
|
||||
{
|
||||
if (node->IsParentNode())
|
||||
@ -604,7 +620,7 @@ namespace big
|
||||
}
|
||||
else if (attach_node->m_attached && is_attachment_infinite(get_game_object(object), attach_node->m_attached_to))
|
||||
{
|
||||
notify::crash_blocked(sender, "recursive infinite ped attachment");
|
||||
// notify::crash_blocked(sender, "recursive infinite ped attachment");
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -650,6 +666,28 @@ namespace big
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RAGE_JOAAT("CVehicleProximityMigrationDataNode"):
|
||||
{
|
||||
if (g_local_player && g_local_player->m_net_object)
|
||||
{
|
||||
const auto migration_node = (CVehicleProximityMigrationDataNode*)(node);
|
||||
if (is_in_vehicle(g_local_player, g_local_player->m_vehicle) && g_local_player->m_vehicle->m_net_object
|
||||
&& g_local_player->m_vehicle->m_net_object->m_object_id == object->m_object_id)
|
||||
return false; // vehicle kick?
|
||||
|
||||
if (!g_local_player->m_vehicle || !g_local_player->m_vehicle->m_net_object
|
||||
|| g_local_player->m_vehicle->m_net_object->m_object_id != object->m_object_id
|
||||
|| !is_in_vehicle(g_local_player, g_local_player->m_vehicle))
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
if (migration_node->m_has_occupants[i]
|
||||
&& migration_node->m_occupants[i] == g_local_player->m_net_object->m_object_id)
|
||||
return true; // remote teleport
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -10,7 +10,7 @@ namespace big
|
||||
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"))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ namespace big
|
||||
const auto result = g_hooking->get_original<gta_thread_kill>()(thread);
|
||||
|
||||
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)
|
||||
g_notification_service->push("Script Thread Termination",
|
||||
std::format("Script Thread '{}' terminated.", thread->m_name));
|
||||
@ -22,6 +23,9 @@ namespace big
|
||||
if (thread == g.m_mission_creator_thread)
|
||||
g.m_mission_creator_thread = nullptr;
|
||||
|
||||
if (thread == g.m_modshop_thread)
|
||||
g.m_modshop_thread = nullptr;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -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].CayoPericoFlags = old_cayo_flags;
|
||||
}
|
||||
|
||||
g.in_script_vm = true;
|
||||
}
|
||||
|
||||
~script_vm_guard()
|
||||
@ -47,6 +49,8 @@ namespace big
|
||||
scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[self::id].CayoPericoFlags = 1;
|
||||
}
|
||||
}
|
||||
|
||||
g.in_script_vm = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
18
src/hooks/voice/direct_sound_capture_create.cpp
Normal file
18
src/hooks/voice/direct_sound_capture_create.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
42
src/hooks/voice/enumerate_audio_devices.cpp
Normal file
42
src/hooks/voice/enumerate_audio_devices.cpp
Normal 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;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#include "stack_trace.hpp"
|
||||
|
||||
#include "gta/script_thread.hpp"
|
||||
#include "memory/module.hpp"
|
||||
|
||||
#include <DbgHelp.h>
|
||||
@ -26,9 +27,13 @@ namespace big
|
||||
m_exception_info = exception_info;
|
||||
|
||||
m_dump << exception_code_to_string(exception_info->ExceptionRecord->ExceptionCode) << '\n';
|
||||
|
||||
if (g.in_script_vm)
|
||||
dump_script_info();
|
||||
dump_module_info();
|
||||
dump_registers();
|
||||
dump_stacktrace();
|
||||
|
||||
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
|
||||
void stack_trace::dump_module_info()
|
||||
{
|
||||
m_dump << "Dumping modules:\n";
|
||||
// modules cached already
|
||||
if (m_modules.size())
|
||||
return;
|
||||
|
||||
// modules cached already
|
||||
if (m_modules.size())
|
||||
return;
|
||||
m_dump << "Dumping modules:\n";
|
||||
|
||||
const auto peb = reinterpret_cast<PPEB>(NtCurrentTeb()->ProcessEnvironmentBlock);
|
||||
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()
|
||||
{
|
||||
CONTEXT context = *m_exception_info->ContextRecord;
|
||||
|
@ -37,6 +37,7 @@ namespace big
|
||||
void dump_module_info();
|
||||
void dump_registers();
|
||||
void dump_stacktrace();
|
||||
void dump_script_info();
|
||||
void grab_stacktrace();
|
||||
const module_info* get_module_by_address(uint64_t addr) const;
|
||||
|
||||
|
@ -66,69 +66,68 @@ namespace big
|
||||
{
|
||||
const auto action = src->get_arg<ControllerInputs>(1);
|
||||
|
||||
if (g.weapons.interior_weapon) // Filtering from the inside of Kosatka
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
// case ControllerInputs::INPUT_JUMP: TODO: add as separate feature
|
||||
case ControllerInputs::INPUT_ATTACK:
|
||||
case ControllerInputs::INPUT_AIM:
|
||||
case ControllerInputs::INPUT_DUCK:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON:
|
||||
case ControllerInputs::INPUT_COVER:
|
||||
case ControllerInputs::INPUT_TALK:
|
||||
case ControllerInputs::INPUT_DETONATE:
|
||||
case ControllerInputs::INPUT_WEAPON_SPECIAL:
|
||||
case ControllerInputs::INPUT_WEAPON_SPECIAL_TWO:
|
||||
case ControllerInputs::INPUT_VEH_AIM:
|
||||
case ControllerInputs::INPUT_VEH_ATTACK:
|
||||
case ControllerInputs::INPUT_VEH_ATTACK2:
|
||||
case ControllerInputs::INPUT_VEH_HEADLIGHT:
|
||||
case ControllerInputs::INPUT_VEH_NEXT_RADIO:
|
||||
case ControllerInputs::INPUT_VEH_PREV_RADIO:
|
||||
case ControllerInputs::INPUT_VEH_NEXT_RADIO_TRACK:
|
||||
case ControllerInputs::INPUT_VEH_PREV_RADIO_TRACK:
|
||||
case ControllerInputs::INPUT_VEH_RADIO_WHEEL:
|
||||
case ControllerInputs::INPUT_VEH_PASSENGER_AIM:
|
||||
case ControllerInputs::INPUT_VEH_PASSENGER_ATTACK:
|
||||
case ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON:
|
||||
case ControllerInputs::INPUT_VEH_SELECT_PREV_WEAPON:
|
||||
case ControllerInputs::INPUT_VEH_ROOF:
|
||||
case ControllerInputs::INPUT_VEH_JUMP:
|
||||
case ControllerInputs::INPUT_VEH_FLY_ATTACK:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK_LIGHT:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK_HEAVY:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK_ALTERNATE:
|
||||
case ControllerInputs::INPUT_MELEE_BLOCK:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_UNARMED:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_MELEE:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_HANDGUN:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_SHOTGUN:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_SMG:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_AUTO_RIFLE:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_SNIPER:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_HEAVY:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_SPECIAL:
|
||||
case ControllerInputs::INPUT_ATTACK2:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK1:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK2:
|
||||
case ControllerInputs::INPUT_VEH_GUN_LEFT:
|
||||
case ControllerInputs::INPUT_VEH_GUN_RIGHT:
|
||||
case ControllerInputs::INPUT_VEH_GUN_UP:
|
||||
case ControllerInputs::INPUT_VEH_GUN_DOWN:
|
||||
case ControllerInputs::INPUT_VEH_HYDRAULICS_CONTROL_TOGGLE:
|
||||
case ControllerInputs::INPUT_VEH_MELEE_HOLD:
|
||||
case ControllerInputs::INPUT_VEH_MELEE_LEFT:
|
||||
case ControllerInputs::INPUT_VEH_MELEE_RIGHT:
|
||||
case ControllerInputs::INPUT_VEH_CAR_JUMP:
|
||||
case ControllerInputs::INPUT_VEH_ROCKET_BOOST:
|
||||
case ControllerInputs::INPUT_VEH_FLY_BOOST:
|
||||
case ControllerInputs::INPUT_VEH_PARACHUTE:
|
||||
case ControllerInputs::INPUT_VEH_BIKE_WINGS:
|
||||
case ControllerInputs::INPUT_VEH_TRANSFORM:
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (g.weapons.interior_weapon) // Filtering from the inside of Kosatka
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
// case ControllerInputs::INPUT_JUMP: TODO: add as separate feature
|
||||
case ControllerInputs::INPUT_ATTACK:
|
||||
case ControllerInputs::INPUT_AIM:
|
||||
case ControllerInputs::INPUT_DUCK:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON:
|
||||
case ControllerInputs::INPUT_COVER:
|
||||
case ControllerInputs::INPUT_TALK:
|
||||
case ControllerInputs::INPUT_DETONATE:
|
||||
case ControllerInputs::INPUT_WEAPON_SPECIAL:
|
||||
case ControllerInputs::INPUT_WEAPON_SPECIAL_TWO:
|
||||
case ControllerInputs::INPUT_VEH_AIM:
|
||||
case ControllerInputs::INPUT_VEH_ATTACK:
|
||||
case ControllerInputs::INPUT_VEH_ATTACK2:
|
||||
case ControllerInputs::INPUT_VEH_HEADLIGHT:
|
||||
case ControllerInputs::INPUT_VEH_NEXT_RADIO:
|
||||
case ControllerInputs::INPUT_VEH_PREV_RADIO:
|
||||
case ControllerInputs::INPUT_VEH_NEXT_RADIO_TRACK:
|
||||
case ControllerInputs::INPUT_VEH_PREV_RADIO_TRACK:
|
||||
case ControllerInputs::INPUT_VEH_RADIO_WHEEL:
|
||||
case ControllerInputs::INPUT_VEH_PASSENGER_AIM:
|
||||
case ControllerInputs::INPUT_VEH_PASSENGER_ATTACK:
|
||||
case ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON:
|
||||
case ControllerInputs::INPUT_VEH_SELECT_PREV_WEAPON:
|
||||
case ControllerInputs::INPUT_VEH_ROOF:
|
||||
case ControllerInputs::INPUT_VEH_JUMP:
|
||||
case ControllerInputs::INPUT_VEH_FLY_ATTACK:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK_LIGHT:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK_HEAVY:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK_ALTERNATE:
|
||||
case ControllerInputs::INPUT_MELEE_BLOCK:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_UNARMED:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_MELEE:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_HANDGUN:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_SHOTGUN:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_SMG:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_AUTO_RIFLE:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_SNIPER:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_HEAVY:
|
||||
case ControllerInputs::INPUT_SELECT_WEAPON_SPECIAL:
|
||||
case ControllerInputs::INPUT_ATTACK2:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK1:
|
||||
case ControllerInputs::INPUT_MELEE_ATTACK2:
|
||||
case ControllerInputs::INPUT_VEH_GUN_LEFT:
|
||||
case ControllerInputs::INPUT_VEH_GUN_RIGHT:
|
||||
case ControllerInputs::INPUT_VEH_GUN_UP:
|
||||
case ControllerInputs::INPUT_VEH_GUN_DOWN:
|
||||
case ControllerInputs::INPUT_VEH_HYDRAULICS_CONTROL_TOGGLE:
|
||||
case ControllerInputs::INPUT_VEH_MELEE_HOLD:
|
||||
case ControllerInputs::INPUT_VEH_MELEE_LEFT:
|
||||
case ControllerInputs::INPUT_VEH_MELEE_RIGHT:
|
||||
case ControllerInputs::INPUT_VEH_CAR_JUMP:
|
||||
case ControllerInputs::INPUT_VEH_ROCKET_BOOST:
|
||||
case ControllerInputs::INPUT_VEH_FLY_BOOST:
|
||||
case ControllerInputs::INPUT_VEH_PARACHUTE:
|
||||
case ControllerInputs::INPUT_VEH_BIKE_WINGS:
|
||||
case ControllerInputs::INPUT_VEH_TRANSFORM: return;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
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)
|
||||
{
|
||||
src->set_return_value<BOOL>(TRUE);
|
||||
}
|
||||
}
|
||||
void RETURN_TRUE(rage::scrNativeCallContext* src)
|
||||
{
|
||||
src->set_return_value<BOOL>(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
@ -46,6 +46,9 @@ namespace big
|
||||
case RAGE_JOAAT("MP1_AWD_FMRALLYWONNAV"):
|
||||
case RAGE_JOAAT("MP1_AWD_FMWINSEARACE"):
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -73,5 +76,13 @@ namespace big
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -111,12 +111,14 @@ namespace big
|
||||
add_native_detour(0xADF692B254977C0C, all_scripts::SET_CURRENT_PED_WEAPON);
|
||||
add_native_detour(0xFE99B66D079CF6BC, all_scripts::DISABLE_CONTROL_ACTION);
|
||||
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"), 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("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"), 0x5E9564D8246B909A, freemode::IS_PLAYER_PLAYING);
|
||||
add_native_detour(RAGE_JOAAT("freemode"), 0xEA1C610A04DB6BBB, freemode::SET_ENTITY_VISIBLE);
|
||||
|
@ -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
|
||||
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_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_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_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_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
|
||||
@ -471,7 +471,7 @@ namespace big
|
||||
|
||||
// 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) {
|
||||
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
|
||||
@ -624,8 +624,8 @@ namespace big
|
||||
|
||||
// Sound Overload Detour
|
||||
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)>();
|
||||
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
|
||||
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
|
||||
*(void**)(bytes.data() + 6) = sound_overload_detour;
|
||||
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>();
|
||||
});
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
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");
|
||||
|
@ -161,8 +161,8 @@ namespace big
|
||||
|
||||
functions::generate_uuid m_generate_uuid{};
|
||||
std::uint64_t* m_host_token{};
|
||||
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_profile_gamer_info{}; // per profile gamer info
|
||||
rage::rlGamerInfo* m_player_info_gamer_info{};// the gamer info that is applied to CPlayerInfo
|
||||
CCommunications** m_communications{};
|
||||
|
||||
PVOID m_update_presence_attribute_int;
|
||||
@ -249,8 +249,15 @@ namespace big
|
||||
PVOID m_write_player_creation_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_allow_weapons_in_vehicle{};
|
||||
|
||||
PVOID m_write_vehicle_proximity_migration_data_node{};
|
||||
functions::migrate_object m_migrate_object{};
|
||||
};
|
||||
|
||||
inline pointers* g_pointers{};
|
||||
|
@ -62,6 +62,45 @@ namespace big
|
||||
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)
|
||||
{
|
||||
populate_ip();
|
||||
@ -77,7 +116,7 @@ namespace big
|
||||
call(thread, gta_util::find_script_program(m_script), args);
|
||||
|
||||
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)
|
||||
|
@ -17,6 +17,7 @@ namespace big
|
||||
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 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
|
||||
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 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);
|
||||
}
|
||||
}
|
@ -141,4 +141,34 @@ namespace big::entity
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -2,7 +2,9 @@
|
||||
#include "blip.hpp"
|
||||
#include "entity.hpp"
|
||||
#include "gta/enums.hpp"
|
||||
#include "gta/net_object_mgr.hpp"
|
||||
#include "services/players/player_service.hpp"
|
||||
#include "vehicle.hpp"
|
||||
|
||||
namespace big::teleport
|
||||
{
|
||||
@ -16,20 +18,49 @@ namespace big::teleport
|
||||
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());
|
||||
return false;
|
||||
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
|
||||
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
|
||||
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)
|
||||
@ -37,36 +68,6 @@ namespace big::teleport
|
||||
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)
|
||||
{
|
||||
if (!ENTITY::IS_ENTITY_A_VEHICLE(veh))
|
||||
@ -90,7 +91,7 @@ namespace big::teleport
|
||||
}
|
||||
|
||||
Vector3 location = ENTITY::GET_ENTITY_COORDS(veh, true);
|
||||
load_ground_at_3dcoord(location);
|
||||
entity::load_ground_at_3dcoord(location);
|
||||
|
||||
Ped ped = self::ped;
|
||||
|
||||
@ -116,7 +117,7 @@ namespace big::teleport
|
||||
return false;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "script.hpp"
|
||||
#include "script_global.hpp"
|
||||
#include "services/vehicle_helper/vehicle_helper.hpp"
|
||||
#include "teleport.hpp"
|
||||
|
||||
namespace big::vehicle
|
||||
{
|
||||
@ -66,7 +65,7 @@ namespace big::vehicle
|
||||
return g_notification_service->push_error("VEHICLE"_T.data(), "VEHICLE_INVALID"_T.data());
|
||||
|
||||
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))
|
||||
return g_notification_service->push_warning("VEHICLE"_T.data(), "VEHICLE_FAILED_CONTROL"_T.data());
|
||||
|
@ -24,6 +24,7 @@ namespace big
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.69f, 0.29f, 0.29f, 1.00f));
|
||||
if (components::nav_button("UNLOAD"_T))
|
||||
{
|
||||
g_fiber_pool->reset();
|
||||
g_fiber_pool->queue_job([] {
|
||||
for (auto& command : g_looped_commands)
|
||||
if (command->is_enabled())
|
||||
|
@ -15,15 +15,13 @@ namespace big
|
||||
{
|
||||
if (ImGui::BeginTabItem("DEBUG_TAB_MISC"_T.data()))
|
||||
{
|
||||
if (components::button("MOV QWORD"))
|
||||
{
|
||||
*static_cast<uint64_t*>(nullptr) = 0;
|
||||
uint64_t i = *static_cast<uint64_t*>(nullptr);
|
||||
}
|
||||
ImGui::Text("Fiber Pool Usage %d/%d", g_fiber_pool->get_used_fibers(), g_fiber_pool->get_total_fibers());
|
||||
|
||||
if (components::button("MOV 0xdead"))
|
||||
ImGui::SameLine();
|
||||
|
||||
if (components::button("Reset"))
|
||||
{
|
||||
*((unsigned int*)0) = 0xDEAD;
|
||||
g_fiber_pool->reset();
|
||||
}
|
||||
|
||||
if (components::button("Dump entrypoints"))
|
||||
|
@ -11,11 +11,9 @@ namespace big
|
||||
{
|
||||
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", &g.spoofing.spoof_blip);
|
||||
components::script_patch_checkbox("SPOOF_BLIP_TYPE"_T, &g.spoofing.spoof_blip);
|
||||
if (g.spoofing.spoof_blip)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ImGui::SameLine();
|
||||
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)
|
||||
{
|
||||
static char model[32];
|
||||
@ -82,6 +80,7 @@ namespace big
|
||||
g.spoofing.player_model = std::string(model);
|
||||
}
|
||||
|
||||
components::command_checkbox<"vcaudio">();
|
||||
|
||||
components::sub_title("SPOOFING_HIDE_FEATURES"_T);
|
||||
ImGui::Checkbox("SPOOFING_HIDE_GOD_MODE"_T.data(), &g.spoofing.spoof_hide_god);
|
||||
|
@ -1,9 +1,9 @@
|
||||
#include "core/data/command_access_levels.hpp"
|
||||
#include "core/data/language_codes.hpp"
|
||||
#include "core/scr_globals.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "services/player_database/player_database_service.hpp"
|
||||
#include "views/view.hpp"
|
||||
#include "natives.hpp"
|
||||
|
||||
#include <script/globals/GPBD_FM.hpp>
|
||||
#include <script/globals/GPBD_FM_3.hpp>
|
||||
@ -16,9 +16,9 @@ namespace big
|
||||
if (ImGui::TreeNode("INFO"_T.data()))
|
||||
{
|
||||
components::button("Open SC Overlay", [] {
|
||||
int gamerHandle;
|
||||
NETWORK::NETWORK_HANDLE_FROM_PLAYER(g_player_service->get_selected()->id(), &gamerHandle, 13);
|
||||
NETWORK::NETWORK_SHOW_PROFILE_UI(&gamerHandle);
|
||||
uint64_t gamerHandle[13];
|
||||
NETWORK::NETWORK_HANDLE_FROM_PLAYER(g_player_service->get_selected()->id(), (Any*)&gamerHandle, 13);
|
||||
NETWORK::NETWORK_SHOW_PROFILE_UI((Any*)&gamerHandle);
|
||||
});
|
||||
ImGui::Text("PLAYER_INFO_ID"_T.data(), g_player_service->get_selected()->id());
|
||||
|
||||
|
@ -15,9 +15,6 @@ namespace big
|
||||
components::player_command_button<"breakup">(g_player_service->get_selected());
|
||||
ImGui::SameLine();
|
||||
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());
|
||||
ImGui::SameLine();
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "script/globals/GPBD_FM_3.hpp"
|
||||
#include "util/scripts.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
#include "views/view.hpp"
|
||||
|
||||
namespace big
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "script.hpp"
|
||||
#include "services/vehicle/persist_car_service.hpp"
|
||||
#include "util/mobile.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
#include "util/teleport.hpp"
|
||||
#include "views/view.hpp"
|
||||
|
||||
namespace big
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "core/data/speed_units.hpp"
|
||||
#include "fiber_pool.hpp"
|
||||
#include "util/mobile.hpp"
|
||||
#include "util/vehicle.hpp"
|
||||
#include "util/teleport.hpp"
|
||||
#include "views/view.hpp"
|
||||
|
||||
namespace big
|
||||
|
Reference in New Issue
Block a user