General improvements (#1693)

* remove(replay): remove replay interface
* fix(context_menu): better console controls
* feat(protections): improve protections
* feat(protections): actually fix parachute crash
* feat(protections): kick rejoin
* feat(context_menu): more context menu stuff
This commit is contained in:
maybegreat48 2023-07-12 17:03:29 +00:00 committed by GitHub
parent c570df8e48
commit f09b1cbda3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 458 additions and 297 deletions

View File

@ -20,7 +20,7 @@ namespace big
virtual void execute(player_ptr player, const std::vector<std::uint64_t>& _args, const std::shared_ptr<command_context> ctx) virtual void execute(player_ptr player, const std::vector<std::uint64_t>& _args, const std::shared_ptr<command_context> ctx)
{ {
if (!g_player_service->get_self()->is_host()) if (!g_player_service->get_self()->is_host() || !player->get_net_data())
return; return;
rage::snMsgRemoveGamersFromSessionCmd cmd{}; rage::snMsgRemoveGamersFromSessionCmd cmd{};
@ -31,43 +31,8 @@ namespace big
if (g.session.show_cheating_message) if (g.session.show_cheating_message)
cmd.m_unk = 19; cmd.m_unk = 19;
if (gta_util::get_network()->m_game_session.is_host())
{
g_pointers->m_gta.m_handle_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr, player->get_session_player(), &cmd); g_pointers->m_gta.m_handle_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr, player->get_session_player(), &cmd);
} }
else if (player->is_host())
{
for (auto& [_, plyr] : g_player_service->players())
{
if (plyr->id() != player->id())
g_pointers->m_gta.m_send_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr,
g_pointers->m_gta.m_get_connection_peer(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr,
plyr->get_session_player()->m_player_data.m_peer_id_2),
gta_util::get_network()->m_game_session_ptr->m_connection_identifier,
&cmd,
0x1000000);
}
g_pointers->m_gta.m_handle_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr, player->get_session_player(), &cmd);
}
else
{
for (auto& [_, plyr] : g_player_service->players())
{
if (plyr->is_host())
{
g_pointers->m_gta.m_send_remove_gamer_cmd(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr,
g_pointers->m_gta.m_get_connection_peer(gta_util::get_network()->m_game_session_ptr->m_net_connection_mgr,
plyr->get_session_player()->m_player_data.m_peer_id_2),
gta_util::get_network()->m_game_session_ptr->m_connection_identifier,
&cmd,
0x1000000);
break;
}
}
}
}
}; };
breakup_kick g_breakup_kick("breakup", "BREAKUP_KICK", "BREAKUP_KICK_DESC", 0, false); breakup_kick g_breakup_kick("breakup", "BREAKUP_KICK", "BREAKUP_KICK_DESC", 0, false);

View File

@ -3,14 +3,6 @@
namespace big namespace big
{ {
class veh_unlimited_weapons : looped_command bool_command g_veh_unlimited_weapons("vehallweapons", "Allow Weapons In Vehicle", "Allows you to use all weapons in vehicle",
{ g.vehicle.unlimited_weapons);
using looped_command::looped_command;
virtual void on_tick() override
{
}
};
veh_unlimited_weapons g_veh_unlimited_weapons("vehallweapons", "Allow Weapons In Vehicle", "Allows you to use all weapons in vehicle", g.vehicle.unlimited_weapons);
} }

View File

@ -36,6 +36,11 @@ namespace big
0, 0,
{0x2B, 0x2B, 0x2B, 0x00, 0x55}, {0x2B, 0x2B, 0x2B, 0x00, 0x55},
&g.self.invisibility}); &g.self.invisibility});
g_script_patcher_service->add_patch({RAGE_JOAAT("freemode"),
"2D 01 03 00 00 38 00 71 72 5D ? ? ? 06 56 ? ? 71 2E ? ? 2C ? ? ? 71",
5,
{0x72, 0x2E, 0x01, 0x01},
&g.session.unhide_players_from_player_list});
g_script_patcher_service->add_patch( 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 {RAGE_JOAAT("carmod_shop"), "2D 01 0A 00 00 4F ? ? 40 ? 41 ? 39 03", 5, {0x2E, 0x01, 0x00}, &g.vehicle.ls_customs}); // disable camera

View File

@ -19,7 +19,7 @@ namespace big
ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST, ATTACKING_WHEN_HIDDEN_FROM_PLAYER_LIST,
SPOOFED_DATA, SPOOFED_DATA,
SPOOFED_HOST_TOKEN, SPOOFED_HOST_TOKEN,
INVALID_PLAYER_MODEL INVALID_PLAYER_MODEL,
}; };
inline std::unordered_map<Infraction, const char*> infraction_desc = { inline std::unordered_map<Infraction, const char*> infraction_desc = {

View File

@ -187,8 +187,9 @@ namespace big
reaction rotate_cam{"Rotate Cam", "Blocked Rotate Cam from %s", "%s tried to mess with my camera!"}; reaction rotate_cam{"Rotate Cam", "Blocked Rotate Cam from %s", "%s tried to mess with my camera!"};
reaction send_to_cutscene{"Send To Cutscene", "Blocked Send To Cutscene from %s", "%s tried to force me into a cutscene!"}; reaction send_to_cutscene{"Send To Cutscene", "Blocked Send To Cutscene from %s", "%s tried to force me into a cutscene!"};
reaction send_to_location{"Send To Location", "Blocked Send To Location from %s", "%s tried to send me to Cayo Perico!"}; reaction send_to_location{"Send To Location", "Blocked Send To Location from %s", "%s tried to send me to Cayo Perico!"};
reaction send_to_interior{"Send To Interior", "Blocked Send To Interior from %s", "%s tried to send me to an interior!"};
reaction sound_spam{"Sound Spam", "Blocked Sound Spam from %s", "%s tried to spam annoying sounds at me!"}; reaction sound_spam{"Sound Spam", "Blocked Sound Spam from %s", "%s tried to spam annoying sounds at me!"};
reaction spectate_notification{"Spectate", "Blocked Spectate from %s", "Blocked Spectate from %s"}; reaction spectate_notification{"Spectate Notification", "Blocked Spectate Notification from %s", "Blocked Spectate Notification from %s"};
reaction give_collectible{"Give Collectible", "Blocked Give Collectible from %s", "%s tried to give me a collectible!"}; reaction give_collectible{"Give Collectible", "Blocked Give Collectible from %s", "%s tried to give me a collectible!"};
reaction transaction_error{"Transaction Error", "Blocked Transaction Error from %s", "%s tried to show me a transaction error!"}; reaction transaction_error{"Transaction Error", "Blocked Transaction Error from %s", "%s tried to show me a transaction error!"};
reaction tse_freeze{"TSE Freeze", "Blocked TSE Freeze from %s", "%s tried to softlock my game!"}; reaction tse_freeze{"TSE Freeze", "Blocked TSE Freeze from %s", "%s tried to softlock my game!"};
@ -211,10 +212,12 @@ namespace big
reaction modder_detection{"Modder Detection", "%s is detected as a modder by the anticheat", "%s is detected as a modder by the anticheat"}; reaction modder_detection{"Modder Detection", "%s is detected as a modder by the anticheat", "%s is detected as a modder by the anticheat"};
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!"};
reaction spectate{"Spectate", "%s is spectating you", "%s is spectating me!"};
interloper_reaction spectate_others{"Spectate Others", "%s is spectating %s!", "%s is spectating %s!", false, false};
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!"};
NLOHMANN_DEFINE_TYPE_INTRUSIVE(reactions, bounty, ceo_money, ceo_kick, clear_wanted_level, crash, end_session_kick, fake_deposit, force_mission, force_teleport, gta_banner, kick_from_interior, mc_teleport, network_bail, personal_vehicle_destroyed, remote_off_radar, rotate_cam, send_to_cutscene, send_to_location, sound_spam, spectate_notification, give_collectible, transaction_error, tse_freeze, tse_sender_mismatch, vehicle_kick, teleport_to_warehouse, trigger_business_raid, start_activity, start_script, null_function_kick, destroy_personal_vehicle, clear_ped_tasks, turn_into_beast, remote_wanted_level, remote_wanted_level_others, remote_ragdoll, kick_vote, report_cash_spawn, modder_detection, request_control_event, report, gamer_instruction_kick) NLOHMANN_DEFINE_TYPE_INTRUSIVE(reactions, bounty, ceo_money, ceo_kick, clear_wanted_level, crash, end_session_kick, fake_deposit, force_mission, force_teleport, gta_banner, kick_from_interior, mc_teleport, network_bail, personal_vehicle_destroyed, remote_off_radar, rotate_cam, send_to_cutscene, send_to_location, sound_spam, spectate_notification, give_collectible, transaction_error, tse_freeze, tse_sender_mismatch, vehicle_kick, teleport_to_warehouse, trigger_business_raid, start_activity, start_script, null_function_kick, destroy_personal_vehicle, clear_ped_tasks, turn_into_beast, remote_wanted_level, remote_wanted_level_others, remote_ragdoll, kick_vote, report_cash_spawn, modder_detection, request_control_event, report, gamer_instruction_kick, send_to_interior, spectate, spectate_others)
} reactions{}; } reactions{};
struct player struct player
@ -263,8 +266,9 @@ namespace big
bool rid_join = false; bool rid_join = false;
bool receive_pickup = false; bool receive_pickup = false;
bool admin_check = true; bool admin_check = true;
bool kick_rejoin = true;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, receive_pickup, admin_check) NLOHMANN_DEFINE_TYPE_INTRUSIVE(protections, script_events, rid_join, receive_pickup, admin_check, kick_rejoin)
} protections{}; } protections{};
struct self struct self
@ -346,6 +350,7 @@ namespace big
bool log_chat_messages = false; bool log_chat_messages = false;
bool log_text_messages = false; bool log_text_messages = false;
bool decloak_players = false; bool decloak_players = false;
bool unhide_players_from_player_list = true;
bool force_session_host = false; bool force_session_host = false;
bool force_script_host = false; bool force_script_host = false;
bool player_magnet_enabled = false; bool player_magnet_enabled = false;
@ -392,7 +397,7 @@ namespace big
bool fast_join = false; bool fast_join = false;
NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session, fast_join) NLOHMANN_DEFINE_TYPE_INTRUSIVE(session, log_chat_messages, log_text_messages, decloak_players, force_session_host, force_script_host, player_magnet_enabled, player_magnet_count, is_team, join_in_sctv_slots, kick_chat_spammers, kick_host_when_forcing_host, explosion_karma, damage_karma, disable_traffic, disable_peds, force_thunder, block_ceo_money, randomize_ceo_colors, block_jobs, block_muggers, block_ceo_raids, send_to_apartment_idx, send_to_warehouse_idx, chat_commands, chat_command_default_access_level, show_cheating_message, anonymous_bounty, lock_session, fast_join, unhide_players_from_player_list)
} session{}; } session{};
struct settings struct settings

