From 01b0a46b5a826ce22f10eeda526f65aebcdc023f Mon Sep 17 00:00:00 2001 From: Mr-X-GTA <110748953+Mr-X-GTA@users.noreply.github.com> Date: Sat, 29 Mar 2025 05:05:12 +0100 Subject: [PATCH] feat(net_events): net event protections (#45) --- src/game/gta/Entity.cpp | 8 + src/game/gta/Entity.hpp | 1 + src/game/hooks/Hooks.hpp | 5 +- src/game/hooks/Network/HandleNetGameEvent.cpp | 297 ++++++++++++++- .../hooks/Network/HandleScriptedGameEvent.cpp | 17 +- src/game/hooks/Network/ReceiveNetMessage.cpp | 2 +- src/types/network/NetEventType.hpp | 92 ----- src/types/network/netGameEvent.cpp | 230 ++++++++++++ src/types/network/netGameEvent.hpp | 343 ++++++++++++++++++ .../nodes/object/CObjectCreationDataNode.hpp | 76 ++-- .../sync/nodes/ped/CPedAttachDataNode.hpp | 3 +- .../physical/CPhysicalAttachDataNode.hpp | 4 +- .../CPickupPlacementCreationDataNode.hpp | 26 +- .../nodes/player/CPlayerSectorPosNode.hpp | 6 +- .../CVehicleProximityMigrationDataNode.hpp | 2 +- src/types/rage/datBitBuffer.hpp | 70 ++++ src/types/rage/vector.hpp | 4 +- src/types/script/CGameScriptId.cpp | 28 ++ src/types/script/CGameScriptId.hpp | 2 + 19 files changed, 1039 insertions(+), 177 deletions(-) delete mode 100644 src/types/network/NetEventType.hpp create mode 100644 src/types/network/netGameEvent.cpp create mode 100644 src/types/network/netGameEvent.hpp create mode 100644 src/types/script/CGameScriptId.cpp diff --git a/src/game/gta/Entity.cpp b/src/game/gta/Entity.cpp index 3f069c8..201a0a8 100644 --- a/src/game/gta/Entity.cpp +++ b/src/game/gta/Entity.cpp @@ -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()) diff --git a/src/game/gta/Entity.hpp b/src/game/gta/Entity.hpp index 0a307b3..298fba1 100644 --- a/src/game/gta/Entity.hpp +++ b/src/game/gta/Entity.hpp @@ -114,6 +114,7 @@ namespace YimMenu // networking bool IsNetworked(); + bool IsRemote(); bool HasControl(); rage::netObject* GetNetworkObject(); diff --git a/src/game/hooks/Hooks.hpp b/src/game/hooks/Hooks.hpp index 1916eb6..76ca93a 100644 --- a/src/game/hooks/Hooks.hpp +++ b/src/game/hooks/Hooks.hpp @@ -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 diff --git a/src/game/hooks/Network/HandleNetGameEvent.cpp b/src/game/hooks/Network/HandleNetGameEvent.cpp index 04c20d6..90d978a 100644 --- a/src/game/hooks/Network/HandleNetGameEvent.cpp +++ b/src/game/hooks/Network/HandleNetGameEvent.cpp @@ -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(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(event_id)) + if (*(int16_t*)&event.m_InteriorIndex < -1) { - case NetEventType::WEAPON_DAMAGE_EVENT: - { - uint8_t damage_type = buffer.Read(2); - uint32_t weapon_type = buffer.Read(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(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(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(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(4); + buffer.Read(1); + CGameScriptId id; + id.Deserialize(buffer); + + if (type == CScriptWorldStateEvent::Type::PopGroupOverride) + { + int pop_schedule = buffer.Read(8); + int pop_group = buffer.Read(32); + int percentage = buffer.Read(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(13); + auto type = buffer.Read(4); + uint32_t unk = buffer.Read(32); + + if (type == CScriptEntityStateChangeEvent::Type::SettingOfTaskVehicleTempAction) + { + uint16_t veh_id = buffer.Read(13); + uint32_t action = buffer.Read(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); } } \ No newline at end of file diff --git a/src/game/hooks/Network/HandleScriptedGameEvent.cpp b/src/game/hooks/Network/HandleScriptedGameEvent.cpp index b1efb32..2986bb2 100644 --- a/src/game/hooks/Network/HandleScriptedGameEvent.cpp +++ b/src/game/hooks/Network/HandleScriptedGameEvent.cpp @@ -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(args); + SCRIPT_EVENT* script_event = reinterpret_cast(event.m_Args); switch (static_cast(script_event->GetEventIndex())) { @@ -15,7 +17,7 @@ namespace YimMenu::Hooks { SCRIPT_EVENT_BOUNTY* bounty = static_cast(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; } diff --git a/src/game/hooks/Network/ReceiveNetMessage.cpp b/src/game/hooks/Network/ReceiveNetMessage.cpp index 49e47df..3ec6d2d 100644 --- a/src/game/hooks/Network/ReceiveNetMessage.cpp +++ b/src/game/hooks/Network/ReceiveNetMessage.cpp @@ -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; } diff --git a/src/types/network/NetEventType.hpp b/src/types/network/NetEventType.hpp deleted file mode 100644 index 0841e19..0000000 --- a/src/types/network/NetEventType.hpp +++ /dev/null @@ -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 -}; \ No newline at end of file diff --git a/src/types/network/netGameEvent.cpp b/src/types/network/netGameEvent.cpp new file mode 100644 index 0000000..fbaf743 --- /dev/null +++ b/src/types/network/netGameEvent.cpp @@ -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(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(32); + m_Amount = buffer.Read(32, true); +} + +void CDoorBreakEvent::Deserialize(rage::datBitBuffer& buffer) +{ + m_VehicleId = buffer.Read(13); + m_DoorId = buffer.Read(3); +} + +void CPlaySoundEvent::Deserialize(rage::datBitBuffer& buffer) +{ + m_IsEntity = buffer.Read(1); + + if (m_IsEntity) + { + m_EntityId = buffer.Read(13); + } + else + { + m_Position = buffer.ReadPosition(19); + } + + bool has_ref = buffer.Read(1); + if (has_ref) + { + m_RefHash = buffer.Read(32); + } + else + { + m_RefHash = 0; + } + + m_SoundHash = buffer.Read(32); + m_SoundId = buffer.Read(8); + + bool has_script_hash = buffer.Read(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(2); + m_WeaponType = buffer.Read(32); + m_OverrideDefaultDamage = buffer.Read(1); + m_HitEntityWeapon = buffer.Read(1); + m_HitWeaponAmmoAttachment = buffer.Read(1); + m_Silenced = buffer.Read(1); + m_DamageFlags = buffer.Read(25); + + bool hasActionResult = buffer.Read(1); + if (hasActionResult) + { + m_ActionResultName = buffer.Read(32); + m_ActionResultId = buffer.Read(16); + m_0x6C = buffer.Read(32); + } + + if (m_OverrideDefaultDamage) + { + m_WeaponDamage = buffer.Read(17); + } + else + { + m_WeaponDamage = 0; + } + + bool _f92 = buffer.Read(1); + if (_f92) + { + m_0x5C = buffer.Read(5); + } + + m_IsNetTargetPos = buffer.Read(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(32); + m_WillKill = buffer.Read(1); + + if (hasActionResult) + { + m_HitGlobalId = buffer.Read(13); + } + else + { + m_HitGlobalId = 0; + } + + bool f112 = buffer.Read(1); + if (f112) + { + m_0x74 = buffer.Read(16); + } + else + { + m_0x74 = buffer.Read(11); + } + } + else + { + m_ParentGlobalId = buffer.Read(13); + m_HitGlobalId = buffer.Read(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(1); + + if (hasVehicleData) + { + m_TyreIndex = buffer.Read(4); + m_SuspensionIndex = buffer.Read(4); + } + } + } + else + { + m_HitComponent = buffer.Read(5); + } + + m_0x89 = buffer.Read(1); + m_HasImpactDir = buffer.Read(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(13); + m_AbilityType = buffer.Read(3); +} + +void CExplosionEvent::Deserialize(rage::datBitBuffer& buffer) +{ + m_0xBA = buffer.Read(16); + m_TargetEntity = buffer.Read(13); + m_OwnerNetId = buffer.Read(13); + m_UnkNetId = buffer.Read(13); + m_ExplosionType = buffer.Read(8, true); + m_DamageScale = buffer.ReadFloat(8, 1.0f); + m_Position = buffer.ReadPosition(22); + m_0xF2 = buffer.Read(1); + m_0x68 = buffer.Read(16); + m_CameraShake = buffer.ReadSignedFloat(8, 1.0f); + m_IsAudible = buffer.Read(1); + m_0xBD = buffer.Read(1); + m_IsInvisible = buffer.Read(1); + m_0x7E = buffer.Read(1); + m_AddOwnedExplosion = buffer.Read(1); + m_0xF1 = buffer.Read(1); + m_HasTargetEnt2 = buffer.Read(1); + m_TargetEnt2 = buffer.Read(13); + m_0x80 = buffer.ReadVector3(16, 1.1f); + m_0xBE = buffer.Read(1); + m_0xBF = buffer.Read(1); + m_0xA4 = buffer.Read(32); + m_InteriorIndex = buffer.Read(32); + + if (m_0xF2) + { + m_PositionUnk = buffer.ReadPosition(31); + } + + m_0xF0 = buffer.Read(1); + + if (m_AddOwnedExplosion) + { + m_ScriptHash = buffer.Read(32); + m_ProgramCounter = buffer.Read(32); + } + + if (m_0xF0) + { + m_0xDA = buffer.Read(16); + + if (m_0xBF) + { + m_0xD8 = buffer.Read(8); + } + } +} + +void CUpdateFxnEvent::Deserialize(rage::datBitBuffer& buffer) +{ + m_0x30 = buffer.Read(32); + m_0x34 = buffer.Read(32); +} \ No newline at end of file diff --git a/src/types/network/netGameEvent.hpp b/src/types/network/netGameEvent.hpp new file mode 100644 index 0000000..eb18b78 --- /dev/null +++ b/src/types/network/netGameEvent.hpp @@ -0,0 +1,343 @@ +#pragma once +#include +#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 +}; \ No newline at end of file diff --git a/src/types/network/sync/nodes/object/CObjectCreationDataNode.hpp b/src/types/network/sync/nodes/object/CObjectCreationDataNode.hpp index 7657b8e..5b4c27c 100644 --- a/src/types/network/sync/nodes/object/CObjectCreationDataNode.hpp +++ b/src/types/network/sync/nodes/object/CObjectCreationDataNode.hpp @@ -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); \ No newline at end of file diff --git a/src/types/network/sync/nodes/ped/CPedAttachDataNode.hpp b/src/types/network/sync/nodes/ped/CPedAttachDataNode.hpp index 0247dc4..24a5b3f 100644 --- a/src/types/network/sync/nodes/ped/CPedAttachDataNode.hpp +++ b/src/types/network/sync/nodes/ped/CPedAttachDataNode.hpp @@ -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); \ No newline at end of file +static_assert(sizeof(CPedAttachDataNode) == 0x100); \ No newline at end of file diff --git a/src/types/network/sync/nodes/physical/CPhysicalAttachDataNode.hpp b/src/types/network/sync/nodes/physical/CPhysicalAttachDataNode.hpp index 4cceb53..0190154 100644 --- a/src/types/network/sync/nodes/physical/CPhysicalAttachDataNode.hpp +++ b/src/types/network/sync/nodes/physical/CPhysicalAttachDataNode.hpp @@ -23,5 +23,5 @@ public: bool unk_0114; //0x0114 bool unk_0115; //0x0115 bool m_IsCargoVehicle; //0x0116 -}; //Size: 0x0118 -static_assert(sizeof(CPhysicalAttachDataNode) == 0x118); \ No newline at end of file +}; //Size: 0x0120 +static_assert(sizeof(CPhysicalAttachDataNode) == 0x120); \ No newline at end of file diff --git a/src/types/network/sync/nodes/pickup_placement/CPickupPlacementCreationDataNode.hpp b/src/types/network/sync/nodes/pickup_placement/CPickupPlacementCreationDataNode.hpp index 085414e..a275665 100644 --- a/src/types/network/sync/nodes/pickup_placement/CPickupPlacementCreationDataNode.hpp +++ b/src/types/network/sync/nodes/pickup_placement/CPickupPlacementCreationDataNode.hpp @@ -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); diff --git a/src/types/network/sync/nodes/player/CPlayerSectorPosNode.hpp b/src/types/network/sync/nodes/player/CPlayerSectorPosNode.hpp index efdcdf4..39c3bbf 100644 --- a/src/types/network/sync/nodes/player/CPlayerSectorPosNode.hpp +++ b/src/types/network/sync/nodes/player/CPlayerSectorPosNode.hpp @@ -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); \ No newline at end of file +}; //Size: 0x0100 +static_assert(sizeof(CPlayerSectorPosNode) == 0x100); \ No newline at end of file diff --git a/src/types/network/sync/nodes/vehicle/CVehicleProximityMigrationDataNode.hpp b/src/types/network/sync/nodes/vehicle/CVehicleProximityMigrationDataNode.hpp index fae5cf6..c353f59 100644 --- a/src/types/network/sync/nodes/vehicle/CVehicleProximityMigrationDataNode.hpp +++ b/src/types/network/sync/nodes/vehicle/CVehicleProximityMigrationDataNode.hpp @@ -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; diff --git a/src/types/rage/datBitBuffer.hpp b/src/types/rage/datBitBuffer.hpp index cbfea94..f7386bc 100644 --- a/src/types/rage/datBitBuffer.hpp +++ b/src/types/rage/datBitBuffer.hpp @@ -1,4 +1,6 @@ #pragma once +#include "vector.hpp" + #include namespace rage @@ -449,6 +451,74 @@ namespace rage } } + float ReadFloat(int size, float divisor) + { + int integer = Read(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(integer, size); + } + + float ReadSignedFloat(int size, float divisor) + { + int integer = Read(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(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 diff --git a/src/types/rage/vector.hpp b/src/types/rage/vector.hpp index a8c2edc..52dba1f 100644 --- a/src/types/rage/vector.hpp +++ b/src/types/rage/vector.hpp @@ -24,13 +24,11 @@ namespace rage }; // atVector? - 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), diff --git a/src/types/script/CGameScriptId.cpp b/src/types/script/CGameScriptId.cpp new file mode 100644 index 0000000..bc1dacd --- /dev/null +++ b/src/types/script/CGameScriptId.cpp @@ -0,0 +1,28 @@ +#include "CGameScriptId.hpp" +#include "types/rage/datBitBuffer.hpp" + +void CGameScriptId::Deserialize(rage::datBitBuffer& buffer) +{ + m_Hash = buffer.Read(32); + m_Timestamp = buffer.Read(32); + + bool has_position_hash = buffer.Read(1); + if (has_position_hash) + { + m_PositionHash = buffer.Read(32); + } + else + { + m_PositionHash = 0; + } + + bool has_instance_id = buffer.Read(1); + if (has_instance_id) + { + m_InstanceId = buffer.Read(8); + } + else + { + m_InstanceId = -1; + } +} \ No newline at end of file diff --git a/src/types/script/CGameScriptId.hpp b/src/types/script/CGameScriptId.hpp index 16f5569..0f48d1c 100644 --- a/src/types/script/CGameScriptId.hpp +++ b/src/types/script/CGameScriptId.hpp @@ -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