617 lines
20 KiB
Lua
617 lines
20 KiB
Lua
local Utils = require 'client.utils'
|
|
local CameraManager = require 'client.minigame.camera_manager'
|
|
local AnimationController = require 'client.minigame.animation_controller'
|
|
local config = require 'config.config_c'
|
|
|
|
local ScrewGame = {}
|
|
ScrewGame.__index = ScrewGame
|
|
ScrewGame.activeInstance = nil
|
|
|
|
---@param entity number
|
|
---@return table
|
|
function ScrewGame.new(entity)
|
|
local self = setmetatable({}, ScrewGame)
|
|
|
|
self.entity = entity
|
|
self.isRunning = false
|
|
self.isInMinigame = false
|
|
self.cameraAlternate = false
|
|
self.inControlRange = false
|
|
|
|
self.camera = CameraManager.new(entity)
|
|
self.animator = AnimationController.new(cache.ped)
|
|
|
|
self.screwDriver = nil
|
|
self.screwObject = nil
|
|
|
|
return self
|
|
end
|
|
|
|
function ScrewGame:createObjects()
|
|
local coords = GetEntityCoords(self.entity)
|
|
|
|
lib.requestModel(config.toilet.screwDriverModel)
|
|
self.screwDriver = CreateObject(config.toilet.screwDriverModel, coords.x, coords.y, coords.z - 10, config.toilet.useNetworkedObjects, true, false)
|
|
if not DoesEntityExist(self.screwDriver) then
|
|
lib.print.error('[ScrewGame] Failed to create screwdriver object')
|
|
return false
|
|
end
|
|
SetEntityVisible(self.screwDriver, false, false)
|
|
SetModelAsNoLongerNeeded(config.toilet.screwDriverModel)
|
|
SetEntityCompletelyDisableCollision(self.screwDriver, false, true)
|
|
lib.print.debug('[ScrewGame] Created screwdriver object:', self.screwDriver)
|
|
|
|
lib.requestModel(config.toilet.screwModel)
|
|
self.screwObject = CreateObject(config.toilet.screwModel, coords.x, coords.y, coords.z - 10, config.toilet.useNetworkedObjects, true, false)
|
|
if not DoesEntityExist(self.screwObject) then
|
|
lib.print.error('[ScrewGame] Failed to create screw object')
|
|
return false
|
|
end
|
|
SetEntityVisible(self.screwObject, false, false)
|
|
SetModelAsNoLongerNeeded(config.toilet.screwModel)
|
|
SetEntityCompletelyDisableCollision(self.screwObject, false, true)
|
|
lib.print.debug('[ScrewGame] Created screw object:', self.screwObject)
|
|
|
|
return true
|
|
end
|
|
|
|
---@param screwIndex number
|
|
function ScrewGame:attachScrewdriver(screwIndex)
|
|
if not DoesEntityExist(self.screwDriver) then
|
|
lib.print.error('[ScrewGame] Cannot attach screwdriver - entity does not exist')
|
|
return
|
|
end
|
|
|
|
SetEntityVisible(self.screwDriver, true, false)
|
|
if screwIndex == 1 or screwIndex == 2 then
|
|
AttachEntityToEntity(self.screwDriver, cache.ped, GetPedBoneIndex(cache.ped, 18905),
|
|
0.13191204624002, 0.082048422891877, -0.00017189368813841,
|
|
158.93643577607, -28.807547138067, -8.8622696090118,
|
|
true, true, false, true, 1, true)
|
|
else
|
|
AttachEntityToEntity(self.screwDriver, cache.ped, GetPedBoneIndex(cache.ped, 57005),
|
|
0.14447676481041, 0.083777311695066, -0.030584143861719,
|
|
-8.9086513739403, 40.146033454762, 160.55496533153,
|
|
true, true, false, true, 1, true)
|
|
end
|
|
lib.print.debug('[ScrewGame] Attached screwdriver for screw #' .. screwIndex)
|
|
end
|
|
|
|
---@param screwIndex number
|
|
---@param progress number
|
|
---@param rotation number
|
|
function ScrewGame:positionScrew(screwIndex, progress, rotation)
|
|
if not DoesEntityExist(self.screwObject) then
|
|
lib.print.error('[ScrewGame] Cannot position screw - entity does not exist')
|
|
return
|
|
end
|
|
|
|
local screwOffset = config.toilet.screwOffsets[screwIndex]
|
|
if not screwOffset then
|
|
lib.print.error('[ScrewGame] Invalid screw offset index:', screwIndex)
|
|
return
|
|
end
|
|
|
|
local isLeftSide = (screwIndex == 1 or screwIndex == 2)
|
|
local entityRot = GetEntityRotation(self.entity)
|
|
|
|
local adjustedOffset = vec3(
|
|
screwOffset.screw.x + (isLeftSide and -progress or progress),
|
|
screwOffset.screw.y,
|
|
screwOffset.screw.z
|
|
)
|
|
|
|
local screwPos = GetOffsetFromEntityInWorldCoords(self.entity, adjustedOffset.x, adjustedOffset.y, adjustedOffset.z)
|
|
SetEntityCoords(self.screwObject, screwPos.x, screwPos.y, screwPos.z, false, false, false, false)
|
|
SetEntityRotation(self.screwObject, entityRot.x + rotation, entityRot.y + (isLeftSide and -90.0 or 90.0), entityRot.z, 2, true)
|
|
SetEntityVisible(self.screwObject, true, false)
|
|
end
|
|
|
|
function ScrewGame:switchToAlternateCamera()
|
|
if not self.isInMinigame or self.cameraAlternate then return end
|
|
|
|
self.cameraAlternate = true
|
|
|
|
self.camera:setCamera({
|
|
vec3(0.0, 0.0, 1.0),
|
|
vec3(0.0, 0.0, GetEntityHeading(self.entity) + 180.0)
|
|
}, true, true)
|
|
self.camera:activate(true, 300)
|
|
lib.print.debug('[ScrewGame] Switched to alternate camera')
|
|
end
|
|
|
|
function ScrewGame:switchToScrewCamera()
|
|
if not self.isInMinigame or not self.cameraAlternate then return end
|
|
|
|
self.cameraAlternate = false
|
|
|
|
local camOffset = config.toilet.screwOffsets[self.currentScrewIndex].cam
|
|
self.camera:setCamera(camOffset, true)
|
|
self.camera:activate(true, 300)
|
|
lib.print.debug('[ScrewGame] Switched back to screw camera')
|
|
end
|
|
|
|
---@param screwIndex number
|
|
---@return boolean
|
|
function ScrewGame:handleScrewMinigame(screwIndex)
|
|
local isLeftSide = (screwIndex == 1 or screwIndex == 2)
|
|
|
|
self.isInMinigame = true
|
|
self.currentScrewIndex = screwIndex
|
|
self.cameraAlternate = false
|
|
|
|
local camOffset = config.toilet.screwOffsets[screwIndex].cam
|
|
self.camera:setCamera(camOffset, false)
|
|
self.camera:activate(true, 1500)
|
|
|
|
self:positionScrew(screwIndex, 0, 0)
|
|
self:attachScrewdriver(screwIndex)
|
|
|
|
self.animator:playScrewAnim(screwIndex)
|
|
Wait(100)
|
|
|
|
local animRange = {start = 0.25, finish = 0.75}
|
|
self.inControlRange = false
|
|
local wasPlaying = false
|
|
local screwRotation = 0.0
|
|
local screwProgress = 0.0
|
|
|
|
SetEntityVisible(self.screwObject, true, false)
|
|
lib.print.debug('[ScrewGame] Starting minigame loop for screw #' .. screwIndex)
|
|
|
|
while self.isRunning do
|
|
local currentTime = self.animator:getCurrentTime()
|
|
local isInRange = self.animator:isInTimeRange(animRange.start, animRange.finish)
|
|
|
|
if IsControlJustPressed(0, 73) then
|
|
lib.print.debug('[ScrewGame] X pressed, cancelling')
|
|
SetNuiFocus(false, false)
|
|
self:cancelWithAnimation()
|
|
self.isRunning = false
|
|
return false
|
|
end
|
|
|
|
if isInRange and not self.inControlRange then
|
|
self.animator:setSpeed(0.0)
|
|
self.inControlRange = true
|
|
SetNuiFocus(false, true)
|
|
lib.print.debug('[ScrewGame] Entered control range, cursor enabled')
|
|
end
|
|
|
|
if self.inControlRange then
|
|
local isAimingAtScrew = Utils.IsCursorOnEntity(self.screwObject, 35.0)
|
|
local isHoldingLMB = IsControlPressed(0, 24) or IsDisabledControlPressed(0, 24)
|
|
|
|
if isAimingAtScrew then
|
|
SetEntityDrawOutline(self.screwObject, true)
|
|
SetEntityDrawOutlineColor(255, 255, 0, 255)
|
|
SetEntityDrawOutlineShader(1)
|
|
else
|
|
SetEntityDrawOutline(self.screwObject, false)
|
|
end
|
|
|
|
if isAimingAtScrew and isHoldingLMB then
|
|
if not wasPlaying then
|
|
self.animator:setSpeed(1.0)
|
|
SetEntityDrawOutlineColor(0, 255, 0, 255)
|
|
wasPlaying = true
|
|
lib.print.debug('[ScrewGame] Started unscrewing from progress:', screwProgress)
|
|
end
|
|
|
|
screwProgress = screwProgress + 0.0001
|
|
if isLeftSide then
|
|
screwRotation = screwRotation - 2.0
|
|
else
|
|
screwRotation = screwRotation + 2.0
|
|
end
|
|
|
|
self:positionScrew(screwIndex, screwProgress, screwRotation)
|
|
|
|
if currentTime >= animRange.finish then
|
|
lib.print.debug('[ScrewGame] Screw #' .. screwIndex .. ' fully unscrewed at progress:', screwProgress)
|
|
SetNuiFocus(false, false)
|
|
SetEntityDrawOutline(self.screwObject, false)
|
|
SetEntityVisible(self.screwObject, false, false)
|
|
|
|
if self.camera then
|
|
self.camera:destroy()
|
|
self.camera = nil
|
|
end
|
|
|
|
return true
|
|
end
|
|
else
|
|
if wasPlaying then
|
|
self.animator:setSpeed(0.0)
|
|
if isAimingAtScrew then
|
|
SetEntityDrawOutlineColor(255, 255, 0, 255)
|
|
end
|
|
wasPlaying = false
|
|
end
|
|
end
|
|
end
|
|
|
|
Wait(0)
|
|
end
|
|
|
|
SetNuiFocus(false, false)
|
|
SetEntityDrawOutline(self.screwObject, false)
|
|
self.isInMinigame = false
|
|
if self.camera then
|
|
self.camera:destroy()
|
|
self.camera = nil
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
function ScrewGame:selectScrew(unscrewed)
|
|
local availableScrews = {}
|
|
for i = 1, 4 do
|
|
if not lib.table.contains(unscrewed, i) then
|
|
table.insert(availableScrews, i)
|
|
end
|
|
end
|
|
|
|
if #availableScrews == 0 then
|
|
return nil
|
|
end
|
|
|
|
local currentIndex = 1
|
|
local nuiData = {}
|
|
for i = 1, 4 do
|
|
table.insert(nuiData, {
|
|
id = i,
|
|
label = locale('select_screw.options.' .. i),
|
|
available = lib.table.contains(availableScrews, i)
|
|
})
|
|
end
|
|
|
|
SendNUIMessage({
|
|
action = 'open',
|
|
data = {
|
|
screws = nuiData,
|
|
location = config.uiLocation,
|
|
locales = {
|
|
title = locale('select_screw.title'),
|
|
select = locale('select_screw.select'),
|
|
cancel = locale('select_screw.cancel'),
|
|
change_selection = locale('select_screw.change_selection'),
|
|
}
|
|
}
|
|
})
|
|
|
|
local selecting = true
|
|
local selectedScrew = nil
|
|
|
|
Wait(100)
|
|
while selecting do
|
|
if IsControlJustPressed(0, 241) or IsControlJustPressed(0, 172) then -- scroll up or arrow up
|
|
currentIndex = currentIndex - 1
|
|
if currentIndex < 1 then
|
|
currentIndex = #availableScrews
|
|
end
|
|
|
|
SendNUIMessage({
|
|
action = 'selectScrew',
|
|
data = availableScrews[currentIndex]
|
|
})
|
|
lib.print.debug('[ScrewGame] Scrolled to screw #' .. availableScrews[currentIndex])
|
|
end
|
|
|
|
if IsControlJustPressed(0, 242) or IsControlJustPressed(0, 173) then -- scroll down or arrow down
|
|
currentIndex = currentIndex + 1
|
|
if currentIndex > #availableScrews then
|
|
currentIndex = 1
|
|
end
|
|
|
|
SendNUIMessage({
|
|
action = 'selectScrew',
|
|
data = availableScrews[currentIndex]
|
|
})
|
|
lib.print.debug('[ScrewGame] Scrolled to screw #' .. availableScrews[currentIndex])
|
|
end
|
|
|
|
if IsControlJustPressed(0, 38) or IsControlJustPressed(0, 191) then -- E or enter
|
|
selectedScrew = availableScrews[currentIndex]
|
|
selecting = false
|
|
SendNUIMessage({ action = 'close' })
|
|
SetNuiFocus(false, false)
|
|
lib.print.debug('[ScrewGame] Confirmed screw #' .. selectedScrew)
|
|
end
|
|
|
|
if IsControlJustPressed(0, 73) or IsControlJustPressed(0, 194) then -- X or backspace
|
|
selecting = false
|
|
SendNUIMessage({ action = 'close' })
|
|
SetNuiFocus(false, false)
|
|
lib.print.debug('[ScrewGame] Cancelled screw selection')
|
|
end
|
|
|
|
Wait(0)
|
|
end
|
|
|
|
return selectedScrew
|
|
end
|
|
|
|
local keybind = lib.addKeybind({
|
|
name = 'prison_cam_switch',
|
|
description = 'Switch Camera View',
|
|
defaultKey = 'R',
|
|
onPressed = function(self)
|
|
if ScrewGame.activeInstance then
|
|
ScrewGame.activeInstance:switchToAlternateCamera()
|
|
end
|
|
end,
|
|
onReleased = function(self)
|
|
if ScrewGame.activeInstance then
|
|
ScrewGame.activeInstance:switchToScrewCamera()
|
|
end
|
|
end
|
|
})
|
|
|
|
function ScrewGame:start()
|
|
lib.print.debug('[ScrewGame] Starting screw minigame')
|
|
self.isRunning = true
|
|
ScrewGame.activeInstance = self
|
|
|
|
if not self:createObjects() then
|
|
lib.print.error('[ScrewGame] Failed to create objects, aborting')
|
|
self:cleanup()
|
|
return
|
|
end
|
|
|
|
local offset = GetOffsetFromEntityInWorldCoords(self.entity, 0.0, -0.5, 0.55)
|
|
|
|
SetEntityCoordsNoOffset(cache.ped, offset.x, offset.y, offset.z, false, false, false)
|
|
SetEntityHeading(cache.ped, GetEntityHeading(self.entity))
|
|
|
|
local totalDuration = GetAnimDuration('promt@jail_3', 'jail_enter_ped') * 1000
|
|
|
|
lib.playAnim(cache.ped, 'promt@jail_3', 'jail_enter_ped', 8.0, -8.0, -1, 2)
|
|
Wait(2000)
|
|
self:attachScrewdriver(1)
|
|
Wait(totalDuration - 2000)
|
|
|
|
AttachEntityToEntity(cache.ped, self.entity, 0, 0.0, 0.0, 0.55, 0.0, 0.0, 0.0, false, false, true, false, 2, true)
|
|
|
|
local allCompleted = false
|
|
local unscrewed = lib.callback.await('prompt_prison_escape:getUnscrewedState', 500) or {}
|
|
lib.print.debug('[ScrewGame] Loaded unscrewed state from server:', json.encode(unscrewed))
|
|
|
|
while self.isRunning and #unscrewed < 4 do
|
|
local screwIndex = self:selectScrew(unscrewed)
|
|
if not screwIndex then
|
|
lib.print.debug('[ScrewGame] User cancelled screw selection')
|
|
self:cancelWithAnimation()
|
|
self.isRunning = false
|
|
break
|
|
end
|
|
|
|
lib.print.debug('[ScrewGame] Selected screw #' .. screwIndex .. ', already unscrewed:', json.encode(unscrewed))
|
|
|
|
AttachEntityToEntity(cache.ped, self.entity, 0, 0.0, 0.0, 0.55, 0.0, 0.0, -180.0, false, false, true, false, 2, true)
|
|
SendNUIMessage({
|
|
action = 'setHint',
|
|
data = locale('screw_minigame.hint')
|
|
})
|
|
local completed = self:handleScrewMinigame(screwIndex)
|
|
SendNUIMessage({
|
|
action = 'setHint',
|
|
})
|
|
|
|
SetNuiFocus(false, false)
|
|
if self.camera then
|
|
self.camera:destroy()
|
|
self.camera = nil
|
|
end
|
|
|
|
if not completed then
|
|
break
|
|
end
|
|
|
|
local saved = lib.callback.await('prompt_prison_escape:unscrewProgress', 500, screwIndex)
|
|
if not saved then
|
|
lib.print.error('[ScrewGame] Failed to save screw progress on server')
|
|
break
|
|
end
|
|
|
|
table.insert(unscrewed, screwIndex)
|
|
lib.print.debug('[ScrewGame] Screw #' .. screwIndex .. ' completed. Total:', #unscrewed .. '/4')
|
|
|
|
if #unscrewed < 4 then
|
|
self.camera = CameraManager.new(self.entity)
|
|
end
|
|
end
|
|
|
|
if #unscrewed >= 4 then
|
|
if self.screwObject and DoesEntityExist(self.screwObject) then
|
|
SetEntityDrawOutline(self.screwObject, false)
|
|
end
|
|
|
|
if self.screwDriver and DoesEntityExist(self.screwDriver) then
|
|
DeleteEntity(self.screwDriver)
|
|
self.screwDriver = nil
|
|
end
|
|
|
|
config.textUI.show(locale('screw_minigame.instructions_escape'))
|
|
|
|
while self.isRunning do
|
|
if IsControlJustPressed(0, 38) then
|
|
config.textUI.hide()
|
|
lib.print.debug('[ScrewGame] Starting exit sequence')
|
|
self:playExitSequence()
|
|
allCompleted = true
|
|
break
|
|
elseif IsControlJustPressed(0, 73) then
|
|
config.textUI.hide()
|
|
lib.print.warn('[ScrewGame] User cancelled escape')
|
|
self:cancelWithAnimation()
|
|
self.isRunning = false
|
|
break
|
|
end
|
|
Wait(0)
|
|
end
|
|
else
|
|
if self.screwObject and DoesEntityExist(self.screwObject) then
|
|
SetEntityDrawOutline(self.screwObject, false)
|
|
end
|
|
|
|
if self.screwDriver and DoesEntityExist(self.screwDriver) then
|
|
DeleteEntity(self.screwDriver)
|
|
self.screwDriver = nil
|
|
end
|
|
end
|
|
|
|
if allCompleted then
|
|
lib.callback.await('prompt_prison_escape:completeEscape', 500)
|
|
else
|
|
lib.callback.await('prompt_prison_escape:stopSitting', 500)
|
|
end
|
|
|
|
self:cleanup()
|
|
lib.print.debug('[ScrewGame] Cleaned up and finished')
|
|
end
|
|
|
|
function ScrewGame:playExitSequence()
|
|
SetNuiFocus(false, false)
|
|
|
|
if self.camera then
|
|
self.camera:destroy()
|
|
self.camera = nil
|
|
end
|
|
|
|
DetachEntity(cache.ped, true, false)
|
|
|
|
local entHeading = GetEntityHeading(self.entity)
|
|
local entityStartCoords = GetEntityCoords(self.entity)
|
|
|
|
local animOffset = GetOffsetFromEntityInWorldCoords(self.entity, 0.0, 0.0, 0.55)
|
|
SetEntityCoordsNoOffset(cache.ped, animOffset.x, animOffset.y, animOffset.z, false, false, false)
|
|
SetEntityHeading(cache.ped, entHeading - 173.0)
|
|
lib.playAnim(cache.ped, 'promt@jail_4', 'jail_exit_open_ped')
|
|
|
|
Wait(4000)
|
|
|
|
local targetPos = GetOffsetFromEntityInWorldCoords(self.entity, -0.5, 0.0, 0.0)
|
|
local totalOffsetX = targetPos.x - entityStartCoords.x
|
|
local totalOffsetY = targetPos.y - entityStartCoords.y
|
|
|
|
local duration = 2000
|
|
local stepTime = 25
|
|
local steps = duration / stepTime
|
|
|
|
for i = 1, steps do
|
|
local progress = i / steps
|
|
SetEntityCoords(self.entity,
|
|
entityStartCoords.x + (totalOffsetX * progress),
|
|
entityStartCoords.y + (totalOffsetY * progress),
|
|
entityStartCoords.z,
|
|
false, false, false)
|
|
Wait(stepTime)
|
|
end
|
|
|
|
local targetExitPos = GetOffsetFromEntityInWorldCoords(self.entity, 0.5, 1.5, 0.0)
|
|
Wait(GetAnimDuration('promt@jail_4', 'jail_exit_open_ped') * 1000 - 7000)
|
|
targetPos = GetOffsetFromEntityInWorldCoords(self.entity, 0.5, -1.0, 0.0)
|
|
SetEntityCoordsNoOffset(cache.ped, targetPos.x, targetPos.y, targetPos.z, false, false, false)
|
|
lib.playAnim(cache.ped, 'promt@jail_5', 'jail_exit_ped')
|
|
SetEntityHeading(cache.ped, entHeading)
|
|
SetEntityCollision(self.entity, false, false)
|
|
|
|
Wait(GetAnimDuration('promt@jail_5', 'jail_exit_ped') * 1000)
|
|
SetEntityCoordsNoOffset(cache.ped, targetExitPos.x, targetExitPos.y, targetExitPos.z, false, false, false)
|
|
SetEntityHeading(cache.ped, entHeading + 180.0)
|
|
SetEntityCollision(self.entity, true, true)
|
|
|
|
local totalCloseDuration = GetAnimDuration('prompt@jail', 'jail_exit_close') * 1000
|
|
|
|
lib.playAnim(cache.ped, 'prompt@jail', 'jail_exit_close')
|
|
Wait(2500)
|
|
|
|
local currentEntityCoords = GetEntityCoords(self.entity)
|
|
local targetPos = GetOffsetFromEntityInWorldCoords(self.entity, 0.5, 0.0, 0.0)
|
|
local totalOffsetX = targetPos.x - currentEntityCoords.x
|
|
local totalOffsetY = targetPos.y - currentEntityCoords.y
|
|
|
|
local duration = 2000
|
|
local stepTime = 25
|
|
local steps = duration / stepTime
|
|
|
|
for i = 1, steps do
|
|
local progress = i / steps
|
|
SetEntityCoords(self.entity,
|
|
currentEntityCoords.x + (totalOffsetX * progress),
|
|
currentEntityCoords.y + (totalOffsetY * progress),
|
|
currentEntityCoords.z,
|
|
false, false, false)
|
|
Wait(stepTime)
|
|
end
|
|
Wait(totalCloseDuration - 2500 - 2000)
|
|
end
|
|
|
|
function ScrewGame:cancelWithAnimation()
|
|
SetNuiFocus(false, false)
|
|
|
|
if self.camera then
|
|
self.camera:destroy()
|
|
self.camera = nil
|
|
end
|
|
|
|
DetachEntity(cache.ped, true, false)
|
|
|
|
local entHeading = GetEntityHeading(self.entity)
|
|
local animOffset = GetOffsetFromEntityInWorldCoords(self.entity, 0.0, 0.0, 0.55)
|
|
SetEntityCoordsNoOffset(cache.ped, animOffset.x, animOffset.y, animOffset.z, false, false, false)
|
|
SetEntityHeading(cache.ped, entHeading - 173.0)
|
|
|
|
local totalDuration = GetAnimDuration('promt@jail_2', 'jail_enter_off_ped') * 1000
|
|
lib.playAnim(cache.ped, 'promt@jail_2', 'jail_enter_off_ped')
|
|
Wait(1000)
|
|
|
|
if self.screwDriver and DoesEntityExist(self.screwDriver) then
|
|
DeleteEntity(self.screwDriver)
|
|
self.screwDriver = nil
|
|
end
|
|
Wait(totalDuration - 1000)
|
|
end
|
|
|
|
function ScrewGame:stop()
|
|
self.isRunning = false
|
|
end
|
|
|
|
|
|
function ScrewGame:cleanup()
|
|
self.isRunning = false
|
|
self.isInMinigame = false
|
|
if ScrewGame.activeInstance == self then
|
|
ScrewGame.activeInstance = nil
|
|
end
|
|
|
|
SetNuiFocus(false, false)
|
|
|
|
if self.screwDriver and DoesEntityExist(self.screwDriver) then
|
|
DeleteEntity(self.screwDriver)
|
|
self.screwDriver = nil
|
|
end
|
|
|
|
if self.screwObject and DoesEntityExist(self.screwObject) then
|
|
SetEntityDrawOutline(self.screwObject, false)
|
|
DeleteEntity(self.screwObject)
|
|
self.screwObject = nil
|
|
end
|
|
|
|
if self.camera then
|
|
self.camera:destroy()
|
|
self.camera = nil
|
|
end
|
|
|
|
DetachEntity(cache.ped, true, false)
|
|
|
|
if self.animator then
|
|
self.animator:stop()
|
|
self.animator = nil
|
|
end
|
|
end
|
|
|
|
return ScrewGame
|