View File

@ -509,6 +509,17 @@ enum class eNetworkEvents : uint16_t
NETWORK_CHECK_CATALOG_CRC NETWORK_CHECK_CATALOG_CRC
}; };
enum class KickReason : std::uint8_t
{
VOTED_OUT,
PEER_COMPLAINTS,
CONNECTION_ERROR,
NAT_TYPE,
SCADMIN,
SCADMIN_BLACKLIST,
NUM_REASONS
};
enum class ScriptEntityChangeType enum class ScriptEntityChangeType
{ {
BlockingOfNonTemporaryEvents, BlockingOfNonTemporaryEvents,

View File

@ -2,7 +2,6 @@
#include "../pointers.hpp" #include "../pointers.hpp"
#include "enums.hpp" #include "enums.hpp"
#include "node_list.hpp" #include "node_list.hpp"
#include "replay.hpp"
class CNetGamePlayer; class CNetGamePlayer;

View File

@ -98,10 +98,12 @@ public:
class GenericPool : public PoolUtils<GenericPool> class GenericPool : public PoolUtils<GenericPool>
{ {
public: public:
UINT64 m_pool_address; UINT64 m_pool_address; // 0x0
BYTE* m_bit_array; BYTE* m_bit_array; // 0x8
UINT32 m_size; UINT32 m_size; // 0x10
UINT32 m_item_size; UINT32 m_item_size; // 0x14
UINT32 m_pad[2]; // 0x18
UINT32 m_item_count; // 0x20
inline bool is_valid(UINT32 i) inline bool is_valid(UINT32 i)
{ {
@ -113,6 +115,11 @@ public:
return mask(i) & (m_pool_address + i * m_item_size); return mask(i) & (m_pool_address + i * m_item_size);
} }
inline int get_item_count()
{
return (4 * m_item_count) >> 2;
}
private: private:
inline long long mask(UINT32 i) inline long long mask(UINT32 i)
{ {
@ -120,3 +127,4 @@ private:
return ~((num1 | -num1) >> 63); return ~((num1 | -num1) >> 63);
} }
}; };
static_assert(offsetof(GenericPool, GenericPool::m_item_count) == 0x20);

View File

@ -1,94 +0,0 @@
#pragma once
#include "base/CObject.hpp"
#include "common.hpp"
#include "fwddec.hpp"
#pragma pack(push, 4)
namespace rage
{
template<typename T = CDynamicEntity>
class CEntityEntry
{
public:
T* m_entity_ptr; //0x0000
int32_t m_handle; //0x0008
char pad_000C[4]; //0x000C
}; //Size: 0x0010
static_assert(sizeof(CEntityEntry<CDynamicEntity>) == 0x10, "CEntityHandle is not properly sized");
class CObjectEntry : public CEntityEntry<CObject>
{
};
class CPedEntry : public CEntityEntry<CPed>
{
};
class CVehicleEntry : public CEntityEntry<CVehicle>
{
}; //Size: 0x8FC0
class CObjectInterface
{
public:
char pad_0000[344]; //0x0000
std::array<CObjectEntry, 2300>* m_object_list; //0x0158
int32_t m_max_objects; //0x0160
char pad_0164[4]; //0x0164
int32_t m_cur_objects; //0x0168
CObject* get_object(const int& index)
{
if (index < m_max_objects)
return (*m_object_list)[index].m_entity_ptr;
return nullptr;
}
}; //Size: 0x016C
class CPedInterface
{
public:
char pad_0000[256]; //0x0000
std::array<CPedEntry, 256>* m_ped_list; //0x0100
int32_t m_max_peds; //0x0108
char pad_010C[4]; //0x010C
int32_t m_cur_peds; //0x0110
CPed* get_ped(const int& index)
{
if (index < m_max_peds)
return (*m_ped_list)[index].m_entity_ptr;
return nullptr;
}
}; //Size: 0x0114
class CVehicleInterface
{
public:
char pad_0000[384]; //0x0000
std::array<CVehicleEntry, 300>* m_vehicle_list; //0x0180
int32_t m_max_vehicles; //0x0188
char pad_018C[4]; //0x018C
int32_t m_cur_vehicles; //0x0190
CVehicle* get_vehicle(const int& index)
{
if (index < m_max_vehicles)
return (*m_vehicle_list)[index].m_entity_ptr;
return nullptr;
}
}; //Size: 0x0194
class CReplayInterface
{
public:
char pad_0000[16]; //0x0000
class CVehicleInterface* m_vehicle_interface; //0x0010
class CPedInterface* m_ped_interface; //0x0018
char pad_0020[8]; //0x0020
class CObjectInterface* m_object_interface; //0x0028
}; //Size: 0x0030
}
#pragma pack(pop)

View File

@ -56,7 +56,6 @@ namespace big
CPedFactory** m_ped_factory{}; CPedFactory** m_ped_factory{};
CNetworkPlayerMgr** m_network_player_mgr{}; CNetworkPlayerMgr** m_network_player_mgr{};
CNetworkObjectMgr** m_network_object_mgr{}; CNetworkObjectMgr** m_network_object_mgr{};
rage::CReplayInterface** m_replay_interface{};
functions::ptr_to_handle m_ptr_to_handle{}; functions::ptr_to_handle m_ptr_to_handle{};
functions::handle_to_ptr m_handle_to_ptr{}; functions::handle_to_ptr m_handle_to_ptr{};
@ -271,6 +270,8 @@ namespace big
PVOID m_error_message_box{}; PVOID m_error_message_box{};
functions::get_title_caption_error_message_box m_get_title_caption_error_message_box{}; functions::get_title_caption_error_message_box m_get_title_caption_error_message_box{};
PVOID m_send_non_physical_player_data;
}; };
#pragma pack(pop) #pragma pack(pop)
static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned"); static_assert(sizeof(gta_pointers) % 8 == 0, "Pointers are not properly aligned");

