feat(net_events): net event protections (#45)

This commit is contained in:
Mr-X-GTA
2025-03-29 05:05:12 +01:00
committed by GitHub
parent 15c5bf3df8
commit 01b0a46b5a
19 changed files with 1039 additions and 177 deletions
+8
View File
@@ -281,6 +281,14 @@ namespace YimMenu
return GetNetworkObject() != nullptr;
}
bool Entity::IsRemote()
{
if (!IsNetworked())
return false;
return GetNetworkObject()->m_IsRemote;
}
rage::netObject* Entity::GetNetworkObject()
{
if (!IsValid())
+1
View File
@@ -114,6 +114,7 @@ namespace YimMenu
// networking
bool IsNetworked();
bool IsRemote();
bool HasControl();
rage::netObject* GetNetworkObject();
+3 -2
View File
@@ -4,6 +4,7 @@
class CNetworkPlayerMgr;
class CNetGamePlayer;
class CProjectBaseSyncDataNode;
class CScriptedGameEvent;
namespace rage
{
class netConnectionManager;
@@ -60,8 +61,8 @@ namespace YimMenu::Hooks
namespace Network
{
extern void ReceiveNetMessage(void* a1, rage::netConnectionManager* mgr, rage::netEvent* event);
extern void ReceiveEvent(YimMenu::Player& player, uint16_t event_id, uint32_t event_index, uint32_t event_handled_bitset, rage::datBitBuffer& buffer);
extern bool HandleScriptedGameEvent(YimMenu::Player& player, int64_t* args, uint32_t args_size);
extern void ReceiveNetGameEvent(Player player, uint16_t event_id, uint32_t event_index, uint32_t event_handled_bits, rage::datBitBuffer& buffer);
extern bool HandleScriptedGameEvent(Player player, CScriptedGameEvent& event);
}
namespace Window
+280 -17
View File
@@ -1,10 +1,12 @@
#include "core/util/Joaat.hpp"
#include "game/backend/Self.hpp"
#include "game/gta/Natives.hpp"
#include "game/hooks/Hooks.hpp"
#include "game/pointers/Pointers.hpp"
#include "types/network/CNetGamePlayer.hpp"
#include "types/network/NetEventType.hpp"
#include "types/network/netGameEvent.hpp"
#include "types/rage/datBitBuffer.hpp"
#include "types/script/globals/GlobalPlayerBD.hpp"
namespace YimMenu::Hooks
{
@@ -19,16 +21,118 @@ namespace YimMenu::Hooks
*reinterpret_cast<std::uint32_t*>(0x118LL * event_index + (uint64_t)event_mgr + 4 * source_player->m_PlayerIndex + 0x458) = event_handled_bits;
}
static bool HandleNetGameEvent(Player& player, uint16_t event_id, rage::datBitBuffer& buffer)
// Returns true if bad event
bool ScanExplosionEvent(CExplosionEvent& event, Player player)
{
switch (static_cast<NetEventType>(event_id))
if (*(int16_t*)&event.m_InteriorIndex < -1)
{
case NetEventType::WEAPON_DAMAGE_EVENT:
{
uint8_t damage_type = buffer.Read<uint8_t>(2);
uint32_t weapon_type = buffer.Read<uint32_t>(32);
LOG(INFO) << "blocked invalid interior crash from " << player.GetName();
return true;
}
if (weapon_type == "WEAPON_TRANQUILIZER"_J)
if (event.m_IsInvisible)
{
float dist = event.m_Position.GetDistance(Self::GetPed().GetPosition());
if (event.m_CameraShake > 0.0f && dist <= 30.0f)
{
// Camera shake
return true;
}
if (event.m_DamageScale > 0.0f && dist <= 10.0f)
{
// Ragdoll
return true;
}
}
// more?
return false;
}
bool ScanPlaySoundEvent(CPlaySoundEvent& event, Player player)
{
static constexpr std::array blocked_ref_hashes = {"Arena_Vehicle_Mod_Shop_Sounds"_J, "CELEBRATION_SOUNDSET"_J, "DLC_AW_Arena_Office_Planning_Wall_Sounds"_J, "DLC_AW_Arena_Spin_Wheel_Game_Frontend_Sounds"_J, "DLC_Biker_SYG_Sounds"_J, "DLC_BTL_SECURITY_VANS_RADAR_PING_SOUNDS"_J, "DLC_BTL_Target_Pursuit_Sounds"_J, "DLC_GR_Bunker_Door_Sounds"_J, "DLC_GR_CS2_Sounds"_J, "DLC_IO_Warehouse_Mod_Garage_Sounds"_J, "DLC_MPSUM2_HSW_Up_Sounds"_J, "DLC_sum20_Business_Battle_AC_Sounds"_J, "DLC_TG_Running_Back_Sounds"_J, "dlc_vw_table_games_frontend_sounds"_J, "dlc_xm_facility_entry_exit_sounds"_J, "Frontend"_J, "GTAO_Boss_Goons_FM_Soundset"_J, "GTAO_Exec_SecuroServ_Computer_Sounds"_J, "GTAO_Exec_SecuroServ_Warehouse_PC_Sounds"_J, "GTAO_Script_Doors_Faded_Screen_Sounds"_J, "GTAO_SMG_Hangar_Computer_Sounds"_J, "HUD_AMMO_SHOP_SOUNDSET"_J, "HUD_FRONTEND_CUSTOM_SOUNDSET"_J, "HUD_FRONTEND_DEFAULT_SOUNDSET"_J, "HUD_FRONTEND_MP_SOUNDSET"_J, "HUD_FRONTEND_MP_COLLECTABLE_SOUNDS"_J, "HUD_FRONTEND_TATTOO_SHOP_SOUNDSET"_J, "HUD_FRONTEND_CLOTHESSHOP_SOUNDSET"_J, "HUD_FRONTEND_STANDARD_PICKUPS_NPC_SOUNDSET"_J, "HUD_FRONTEND_VEHICLE_PICKUPS_NPC_SOUNDSET"_J, "HUD_FRONTEND_WEAPONS_PICKUPS_NPC_SOUNDSET"_J, "HUD_FREEMODE_SOUNDSET"_J, "HUD_MINI_GAME_SOUNDSET"_J, "HUD_AWARDS"_J, "JA16_Super_Mod_Garage_Sounds"_J, "Low2_Super_Mod_Garage_Sounds"_J, "MissionFailedSounds"_J, "MP_CCTV_SOUNDSET"_J, "MP_LOBBY_SOUNDS"_J, "MP_MISSION_COUNTDOWN_SOUNDSET"_J, "Phone_SoundSet_Default"_J, "Phone_SoundSet_Glasses_Cam"_J, "Phone_SoundSet_Prologue"_J, "Phone_SoundSet_Franklin"_J, "Phone_SoundSet_Michael"_J, "Phone_SoundSet_Trevor"_J, "PLAYER_SWITCH_CUSTOM_SOUNDSET"_J, "RESPAWN_ONLINE_SOUNDSET"_J, "TATTOOIST_SOUNDS"_J, "WastedSounds"_J, "WEB_NAVIGATION_SOUNDS_PHONE"_J};
static constexpr std::array blocked_sound_hashes = {"Remote_Ring"_J, "COP_HELI_CAM_ZOOM"_J, "Object_Dropped_Remote"_J};
static constexpr std::array blocked_script_hashes = {"main_persistent"_J, "shop_controller"_J};
if (std::ranges::contains(blocked_ref_hashes, event.m_RefHash)
|| std::ranges::contains(blocked_sound_hashes, event.m_SoundHash)
|| std::ranges::contains(blocked_script_hashes, event.m_ScriptId.m_Hash))
return true;
switch (event.m_SoundHash)
{
case "DLC_XM_Explosions_Orbital_Cannon"_J:
{
if (event.m_IsEntity)
return true;
if (event.m_ScriptId.m_Hash != "am_mp_defunct_base"_J && event.m_ScriptId.m_Hash != "am_mp_orbital_cannon"_J
&& event.m_ScriptId.m_Hash != "fm_mission_controller_2020"_J && event.m_ScriptId.m_Hash != "fm_mission_controller"_J)
return true;
if (!GlobalPlayerBD::Get()->Entries[player.GetId()].OrbitalBitset.IsSet(eOrbitalBitset::kOrbitalCannonActive))
return true;
break;
}
}
switch (event.m_RefHash)
{
case "GTAO_Biker_Modes_Soundset"_J:
case "DLC_Biker_Sell_Postman_Sounds"_J:
{
if (event.m_IsEntity)
return true;
if (event.m_ScriptId.m_Hash != "gb_biker_contraband_sell"_J)
return true;
break;
}
case "DLC_AW_General_Sounds"_J:
{
if (event.m_SoundHash != "Airhorn_Blast_Long"_J)
return true;
if (event.m_ScriptId.m_Hash != "gb_casino_heist"_J)
return true;
break;
}
case "GTAO_FM_Events_Soundset"_J:
{
if (!event.m_IsEntity)
return true;
if (event.m_SoundHash != "Explosion_Countdown"_J)
return true;
break;
}
}
return false;
}
bool ShouldAllowNetEvent(Player player, uint16_t event_id, rage::datBitBuffer& buffer)
{
switch (static_cast<rage::netGameEvent::Type>(event_id))
{
case rage::netGameEvent::Type::REQUEST_CONTROL_EVENT:
{
// TODO
break;
}
case rage::netGameEvent::Type::WEAPON_DAMAGE_EVENT:
{
CWeaponDamageEvent event;
event.Deserialize(buffer);
if (event.m_WeaponType == "WEAPON_TRANQUILIZER"_J)
{
LOG(INFO) << "blocked this thing from " << player.GetName();
//player.AddDetection();
@@ -37,18 +141,177 @@ namespace YimMenu::Hooks
break;
}
case NetEventType::SCRIPTED_GAME_EVENT:
case rage::netGameEvent::Type::EXPLOSION_EVENT:
{
int64_t args[54]{};
uint32_t args_size = buffer.Read<uint32_t>(32);
CExplosionEvent event;
event.Deserialize(buffer);
if (args_size > sizeof(args))
if (ScanExplosionEvent(event, player))
{
return false;
}
break;
}
case rage::netGameEvent::Type::CHANGE_RADIO_STATION_EVENT:
{
uint16_t veh_id = buffer.Read<uint16_t>(13);
Vehicle self_veh = Self::GetVehicle();
Vehicle sender_veh = player.GetPed().GetVehicle();
if (self_veh && self_veh.GetNetworkObjectId() == veh_id && sender_veh && sender_veh.GetNetworkObjectId() != veh_id)
{
// Vehicle takeover
return false;
}
break;
}
case rage::netGameEvent::Type::DOOR_BREAK_EVENT:
{
// never used for legitimate reasons
return false;
}
case rage::netGameEvent::Type::SCRIPTED_GAME_EVENT:
{
CScriptedGameEvent event;
if (!event.Deserialize(buffer))
return false;
buffer.ReadArray(args, 8 * args_size);
if (!Network::HandleScriptedGameEvent(player, args, args_size))
if (!Network::HandleScriptedGameEvent(player, event))
return false;
break;
}
case rage::netGameEvent::Type::SCRIPT_WORLD_STATE_EVENT:
{
auto type = buffer.Read<CScriptWorldStateEvent::Type>(4);
buffer.Read<bool>(1);
CGameScriptId id;
id.Deserialize(buffer);
if (type == CScriptWorldStateEvent::Type::PopGroupOverride)
{
int pop_schedule = buffer.Read<int>(8);
int pop_group = buffer.Read<int>(32);
int percentage = buffer.Read<int>(7);
if (pop_group == 0 && (percentage == 0 || percentage == 103))
{
// pop group override crash
return false;
}
}
else if (type == CScriptWorldStateEvent::Type::PopMultiplierArea && !NETWORK::NETWORK_IS_ACTIVITY_SESSION())
{
// Stop traffic
return false;
}
break;
}
case rage::netGameEvent::Type::SCRIPT_ENTITY_STATE_CHANGE_EVENT:
{
uint16_t entity = buffer.Read<uint16_t>(13);
auto type = buffer.Read<CScriptEntityStateChangeEvent::Type>(4);
uint32_t unk = buffer.Read<uint32_t>(32);
if (type == CScriptEntityStateChangeEvent::Type::SettingOfTaskVehicleTempAction)
{
uint16_t veh_id = buffer.Read<uint16_t>(13);
uint32_t action = buffer.Read<uint32_t>(8);
if (action >= 15 && action <= 18)
{
// vehicle temp action crash
return false;
}
if (Self::GetPed().GetNetworkObjectId() == entity)
{
// Ped takeover
return false;
}
Vehicle self_veh = Self::GetVehicle();
if (self_veh && self_veh.GetNetworkObjectId() == veh_id)
{
// Vehicle takeover
return false;
}
}
else if (type == CScriptEntityStateChangeEvent::Type::SetVehicleLockState)
{
Vehicle self_veh = Self::GetVehicle();
if (self_veh && self_veh.GetNetworkObjectId() == entity)
{
LOGF(WARNING, "Blocked SCRIPT_ENTITY_STATE_CHANGE_EVENT of type SetVehicleLockState from {} on our local vehicle", player.GetName());
return false;
}
}
else if (type == CScriptEntityStateChangeEvent::Type::SetVehicleExclusiveDriver)
{
Vehicle self_veh = Self::GetVehicle();
if (self_veh && self_veh.GetNetworkObjectId() == entity)
{
// Vehicle kick
return false;
}
}
else if (type == CScriptEntityStateChangeEvent::Type::SetPedFacialIdleAnimOverride)
{
if (Self::GetPed().GetNetworkObjectId() == entity)
{
LOGF(WARNING, "Blocked SCRIPT_ENTITY_STATE_CHANGE_EVENT of type SetPedFacialIdleAnimOverride from {} on our local player", player.GetName());
return false;
}
}
else if (type > CScriptEntityStateChangeEvent::Type::SetVehicleExclusiveDriver)
{
// invalid script entity change type crash
return false;
}
break;
}
case rage::netGameEvent::Type::NETWORK_PLAY_SOUND_EVENT:
{
CPlaySoundEvent event;
event.Deserialize(buffer);
if (ScanPlaySoundEvent(event, player))
{
LOGF(WARNING, "Blocked NETWORK_PLAY_SOUND_EVENT from {} with IsEntity: {}, RefHash: {:X}, SoundHash: {:X}, SoundId: {}, ScriptHash: {:X}", player.GetName(), event.m_IsEntity, event.m_RefHash, event.m_SoundHash, event.m_SoundId, event.m_ScriptId.m_Hash);
return false;
}
break;
}
case rage::netGameEvent::Type::REPORT_MYSELF_EVENT:
{
CUpdateFxnEvent event;
event.Deserialize(buffer);
if (event.m_0x30 != 6) // false positives when telemetry endpoint is unreachable
{
// Triggered anti cheat
}
break;
}
case rage::netGameEvent::Type::ACTIVATE_VEHICLE_SPECIAL_ABILITY_EVENT:
{
CActivateVehicleSpecialAbilityEvent event;
event.Deserialize(buffer);
if (Self::GetPed().GetVehicleObjectId() == event.m_VehicleId && !Self::GetVehicle().IsRemote())
{
// Vehicle takeover
return false;
}
break;
}
@@ -59,9 +322,9 @@ namespace YimMenu::Hooks
return true;
}
void Network::ReceiveEvent(Player& player, uint16_t event_id, uint32_t event_index, uint32_t event_handled_bits, rage::datBitBuffer& buffer)
void Network::ReceiveNetGameEvent(Player player, uint16_t event_id, uint32_t event_index, uint32_t event_handled_bits, rage::datBitBuffer& buffer)
{
if (!HandleNetGameEvent(player, event_id, buffer))
if (!ShouldAllowNetEvent(player, event_id, buffer))
SendEventAck(*Pointers.NetEventMgr, player.GetHandle(), Self::GetPlayer().GetHandle(), event_index, event_handled_bits);
}
}
@@ -1,13 +1,15 @@
#include "game/backend/Self.hpp"
#include "game/hooks/Hooks.hpp"
#include "game/pointers/Pointers.hpp"
#include "types/network/netGameEvent.hpp"
#include "types/script/globals/GPBD_FM_3.hpp"
#include "types/script/ScriptEvent.hpp"
namespace YimMenu::Hooks
{
bool Network::HandleScriptedGameEvent(YimMenu::Player& player, int64_t* args, uint32_t args_size)
bool Network::HandleScriptedGameEvent(Player player, CScriptedGameEvent& event)
{
SCRIPT_EVENT* script_event = reinterpret_cast<SCRIPT_EVENT*>(args);
SCRIPT_EVENT* script_event = reinterpret_cast<SCRIPT_EVENT*>(event.m_Args);
switch (static_cast<ScriptEventIndex>(script_event->GetEventIndex()))
{
@@ -15,7 +17,7 @@ namespace YimMenu::Hooks
{
SCRIPT_EVENT_BOUNTY* bounty = static_cast<SCRIPT_EVENT_BOUNTY*>(script_event);
if (args_size != SCRIPT_EVENT_BOUNTY::GetSize())
if (event.m_ArgsSize != SCRIPT_EVENT_BOUNTY::GetSize())
{
//player.AddDetection();
return false;
@@ -33,6 +35,15 @@ namespace YimMenu::Hooks
//player.AddDetection();
return false;
}
case ScriptEventIndex::CeoKick:
{
if (player.GetId() != GPBD_FM_3::Get()->Entries[Self::GetPlayer().GetId()].BossGoon.Boss)
{
return false;
}
break;
}
default:
break;
}
+1 -1
View File
@@ -83,7 +83,7 @@ namespace YimMenu::Hooks
rage::datBitBuffer event_buffer(event_data, sizeof(event_data), true);
event_buffer.m_MaxBit = event_data_size + 1;
ReceiveEvent(player, event_id, event_index, event_handled_bits, event_buffer);
ReceiveNetGameEvent(player, event_id, event_index, event_handled_bits, event_buffer);
remaining -= (int)buffer.m_BitsRead - bits_read;
}
-92
View File
@@ -1,92 +0,0 @@
#pragma once
enum class NetEventType : uint16_t
{
OBJECT_ID_FREED_EVENT,
OBJECT_ID_REQUEST_EVENT,
ARRAY_DATA_VERIFY_EVENT,
SCRIPT_ARRAY_DATA_VERIFY_EVENT,
REQUEST_CONTROL_EVENT,
GIVE_CONTROL_EVENT,
WEAPON_DAMAGE_EVENT,
REQUEST_PICKUP_EVENT,
REQUEST_MAP_PICKUP_EVENT,
GAME_CLOCK_EVENT,
GAME_WEATHER_EVENT,
RESPAWN_PLAYER_PED_EVENT,
GIVE_WEAPON_EVENT,
REMOVE_WEAPON_EVENT,
REMOVE_ALL_WEAPONS_EVENT,
VEHICLE_COMPONENT_CONTROL_EVENT,
FIRE_EVENT,
EXPLOSION_EVENT,
START_PROJECTILE_EVENT,
UPDATE_PROJECTILE_TARGET_EVENT,
REMOVE_PROJECTILE_ENTITY_EVENT,
BREAK_PROJECTILE_TARGET_LOCK_EVENT,
ALTER_WANTED_LEVEL_EVENT,
CHANGE_RADIO_STATION_EVENT,
RAGDOLL_REQUEST_EVENT,
PLAYER_TAUNT_EVENT,
PLAYER_CARD_STAT_EVENT,
DOOR_BREAK_EVENT,
SCRIPTED_GAME_EVENT,
REMOTE_SCRIPT_INFO_EVENT,
REMOTE_SCRIPT_LEAVE_EVENT,
MARK_AS_NO_LONGER_NEEDED_EVENT,
CONVERT_TO_SCRIPT_ENTITY_EVENT,
SCRIPT_WORLD_STATE_EVENT,
CLEAR_AREA_EVENT,
CLEAR_RECTANGLE_AREA_EVENT,
NETWORK_REQUEST_SYNCED_SCENE_EVENT,
NETWORK_START_SYNCED_SCENE_EVENT,
NETWORK_STOP_SYNCED_SCENE_EVENT,
NETWORK_UPDATE_SYNCED_SCENE_EVENT,
INCIDENT_ENTITY_EVENT,
GIVE_PED_SCRIPTED_TASK_EVENT,
GIVE_PED_SEQUENCE_TASK_EVENT,
NETWORK_CLEAR_PED_TASKS_EVENT,
NETWORK_START_PED_ARREST_EVENT,
NETWORK_START_PED_UNCUFF_EVENT,
NETWORK_SOUND_CAR_HORN_EVENT,
NETWORK_ENTITY_AREA_STATUS_EVENT,
NETWORK_GARAGE_OCCUPIED_STATUS_EVENT,
PED_CONVERSATION_LINE_EVENT,
SCRIPT_ENTITY_STATE_CHANGE_EVENT,
NETWORK_PLAY_SOUND_EVENT,
NETWORK_STOP_SOUND_EVENT,
NETWORK_PLAY_AIRDEFENSE_FIRE_EVENT,
NETWORK_BANK_REQUEST_EVENT,
NETWORK_AUDIO_BARK_EVENT,
REQUEST_DOOR_EVENT,
NETWORK_TRAIN_REPORT_EVENT,
NETWORK_TRAIN_REQUEST_EVENT,
NETWORK_INCREMENT_STAT_EVENT,
MODIFY_VEHICLE_LOCK_WORD_STATE_DATA,
MODIFY_PTFX_WORD_STATE_DATA_SCRIPTED_EVOLVE_EVENT,
REQUEST_PHONE_EXPLOSION_EVENT,
REQUEST_DETACHMENT_EVENT,
KICK_VOTES_EVENT,
GIVE_PICKUP_REWARDS_EVENT,
BLOW_UP_VEHICLE_EVENT,
NETWORK_SPECIAL_FIRE_EQUIPPED_WEAPON,
NETWORK_RESPONDED_TO_THREAT_EVENT,
NETWORK_SHOUT_TARGET_POSITION,
VOICE_DRIVEN_MOUTH_MOVEMENT_FINISHED_EVENT,
PICKUP_DESTROYED_EVENT,
UPDATE_PLAYER_SCARS_EVENT,
NETWORK_CHECK_EXE_SIZE_EVENT,
NETWORK_PTFX_EVENT,
NETWORK_PED_SEEN_DEAD_PED_EVENT,
REMOVE_STICKY_BOMB_EVENT,
NETWORK_CHECK_CODE_CRCS_EVENT,
INFORM_SILENCED_GUNSHOT_EVENT,
PED_PLAY_PAIN_EVENT,
CACHE_PLAYER_HEAD_BLEND_DATA_EVENT,
REMOVE_PED_FROM_PEDGROUP_EVENT,
REPORT_MYSELF_EVENT,
REPORT_CASH_SPAWN_EVENT,
ACTIVATE_VEHICLE_SPECIAL_ABILITY_EVENT,
BLOCK_WEAPON_SELECTION,
NETWORK_CHECK_CATALOG_CRC
};
+230
View File
@@ -0,0 +1,230 @@
#include "netGameEvent.hpp"
#include "types/fx/ExplosionType.hpp"
#include "types/rage/datBitBuffer.hpp"
bool CScriptedGameEvent::Deserialize(rage::datBitBuffer& buffer)
{
m_ArgsSize = buffer.Read<uint32_t>(32);
if (m_ArgsSize > sizeof(m_Args))
return false;
buffer.ReadArray(m_Args, 8 * m_ArgsSize);
return true;
}
void CNetworkIncrementStatEvent::Deserialize(rage::datBitBuffer& buffer)
{
m_Stat = buffer.Read<uint32_t>(32);
m_Amount = buffer.Read<uint32_t>(32, true);
}
void CDoorBreakEvent::Deserialize(rage::datBitBuffer& buffer)
{
m_VehicleId = buffer.Read<uint16_t>(13);
m_DoorId = buffer.Read<uint8_t>(3);
}
void CPlaySoundEvent::Deserialize(rage::datBitBuffer& buffer)
{
m_IsEntity = buffer.Read<bool>(1);
if (m_IsEntity)
{
m_EntityId = buffer.Read<uint16_t>(13);
}
else
{
m_Position = buffer.ReadPosition(19);
}
bool has_ref = buffer.Read<bool>(1);
if (has_ref)
{
m_RefHash = buffer.Read<uint32_t>(32);
}
else
{
m_RefHash = 0;
}
m_SoundHash = buffer.Read<uint32_t>(32);
m_SoundId = buffer.Read<uint8_t>(8);
bool has_script_hash = buffer.Read<bool>(1);
if (has_script_hash)
{
m_ScriptId.Deserialize(buffer);
}
else
{
m_ScriptId.m_Hash = 0;
}
}
void CWeaponDamageEvent::Deserialize(rage::datBitBuffer& buffer)
{
m_DamageType = buffer.Read<uint8_t>(2);
m_WeaponType = buffer.Read<uint32_t>(32);
m_OverrideDefaultDamage = buffer.Read<bool>(1);
m_HitEntityWeapon = buffer.Read<bool>(1);
m_HitWeaponAmmoAttachment = buffer.Read<bool>(1);
m_Silenced = buffer.Read<bool>(1);
m_DamageFlags = buffer.Read<uint32_t>(25);
bool hasActionResult = buffer.Read<bool>(1);
if (hasActionResult)
{
m_ActionResultName = buffer.Read<uint32_t>(32);
m_ActionResultId = buffer.Read<uint16_t>(16);
m_0x6C = buffer.Read<uint32_t>(32);
}
if (m_OverrideDefaultDamage)
{
m_WeaponDamage = buffer.Read<uint32_t>(17);
}
else
{
m_WeaponDamage = 0;
}
bool _f92 = buffer.Read<uint8_t>(1);
if (_f92)
{
m_0x5C = buffer.Read<uint8_t>(5);
}
m_IsNetTargetPos = buffer.Read<uint8_t>(1);
if (m_IsNetTargetPos)
{
m_LocalPos.x = buffer.ReadSignedFloat(16, 90.f);
m_LocalPos.y = buffer.ReadSignedFloat(16, 90.f);
m_LocalPos.z = buffer.ReadSignedFloat(16, 90.f);
}
if (m_DamageType == 3)
{
m_DamageTime = buffer.Read<uint32_t>(32);
m_WillKill = buffer.Read<bool>(1);
if (hasActionResult)
{
m_HitGlobalId = buffer.Read<uint16_t>(13);
}
else
{
m_HitGlobalId = 0;
}
bool f112 = buffer.Read<bool>(1);
if (f112)
{
m_0x74 = buffer.Read<uint16_t>(16);
}
else
{
m_0x74 = buffer.Read<uint16_t>(11);
}
}
else
{
m_ParentGlobalId = buffer.Read<uint16_t>(13);
m_HitGlobalId = buffer.Read<uint16_t>(13);
}
if (m_DamageType < 2)
{
m_LocalPos.x = buffer.ReadSignedFloat(16, 90.f);
m_LocalPos.y = buffer.ReadSignedFloat(16, 90.f);
m_LocalPos.z = buffer.ReadSignedFloat(16, 90.f);
if (m_DamageType == 1)
{
bool hasVehicleData = buffer.Read<bool>(1);
if (hasVehicleData)
{
m_TyreIndex = buffer.Read<uint8_t>(4);
m_SuspensionIndex = buffer.Read<uint8_t>(4);
}
}
}
else
{
m_HitComponent = buffer.Read<int>(5);
}
m_0x89 = buffer.Read<bool>(1);
m_HasImpactDir = buffer.Read<bool>(1);
if (m_HasImpactDir)
{
m_ImpactDir.x = buffer.ReadSignedFloat(16, 6.2831855f);
m_ImpactDir.y = buffer.ReadSignedFloat(16, 6.2831855f);
m_ImpactDir.z = buffer.ReadSignedFloat(16, 6.2831855f);
}
}
void CActivateVehicleSpecialAbilityEvent::Deserialize(rage::datBitBuffer& buffer)
{
m_VehicleId = buffer.Read<uint16_t>(13);
m_AbilityType = buffer.Read<uint32_t>(3);
}
void CExplosionEvent::Deserialize(rage::datBitBuffer& buffer)
{
m_0xBA = buffer.Read<uint16_t>(16);
m_TargetEntity = buffer.Read<uint16_t>(13);
m_OwnerNetId = buffer.Read<uint16_t>(13);
m_UnkNetId = buffer.Read<uint16_t>(13);
m_ExplosionType = buffer.Read<ExplosionType>(8, true);
m_DamageScale = buffer.ReadFloat(8, 1.0f);
m_Position = buffer.ReadPosition(22);
m_0xF2 = buffer.Read<bool>(1);
m_0x68 = buffer.Read<uint32_t>(16);
m_CameraShake = buffer.ReadSignedFloat(8, 1.0f);
m_IsAudible = buffer.Read<bool>(1);
m_0xBD = buffer.Read<bool>(1);
m_IsInvisible = buffer.Read<bool>(1);
m_0x7E = buffer.Read<bool>(1);
m_AddOwnedExplosion = buffer.Read<bool>(1);
m_0xF1 = buffer.Read<bool>(1);
m_HasTargetEnt2 = buffer.Read<bool>(1);
m_TargetEnt2 = buffer.Read<uint16_t>(13);
m_0x80 = buffer.ReadVector3(16, 1.1f);
m_0xBE = buffer.Read<bool>(1);
m_0xBF = buffer.Read<bool>(1);
m_0xA4 = buffer.Read<uint32_t>(32);
m_InteriorIndex = buffer.Read<uint32_t>(32);
if (m_0xF2)
{
m_PositionUnk = buffer.ReadPosition(31);
}
m_0xF0 = buffer.Read<bool>(1);
if (m_AddOwnedExplosion)
{
m_ScriptHash = buffer.Read<uint32_t>(32);
m_ProgramCounter = buffer.Read<uint32_t>(32);
}
if (m_0xF0)
{
m_0xDA = buffer.Read<uint16_t>(16);
if (m_0xBF)
{
m_0xD8 = buffer.Read<uint8_t>(8);
}
}
}
void CUpdateFxnEvent::Deserialize(rage::datBitBuffer& buffer)
{
m_0x30 = buffer.Read<uint32_t>(32);
m_0x34 = buffer.Read<uint32_t>(32);
}
+343
View File
@@ -0,0 +1,343 @@
#pragma once
#include <cstdint>
#include "types/rage/vector.hpp"
#include "types/script/CGameScriptId.hpp"
namespace rage
{
class datBitBuffer;
class netPlayer;
class netGameEvent
{
public:
enum class Type : uint16_t
{
OBJECT_ID_FREED_EVENT,
OBJECT_ID_REQUEST_EVENT,
ARRAY_DATA_VERIFY_EVENT,
SCRIPT_ARRAY_DATA_VERIFY_EVENT,
REQUEST_CONTROL_EVENT,
GIVE_CONTROL_EVENT,
WEAPON_DAMAGE_EVENT,
REQUEST_PICKUP_EVENT,
REQUEST_MAP_PICKUP_EVENT,
GAME_CLOCK_EVENT,
GAME_WEATHER_EVENT,
RESPAWN_PLAYER_PED_EVENT,
GIVE_WEAPON_EVENT,
REMOVE_WEAPON_EVENT,
REMOVE_ALL_WEAPONS_EVENT,
VEHICLE_COMPONENT_CONTROL_EVENT,
FIRE_EVENT,
EXPLOSION_EVENT,
START_PROJECTILE_EVENT,
UPDATE_PROJECTILE_TARGET_EVENT,
REMOVE_PROJECTILE_ENTITY_EVENT,
BREAK_PROJECTILE_TARGET_LOCK_EVENT,
ALTER_WANTED_LEVEL_EVENT,
CHANGE_RADIO_STATION_EVENT,
RAGDOLL_REQUEST_EVENT,
PLAYER_TAUNT_EVENT,
PLAYER_CARD_STAT_EVENT,
DOOR_BREAK_EVENT,
SCRIPTED_GAME_EVENT,
REMOTE_SCRIPT_INFO_EVENT,
REMOTE_SCRIPT_LEAVE_EVENT,
MARK_AS_NO_LONGER_NEEDED_EVENT,
CONVERT_TO_SCRIPT_ENTITY_EVENT,
SCRIPT_WORLD_STATE_EVENT,
CLEAR_AREA_EVENT,
CLEAR_RECTANGLE_AREA_EVENT,
NETWORK_REQUEST_SYNCED_SCENE_EVENT,
NETWORK_START_SYNCED_SCENE_EVENT,
NETWORK_STOP_SYNCED_SCENE_EVENT,
NETWORK_UPDATE_SYNCED_SCENE_EVENT,
INCIDENT_ENTITY_EVENT,
GIVE_PED_SCRIPTED_TASK_EVENT,
GIVE_PED_SEQUENCE_TASK_EVENT,
NETWORK_CLEAR_PED_TASKS_EVENT,
NETWORK_START_PED_ARREST_EVENT,
NETWORK_START_PED_UNCUFF_EVENT,
NETWORK_SOUND_CAR_HORN_EVENT,
NETWORK_ENTITY_AREA_STATUS_EVENT,
NETWORK_GARAGE_OCCUPIED_STATUS_EVENT,
PED_CONVERSATION_LINE_EVENT,
SCRIPT_ENTITY_STATE_CHANGE_EVENT,
NETWORK_PLAY_SOUND_EVENT,
NETWORK_STOP_SOUND_EVENT,
NETWORK_PLAY_AIRDEFENSE_FIRE_EVENT,
NETWORK_BANK_REQUEST_EVENT,
NETWORK_AUDIO_BARK_EVENT,
REQUEST_DOOR_EVENT,
NETWORK_TRAIN_REPORT_EVENT,
NETWORK_TRAIN_REQUEST_EVENT,
NETWORK_INCREMENT_STAT_EVENT,
MODIFY_VEHICLE_LOCK_WORD_STATE_DATA,
MODIFY_PTFX_WORD_STATE_DATA_SCRIPTED_EVOLVE_EVENT,
REQUEST_PHONE_EXPLOSION_EVENT,
REQUEST_DETACHMENT_EVENT,
KICK_VOTES_EVENT,
GIVE_PICKUP_REWARDS_EVENT,
BLOW_UP_VEHICLE_EVENT,
NETWORK_SPECIAL_FIRE_EQUIPPED_WEAPON,
NETWORK_RESPONDED_TO_THREAT_EVENT,
NETWORK_SHOUT_TARGET_POSITION,
VOICE_DRIVEN_MOUTH_MOVEMENT_FINISHED_EVENT,
PICKUP_DESTROYED_EVENT,
UPDATE_PLAYER_SCARS_EVENT,
NETWORK_CHECK_EXE_SIZE_EVENT,
NETWORK_PTFX_EVENT,
NETWORK_PED_SEEN_DEAD_PED_EVENT,
REMOVE_STICKY_BOMB_EVENT,
NETWORK_CHECK_CODE_CRCS_EVENT,
INFORM_SILENCED_GUNSHOT_EVENT,
PED_PLAY_PAIN_EVENT,
CACHE_PLAYER_HEAD_BLEND_DATA_EVENT,
REMOVE_PED_FROM_PEDGROUP_EVENT,
REPORT_MYSELF_EVENT,
REPORT_CASH_SPAWN_EVENT,
ACTIVATE_VEHICLE_SPECIAL_ABILITY_EVENT,
BLOCK_WEAPON_SELECTION,
NETWORK_CHECK_CATALOG_CRC
};
virtual ~netGameEvent() = default;
virtual const char* GetName() = 0;
virtual bool IsInScope(netPlayer* player) = 0;
virtual bool TimeToResend(uint32_t time) = 0;
virtual bool CanChangeScope() = 0;
virtual void PrepareData(datBitBuffer* buffer, netPlayer* source_player, netPlayer* target_player) {};
virtual void HandleData(datBitBuffer* buffer, netPlayer* source_player, netPlayer* target_player) {};
virtual bool Decide(netPlayer* source_player, netPlayer* target_player) = 0;
virtual void PrepareReply(datBitBuffer* buffer, netPlayer* reply_player) {};
virtual void HandleReply(datBitBuffer* buffer, netPlayer* souce_player) {};
virtual void PrepareExtraData(datBitBuffer* buffer, bool is_reply, netPlayer* player, netPlayer* player2) {};
virtual void HandleExtraData(datBitBuffer* buffer, bool is_reply, netPlayer* player, netPlayer* player2) {};
private:
virtual void unk_0x60() {};
virtual void unk_0x68() {};
virtual void unk_0x70() {};
virtual void unk_0x78() {};
public:
virtual bool operator==(netGameEvent const& other) = 0;
virtual bool operator!=(netGameEvent const& other) = 0;
virtual bool MustPersist() = 0;
virtual bool MustPersistWhenOutOfScope() = 0;
virtual bool HasTimedOut() = 0;
public:
Type m_Type; // 0x08
bool m_RequiresReply; // 0x0A
private:
char m_padding1[0x05]; // 0x0B
public:
netPlayer* m_SourcePlayer; // 0x10
netPlayer* m_TargetPlayer; // 0x18
uint32_t m_ResendTime; // 0x20
private:
uint16_t m_0x24; // 0x24
uint8_t m_0x26; // 0x26
uint8_t m_0x27; // 0x27
uint32_t m_0x28; // 0x28
};
static_assert(sizeof(rage::netGameEvent) == 0x30);
}
class CScriptedGameEvent // : public rage::netGameEvent
{
public:
bool Deserialize(rage::datBitBuffer& buffer);
char m_padding[0x40]; // 0x30
int64_t m_Args[54]; // 0x70
uint32_t m_Bitset; // 0x220
uint32_t m_ArgsSize; // 0x224
};
class CNetworkIncrementStatEvent
{
public:
void Deserialize(rage::datBitBuffer& buffer);
uint32_t m_Stat; // 0x30
uint32_t m_Amount; // 0x34
};
class CDoorBreakEvent
{
public:
void Deserialize(rage::datBitBuffer& buffer);
uint16_t m_VehicleId; // 0x30
uint8_t m_DoorId; // 0x32
};
class CPlaySoundEvent
{
public:
void Deserialize(rage::datBitBuffer& buffer);
bool m_IsEntity; // 0x30
uint16_t m_EntityId; // 0x32
rage::fvector3 m_Position; // 0x40
uint32_t m_RefHash; // 0x50
uint32_t m_SoundHash; // 0x54
uint8_t m_SoundId; // 0x58
CGameScriptId m_ScriptId; // 0x60
int m_0xA0; // 0xA0
};
class CWeaponDamageEvent
{
public:
void Deserialize(rage::datBitBuffer& buffer);
rage::fvector3 m_LocalPos; // 0x30
rage::fvector3 m_ImpactDir; // 0x40
uint32_t m_DamageFlags; // 0x50
uint32_t m_WeaponType; // 0x54
uint32_t m_WeaponDamage; // 0x58
uint8_t m_0x5C; // 0x5C
uint32_t m_0x60; // 0x60
uint32_t m_DamageTime; // 0x64
uint32_t m_ActionResultName; // 0x68
uint32_t m_0x6C; // 0x6C
int m_HitComponent; // 0x70
uint16_t m_0x74; // 0x74
int16_t m_0x76; // 0x76
uint16_t m_ActionResultId; // 0x78
uint16_t m_ParentGlobalId; // 0x7A Source entity?
uint16_t m_HitGlobalId; // 0x7C Target entity?
uint8_t m_TyreIndex; // 0x7E
uint8_t m_SuspensionIndex; // 0x7F
uint8_t m_DamageType; // 0x80
bool m_HasImpactDir; // 0x81
bool m_HitEntityWeapon; // 0x82
bool m_HitWeaponAmmoAttachment; // 0x83
bool m_Silenced; // 0x84
bool m_WillKill; // 0x85
bool m_0x86; // 0x86
bool m_0x87; // 0x87
bool m_OverrideDefaultDamage; // 0x88
bool m_0x89; // 0x89
bool m_0x8A; // 0x8A
bool m_IsNetTargetPos; // 0x8B
bool m_0x8C; // 0x8C
uint32_t m_Time; // 0x90
uint8_t m_0x94; // 0x94
};
class CActivateVehicleSpecialAbilityEvent
{
public:
void Deserialize(rage::datBitBuffer& buffer);
uint16_t m_VehicleId; // 0x30
uint32_t m_AbilityType; // 0x34
uint32_t m_Time; // 0x38
};
enum class ExplosionType;
class CExplosionEvent
{
public:
void Deserialize(rage::datBitBuffer& buffer);
struct
{
ExplosionType m_ExplosionType; // 0x30
rage::fvector3 m_Position; // 0x40
uint64_t m_0x50; // 0x50
uint64_t m_0x58; // 0x58
uint64_t m_0x60; // 0x60
uint32_t m_0x68; // 0x68
float m_DamageScale; // 0x6C
uint32_t m_0x70; // 0x70
float m_CameraShake; // 0x74
float m_0x78; // 0x78
bool m_IsAudible; // 0x7C
bool m_IsInvisible; // 0x7D
bool m_0x7E; // 0x7E
rage::fvector3 m_0x80; // 0x80
uint64_t m_0x90; // 0x90
int m_0x98; // 0x98
int m_0x9C; // 0x9C
uint32_t m_0xA0; // 0xA0
uint32_t m_0xA4; // 0xA4
uint32_t m_InteriorIndex; // 0xA8
uint64_t m_0xB0; // 0xB0
uint8_t m_0xB8; // 0xB8
uint16_t m_0xBA; // 0xBA
bool m_0xBC; // 0xBC
bool m_0xBD; // 0xBD
bool m_0xBE; // 0xBE
bool m_0xBF; // 0xBF
bool m_0xC0; // 0xC0
bool m_AddOwnedExplosion; // 0xC1
bool m_Expected; // 0xC2 -- for telemetry
uint32_t m_ScriptHash; // 0xC4 -- for telemetry
uint32_t m_ProgramCounter; // 0xC8 -- for telemetry
};
uint16_t m_TargetEntity; // 0xD0
uint16_t m_TargetEnt2; // 0xD2
uint16_t m_OwnerNetId; // 0xD4
uint16_t m_UnkNetId; // 0xD6
uint8_t m_0xD8; // 0xD8
uint16_t m_0xDA; // 0xDA
rage::fvector3 m_PositionUnk; // 0xE0
bool m_0xF0; // 0xF0
bool m_0xF1; // 0xF1
bool m_0xF2; // 0xF2
bool m_HasTargetEnt2; // 0xF3
bool m_0xF4; // 0xF4
uint32_t m_Time; // 0xF8
};
class CScriptEntityStateChangeEvent
{
public:
enum class Type : uint32_t
{
BlockingOfNonTemporaryEvents,
SettingOfPedRelationshipGroupHash,
SettingOfDriveTaskCruiseSpeed,
SettingOfLookAtEntity,
SettingOfPlaneMinHeightAboveTerrain,
SetPedRagdollBlockFlag,
SettingOfTaskVehicleTempAction,
SetPedFacialIdleAnimOverride,
SetVehicleLockState,
SetVehicleExclusiveDriver
};
};
class CScriptWorldStateEvent
{
public:
enum class Type : uint32_t
{
CarGen,
EntityArea,
PopGroupOverride,
PopMultiplierArea,
PTFX,
RoadNode,
Rope,
ScenarioBlockingArea,
VehiclePlayerLocking
};
};
class CUpdateFxnEvent
{
public:
void Deserialize(rage::datBitBuffer& buffer);
uint32_t m_0x30; // 0x30
uint32_t m_0x34; // 0x34
};
@@ -1,45 +1,45 @@
#pragma once
#include "types/rage/vector.hpp"
#include "types/network/sync/CProjectBaseSyncDataNode.hpp"
#include "types/rage/vector.hpp"
struct ObjectCreationTelemetry
{
uint32_t unk_0000; //0x0000 "et"
uint32_t m_ScriptHash; //0x0004 "es"
uint32_t unk_0008; //0x0008 "ep"
bool unk_000C; //0x000C "ec"
bool m_HasData; //0x000D
};
// TODO: verify if this is right
class CObjectCreationDataNode : CProjectBaseSyncDataNode
{
public:
uint32_t unk_00C0; //0x00C0
uint32_t unk_00C4; //0x00C4
uint32_t unk_00C8; //0x00C8
bool unk_00CC;
bool unk_00CD;
uint16_t unk_00D0; //0x00D0
char pad_0xC2[14]; //0x00D2
rage::fvector4 m_ObjectOrientation; //0x00E0
char pad_00E0[30]; //0x00F0
rage::fvector3 m_ObjectPosition; //0x0110
char pad_010C[4]; //0x011C
rage::fvector3 m_DummyPosition; //0x011E
char pad_011A[16]; //0x012C
rage::fvector3 m_ScriptGrabPosition; //0x0140
char pad_013C[8]; //0x013C
float m_ScriptGrabRadius; //0x0148
uint32_t m_CreatedBy; //0x014C
uint32_t m_Model; //0x0150
uint32_t m_FragGroupIndex; //0x0154
uint32_t m_OwnershipToken; //0x0158
uint32_t unk_015C; //0x015C
// everything after this is probably wrong
bool m_NoReassign; //0x0160
bool unk_0161; //0x0161
bool m_PlayerWantsControl; //0x0162
bool m_HasInitPhysics; //0x0163
bool m_ScriptGrabbedFromWorld; //0x0164
bool m_IsFragObject; //0x0165
bool m_IsBroken; //0x0166
bool m_HasExploded; //0x0167
bool m_KeepRegistered; //0x0168
bool unk_0169; //0x0169
bool unk_016A; //0x016A
bool unk_016B; //0x016B
}; //Size: 0x016C
ObjectCreationTelemetry m_TelemetryData; //0x00C0 -- netObject + 0x270
uint16_t unk_00D0; //0x00D0
char pad_0xC2[14]; //0x00D2
rage::fvector4 m_ObjectOrientation[4]; //0x00E0
rage::fvector3 m_DummyPosition; //0x0120
rage::fvector3 m_ObjectPosition; //0x0130
rage::fvector3 m_ScriptGrabPosition; //0x0140
char pad_0150[8]; //0x0150
float m_ScriptGrabRadius; //0x0158
uint32_t m_CreatedBy; //0x015C
uint32_t m_Model; //0x0160
uint32_t m_FragGroupIndex; //0x0164
uint32_t m_OwnershipToken; //0x0168
uint32_t unk_016C; //0x016C
bool m_NoReassign; //0x0170
bool unk_0171; //0x0171
bool m_PlayerWantsControl; //0x0172
bool m_HasInitPhysics; //0x0173
bool m_ScriptGrabbedFromWorld; //0x0174
bool m_IsFragObject; //0x0175
bool m_IsBroken; //0x0176
bool unk_0177; //0x0177
bool m_HasExploded; //0x0178
bool m_KeepRegistered; //0x0179
bool unk_017A; //0x017A
bool unk_017B; //0x017B
bool unk_017C; //0x017C
}; //Size: 0x0180
static_assert(sizeof(CObjectCreationDataNode) == 0x180);
@@ -7,7 +7,6 @@ class CPedAttachDataNode : CSyncDataNodeInfrequent
{
public:
rage::fvector3 m_Offset; //0x00C0
char pad_00CC[4]; //0x00CC
rage::fvector4 m_Orientation; //0x00D0
uint16_t m_AttachedTo; //0x00E0
uint16_t m_AttachmentBone; //0x00E2
@@ -17,4 +16,4 @@ public:
bool m_IsAttached; //0x00F0
bool unk_00F1; //0x00F1
};
static_assert(sizeof(CPedAttachDataNode) == 0xF8);
static_assert(sizeof(CPedAttachDataNode) == 0x100);
@@ -23,5 +23,5 @@ public:
bool unk_0114; //0x0114
bool unk_0115; //0x0115
bool m_IsCargoVehicle; //0x0116
}; //Size: 0x0118
static_assert(sizeof(CPhysicalAttachDataNode) == 0x118);
}; //Size: 0x0120
static_assert(sizeof(CPhysicalAttachDataNode) == 0x120);
@@ -1,20 +1,20 @@
#pragma once
#include "types/rage/vector.hpp"
#include "types/network/sync/CProjectBaseSyncDataNode.hpp"
#include "types/script/CGameScriptObjInfo.hpp"
class CPickupPlacementCreationDataNode : CProjectBaseSyncDataNode
{
public:
bool m_HasPickupData; //0x00C0
char pad_00C1[15]; //0x00C1
rage::fvector3 m_PickupPos; //0x00D0
rage::fvector4 m_PickupOrientation; //0x00E0
uint32_t m_PickupType; //0x00F0
uint32_t m_PickupFlags; //0x00F4
uint32_t m_Amount; //0x00F8
uint32_t m_CustomModel; //0x00FC
uint32_t m_CustomRegenerationTime; //0x0100
uint32_t m_TeamPermits; //0x0104
uint64_t *unk_struct_0108; //0x0108
}; //Size: 0x0110
static_assert(sizeof(CPickupPlacementCreationDataNode) == 0x110);
bool m_HasPickupData; //0x00C0
rage::fvector3 m_PickupPos; //0x00D0
rage::fvector4 m_PickupOrientation; //0x00E0
uint32_t m_PickupType; //0x00F0
uint32_t m_PickupFlags; //0x00F4
uint32_t m_Amount; //0x00F8
uint32_t m_CustomModel; //0x00FC
uint32_t m_CustomRegenerationTime; //0x0100
uint32_t m_TeamPermits; //0x0104
CGameScriptObjInfo m_ScriptObjectInfo; //0x0108
}; //Size: 0x0160
static_assert(sizeof(CPickupPlacementCreationDataNode) == 0x160);
@@ -17,7 +17,7 @@ public:
uint16_t m_EntityStandingOn; //0x00D0
char pad_00D2[12]; //0x00D2
rage::fvector3 m_StandingOnEntityOffset; //0x00E0
char pad_00EC[4]; //0x00EC
char pad_00F0[4]; //0x00F0
uint32_t m_StealthNoise; //0x00F4
}; //Size: 0x00F8
static_assert(sizeof(CPlayerSectorPosNode) == 0xF8);
}; //Size: 0x0100
static_assert(sizeof(CPlayerSectorPosNode) == 0x100);
@@ -10,7 +10,7 @@ public:
int16_t m_Occupants[16];
char pad[16];
bool m_OverridePosition;
alignas(16) rage::fvector3 m_Position;
rage::fvector3 m_Position;
std::int32_t m_VelocityX;
std::int32_t m_VelocityY;
std::int32_t m_VelocityZ;
+70
View File
@@ -1,4 +1,6 @@
#pragma once
#include "vector.hpp"
#include <cstdint>
namespace rage
@@ -449,6 +451,74 @@ namespace rage
}
}
float ReadFloat(int size, float divisor)
{
int integer = Read<int>(size);
float max = (1 << size) - 1;
return ((float)integer / max) * divisor;
}
void WriteFloat(int size, float divisor, float value)
{
float max = (1 << size) - 1;
int integer = (int)((value / divisor) * max);
Write<int>(integer, size);
}
float ReadSignedFloat(int size, float divisor)
{
int integer = Read<int>(size, true);
float max = (1 << (size - 1)) - 1;
return ((float)integer / max) * divisor;
}
void WriteSignedFloat(int size, float divisor, float value)
{
float max = (1 << (size - 1)) - 1;
int integer = (int)((value / divisor) * max);
Write<int>(integer, size, true);
}
rage::fvector3 ReadPosition(int size)
{
rage::fvector3 pos;
pos.x = ReadSignedFloat(size, 27648.0f);
pos.y = ReadSignedFloat(size, 27648.0f);
pos.z = ReadFloat(size, 4416.0f) - 1700.0f;
return pos;
}
void WritePosition(int size, rage::fvector3& pos)
{
WriteSignedFloat(size, 27648.0f, pos.x);
WriteSignedFloat(size, 27648.0f, pos.y);
WriteFloat(size, 4416.0f, pos.z + 1700.0f);
}
rage::fvector3 ReadVector3(int size, float divisor)
{
rage::fvector3 vec;
vec.x = ReadSignedFloat(size, divisor);
vec.y = ReadSignedFloat(size, divisor);
vec.z = ReadSignedFloat(size, divisor);
return vec;
}
void WriteVector3(int size, float divisor, rage::fvector3& vec)
{
WriteSignedFloat(size, divisor, vec.x);
WriteSignedFloat(size, divisor, vec.y);
WriteSignedFloat(size, divisor, vec.z);
}
public:
void* m_Data; //0x0000
uint32_t m_BitOffset; //0x0008
+1 -3
View File
@@ -24,13 +24,11 @@ namespace rage
};
// atVector<float, 3>?
class vector3
class alignas(16) vector3
{
public:
float x, y, z;
private:
int _PAD; // because alignof doesn't work
public:
constexpr vector3(float x, float y, float z) :
x(x),
+28
View File
@@ -0,0 +1,28 @@
#include "CGameScriptId.hpp"
#include "types/rage/datBitBuffer.hpp"
void CGameScriptId::Deserialize(rage::datBitBuffer& buffer)
{
m_Hash = buffer.Read<uint32_t>(32);
m_Timestamp = buffer.Read<uint32_t>(32);
bool has_position_hash = buffer.Read<bool>(1);
if (has_position_hash)
{
m_PositionHash = buffer.Read<uint32_t>(32);
}
else
{
m_PositionHash = 0;
}
bool has_instance_id = buffer.Read<bool>(1);
if (has_instance_id)
{
m_InstanceId = buffer.Read<int32_t>(8);
}
else
{
m_InstanceId = -1;
}
}
+2
View File
@@ -4,6 +4,8 @@
class CGameScriptId : public rage::scriptId
{
public:
void Deserialize(rage::datBitBuffer& buffer);
std::int32_t m_Timestamp; // 0x30
std::int32_t m_PositionHash; // 0x34
std::int32_t m_InstanceId; // 0x38