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

180 lines
7.2 KiB
Lua

-- ============================================================
-- advancedgarages | Système de caméra d'inactivité
-- ============================================================
LocalData = {
CurrentPlayerCamera = nil,
CurrentPlayerCamera_CameraTo = nil,
CurrentPlayerCamera_CameraToPosition = { x = 0.0, y = 0.0, z = 0.0 },
IsInVehicle = false,
}
inactive = false
lastInputTime = GetGameTimer()
-- ============================================================
-- StartIdleCam : lance la caméra d'inactivité en boucle
-- entity : entité autour de laquelle tourner les caméras
-- startPos : index de départ dans CameraAnimations (optionnel)
-- ============================================================
function StartIdleCam(entity, startPos)
if LocalData.CurrentPlayerCamera ~= nil then return end
Debug("Starting idle camera", entity, "position", startPos)
if #Config.CameraAnimations < 2 then
print("No valid camera positions found in config. Please add at least 2 positions.")
return
end
DoScreenFadeOut(1000)
CreateThread(function()
local animIndex = startPos or 1
if Config.RandomizedPositions and not startPos then
animIndex = math.random(1, #Config.CameraAnimations)
end
while true do
if not LocalData.CurrentPlayerCamera then break end
local anim = Config.CameraAnimations[animIndex]
local fromPos = GetRelativePosition(entity, anim.from, anim.distance)
local toPos = GetRelativePosition(entity, anim.to, anim.distance)
local entityRot = GetEntityRotation(entity, 2)
DoScreenFadeIn(1000)
StartCameraTransition(fromPos, entityRot, toPos, entityRot, Config.CameraDuration, anim.fovFrom, anim.fovTo, entity)
Wait(Config.CameraDuration - 3000)
-- Si on a fourni un startPos fixe, on ne boucle qu'une fois
if startPos then break end
DoScreenFadeOut(3000)
if LocalData.CurrentPlayerCamera == nil then StopCamera() return end
Wait(3000)
if LocalData.CurrentPlayerCamera == nil then StopCamera() return end
animIndex = animIndex + 1
if Config.RandomizedPositions and not startPos then
animIndex = math.random(1, #Config.CameraAnimations)
end
if animIndex > #Config.CameraAnimations then
animIndex = 1
end
end
if not LocalData.CurrentPlayerCamera then
StopCamera()
end
end)
end
-- ============================================================
-- StartCameraTransition : crée deux caméras et interpole
-- fromPos/fromRot : position et rotation de départ
-- toPos/toRot : position et rotation de destination
-- duration : durée de la transition en ms
-- fovFrom/fovTo : champ de vision de départ et d'arrivée
-- targetEntity : entité vers laquelle pointer les caméras
-- ============================================================
function StartCameraTransition(fromPos, fromRot, toPos, toRot, duration, fovFrom, fovTo, targetEntity)
if LocalData.CurrentPlayerCamera then
DestroyCam(LocalData.CurrentPlayerCamera)
end
if LocalData.CurrentPlayerCamera_CameraTo then
DestroyCam(LocalData.CurrentPlayerCamera_CameraTo)
end
LocalData.CurrentPlayerCamera = CreateCamWithParams(
"DEFAULT_SCRIPTED_CAMERA",
fromPos.x, fromPos.y, fromPos.z,
fromRot.x, fromRot.y, fromRot.z,
fovFrom, true, 2
)
LocalData.CurrentPlayerCamera_CameraTo = CreateCamWithParams(
"DEFAULT_SCRIPTED_CAMERA",
toPos.x, toPos.y, toPos.z,
toRot.x, toRot.y, toRot.z,
fovTo, true, 2
)
PointCamAtEntity(LocalData.CurrentPlayerCamera, targetEntity, 0.0, 0.0, 0.0)
PointCamAtEntity(LocalData.CurrentPlayerCamera_CameraTo, targetEntity, 0.0, 0.0, 0.0)
SetCamActive(LocalData.CurrentPlayerCamera, true)
RenderScriptCams(true, false, 0, true, true)
SetCamActiveWithInterp(
LocalData.CurrentPlayerCamera_CameraTo,
LocalData.CurrentPlayerCamera,
duration, 100, 50
)
end
-- ============================================================
-- GetRelativePosition : calcule une position autour d'une entité
-- entity : entité de référence
-- direction : clé de direction ("front-left", "right", "top-middle"…)
-- distance : distance depuis le centre de l'entité
-- ============================================================
function GetRelativePosition(entity, direction, distance)
local entityPos = GetEntityCoords(entity)
local forward = GetEntityForwardVector(entity)
local up = vector3(0.0, 0.0, 1.0)
local right = vector3(-forward.y, forward.x, 0.0)
local minDim, maxDim = GetModelDimensions(GetEntityModel(entity))
local height = (maxDim.z - minDim.z) * 2
local width = (maxDim.x - minDim.x) * 2
local halfWidth = width * 0.5
local positions = {
["front-left"] = forward * distance - right * (halfWidth + distance * 0.5),
["front-middle"] = forward * distance,
["front-right"] = forward * distance + right * (halfWidth + distance * 0.5),
["back-left"] = -forward * distance - right * (halfWidth + distance * 0.5),
["back-middle"] = -forward * distance,
["back-right"] = -forward * distance + right * (halfWidth + distance * 0.5),
["left"] = -right * (distance + halfWidth),
["right"] = right * (distance + halfWidth),
["top-left"] = forward * distance - right * (halfWidth + distance * 0.5) + up * (height + distance),
["top-middle"] = up * (height + distance),
["top-right"] = forward * distance + right * (halfWidth + distance * 0.5) + up * (height + distance),
["center"] = vector3(0.0, 0.0, height),
["front-left-diagonal"] = forward * distance * 0.7 - right * (halfWidth + distance * 0.7),
["front-right-diagonal"] = forward * distance * 0.7 + right * (halfWidth + distance * 0.7),
["back-left-diagonal"] = -forward * distance * 0.7 - right * (halfWidth + distance * 0.7),
["back-right-diagonal"] = -forward * distance * 0.7 + right * (halfWidth + distance * 0.7),
}
return entityPos + positions[direction]
end
-- ============================================================
-- StopCamera : arrête et détruit les caméras actives
-- ============================================================
function StopCamera()
if LocalData.CurrentPlayerCamera ~= nil then
DestroyCam(LocalData.CurrentPlayerCamera)
end
if LocalData.CurrentPlayerCamera_CameraTo ~= nil then
DestroyCam(LocalData.CurrentPlayerCamera_CameraTo)
end
LocalData.CurrentPlayerCamera = nil
LocalData.CurrentPlayerCamera_CameraTo = nil
DoScreenFadeIn(1000)
end