View File

@ -114,6 +114,8 @@ namespace big
detour_hook_helper::add<hooks::log_error_message_box>("E0MBH", g_pointers->m_gta.m_error_message_box); detour_hook_helper::add<hooks::log_error_message_box>("E0MBH", g_pointers->m_gta.m_error_message_box);
detour_hook_helper::add<hooks::send_non_physical_player_data>("SNPPD", g_pointers->m_gta.m_send_non_physical_player_data);
g_hooking = this; g_hooking = this;
} }

View File

@ -30,6 +30,7 @@ class CPlayerAppearanceDataNode;
class CFoundDevice; class CFoundDevice;
class IDirectSoundCapture; class IDirectSoundCapture;
class CVehicleProximityMigrationDataNode; class CVehicleProximityMigrationDataNode;
class CNonPhysicalPlayerData;
namespace rage namespace rage
{ {
@ -151,6 +152,8 @@ namespace big
static int netfilter_handle_message(__int64 filter, char* message, int flags); static int netfilter_handle_message(__int64 filter, char* message, int flags);
static void log_error_message_box(rage::joaat_t joaated_error_code, char a2); static void log_error_message_box(rage::joaat_t joaated_error_code, char a2);
static void send_non_physical_player_data(CNetGamePlayer* player, __int64 message, int flags, void* a4, CNetGamePlayer* a5);
}; };
class minhook_keepalive class minhook_keepalive

View File

@ -21,9 +21,6 @@ namespace big
if (!player->get_ped()) if (!player->get_ped())
return false; return false;
if (!NETWORK::NETWORK_ARE_PLAYERS_IN_SAME_TUTORIAL_SESSION(self::id, player->id()))
return false; // probably not
if (scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].IsInvisible) if (scr_globals::globalplayer_bd.as<GlobalPlayerBD*>()->Entries[player->id()].IsInvisible)
return true; return true;
@ -61,8 +58,18 @@ namespace big
switch (net_event->get_type()) switch (net_event->get_type())
{ {
case rage::eEventNetworkType::CEventNetworkRemovedFromSessionDueToComplaints: case rage::eEventNetworkType::CEventNetworkRemovedFromSessionDueToComplaints:
{
if (g.protections.kick_rejoin && !NETWORK::NETWORK_IS_ACTIVITY_SESSION() && SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0 && !STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS())
{
g_fiber_pool->queue_job([] {
session::join_session(gta_util::get_network()->m_last_joined_session.m_session_info);
});
g_notification_service->push_warning("KICKED"_T.data(), "You have been desync kicked. Rejoining previous session...");
}
else
{ {
g_notification_service->push_warning("KICKED"_T.data(), "USER_DESYNC_KICKED"_T.data()); g_notification_service->push_warning("KICKED"_T.data(), "USER_DESYNC_KICKED"_T.data());
}
break; break;
} }
case rage::eEventNetworkType::CEventNetworkEntityDamage: case rage::eEventNetworkType::CEventNetworkEntityDamage:
@ -101,6 +108,9 @@ namespace big
if (NETWORK::NETWORK_IS_ACTIVITY_SESSION()) if (NETWORK::NETWORK_IS_ACTIVITY_SESSION())
break; break;
if (!NETWORK::NETWORK_ARE_PLAYERS_IN_SAME_TUTORIAL_SESSION(self::id, player->id()))
break;
if (globals::get_interior_from_player(player->id()) != 0) if (globals::get_interior_from_player(player->id()) != 0)
break; break;

View File

@ -723,22 +723,9 @@ namespace big
inline bool is_sane_override_pos(float x, float y, float z) inline bool is_sane_override_pos(float x, float y, float z)
{ {
if (isnan(x) || isnan(y) || isnan(z)) bool crash = (char)(fmaxf(0.0, (x + 149.0) - -8192.0) / 75.0) == 255 || (char)(fmaxf(0.0, (y + 149.0) - -8192.0) / 75.0) == 255;
return false;
if (isinf(x) || isinf(y) || isinf(z)) return !crash;
return false;
if (x > 5000.0f || x < -5000.0f)
return false;
if (y > 8500.0f || y < -5000.0f)
return false;
if (z > 1600.0f || z < -700.0f)
return false;
return true;
} }
bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, rage::netObject* object) bool check_node(rage::netSyncNodeBase* node, CNetGamePlayer* sender, rage::netObject* object)
@ -807,6 +794,22 @@ namespace big
return true; return true;
} }
if (attach_node->m_attached && object && object->m_object_type == (int16_t)eNetObjType::NET_OBJ_TYPE_TRAILER)
{
if (auto net_obj =
g_pointers->m_gta.m_get_net_object(*g_pointers->m_gta.m_network_object_mgr, attach_node->m_attached_to, false))
{
if (auto entity = net_obj->GetGameObject())
{
if (entity->m_entity_type != 3)
{
notify::crash_blocked(sender, "invalid attachment");
return true;
}
}
}
}
break; break;
} }
case sync_node_id("CPedCreationDataNode"): case sync_node_id("CPedCreationDataNode"):
@ -887,11 +890,72 @@ namespace big
if (game_state_node->m_is_overriding_population_control_sphere if (game_state_node->m_is_overriding_population_control_sphere
&& !is_sane_override_pos(game_state_node->m_population_control_sphere_x, && !is_sane_override_pos(game_state_node->m_population_control_sphere_x,
game_state_node->m_population_control_sphere_y, game_state_node->m_population_control_sphere_y,
game_state_node->m_population_control_sphere_z)) game_state_node->m_population_control_sphere_z)
&& gta_util::get_network()->m_game_session_ptr->is_host())
{ {
notify::crash_blocked(sender, "invalid sector position (player game state node)"); notify::crash_blocked(sender, "invalid sector position (player game state node)");
return true; return true;
} }
if (sender_plyr)
{
if (game_state_node->m_is_spectating)
{
if (!sender_plyr->get_ped())
break;
if (sender_plyr->get_ped()->m_health <= 0.0f) // you spectate the player that killed you
break;
auto net_obj = g_pointers->m_gta.m_get_net_object(*g_pointers->m_gta.m_network_object_mgr,
game_state_node->m_spectating_net_id,
false);
if (!net_obj)
break;
auto entity = net_obj->GetGameObject();
if (!entity || entity->m_entity_type != 4)
break;
auto player_info = ((CPed*)entity)->m_player_info;
if (!player_info)
break;
player_ptr target = nullptr;
if (g_local_player && (CPed*)entity == g_local_player)
{
target = g_player_service->get_self();
}
else
{
for (auto p : g_player_service->players())
if (p.second->get_player_info() == player_info)
target = p.second;
}
if (!target || !target->is_valid())
break;
if (target->id() != sender_plyr->spectating_player)
{
if (target->id() == self::id)
g.reactions.spectate.process(sender_plyr);
else
g.reactions.spectate_others.process(sender_plyr, target);
sender_plyr->spectating_player = target->id();
}
}
else
{
sender_plyr->spectating_player = -1;
}
}
break; break;
} }
case sync_node_id("CTrainGameStateDataNode"): case sync_node_id("CTrainGameStateDataNode"):
@ -900,6 +964,7 @@ namespace big
if (train_node->m_track_id < 0 || train_node->m_track_id >= 27) if (train_node->m_track_id < 0 || train_node->m_track_id >= 27)
{ {
//notify::crash_blocked(sender, "out of bounds train track index"); //notify::crash_blocked(sender, "out of bounds train track index");
//LOG(INFO) << train_node->m_track_id;
return true; return true;
} }
break; break;

