Skip to content

Commit e05bc13

Browse files
authored
admin & admin2: add option to make camera collide when spectate (#323)
1 parent 4ce2de4 commit e05bc13

File tree

2 files changed

+90
-6
lines changed

2 files changed

+90
-6
lines changed

[admin]/admin/client/gui/admin_spectator.lua

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ function aSpectator.Initialize ()
5151
i = i + 1
5252
end
5353

54+
aSpectator.CollideWithWalls = guiCreateCheckBox ( 0.08, 0.8, 0.84, 0.04, "Collide with walls", true, true, aSpectator.Actions )
5455
aSpectator.Skip = guiCreateCheckBox ( 0.08, 0.85, 0.84, 0.04, "Skip dead players", true, true, aSpectator.Actions )
5556
guiCreateLabel ( 0.08, 0.89, 0.84, 0.04, "____________________", true, aSpectator.Actions )
5657
aSpectator.Back = guiCreateButton ( 0.10, 0.93, 0.80, 0.05, "Back", true, aSpectator.Actions )
@@ -250,10 +251,19 @@ function aSpectator.Render ()
250251
return
251252
end
252253

254+
local offset = aSpectator.Offset
255+
256+
if guiCheckBoxGetSelected(aSpectator.CollideWithWalls) then
257+
local nearest_hit = aSpectator.CheckCollision(x, y, z)
258+
if nearest_hit and (nearest_hit < offset) then
259+
offset = nearest_hit
260+
end
261+
end
262+
253263
local ox, oy, oz
254-
ox = x - math.sin ( math.rad ( aSpectator.AngleX ) ) * aSpectator.Offset
255-
oy = y - math.cos ( math.rad ( aSpectator.AngleX ) ) * aSpectator.Offset
256-
oz = z + math.tan ( math.rad ( aSpectator.AngleZ ) ) * aSpectator.Offset
264+
ox = x - math.sin ( math.rad ( aSpectator.AngleX ) ) * offset
265+
oy = y - math.cos ( math.rad ( aSpectator.AngleX ) ) * offset
266+
oz = z + math.tan ( math.rad ( aSpectator.AngleZ ) ) * offset
257267
setCameraMatrix ( ox, oy, oz, x, y, z )
258268

259269
local sx, sy = guiGetScreenSize ()
@@ -269,6 +279,30 @@ function aSpectator.Render ()
269279
end
270280
end
271281

282+
local checks = {
283+
{-1, -0.5},
284+
{-1, 0.5},
285+
{1, 0.5},
286+
{1, -0.5},
287+
}
288+
289+
function aSpectator.CheckCollision(x, y, z)
290+
local nearest_distance
291+
292+
for k, v in ipairs(checks) do
293+
local xx, yy, zz = getPositionFromOffset(getCamera(), v[1], 0, v[2])
294+
local hit, hitx, hity, hitz = processLineOfSight(xx, yy, zz, x, y, z, true, true, false, true, true, false, false, false, (getPedOccupiedVehicle(localPlayer) or nil))
295+
if hit then
296+
local dist = getDistanceBetweenPoints3D(x, y, z, hitx, hity, hitz)
297+
if (dist <= (nearest_distance or math.huge)) then
298+
nearest_distance = dist
299+
end
300+
end
301+
end
302+
303+
return nearest_distance or false
304+
end
305+
272306
function aSpectator.MoveOffset ( key, state, inc )
273307
if ( not isCursorShowing() ) then
274308
aSpectator.Offset = aSpectator.Offset + tonumber ( inc )
@@ -286,3 +320,11 @@ function aSpectator.GetAlive ()
286320
end
287321
return alive
288322
end
323+
324+
function getPositionFromOffset(element, x, y, z)
325+
local matrix = getElementMatrix(element)
326+
local offX = x * matrix[1][1] + y * matrix[2][1] + z * matrix[3][1] + matrix[4][1]
327+
local offY = x * matrix[1][2] + y * matrix[2][2] + z * matrix[3][2] + matrix[4][2]
328+
local offZ = x * matrix[1][3] + y * matrix[2][3] + z * matrix[3][3] + matrix[4][3]
329+
return offX, offY, offZ
330+
end

[admin]/admin2/client/widgets/admin_spectator.lua

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ function aSpectator.Open()
5050
end
5151
guiGridListRemoveColumn(aSpectator.Slaps, 1)
5252

53+
aSpectator.CollideWithWalls = guiCreateCheckBox ( 0.08, 0.8, 0.84, 0.04, "Collide with walls", true, true, aSpectator.Actions )
5354
aSpectator.Skip = guiCreateCheckBox(0.08, 0.85, 0.84, 0.04, "Skip dead players", true, true, aSpectator.Actions)
5455
guiCreateLabel(0.08, 0.89, 0.84, 0.04, "____________________", true, aSpectator.Actions)
5556
aSpectator.Back = guiCreateButton(0.10, 0.93, 0.80, 0.05, "Back", true, aSpectator.Actions)
@@ -244,10 +245,19 @@ function aSpectator.Render()
244245
return
245246
end
246247

248+
local offset = aSpectator.Offset
249+
250+
if guiCheckBoxGetSelected(aSpectator.CollideWithWalls) then
251+
local nearest_hit = aSpectator.CheckCollision(x, y, z)
252+
if nearest_hit and (nearest_hit < offset) then
253+
offset = nearest_hit
254+
end
255+
end
256+
247257
local ox, oy, oz
248-
ox = x - math.sin(math.rad(aSpectator.AngleX)) * aSpectator.Offset
249-
oy = y - math.cos(math.rad(aSpectator.AngleX)) * aSpectator.Offset
250-
oz = z + math.tan(math.rad(aSpectator.AngleZ)) * aSpectator.Offset
258+
ox = x - math.sin(math.rad(aSpectator.AngleX)) * offset
259+
oy = y - math.cos(math.rad(aSpectator.AngleX)) * offset
260+
oz = z + math.tan(math.rad(aSpectator.AngleZ)) * offset
251261
setCameraMatrix(ox, oy, oz, x, y, z)
252262

253263
local sx, sy = guiGetScreenSize()
@@ -300,6 +310,30 @@ function aSpectator.Render()
300310
end
301311
end
302312

313+
local checks = {
314+
{-1, -0.5},
315+
{-1, 0.5},
316+
{1, 0.5},
317+
{1, -0.5},
318+
}
319+
320+
function aSpectator.CheckCollision(x, y, z)
321+
local nearest_distance
322+
323+
for k, v in ipairs(checks) do
324+
local xx, yy, zz = getPositionFromOffset(getCamera(), v[1], 0, v[2])
325+
local hit, hitx, hity, hitz = processLineOfSight(xx, yy, zz, x, y, z, true, true, false, true, true, false, false, false, (getPedOccupiedVehicle(localPlayer) or nil))
326+
if hit then
327+
local dist = getDistanceBetweenPoints3D(x, y, z, hitx, hity, hitz)
328+
if (dist <= (nearest_distance or math.huge)) then
329+
nearest_distance = dist
330+
end
331+
end
332+
end
333+
334+
return nearest_distance or false
335+
end
336+
303337
function aSpectator.MoveOffset(key, state, inc)
304338
if (not isCursorShowing()) then
305339
aSpectator.Offset = aSpectator.Offset + tonumber(inc)
@@ -320,3 +354,11 @@ function aSpectator.GetAlive()
320354
end
321355
return alive
322356
end
357+
358+
function getPositionFromOffset(element, x, y, z)
359+
local matrix = getElementMatrix(element)
360+
local offX = x * matrix[1][1] + y * matrix[2][1] + z * matrix[3][1] + matrix[4][1]
361+
local offY = x * matrix[1][2] + y * matrix[2][2] + z * matrix[3][2] + matrix[4][2]
362+
local offZ = x * matrix[1][3] + y * matrix[2][3] + z * matrix[3][3] + matrix[4][3]
363+
return offX, offY, offZ
364+
end

0 commit comments

Comments
 (0)