forked from mkafrin/PolyZone
-
Notifications
You must be signed in to change notification settings - Fork 0
/
EntityZone.lua
143 lines (121 loc) · 4.45 KB
/
EntityZone.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
EntityZone = {}
-- Inherits from BoxZone
setmetatable(EntityZone, { __index = BoxZone })
-- Utility functions
local deg, atan2 = math.deg, math.atan2
local function GetRotation(entity)
local fwdVector = GetEntityForwardVector(entity)
return deg(atan2(fwdVector.y, fwdVector.x))
end
local function _calculateMinAndMaxZ(entity, dimensions, scaleZ, offsetZ)
local min, max = dimensions[1], dimensions[2]
local minX, minY, minZ, maxX, maxY, maxZ = min.x, min.y, min.z, max.x, max.y, max.z
-- Bottom vertices
local p1 = GetOffsetFromEntityInWorldCoords(entity, minX, minY, minZ).z
local p2 = GetOffsetFromEntityInWorldCoords(entity, maxX, minY, minZ).z
local p3 = GetOffsetFromEntityInWorldCoords(entity, maxX, maxY, minZ).z
local p4 = GetOffsetFromEntityInWorldCoords(entity, minX, maxY, minZ).z
-- Top vertices
local p5 = GetOffsetFromEntityInWorldCoords(entity, minX, minY, maxZ).z
local p6 = GetOffsetFromEntityInWorldCoords(entity, maxX, minY, maxZ).z
local p7 = GetOffsetFromEntityInWorldCoords(entity, maxX, maxY, maxZ).z
local p8 = GetOffsetFromEntityInWorldCoords(entity, minX, maxY, maxZ).z
local entityMinZ = math.min(p1, p2, p3, p4, p5, p6, p7, p8)
local entityMaxZ = math.max(p1, p2, p3, p4, p5, p6, p7, p8)
return BoxZone.calculateMinAndMaxZ(entityMinZ, entityMaxZ, scaleZ, offsetZ)
end
-- Initialization functions
local function _initDebug(zone, options)
if options.debugBlip then zone:addDebugBlip() end
if not options.debugPoly and not options.debugBlip then
return
end
Citizen.CreateThread(function()
local entity = zone.entity
local shouldDraw = options.debugPoly
while not zone.destroyed do
UpdateOffsets(entity, zone)
if shouldDraw then zone:draw(false) end
Citizen.Wait(0)
end
end)
end
function EntityZone:new(entity, options)
assert(DoesEntityExist(entity), "Entity does not exist")
local min, max = GetModelDimensions(GetEntityModel(entity))
local dimensions = {min, max}
local length = max.y - min.y
local width = max.x - min.x
local pos = GetEntityCoords(entity)
local zone = BoxZone:new(pos, length, width, options)
if options.useZ == true then
options.minZ, options.maxZ = _calculateMinAndMaxZ(entity, dimensions, zone.scaleZ, zone.offsetZ)
else
options.minZ = nil
options.maxZ = nil
end
zone.entity = entity
zone.dimensions = dimensions
zone.useZ = options.useZ
zone.damageEventHandlers = {}
zone.isEntityZone = true
setmetatable(zone, self)
self.__index = self
return zone
end
function EntityZone:Create(entity, options)
local zone = EntityZone:new(entity, options)
_initDebug(zone, options)
return zone
end
function UpdateOffsets(entity, zone)
local pos = GetEntityCoords(entity)
local rot = GetRotation(entity)
zone.offsetPos = pos.xy - zone.startPos
zone.offsetRot = rot - 90.0
if zone.useZ then
zone.minZ, zone.maxZ = _calculateMinAndMaxZ(entity, zone.dimensions, zone.scaleZ, zone.offsetZ)
end
if zone.debugBlip then SetBlipCoords(zone.debugBlip, pos.x, pos.y, 0.0) end
end
-- Helper functions
function EntityZone:isPointInside(point)
local entity = self.entity
if entity == nil then
print("[PolyZone] Error: Called isPointInside on Entity zone with no entity {name=" .. self.name .. "}")
return false
end
UpdateOffsets(entity, self)
return BoxZone.isPointInside(self, point)
end
function EntityZone:onEntityDamaged(onDamagedCb)
local entity = self.entity
if not entity then
print("[PolyZone] Error: Called onEntityDamage on Entity Zone with no entity {name=" .. self.name .. "}")
return
end
self.damageEventHandlers[#self.damageEventHandlers + 1] = AddEventHandler('gameEventTriggered', function (name, args)
if self.destroyed or self.paused then
return
end
if name == 'CEventNetworkEntityDamage' then
local victim, attacker, victimDied, weaponHash, isMelee = args[1], args[2], args[4], args[5], args[10]
--print(entity, victim, attacker, victimDied, weaponHash, isMelee)
if victim ~= entity then return end
onDamagedCb(victimDied == 1, attacker, weaponHash, isMelee == 1)
end
end)
end
function EntityZone:destroy()
for i=1, #self.damageEventHandlers do
print("Destroying damageEventHandler:", self.damageEventHandlers[i])
RemoveEventHandler(self.damageEventHandlers[i])
end
self.damageEventHandlers = {}
PolyZone.destroy(self)
end
function EntityZone:addDebugBlip()
local blip = PolyZone.addDebugBlip(self)
self.debugBlip = blip
return blip
end