View File

@ -177,16 +177,6 @@ namespace big
} }
return true; return true;
} }
case rage::eNetMessage::MsgRequestObjectIds:
{
if (player->block_join)
{
g_notification_service->push("BLOCK_JOIN"_T.data(),
std::vformat("BLOCK_JOIN_PREVENT_PLAYER_JOIN"_T, std::make_format_args(player->get_name())));
return true;
}
break;
}
case rage::eNetMessage::MsgScriptHostRequest: case rage::eNetMessage::MsgScriptHostRequest:
{ {
CGameScriptId script; CGameScriptId script;
@ -216,7 +206,7 @@ namespace big
} }
case rage::eNetMessage::MsgTransitionGamerInstruction: case rage::eNetMessage::MsgTransitionGamerInstruction:
{ {
// this kick is still a thing // it doesn't work but a certain p2c uses it
if (is_kick_instruction(buffer)) if (is_kick_instruction(buffer))
{ {
g.reactions.gamer_instruction_kick.process(player); g.reactions.gamer_instruction_kick.process(player);
@ -224,6 +214,28 @@ namespace big
} }
break; break;
} }
case rage::eNetMessage::MsgKickPlayer:
{
KickReason reason = buffer.Read<KickReason>(3);
if (!player->is_host())
return true;
if (reason == KickReason::VOTED_OUT)
{
g_notification_service->push_warning("Protections", "You have been kicked by the host");
return true;
}
break;
}
}
}
else
{
switch (msgType)
{
case rage::eNetMessage::MsgScriptMigrateHost: return true;
} }
} }

View File

@ -4,6 +4,7 @@
#include "gta_util.hpp" #include "gta_util.hpp"
#include "hooking.hpp" #include "hooking.hpp"
#include "lua/lua_manager.hpp" #include "lua/lua_manager.hpp"
#include "util/math.hpp"
#include "util/session.hpp" #include "util/session.hpp"
#include <network/CNetGamePlayer.hpp> #include <network/CNetGamePlayer.hpp>
@ -51,6 +52,11 @@ namespace big
return false; return false;
} }
inline bool is_player_our_boss(Player sender)
{
return sender == scr_globals::gpbd_fm_3.as<GPBD_FM_3*>()->Entries[self::id].BossGoon.Boss;
}
bool hooks::scripted_game_event(CScriptedGameEvent* scripted_game_event, CNetGamePlayer* player) bool hooks::scripted_game_event(CScriptedGameEvent* scripted_game_event, CNetGamePlayer* player)
{ {
const auto args = scripted_game_event->m_args; const auto args = scripted_game_event->m_args;
@ -156,11 +162,17 @@ namespace big
} }
break; break;
case eRemoteEvent::MCTeleport: case eRemoteEvent::MCTeleport:
if (g.protections.script_events.mc_teleport && args[3] <= 32) if (g.protections.script_events.mc_teleport && args[3] <= 32 && !is_player_our_boss(plyr->id()))
{
for (int i = 0; i < 32; i++)
{
if (args[4 + i] == NETWORK::NETWORK_HASH_FROM_PLAYER_HANDLE(self::id))
{ {
g.reactions.mc_teleport.process(plyr); g.reactions.mc_teleport.process(plyr);
return true; return true;
} }
}
}
else if (args[3] > 32) else if (args[3] > 32)
{ {
g.reactions.crash.process(plyr); g.reactions.crash.process(plyr);
@ -175,16 +187,14 @@ namespace big
} }
break; break;
case eRemoteEvent::RemoteOffradar: case eRemoteEvent::RemoteOffradar:
if (g.protections.script_events.remote_off_radar if (g.protections.script_events.remote_off_radar && !is_player_our_boss(plyr->id()) && !is_player_driver_of_local_vehicle(plyr->id()))
&& player->m_player_id != scr_globals::gpbd_fm_3.as<GPBD_FM_3*>()->Entries[self::id].BossGoon.Boss)
{ {
g.reactions.remote_off_radar.process(plyr); g.reactions.remote_off_radar.process(plyr);
return true; return true;
} }
break; break;
case eRemoteEvent::TSECommand: case eRemoteEvent::TSECommand:
if (g.protections.script_events.rotate_cam && static_cast<eRemoteEvent>(args[2]) == eRemoteEvent::TSECommandRotateCam if (g.protections.script_events.rotate_cam && static_cast<eRemoteEvent>(args[2]) == eRemoteEvent::TSECommandRotateCam && !NETWORK::NETWORK_IS_ACTIVITY_SESSION())
&& !gta_util::get_network()->m_is_activity_session)
{ {
g.reactions.rotate_cam.process(plyr); g.reactions.rotate_cam.process(plyr);
return true; return true;
@ -198,8 +208,7 @@ namespace big
} }
break; break;
case eRemoteEvent::SendToCutscene: case eRemoteEvent::SendToCutscene:
if (g.protections.script_events.send_to_cutscene if (g.protections.script_events.send_to_cutscene && !is_player_our_boss(plyr->id()))
&& player->m_player_id != scr_globals::gpbd_fm_3.as<GPBD_FM_3*>()->Entries[self::id].BossGoon.Boss)
{ {
g.reactions.send_to_cutscene.process(plyr); g.reactions.send_to_cutscene.process(plyr);
return true; return true;
@ -207,6 +216,9 @@ namespace big
break; break;
case eRemoteEvent::SendToLocation: case eRemoteEvent::SendToLocation:
{ {
if (is_player_our_boss(plyr->id()))
break;
bool known_location = false; bool known_location = false;
if (args[2] == 0 && args[3] == 0) if (args[2] == 0 && args[3] == 0)
@ -242,11 +254,9 @@ namespace big
} }
case eRemoteEvent::SoundSpam: case eRemoteEvent::SoundSpam:
{ {
auto plyr = g_player_service->get_by_id(player->m_player_id);
if (g.protections.script_events.sound_spam && (!plyr || plyr->m_invites_rate_limit.process())) if (g.protections.script_events.sound_spam && (!plyr || plyr->m_invites_rate_limit.process()))
{ {
if (plyr && plyr->m_invites_rate_limit.exceeded_last_process()) if (plyr->m_invites_rate_limit.exceeded_last_process())
g.reactions.sound_spam.process(plyr); g.reactions.sound_spam.process(plyr);
return true; return true;
} }
@ -275,7 +285,6 @@ namespace big
} }
break; break;
case eRemoteEvent::NetworkBail: case eRemoteEvent::NetworkBail:
if (auto plyr = g_player_service->get_by_id(player->m_player_id))
session::add_infraction(plyr, Infraction::TRIED_KICK_PLAYER); session::add_infraction(plyr, Infraction::TRIED_KICK_PLAYER);
g.reactions.network_bail.process(plyr); g.reactions.network_bail.process(plyr);
return true; return true;
@ -341,6 +350,25 @@ namespace big
g.reactions.null_function_kick.process(plyr); g.reactions.null_function_kick.process(plyr);
return true; return true;
} }
if (NETWORK::NETWORK_IS_ACTIVITY_SESSION())
break;
if (!g_local_player)
break;
if (is_player_our_boss(plyr->id()))
break;
if (is_player_driver_of_local_vehicle(plyr->id()))
break;
if (!plyr->get_ped() || math::distance_between_vectors(*plyr->get_ped()->get_position(), *g_local_player->get_position()) > 75.0f)
{
g.reactions.send_to_interior.process(plyr);
return true;
}
break; break;
} }
case eRemoteEvent::DestroyPersonalVehicle: g.reactions.destroy_personal_vehicle.process(plyr); return true; case eRemoteEvent::DestroyPersonalVehicle: g.reactions.destroy_personal_vehicle.process(plyr); return true;

View File

