Skip to content

Commit 900af4f

Browse files
committed
fix(Entity): fix assertion errors
- Fix assertion error in the `Entity` module's constructor. - Add missing fields in the `CEntity` class.
1 parent 6bd86b9 commit 900af4f

6 files changed

Lines changed: 73 additions & 50 deletions

File tree

SSV2/includes/classes/gta/CEntity.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ local fwDrawData = require("includes.classes.gta.fwDrawData")
2222
---@class CEntity: ClassMeta<CEntity>
2323
---@field protected m_ptr pointer
2424
---@field m_model_info pointer<CBaseModelInfo> -- 0x0020
25-
---@field m_entity_type uint8_t
2625
---@field m_model_type pointer<eModelType> CBaseModelInfo + 0x009D
26+
---@field m_entity_type pointer<uint8_t>
2727
---@field m_flags pointer<uint32_t> `FLAG_ISVISIBLE = 1 << 0`
2828
---@field m_draw_data fwDrawData
2929
---@field m_transform_matrix pointer<fMatrix44>
@@ -50,11 +50,13 @@ function CEntity:init(entity)
5050
local instance = setmetatable({ m_ptr = ptr }, CEntity)
5151
instance.m_model_info = ptr:add(0x0020):deref()
5252
instance.m_model_type = instance.m_model_info:add(0x009D)
53+
instance.m_entity_type = ptr:add(0x0028)
5354
instance.m_flags = ptr:add(0x002D)
5455
instance.m_draw_data = fwDrawData(ptr:add(0x0048):deref())
5556
instance.m_transform_matrix = ptr:add(0x0060)
5657
instance.m_render_focus_distance = ptr:add(0x00A8)
5758
instance.m_shadow_flags = ptr:add(0x00B0)
59+
instance.m_damage_bits = ptr:add(0x0188)
5860
instance.m_hostility = ptr:add(0x018C)
5961
instance.m_health = ptr:add(0x0280)
6062
instance.m_max_health = ptr:add(0x0284)

SSV2/includes/classes/gta/CVehicle.lua

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,23 +68,23 @@ function CVehicle:init(vehicle)
6868

6969
local ptr = memory.handle_to_ptr(vehicle)
7070
instance.m_ptr = ptr
71-
instance.m_model_info = CVehicleModelInfo(ptr:add(0x20):deref())
72-
instance.m_vehicle_damage = ptr:add(0x0420)
73-
instance.m_handling_data = CHandlingData(ptr:add(0x0960):deref())
71+
instance.m_model_info = CVehicleModelInfo(ptr:add(0x0020):deref())
72+
instance.m_water_damage = ptr:add(0x00D8)
7473
instance.m_physics_fragments = phFragInst(ptr:add(0x0030):deref())
7574
instance.m_draw_data = CVehicleDrawData(ptr:add(0x0048):deref())
7675
instance.m_can_boost_jump = ptr:add(0x03A4)
76+
instance.m_vehicle_damage = ptr:add(0x0420)
7777
instance.m_velocity = ptr:add(0x07D0)
78-
instance.m_deform_god = ptr:add(0x096C)
7978
instance.m_is_targetable = ptr:add(0x0AEE)
80-
instance.m_door_lock_status = ptr:add(0x13D0)
81-
instance.m_water_damage = ptr:add(0x00D8)
8279
instance.m_next_gear = ptr:add(0x0880)
8380
instance.m_current_gear = ptr:add(0x0882)
8481
instance.m_top_gear = ptr:add(0x0886)
8582
instance.m_engine_health = ptr:add(0x0910)
83+
instance.m_handling_data = CHandlingData(ptr:add(0x0960):deref())
84+
instance.m_deform_god = ptr:add(0x096C)
8685
instance.m_steering_input = ptr:add(0x09D4)
8786
instance.m_current_steering = ptr:add(0x09DC)
87+
instance.m_door_lock_status = ptr:add(0x13D0)
8888

8989
local array_ptr = ptr:add(0x0C30)
9090
instance.m_wheels = atArray(array_ptr, CWheel)

SSV2/includes/modules/Entity.lua

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,29 +62,37 @@ function Entity:__eq(right)
6262
end
6363

6464
---@param handle number
65-
---@param opts? {expectedType?: eEntityType, noassert: boolean }
65+
---@param opts? { expectedType?: eEntityType, noassert?: boolean }
6666
---@return Entity
6767
function Entity.new(handle, opts)
68-
opts = opts or {}
69-
if not (opts.noassert and Game.IsScriptHandle(handle)) then
70-
error("Attempt to create an Entity instance from an invalid entity script handle", 2)
68+
opts = opts or {}
69+
handle = handle or 0
70+
if (not opts.noassert) then
71+
if (not Game.IsScriptHandle(handle)) then
72+
error("Attempt to create an Entity instance from an invalid entity script handle", 2)
73+
end
7174
end
7275

