2026-04-14 17:41:39 +02:00

155 lines
4.7 KiB
Lua

local sincos = require("glm").sincos
local rad = require("glm").rad
local abs = math.abs
local getCamCoords = GetFinalRenderedCamCoord
local getCamRot = GetFinalRenderedCamRot
local getEntityCoords = GetEntityCoords
local disableControls = DisableAllControlActions
local drawLine = DrawLine
local getCamMatrix = GetCamMatrix
local createCamera = Utils.CreateCamera
local handleFlyCam = Utils.HandleFlyCam
local drawScaleform = Utils.DrawScaleform
raycast = {
cameraOptions = {
controls = { "up", "right", "forward" }
}
}
function raycast.getForwardVector(self)
local camRot = getCamRot(2)
local sinResult, cosResult = sincos(rad(camRot))
return vec3(
-sinResult.z * abs(cosResult.x),
cosResult.z * abs(cosResult.x),
sinResult.x
)
end
function raycast.gameplayCamera(self, callback, options, flags)
assert(type(callback) == "function", "raycast:gameplayCamera ::: fn must be a function")
options = options or {}
self.controls = Utils.GetControls(options)
self.scaleform = Utils.CreateInstructional(self.controls)
self.active = true
if not flags then flags = 17 end
while self.active do
DisablePlayerFiring(cache.playerId, true)
local camPos = getCamCoords()
local forward = self:getForwardVector() * 50.0
local endPos = camPos + forward
local rayHandle = StartExpensiveSynchronousShapeTestLosProbe(
camPos.x, camPos.y, camPos.z,
endPos.x, endPos.y, endPos.z,
flags, cache.ped, 4
)
local pedPos = getEntityCoords(cache.ped)
local _, hitResult, hitCoords, _, hitEntity = GetShapeTestResultIncludingMaterial(rayHandle)
self.coords = hitCoords
self.entity = (hitEntity ~= 0 and hitEntity) or nil
self.hit = (hitResult == 1)
if self.hit then
DrawMarker(28,
self.coords.x, self.coords.y, self.coords.z,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.2, 0.2, 0.2, 255, 42, 24, 100,
false, false, 0, true, false, false, false
)
drawLine(
pedPos.x, pedPos.y, pedPos.z,
self.coords.x, self.coords.y, self.coords.z,
255, 42, 24, 100
)
end
callback(self)
drawScaleform(self.scaleform)
self.lastCoords = self.coords
Wait(0)
end
end
function raycast.freeCamera(self, callback, extraControls)
assert(type(callback) == "function", "raycast:camera ::: fn must be a function")
local _, forward, _, origin = GetEntityMatrix(cache.ped)
local camPos = origin + forward * 2
local camRot = GetEntityRotation(cache.ped)
self.camRot = camRot
self.camPos = camPos
self.camera = createCamera("DEFAULT_SCRIPTED_CAMERA", camPos, camRot, true)
self.active = true
SetPlayerControl(cache.playerId, false, 0)
local allControls = table.deepclone(self.cameraOptions.controls)
if extraControls then
for _, ctrl in pairs(extraControls) do
allControls[#allControls + 1] = ctrl
end
end
self.controls = Utils.GetControls(allControls)
self.scaleform = Utils.CreateInstructional(self.controls)
while self.active do
disableControls(0)
self.camPos, self.camRot = handleFlyCam(self.camera)
local _, rightVec, _, _ = getCamMatrix(self.camera)
local endPos = vec3(
self.camPos.x + rightVec.x * 100.0,
self.camPos.y + rightVec.y * 100.0,
self.camPos.z + rightVec.z * 100.0
)
local rayHandle = StartExpensiveSynchronousShapeTestLosProbe(
self.camPos.x, self.camPos.y, self.camPos.z,
endPos.x, endPos.y, endPos.z,
17, cache.ped, 4
)
local _, _, hitCoords, _, hitEntity = GetShapeTestResultIncludingMaterial(rayHandle)
self.coords = hitCoords
self.entity = hitEntity
self.hit = (hitResult == 1)
local cx, cy, cz = self.coords.x, self.coords.y, self.coords.z
drawLine(cx - 0.3, cy, cz, cx + 0.3, cy, cz, 255, 0, 0, 255)
drawLine(cx, cy, cz, cx, cy, cz + 0.3, 255, 0, 0, 255)
drawLine(cx, cy - 0.3, cz, cx, cy + 0.3, cz, 255, 0, 0, 255)
drawScaleform(self.scaleform)
callback(self)
Wait(0)
end
end
function raycast.destroy(self)
self.active = false
if self.camera then
Utils.DestroyFlyCam(self.camera, 1000)
self.camera = nil
SetPlayerControl(cache.playerId, true, 0)
end
end
AddEventHandler("onResourceStop", function(resourceName)
if resourceName == GetCurrentResourceName() then
raycast:destroy()
end
end)