@ -0,0 +1,25 @@
#include "hooking.hpp"
#include "services/players/player_service.hpp"
#include <network/CNetGamePlayer.hpp>
#include <player/CNonPhysicalPlayerData.hpp>
namespace big
{
void hooks::send_non_physical_player_data(CNetGamePlayer* player, __int64 message, int flags, void* a4, CNetGamePlayer* a5)
{
auto plyr = g_player_service->get_by_id(player->m_player_id);
auto data = *(CNonPhysicalPlayerData**)(message + 0x10);
int old_bubble_id = data->m_bubble_id;
if (plyr && plyr->block_join)
{
data->m_bubble_id = 10;
g_notification_service->push("BLOCK_JOIN"_T.data(), std::vformat("BLOCK_JOIN_PREVENT_PLAYER_JOIN"_T, std::make_format_args(plyr->get_name())));
}
g_hooking->get_original<hooks::send_non_physical_player_data>()(player, message, flags, a4, a5);
data->m_bubble_id = old_bubble_id;
}
}

View File

@ -5,12 +5,32 @@
namespace big namespace big
{ {
constexpr uint32_t valid_parachute_models[] = {
RAGE_JOAAT("p_parachute_s"),
RAGE_JOAAT("vw_p_para_bag_vine_s"),
RAGE_JOAAT("reh_p_para_bag_reh_s_01a"),
RAGE_JOAAT("xm_prop_x17_scuba_tank"),
RAGE_JOAAT("lts_p_para_bag_pilot2_s"),
RAGE_JOAAT("lts_p_para_bag_lts_s"),
RAGE_JOAAT("p_para_bag_tr_s_01a"),
RAGE_JOAAT("p_para_bag_xmas_s"),
};
bool is_valid_parachute_model(rage::joaat_t hash)
{
for (auto& model : valid_parachute_models)
if (model == hash)
return true;
return false;
}
void hooks::serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer) void hooks::serialize_take_off_ped_variation_task(ClonedTakeOffPedVariationInfo* info, rage::CSyncDataBase* serializer)
{ {
g_hooking->get_original<hooks::serialize_take_off_ped_variation_task>()(info, serializer); 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 (!is_valid_parachute_model(info->m_prop_hash))
{ {
// notify::crash_blocked(g.m_syncing_player, "invalid parachute"); false positives notify::crash_blocked(g.m_syncing_player, "invalid parachute");
info->m_prop_hash = 0; info->m_prop_hash = 0;
} }
} }

View File

@ -53,6 +53,15 @@ namespace big
} }
} }
inline void STAT_SET_INT(rage::scrNativeCallContext* src)
{
const auto hash = src->get_arg<Hash>(0);
if (hash == RAGE_JOAAT("SP0_TOTAL_CASH") || hash == RAGE_JOAAT("SP1_TOTAL_CASH") || hash == RAGE_JOAAT("SP2_TOTAL_CASH"))
return;
src->set_return_value<BOOL>(STATS::STAT_SET_INT(hash, src->get_arg<int>(1), src->get_arg<int>(2)));
}
inline void SET_ENTITY_COORDS(rage::scrNativeCallContext* src) inline void SET_ENTITY_COORDS(rage::scrNativeCallContext* src)
{ {
if (!g.vehicle.ls_customs) if (!g.vehicle.ls_customs)

View File

@ -125,6 +125,7 @@ namespace big
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"), 0xB3271D7AB655B441, carmod_shop::STAT_SET_INT);
add_native_detour(RAGE_JOAAT("carmod_shop"), 0x5F4B6931816E599B, carmod_shop::DISABLE_ALL_CONTROL_ACTIONS); add_native_detour(RAGE_JOAAT("carmod_shop"), 0x5F4B6931816E599B, carmod_shop::DISABLE_ALL_CONTROL_ACTIONS);
add_native_detour(RAGE_JOAAT("freemode"), 0x2C83A9DA6BFFC4F9, freemode::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH); add_native_detour(RAGE_JOAAT("freemode"), 0x2C83A9DA6BFFC4F9, freemode::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH);

View File

@ -297,15 +297,6 @@ namespace big
g_pointers->m_gta.m_write_player_game_state_data_node = ptr.as<functions::write_player_game_state_data_node>(); g_pointers->m_gta.m_write_player_game_state_data_node = ptr.as<functions::write_player_game_state_data_node>();
} }
}, },
// Replay Interface
{
"RI",
"0F B7 44 24 ? 66 89 44 4E",
[](memory::handle ptr)
{
g_pointers->m_gta.m_replay_interface = ptr.add(0x1F).rip().as<rage::CReplayInterface**>();
}
},
// Ptr To Handle // Ptr To Handle
{ {
"PTH", "PTH",
@ -1217,6 +1208,15 @@ namespace big
g_pointers->m_gta.m_get_host_array_handler_by_index = ptr.as<functions::get_host_array_handler_by_index>(); g_pointers->m_gta.m_get_host_array_handler_by_index = ptr.as<functions::get_host_array_handler_by_index>();
} }
}, },
// Send Non Physical Player Data
{
"SNPPD",
"E8 ? ? ? ? 4C 8B 0F 44 0F B7 85 A0 01 00 00",
[](memory::handle ptr)
{
g_pointers->m_gta.m_send_non_physical_player_data = ptr.add(1).rip().as<PVOID>();
}
},
// Max Wanted Level // Max Wanted Level
{ {
"MWL", "MWL",

View File

@ -2,7 +2,6 @@
#include "base/HashTable.hpp" #include "base/HashTable.hpp"
#include "function_types.hpp" #include "function_types.hpp"
#include "gta/fwddec.hpp" #include "gta/fwddec.hpp"
#include "gta/replay.hpp"
#include "gta_pointers.hpp" #include "gta_pointers.hpp"
#include "memory/batch.hpp" #include "memory/batch.hpp"
#include "memory/byte_patch.hpp" #include "memory/byte_patch.hpp"

View File

@ -37,5 +37,7 @@ namespace big
static inline script_function modshop_loop("ML", RAGE_JOAAT("carmod_shop"), "2D 00 07 00 00 71 51", 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); static inline script_function setup_modshop("SM", RAGE_JOAAT("carmod_shop"), "2D 04 12 00 00 38 00 51", 0);
static inline script_function reset_session_data("RSD", RAGE_JOAAT("pausemenu_multiplayer"), "2D 02 7D 00 00", 0);
} }
} }

View File