7376
local expectedType = opts.expectedType
74-
if (expectedType and ENTITY.GET_ENTITY_TYPE(handle) ~= expectedType) then
75-
local type_str = EnumToString(Enums.eEntityType, expectedType)
76-
error(_F("The handle provided does not match the expected entity type (%s).", type_str))
77+
if (expectedType) then
78+
if (ENTITY.GET_ENTITY_TYPE(handle) ~= expectedType) then
79+
local type_str = EnumToString(Enums.eEntityType, expectedType)
80+
error(_F("The handle provided does not match the expected entity type (%s).", type_str))
81+
end
7782
end
7883

7984
---@type Entity
80-
---@diagnostic disable-next-line
81-
local instance = setmetatable({}, Entity)
82-
instance.m_handle = handle
85+
---@diagnostic disable-next-line: param-type-mismatch
86+
local instance = setmetatable({ m_handle = handle }, Entity)
8387

8488
if (handle ~= 0) then
85-
instance.m_modelhash = Game.GetEntityModel(handle)
86-
instance.m_ptr = memory.handle_to_ptr(handle)
87-
instance.m_internal = instance:Resolve()
89+
ThreadManager:Run(function()
90+
---@diagnostic disable: invisible
91+
instance.m_modelhash = Game.GetEntityModel(handle)
92+
instance.m_ptr = memory.handle_to_ptr(handle)
93+
instance.m_internal = instance:Resolve()
94+
---@diagnostic enable: invisible
95+
end)
8896
end
8997

9098
return instance
@@ -169,10 +177,10 @@ function Entity:Resolve()
169177
end
170178

171179
-- **DO NOT REMOVE. THIS IS NOT USELESS CODE.**
172-
-- We have to do this because `Self` is static, it inherits from `Entity` but doesn't have a constructor
180+
-- We have to do this because `LocalPlayer` inherits from `Entity` but doesn't have a constructor
173181
-- and doesn't store handles or hashes as members (because they can change on player switch).
174182

175-
local hndl = self:GetHandle() -- This is overridden in `Self` to always invoke `PLAYER.PLAYER_PED_ID()`
183+
local hndl = self:GetHandle() -- This is overridden in `LocalPlayer` to always invoke `PLAYER.PLAYER_PED_ID()`
176184
local ent_type = Game.GetEntityType(hndl)
177185
if (ent_type == Enums.eEntityType.Ped) then
178186
self.m_internal = CPed(hndl)
@@ -185,6 +193,7 @@ function Entity:Resolve()
185193
return self.m_internal
186194
end
187195

196+
---@return nil
188197
function Entity:Destroy()
189198
self.m_handle = nil
190199
self.m_modelhash = nil

SSV2/includes/modules/HandlingEditor.lua

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,20 @@ end
8282
---@param obj HandlingObject
8383
---@return boolean
8484
function HandlingEditor:GetFlagDefault(obj)
85-
return Switch(obj.m_type) {
86-
[Enums.eHandlingEditorTypes.TYPE_HF] = self.m_pv:GetHandlingFlag(obj.m_flag),
87-
[Enums.eHandlingEditorTypes.TYPE_AF] = self.m_pv:GetAdvancedFlag(obj.m_flag),
88-
[Enums.eHandlingEditorTypes.TYPE_MIF] = self.m_pv:GetModelInfoFlag(obj.m_flag),
89-
default = false
90-
}
85+
local __type = obj.m_type
86+
if ((__type) == Enums.eHandlingEditorTypes.TYPE_HF) then
87+
return self.m_pv:GetHandlingFlag(obj.m_flag)
88+
end
89+
90+
if ((__type) == Enums.eHandlingEditorTypes.TYPE_AF) then
91+
return self.m_pv:GetAdvancedFlag(obj.m_flag)
92+
end
93+
94+
if ((__type) == Enums.eHandlingEditorTypes.TYPE_MIF) then
95+
return self.m_pv:GetModelInfoFlag(obj.m_flag)
96+
end
97+
98+
return false
9199
end
92100

93101
---@param gvarKey string

SSV2/includes/modules/LocalPlayer.lua

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -154,24 +154,28 @@ function LocalPlayer:GetCharacterName()
154154
end
155155

156156
function LocalPlayer:OnVehicleSwitch()
157-
if (self.m_vehicle:IsValid()) then
158-
self.m_vehicle:RestoreHeadlights()
159-
160-
self.m_last_vehicle = Vehicle(self.m_vehicle:GetHandle())
157+
local veh = self.m_vehicle
158+
if (veh:IsValid()) then
159+
veh:RestoreHeadlights()
160+
self.m_last_vehicle = Vehicle(veh:GetHandle())
161161
end
162162

