From 2826bc95c7801e9c48e4b42009a0eda93187b86e Mon Sep 17 00:00:00 2001 From: Jim Shield Date: Fri, 5 Sep 2025 16:34:45 +0100 Subject: [PATCH] Enhance built in camera function file - Allows filters to be applied to custom cameras when running `startTempCam()` - Automatically interpolates between cameras created in the same script - Toggle to attempt to render the location if camera is far away from the ped - Clears all created cameras when `stopTempCam()` is run --- shared/make/cameras.lua | 150 +++++++++++++++++++++++++++++++--------- 1 file changed, 117 insertions(+), 33 deletions(-) diff --git a/shared/make/cameras.lua b/shared/make/cameras.lua index ae6b34b..0ed8ec9 100644 --- a/shared/make/cameras.lua +++ b/shared/make/cameras.lua @@ -1,3 +1,5 @@ +local camCache = {} + --- Creates a temporary camera at a specified position, pointing towards given coordinates. -- -- This function creates a camera at a position relative to an entity or at a specified position and orients it to look at the target coordinates. @@ -7,55 +9,120 @@ -- If `ent` is an entity, the camera position is calculated as an offset from the entity's position using `GetOffsetFromEntityInWorldCoords`. -- If `ent` is a `vector3`, it is used directly as the camera's position. -- ----@param coords vector3 The target `vector3` coordinates that the camera will point at. +---@param coords vector3|entityId The target `vector3` coordinates that the camera will point at. -- ----@return cam camID The handle of the created camera, or `nil` if the camera was not created (e.g., if `Config.Crafting.craftCam` is `false`). +---@return camID number The handle of the created camera, or `nil` if the camera was not created (e.g., if `Config.Crafting.craftCam` is `false`). -- ---@usage -- ```lua -- local cam = createTempCam(entity, targetCoords) -- ``` function createTempCam(ent, coords) - local cam = nil - if Config.Crafting.craftCam then - if debugMode then - triggerNotify(nil, "ModCam Created", "success") - end + local camID = nil + if Config.Crafting?.craftCam or Config.System.enableCam then + debugPrint("^6Bridge^7: ^2Custom Camera Created") + local camCoords = nil - local pointCoords = nil - if type(ent) ~= "vector3" then - camCoords = GetOffsetFromEntityInWorldCoords(ent, 1.0, -0.3, 0.8) - else + --local pointCoords = nil + + if type(ent) ~= "number" then -- if received a vector3 or vector4 use those coords for origin point camCoords = ent - end - - cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", camCoords.x, camCoords.y, camCoords.z + 0.5, 1.0, 0.0, 0.0, 60.00, false, 0) - - if type(coords) == "number" then - SetCamCoord(cam, GetCamCoord(cam) + vec3(0, 0, 1.0)) - PointCamAtEntity(cam, coords) else - PointCamAtCoord(cam, coords) + camCoords = GetOffsetFromEntityInWorldCoords(ent, 1.0, -0.3, 0.8) end + + -- Create the camera + camID = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", camCoords.x, camCoords.y, camCoords.z + 0.5, 1.0, 0.0, 0.0, 60.00, false, 0) + camCache[#camCache+1] = camID + + --if type(coords) == "number" then + -- SetCamCoord(camID, GetCamCoord(camID) + vec3(0, 0, 1.0)) + --end + + camLookAt(camID, coords) + end - return cam + return camID end + +local cacheCameraEffect = {} +local cachePrevCam = nil --- Activates and starts rendering the temporary camera. -- -- This function sets the specified camera as active and begins rendering it with a smooth transition. -- The camera is only activated if `Config.Crafting.craftCam` is enabled in the configuration. -- ----@param cam camID The handle of the camera to activate and render. +---@param cam number The handle of the camera to activate and render. +---@param renderTime number The handle of the camera to activate and render. +---@param loadScene boolean The handle of the camera to activate and render. +---@param filter table The filter or postFx to render when starting the camera. -- ---@usage -- ```lua --- startTempCam(cam) +-- startTempCam(camID, 1000, true, { postFx = "HeistCelebEnd" }) -- ``` -function startTempCam(cam) - if Config.Crafting.craftCam then - SetCamActive(cam, true) - RenderScriptCams(true, true, 1000, true, true) +function startTempCam(cam, renderTime, loadScene, filter) + if cam and DoesCamExist(cam) then + if cachePrevCam then + SetCamActiveWithInterp(cam, cachePrevCam, renderTime or 1000, 0, 0) + else + SetCamActive(cam, true) + end + cachePrevCam = cam + + -- Clear previous filters + if cacheCameraEffect.postFx then + AnimpostfxStop(cacheCameraEffect.postFx) + cacheCameraEffect.postFx = nil + end + if cacheCameraEffect.timecycle then + ClearTimecycleModifier() + cacheCameraEffect.timecycle = nil + end + + -- Apply filters (timecycle) here as requested + if filter and filter.modifier then + SetTimecycleModifier(filter.modifier) + SetTimecycleModifierStrength((filter.strength or 1.0) + 0.0) + cacheCameraEffect.timecycle = true + end + + if filter and filter.postFx then + AnimpostfxPlay(filter.postFx, 0, filter.loop and true or false) + cacheCameraEffect.postFx = filter.postFx + end + + if loadScene then + local pos = GetCamCoord(cam) + + local radius = 100.0 + + SetFocusPosAndVel(pos.x, pos.y, pos.z, 0.0, 0.0, 0.0) + RequestCollisionAtCoord(pos.x, pos.y, pos.z) + NewLoadSceneStart(pos.x, pos.y, pos.z, 0.0, 0.0, 0.0, radius, 0) + + local t0 = GetGameTimer() + while not IsNewLoadSceneLoaded() and (GetGameTimer() - t0) < 2000 do + RequestCollisionAtCoord(pos.x, pos.y, pos.z) + Wait(0) + end + + NewLoadSceneStop() + end + + RenderScriptCams(true, true, renderTime or 1000, true, true) + end +end + +-- Follow cam or coords +function camLookAt(cam, entCoords) + if cam and entCoords then + if type(entCoords) ~= "number" then + PointCamAtCoord(cam, entCoords.xyz) + else + PointCamAtEntity(cam, entCoords) + end end end @@ -71,11 +138,28 @@ end -- stopTempCam() -- ``` function stopTempCam() - if Config.Crafting.craftCam then - CreateThread(function() - Wait(1000) - RenderScriptCams(false, true, 500, true, true) - DestroyAllCams() - end) - end + CreateThread(function() + Wait(1000) + + cachePrevCam = nil + + -- Clear previous filters + if cacheCameraEffect.postFx then + AnimpostfxStop(cacheCameraEffect.postFx) + cacheCameraEffect.postFx = nil + end + if cacheCameraEffect.timecycle then + ClearTimecycleModifier() + cacheCameraEffect.timecycle = nil + end + + RenderScriptCams(false, true, 500, true, true) + for i = 1, #camCache do + DestroyCam(camCache[i], true) + end + camCache = {} + --DestroyAllCams() + ClearFocus() + NewLoadSceneStop() + end) end \ No newline at end of file