@ -1,12 +1,13 @@
#include "context_menu_service.hpp" #include "context_menu_service.hpp"
#include "fiber_pool.hpp" #include "fiber_pool.hpp"
#include "gta/replay.hpp"
#include "gui.hpp" #include "gui.hpp"
#include "natives.hpp" #include "natives.hpp"
#include "pointers.hpp" #include "pointers.hpp"
#include "util/misc.hpp" #include "util/misc.hpp"
#include <network/ChatData.hpp>
namespace big namespace big
{ {
context_menu_service::context_menu_service() context_menu_service::context_menu_service()
@ -228,11 +229,11 @@ namespace big
ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON, ControllerInputs::INPUT_VEH_SELECT_NEXT_WEAPON,
ControllerInputs::INPUT_SELECT_NEXT_WEAPON, ControllerInputs::INPUT_SELECT_NEXT_WEAPON,
ControllerInputs::INPUT_SELECT_PREV_WEAPON, ControllerInputs::INPUT_SELECT_PREV_WEAPON,
ControllerInputs::INPUT_WEAPON_WHEEL_NEXT,
ControllerInputs::INPUT_WEAPON_WHEEL_PREV,
ControllerInputs::INPUT_ATTACK, ControllerInputs::INPUT_ATTACK,
ControllerInputs::INPUT_ATTACK2,
ControllerInputs::INPUT_SPECIAL_ABILITY, ControllerInputs::INPUT_SPECIAL_ABILITY,
ControllerInputs::INPUT_VEH_MOUSE_CONTROL_OVERRIDE, ControllerInputs::INPUT_VEH_MOUSE_CONTROL_OVERRIDE,
ControllerInputs::INPUT_SNIPER_ZOOM,
}; };
void context_menu_service::disable_control_action_loop() void context_menu_service::disable_control_action_loop()
@ -248,11 +249,13 @@ namespace big
{ {
while (g_running) while (g_running)
{ {
if (g_gui->is_open()) if (g_gui->is_open() || HUD::IS_PAUSE_MENU_ACTIVE()
|| (*g_pointers->m_gta.m_chat_data && (*g_pointers->m_gta.m_chat_data)->m_chat_open))
{ {
script::get_current()->yield(); script::get_current()->yield();
continue; continue;
} }
if (!g.context_menu.enabled) if (!g.context_menu.enabled)
{ {
g_context_menu_service->enabled = false; g_context_menu_service->enabled = false;
@ -261,10 +264,20 @@ namespace big
continue; continue;
} }
if (PAD::IS_USING_KEYBOARD_AND_MOUSE(0))
{
if (PAD::IS_DISABLED_CONTROL_JUST_RELEASED(0, (int)ControllerInputs::INPUT_VEH_DUCK)) if (PAD::IS_DISABLED_CONTROL_JUST_RELEASED(0, (int)ControllerInputs::INPUT_VEH_DUCK))
{ {
g_context_menu_service->enabled = !g_context_menu_service->enabled; g_context_menu_service->enabled = !g_context_menu_service->enabled;
} }
}
else
{
if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_AIM) && PAD::IS_DISABLED_CONTROL_JUST_RELEASED(0, (int)ControllerInputs::INPUT_FRONTEND_Y))
{
g_context_menu_service->enabled = !g_context_menu_service->enabled;
}
}
if (g_context_menu_service->enabled) if (g_context_menu_service->enabled)
{ {
@ -279,12 +292,20 @@ namespace big
continue; continue;
} }
if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_WEAPON_WHEEL_NEXT)) ControllerInputs next_key = PAD::IS_USING_KEYBOARD_AND_MOUSE(0) ? ControllerInputs::INPUT_WEAPON_WHEEL_NEXT : ControllerInputs::INPUT_SCRIPT_PAD_DOWN;
ControllerInputs prev_key = PAD::IS_USING_KEYBOARD_AND_MOUSE(0) ? ControllerInputs::INPUT_WEAPON_WHEEL_PREV : ControllerInputs::INPUT_SCRIPT_PAD_UP;
ControllerInputs execute_key = PAD::IS_USING_KEYBOARD_AND_MOUSE(0) ? ControllerInputs::INPUT_ATTACK : ControllerInputs::INPUT_FRONTEND_ACCEPT;
PAD::DISABLE_CONTROL_ACTION(0, static_cast<int>(next_key), true);
PAD::DISABLE_CONTROL_ACTION(0, static_cast<int>(prev_key), true);
PAD::DISABLE_CONTROL_ACTION(0, static_cast<int>(execute_key), true);
if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)next_key))
cm->current_option = cm->options.size() <= cm->current_option + 1 ? 0 : cm->current_option + 1; cm->current_option = cm->options.size() <= cm->current_option + 1 ? 0 : cm->current_option + 1;
if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_WEAPON_WHEEL_PREV)) if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)prev_key))
cm->current_option = 0 > cm->current_option - 1 ? static_cast<int>(cm->options.size()) - 1 : cm->current_option - 1; cm->current_option = 0 > cm->current_option - 1 ? static_cast<int>(cm->options.size()) - 1 : cm->current_option - 1;
if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_ATTACK) || PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)ControllerInputs::INPUT_SPECIAL_ABILITY)) if (PAD::IS_DISABLED_CONTROL_JUST_PRESSED(0, (int)execute_key))
{ {
if (!g_context_menu_service->m_pointer) if (!g_context_menu_service->m_pointer)
{ {

View File

@ -137,13 +137,17 @@ namespace big
for (auto& [_, weapon] : g_gta_data_service->weapons()) for (auto& [_, weapon] : g_gta_data_service->weapons())
WEAPON::REMOVE_WEAPON_FROM_PED(m_handle, weapon.m_hash); WEAPON::REMOVE_WEAPON_FROM_PED(m_handle, weapon.m_hash);
}}, }},
{"KILL",
[this] {
ped::kill_ped(m_handle);
}},
{"RAGDOLL", {"RAGDOLL",
[this] { [this] {
PED::SET_PED_TO_RAGDOLL(m_handle, 2000, 2000, 0, 0, 0, 0); PED::SET_PED_TO_RAGDOLL(m_handle, 2000, 2000, 0, 0, 0, 0);
}}, }},
{"DANCE", {"DANCE",
[this] { [this] {
ped::ped_play_animation(m_handle, "mini@strip_club@private_dance@part1", "priv_dance_p1"); ped::ped_play_animation(m_handle, "mini@strip_club@private_dance@part1", "priv_dance_p1", 3.5f, -4.0f, -1, 1);
}}, }},
{"RECRUIT", [this] { {"RECRUIT", [this] {
TASK::CLEAR_PED_TASKS(m_handle); TASK::CLEAR_PED_TASKS(m_handle);
@ -177,19 +181,19 @@ namespace big
[this] { [this] {
ped::steal_identity(m_handle); ped::steal_identity(m_handle);
}}, }},
{"BREAKUP KICK",
[this] {
static player_command* command = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("breakup")));
command->call(ped::get_player_from_ped(m_handle), {});
}},
{"KICK", {"KICK",
[this] { [this] {
static player_command* command = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("nfkick"))); static player_command* command = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("nfkick")));
static player_command* command1 = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("shkick"))); static player_command* command1 = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("shkick")));
static player_command* command2 = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("endkick"))); static player_command* command2 = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("endkick")));
static player_command* command3 = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("desync")));
static player_command* command4 = dynamic_cast<player_command*>(command::get(rage::consteval_joaat("breakup")));
command->call(ped::get_player_from_ped(m_handle), {}); command->call(ped::get_player_from_ped(m_handle), {});
command1->call(ped::get_player_from_ped(m_handle), {}); command1->call(ped::get_player_from_ped(m_handle), {});
command2->call(ped::get_player_from_ped(m_handle), {}); command2->call(ped::get_player_from_ped(m_handle), {});
command3->call(ped::get_player_from_ped(m_handle), {});
script::get_current()->yield(500ms);
command4->call(ped::get_player_from_ped(m_handle), {});
}}, }},
{"DISARM", {"DISARM",
[this] { [this] {
@ -218,6 +222,25 @@ namespace big
[this] { [this] {
teleport::tp_on_top(m_handle, true); teleport::tp_on_top(m_handle, true);
}}, }},
{"BRING",
[this] {
rage::fvector3 pos = *g_local_player->m_navigation->get_position();
if (PED::IS_PED_A_PLAYER(m_handle))
{
if (auto plyr = g_player_service->get_by_id(NETWORK::NETWORK_GET_PLAYER_INDEX_FROM_PED(m_handle)))
{
teleport::teleport_player_to_coords(plyr, {pos.x, pos.y, pos.z});
}
}
else
{
if (entity::take_control_of(m_handle))
{
ENTITY::SET_ENTITY_COORDS(m_handle, pos.x, pos.y, pos.z, false, false, false, false);
}
}
}},
{"ENFLAME", {"ENFLAME",
[this] { [this] {
Vector3 pos = ENTITY::GET_ENTITY_COORDS(m_handle, TRUE); Vector3 pos = ENTITY::GET_ENTITY_COORDS(m_handle, TRUE);

View File

@ -378,21 +378,9 @@ namespace big
Vector3 campos = CAM::GET_CAM_COORD(m_cam); Vector3 campos = CAM::GET_CAM_COORD(m_cam);
Vector3 entpos = ENTITY::GET_ENTITY_COORDS(entity::get_entity_closest_to_middle_of_screen(), 0); Vector3 entpos = ENTITY::GET_ENTITY_COORDS(entity::get_entity_closest_to_middle_of_screen(), 0);
if (*g_pointers->m_gta.m_is_session_started && g_player_service->get_selected()->is_valid()
&& ENTITY::DOES_ENTITY_EXIST(g_pointers->m_gta.m_ptr_to_handle(g_player_service->get_selected()->get_ped())))
{
toxic::blame_explode_coord(g_player_service->get_selected(), m_ground_pos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f);
if (MISC::GET_DISTANCE_BETWEEN_COORDS(campos.x, campos.y, campos.z, entpos.x, entpos.y, entpos.z, false) < 10)
toxic::blame_explode_coord(g_player_service->get_selected(), entpos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f);
}
else
{
toxic::blame_explode_coord(*g_pointers->m_gta.m_is_session_started ? g_player_service->get_self() : nullptr, m_ground_pos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f); toxic::blame_explode_coord(*g_pointers->m_gta.m_is_session_started ? g_player_service->get_self() : nullptr, m_ground_pos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f);
if (MISC::GET_DISTANCE_BETWEEN_COORDS(campos.x, campos.y, campos.z, entpos.x, entpos.y, entpos.z, false) < 10) if (MISC::GET_DISTANCE_BETWEEN_COORDS(campos.x, campos.y, campos.z, entpos.x, entpos.y, entpos.z, false) < 10)
toxic::blame_explode_coord(*g_pointers->m_gta.m_is_session_started ? g_player_service->get_self() : nullptr, entpos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f); toxic::blame_explode_coord(*g_pointers->m_gta.m_is_session_started ? g_player_service->get_self() : nullptr, entpos, eExplosionTag::EXP_TAG_ORBITAL_CANNON, 1.f, TRUE, TRUE, 1.f);
}
if (!STREAMING::HAS_NAMED_PTFX_ASSET_LOADED("scr_xm_orbital")) if (!STREAMING::HAS_NAMED_PTFX_ASSET_LOADED("scr_xm_orbital"))
{ {

View File

@ -85,6 +85,8 @@ namespace big
bool block_explosions = false; bool block_explosions = false;
int spectating_player = -1;
protected: protected:
bool equals(const CNetGamePlayer* net_game_player) const; bool equals(const CNetGamePlayer* net_game_player) const;

View File

@ -41,7 +41,7 @@ namespace big
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
LOG(WARNING) << "Failed fetching xml vehicles: " << e.what() << std::endl; LOG(WARNING) << "Failed fetching XML vehicles: " << e.what() << std::endl;
} }
} }
@ -213,6 +213,7 @@ namespace big
ENTITY::SET_ENTITY_VISIBLE(vehicle_handle, vehicle_node.child("IsVisible").text().as_bool(), false); ENTITY::SET_ENTITY_VISIBLE(vehicle_handle, vehicle_node.child("IsVisible").text().as_bool(), false);
ENTITY::SET_ENTITY_INVINCIBLE(vehicle_handle, vehicle_node.child("IsInvincible").text().as_bool()); ENTITY::SET_ENTITY_INVINCIBLE(vehicle_handle, vehicle_node.child("IsInvincible").text().as_bool());
ENTITY::SET_ENTITY_ALPHA(vehicle_handle, vehicle_node.child("OpacityLevel").text().as_int(), false);
ENTITY::SET_ENTITY_PROOFS(vehicle_handle, ENTITY::SET_ENTITY_PROOFS(vehicle_handle,
vehicle_node.child("IsBulletProof").text().as_bool(), vehicle_node.child("IsBulletProof").text().as_bool(),
vehicle_node.child("IsFireProof").text().as_bool(), vehicle_node.child("IsFireProof").text().as_bool(),
@ -267,7 +268,23 @@ namespace big
if (STREAMING::HAS_NAMED_PTFX_ASSET_LOADED(asset)) if (STREAMING::HAS_NAMED_PTFX_ASSET_LOADED(asset))
{ {
GRAPHICS::USE_PARTICLE_FX_ASSET(asset); GRAPHICS::USE_PARTICLE_FX_ASSET(asset);
GRAPHICS::START_NETWORKED_PARTICLE_FX_LOOPED_ON_ENTITY(const_cast<PCHAR>(attachment_item.child("PtfxLopEffect").text().as_string()), attachment_handle, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1); GRAPHICS::START_NETWORKED_PARTICLE_FX_LOOPED_ON_ENTITY(
const_cast<PCHAR>(attachment_item.child("PtfxLopEffect").text().as_string()),
attachment_handle,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
1,
1,
1);
STREAMING::REMOVE_NAMED_PTFX_ASSET(asset); STREAMING::REMOVE_NAMED_PTFX_ASSET(asset);
} }
} }

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "gta/joaat.hpp" #include "gta/joaat.hpp"
#include "gta/replay.hpp"
#include "gta_util.hpp" #include "gta_util.hpp"
#include "math.hpp" #include "math.hpp"
#include "natives.hpp" #include "natives.hpp"

View File

@ -14,6 +14,11 @@ namespace big::math
return (float)sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2) + pow((a.z - b.z), 2)); return (float)sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2) + pow((a.z - b.z), 2));
} }
inline float distance_between_vectors(rage::fvector3 a, rage::fvector3 b)
{
return (float)sqrt(pow((a.x - b.x), 2) + pow((a.y - b.y), 2) + pow((a.z - b.z), 2));
}
inline Vector3 rotation_to_direction(Vector3 rotation) inline Vector3 rotation_to_direction(Vector3 rotation)
{ {
float x = deg_to_rad(rotation.x); float x = deg_to_rad(rotation.x);

View File

@ -22,12 +22,16 @@ namespace big::notify
{ {
if (player) if (player)
{ {
if (g.reactions.crash.notify)
g_notification_service->push_error("Protections", std::format("Blocked {} crash from {}", crash, player->get_name())); g_notification_service->push_error("Protections", std::format("Blocked {} crash from {}", crash, player->get_name()));
if (g.reactions.crash.log)
LOG(WARNING) << "Blocked " << crash << " crash from " << player->get_name() << " (" LOG(WARNING) << "Blocked " << crash << " crash from " << player->get_name() << " ("
<< (player->get_net_data() ? player->get_net_data()->m_gamer_handle.m_rockstar_id : 0) << ")"; << (player->get_net_data() ? player->get_net_data()->m_gamer_handle.m_rockstar_id : 0) << ")";
} }
else else
{ {
if (g.reactions.crash.notify)
g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash)); g_notification_service->push_error("Protections", std::format("Blocked {} crash from unknown player", crash));
} }
} }