163-
self.m_vehicle:Reset()
163+
veh:Reset()
164164
sleep(500)
165-
self.m_vehicle:Set(self:GetVehicleNative())
165+
veh:Set(self:GetVehicleNative())
166166
end
167167

168168
function LocalPlayer:OnVehicleExit()
169-
if (not self.m_last_vehicle or self.m_last_vehicle:GetHandle() ~= self.m_vehicle:GetHandle()) then
170-
self.m_last_vehicle = Vehicle(self.m_vehicle:GetHandle())
169+
local veh = self.m_vehicle
170+
if (not veh:IsValid()) then
171+
veh:Cleanup()
172+
return
171173
end
172174

173-
if (not self.m_vehicle:IsValid()) then
174-
self.m_vehicle:Cleanup()
175+
local prevHandle = veh:GetHandle()
176+
local lastVeh = self.m_last_vehicle
177+
if (prevHandle ~= 0 and (not lastVeh or lastVeh:GetHandle() ~= prevHandle)) then
178+
self.m_last_vehicle = Vehicle(prevHandle)
175179
end
176180
end
177181

SSV2/includes/modules/PlayerVehicle.lua

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ local Stancer = require("includes.features.vehicle.stancer")
5656
---@field public m_is_shooting_flares boolean
5757
---@field public m_is_flatbed boolean cache it so we don't have to call natives in UI threads
5858
---@field public m_stancer Stancer
59-
---@overload fun(handle: handle): PlayerVehicle
59+
---@overload fun(handle: handle, opts?: { noassert: boolean }): PlayerVehicle
6060
local PlayerVehicle = Class("PlayerVehicle", { parent = Vehicle })
6161

6262
PlayerVehicle.mines = {
@@ -143,12 +143,12 @@ function PlayerVehicle.new(handle)
143143
m_default_xenon_lights = { enabled = false, index = 0 },
144144
m_default_tire_smoke = { enabled = false, color = vec3:zero() },
145145
m_autopilot = {
146-
eligible = false,
147-
state = PlayerVehicle.eAutoPilotState.NONE,
146+
eligible = false,
147+
state = PlayerVehicle.eAutoPilotState.NONE,
148148
initial_nozzle_pos = 1,
149149
},
150150
m_default_max_speed = 0,
151-
---@diagnostic disable-next-line
151+
---@diagnostic disable-next-line: param-type-mismatch
152152
}, PlayerVehicle)
153153

154154
instance.m_esc_sm = StateMachine({
@@ -164,16 +164,15 @@ function PlayerVehicle.new(handle)
164164
instance:InitFeatures()
165165
instance:InitHandlingEditor()
166166

167-
local main_thread = ThreadManager:RegisterLooped("SS_VEHICLE", function()
168-
instance:Main()
169-
end)
170-
171167
Backend:RegisterEventCallbackAll(function()
172168
---@diagnostic disable-next-line: invisible
173169
instance.m_feat_mgr:Cleanup()
174170
end)
175171

176-
table.insert(instance.m_threads, main_thread)
172+
table.insert(instance.m_threads, ThreadManager:RegisterLooped("SS_VEHICLE", function()
173+
instance:Main()
174+
end))
175+
177176
return instance
178177
end
179178

@@ -185,7 +184,8 @@ function PlayerVehicle:Set(handle)
185184

186185
local new_model = ENTITY.GET_ENTITY_MODEL(handle)
187186
self.m_default_max_speed = VEHICLE.GET_VEHICLE_MODEL_ESTIMATED_MAX_SPEED(new_model)
188-
self.m_last_model = new_model
187+
self.m_last_model = self:GetModelHash()
188+
self.m_modelhash = new_model
189189
self.m_handle = handle
190190
---@diagnostic disable-next-line
191191

@@ -209,7 +209,7 @@ end
209209
function PlayerVehicle:Reset()
210210
-- self:SuspendThreads()
211211
if (self:IsValid() and self:IsLocked()) then
212-
VEHICLE.SET_VEHICLE_DOORS_LOCKED(self:GetHandle(), 1)
212+
self:LockDoors(false)
213213
self.m_generic_toggleables["autolockdoors"] = nil
214214
self.m_last_model = self:GetModelHash()
215215
end
@@ -860,4 +860,4 @@ PlayerVehicle.m_flag_registry = {
860860
},
861861
}
862862

863-
return PlayerVehicle.new(0)
863+
return PlayerVehicle(0, { noassert = true })

0 commit comments

Comments
 (0)