View File

@ -8,6 +8,7 @@
#include "pointers.hpp" #include "pointers.hpp"
#include "rage/rlSessionByGamerTaskResult.hpp" #include "rage/rlSessionByGamerTaskResult.hpp"
#include "script.hpp" #include "script.hpp"
#include "script_function.hpp"
#include "script_global.hpp" #include "script_global.hpp"
#include "services/api/api_service.hpp" #include "services/api/api_service.hpp"
#include "services/player_database/player_database_service.hpp" #include "services/player_database/player_database_service.hpp"
@ -36,24 +37,41 @@ namespace big::session
inline bool join_type(eSessionType session) inline bool join_type(eSessionType session)
{ {
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) != 0 || STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS()) SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(RAGE_JOAAT("pausemenu_multiplayer"));
{
g_notification_service->push_error("RID Joiner", "Player switch in progress, wait a bit.");
return false; while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(RAGE_JOAAT("pausemenu_multiplayer")))
} script::get_current()->yield();
*script_global(2695915).as<int*>() = (session == eSessionType::SC_TV ? 1 : 0); // If SC TV Then Enable Spectator Mode *script_global(2695915).as<int*>() = (session == eSessionType::SC_TV ? 1 : 0); // If SCTV then enable spectator mode
if (session == eSessionType::LEAVE_ONLINE) if (session == eSessionType::LEAVE_ONLINE)
*script_global(1574589).at(2).as<int*>() = -1; *script_global(1574589).at(2).as<int*>() = -1;
else else
{
*script_global(1574589).at(2).as<int*>() = 0;
*script_global(1575020).as<int*>() = (int)session; *script_global(1575020).as<int*>() = (int)session;
}
*script_global(1574589).as<int*>() = 1; *script_global(1574589).as<int*>() = 1;
if (*g_pointers->m_gta.m_is_session_started && session != eSessionType::LEAVE_ONLINE)
{
*scr_globals::transition_state.as<eTransitionState*>() = eTransitionState::TRANSITION_STATE_LOOK_TO_JOIN_ANOTHER_SESSION_FM;
}
scr_functions::reset_session_data({true, true});
*script_global(32284).as<int*>() = 0;
*script_global(1574934).as<int*>() = 1;
*script_global(1574995).as<int*>() = 32;
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) == 0)
{
*script_global(2694534).as<int*>() = 1;
script::get_current()->yield(200ms); script::get_current()->yield(200ms);
*script_global(1574589).as<int*>() = 0; *script_global(1574589).as<int*>() = 0;
}
SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(RAGE_JOAAT("pausemenu_multiplayer"));
return true; return true;
} }
@ -77,6 +95,12 @@ namespace big::session
inline void join_session(const rage::rlSessionInfo& info) inline void join_session(const rage::rlSessionInfo& info)
{ {
if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(RAGE_JOAAT("maintransition")) != 0 || STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS())
{
g_notification_service->push_error("RID Joiner", "Player switch in progress, wait a bit.");
return;
}
g.session.join_queued = true; g.session.join_queued = true;
g.session.info = info; g.session.info = info;
session::join_type({eSessionType::NEW_PUBLIC}); session::join_type({eSessionType::NEW_PUBLIC});

View File

@ -1,3 +1,4 @@
#include "gta/pools.hpp"
#include "gta_util.hpp" #include "gta_util.hpp"
#include "gui.hpp" #include "gui.hpp"
#include "pointers.hpp" #include "pointers.hpp"
@ -77,28 +78,28 @@ namespace big
ImGui::Text("Pos: %.2f, %.2f, %.2f", pos.x, pos.y, pos.z); ImGui::Text("Pos: %.2f, %.2f, %.2f", pos.x, pos.y, pos.z);
} }
// can't easily get used item count using pools, so keeping replay interface for now if (g.window.ingame_overlay.show_replay_interface)
if (auto replay_interface = *g_pointers->m_gta.m_replay_interface; g.window.ingame_overlay.show_replay_interface)
{ {
if (replay_interface->m_ped_interface || replay_interface->m_vehicle_interface || replay_interface->m_object_interface) if (*g_pointers->m_gta.m_ped_pool || (*g_pointers->m_gta.m_vehicle_pool && **g_pointers->m_gta.m_vehicle_pool)
|| *g_pointers->m_gta.m_prop_pool)
ImGui::Separator(); ImGui::Separator();
if (replay_interface->m_ped_interface) if (*g_pointers->m_gta.m_ped_pool)
ImGui::Text(std::format("Ped Pool: {}/{}", ImGui::Text(std::format("Ped Pool: {}/{}",
replay_interface->m_ped_interface->m_cur_peds, (*g_pointers->m_gta.m_ped_pool)->get_item_count(),
replay_interface->m_ped_interface->m_max_peds) (*g_pointers->m_gta.m_ped_pool)->m_size)
.c_str()); .c_str());
if (replay_interface->m_vehicle_interface) if (*g_pointers->m_gta.m_vehicle_pool && **g_pointers->m_gta.m_vehicle_pool)
ImGui::Text(std::format("Vehicle Pool: {}/{}", ImGui::Text(std::format("Vehicle Pool: {}/{}",
replay_interface->m_vehicle_interface->m_cur_vehicles, (**g_pointers->m_gta.m_vehicle_pool)->m_item_count,
replay_interface->m_vehicle_interface->m_max_vehicles) (**g_pointers->m_gta.m_vehicle_pool)->m_size)
.c_str()); .c_str());
if (replay_interface->m_object_interface) if (*g_pointers->m_gta.m_prop_pool)
ImGui::Text(std::format("Object Pool: {}/{}", ImGui::Text(std::format("Object Pool: {}/{}",
replay_interface->m_object_interface->m_cur_objects, (*g_pointers->m_gta.m_prop_pool)->get_item_count(),
replay_interface->m_object_interface->m_max_objects) (*g_pointers->m_gta.m_prop_pool)->m_size)
.c_str()); .c_str());
} }

View File

@ -120,7 +120,8 @@ namespace big
ImGui::EndDisabled(); ImGui::EndDisabled();
components::script_patch_checkbox("REVEAL_OTR_PLAYERS"_T, &g.session.decloak_players); components::script_patch_checkbox("REVEAL_OTR_PLAYERS"_T, &g.session.decloak_players, "Reveals players that are off the radar");
components::script_patch_checkbox("Reveal Hidden Players", &g.session.unhide_players_from_player_list, "Reveals players that have hidden themselves from the player list");
ImGui::EndListBox(); ImGui::EndListBox();
} }

View File

@ -45,6 +45,7 @@ namespace big
if (ImGui::IsItemHovered()) if (ImGui::IsItemHovered())
ImGui::SetTooltip("This prevents the collection of pickups such as unwanted money bags\nNote: Normal pickups are also no longer possible to collect with this enabled"); ImGui::SetTooltip("This prevents the collection of pickups such as unwanted money bags\nNote: Normal pickups are also no longer possible to collect with this enabled");
ImGui::Checkbox("ADMIN_CHECK"_T.data(), &g.protections.admin_check); ImGui::Checkbox("ADMIN_CHECK"_T.data(), &g.protections.admin_check);
ImGui::Checkbox("Kick Rejoin", &g.protections.kick_rejoin);
ImGui::EndGroup(); ImGui::EndGroup();
} }

View File

@ -14,6 +14,7 @@ namespace big
void draw_reaction(reaction& reaction) void draw_reaction(reaction& reaction)
{ {
ImGui::PushID(&reaction);
if (ImGui::TreeNode(reaction.m_event_name)) if (ImGui::TreeNode(reaction.m_event_name))
{ {
ImGui::Checkbox("REACTION_CHAT"_T.data(), &reaction.announce_in_chat); ImGui::Checkbox("REACTION_CHAT"_T.data(), &reaction.announce_in_chat);
@ -25,11 +26,13 @@ namespace big
ImGui::Checkbox("REACTION_KICK_PLAYER"_T.data(), &reaction.kick); ImGui::Checkbox("REACTION_KICK_PLAYER"_T.data(), &reaction.kick);
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::PopID();
} }
// TODO code duplication // TODO code duplication
void draw_interloper_reaction(interloper_reaction& reaction) void draw_interloper_reaction(interloper_reaction& reaction)
{ {
ImGui::PushID(&reaction);
if (ImGui::TreeNode(reaction.m_event_name)) if (ImGui::TreeNode(reaction.m_event_name))
{ {
ImGui::Checkbox("REACTION_CHAT"_T.data(), &reaction.announce_in_chat); ImGui::Checkbox("REACTION_CHAT"_T.data(), &reaction.announce_in_chat);
@ -51,6 +54,7 @@ namespace big
ImGui::TreePop(); ImGui::TreePop();
} }
ImGui::PopID();
} }
void view::reaction_settings() void view::reaction_settings()
@ -77,6 +81,7 @@ namespace big
draw_reaction(g.reactions.rotate_cam); draw_reaction(g.reactions.rotate_cam);
draw_reaction(g.reactions.send_to_cutscene); draw_reaction(g.reactions.send_to_cutscene);
draw_reaction(g.reactions.send_to_location); draw_reaction(g.reactions.send_to_location);
draw_reaction(g.reactions.send_to_interior);
draw_reaction(g.reactions.sound_spam); draw_reaction(g.reactions.sound_spam);
draw_reaction(g.reactions.spectate_notification); draw_reaction(g.reactions.spectate_notification);
draw_reaction(g.reactions.start_activity); draw_reaction(g.reactions.start_activity);
@ -98,6 +103,8 @@ namespace big
draw_reaction(g.reactions.report); draw_reaction(g.reactions.report);
draw_reaction(g.reactions.report_cash_spawn); draw_reaction(g.reactions.report_cash_spawn);
draw_reaction(g.reactions.request_control_event); draw_reaction(g.reactions.request_control_event);
draw_reaction(g.reactions.spectate);
draw_interloper_reaction(g.reactions.spectate_others);
ImGui::Separator(); ImGui::Separator();
draw_reaction(g.reactions.gamer_instruction_kick); draw_reaction(g.reactions.gamer_instruction_kick);