398 lines
16 KiB
Lua
398 lines
16 KiB
Lua
vRP = nil
|
|
ESX = nil
|
|
|
|
if ConfigHose.Notifications.Enabled and ConfigHose.Notifications.Framework.vRP then
|
|
local Tunnel = module("vrp", "lib/Tunnel")
|
|
local Proxy = module("vrp", "lib/Proxy")
|
|
vRP = Proxy.getInterface("vRP")
|
|
end
|
|
|
|
if ConfigHose.Notifications.Enabled and ConfigHose.Notifications.Framework.ESX then
|
|
ESX = exports["es_extended"]:getSharedObject()
|
|
end
|
|
|
|
if ConfigHose.EnablePositioningCommand then
|
|
TriggerEvent('chat:addSuggestion', '/'.."findhosepositioning", "Find positioning of the hose/supply line on your fire truck")
|
|
|
|
RegisterCommand("findhosepositioning", function(source, args)
|
|
|
|
local ped = PlayerPedId()
|
|
local targetVehicle = GetVehiclePedIsIn(ped, false)
|
|
|
|
if targetVehicle == nil or targetVehicle == 0 then
|
|
Notify("No vehicle found!")
|
|
else
|
|
local model = `p_ld_soc_ball_01`
|
|
SetEntityAlpha(targetVehicle, 150, false)
|
|
RequestModel(model)
|
|
while not HasModelLoaded(model) do Wait(0) end
|
|
local ballProp = CreateObject(model, coords, false, false, false)
|
|
|
|
while not DoesEntityExist(ballProp) do Wait(0) end
|
|
|
|
SetModelAsNoLongerNeeded(model)
|
|
local offSet = {0.0, 0.0, 0.0}
|
|
local rotation = {0.0, 0.0, 0.0}
|
|
local offSetComplete = false
|
|
while not offSetComplete do
|
|
if targetVehicle ~= nil and targetVehicle ~= 0 then
|
|
DetachEntity(ballProp, true, false)
|
|
AttachEntityToEntity(ballProp, targetVehicle, -1, offSet[1], offSet[2], offSet[3], rotation[1], rotation[2], rotation[3], true, false, true, false, 1, true)
|
|
if not IsControlReleased(0, 207) then --page down
|
|
offSet = {offSet[1], offSet[2], offSet[3] - 0.01}
|
|
end
|
|
|
|
if not IsControlReleased(0, 208) then --page up
|
|
offSet = {offSet[1], offSet[2], offSet[3] + 0.01}
|
|
end
|
|
|
|
if not IsControlReleased(0, 173) then --arrow down
|
|
offSet = {offSet[1], offSet[2] - 0.01, offSet[3]}
|
|
end
|
|
|
|
if not IsControlReleased(0, 172) then --arrow up
|
|
offSet = {offSet[1], offSet[2] + 0.01, offSet[3]}
|
|
end
|
|
|
|
if not IsControlReleased(0, 174) then --arrow left
|
|
offSet = {offSet[1] - 0.01, offSet[2], offSet[3]}
|
|
end
|
|
|
|
if not IsControlReleased(0, 175) then --arrow right
|
|
offSet = {offSet[1] + 0.01, offSet[2], offSet[3]}
|
|
end
|
|
|
|
if IsControlJustPressed(0, 191) then -- enter - finish
|
|
offSetComplete = true
|
|
end
|
|
end
|
|
|
|
Wait(0)
|
|
end
|
|
|
|
Notify("OffSet Values are now printed in your console")
|
|
print("OffSet: {"..offSet[1]..", "..offSet[2]..", "..offSet[3].."}")
|
|
DeleteEntity(ballProp)
|
|
ResetEntityAlpha(targetVehicle)
|
|
end
|
|
|
|
end, false)
|
|
end
|
|
|
|
|
|
function Notify(text)
|
|
|
|
if not ConfigHose.Notifications.Enabled then
|
|
return
|
|
end
|
|
|
|
if ConfigHose.Notifications.Framework.ESX then
|
|
if ESX ~= nil then
|
|
ESX.ShowNotification(text)
|
|
end
|
|
elseif ConfigHose.Notifications.Framework.QBCore then
|
|
TriggerEvent('QBCore:Notify', text, 'primary')
|
|
elseif ConfigHose.Notifications.Framework.QBX then
|
|
exports.qbx_core:Notify(text, 'primary')
|
|
elseif ConfigHose.Notifications.Framework.vRP then
|
|
vRP.notify(source, {text})
|
|
elseif ConfigHose.Notifications.Framework.okok then
|
|
exports['okokNotify']:Alert("Smart Hose", text, 2000, 'info', true)
|
|
else
|
|
showBaseNotification(text)
|
|
end
|
|
end
|
|
|
|
function showBaseNotification(message)
|
|
-- Base game notifications
|
|
SetNotificationTextEntry("STRING")
|
|
AddTextComponentString(message)
|
|
DrawNotification(0,1)
|
|
end
|
|
|
|
-- General Functions @GeneralFunctions
|
|
function DisplayHelpText(text)
|
|
SetTextComponentFormat("STRING")
|
|
AddTextComponentString(text)
|
|
DisplayHelpTextFromStringLabel(0, 0, ConfigHose.Notifications.HelpTextSound, -1)
|
|
end
|
|
|
|
function drawInstructionalText(msg, coords)
|
|
AddTextEntry('instructionalText', msg)
|
|
SetFloatingHelpTextWorldPosition(1, coords)
|
|
SetFloatingHelpTextStyle(1, 1, 2, -1, 3, 0)
|
|
BeginTextCommandDisplayHelp('instructionalText')
|
|
AddTextComponentSubstringPlayerName(msg)
|
|
EndTextCommandDisplayHelp(2, false, false, -1)
|
|
end
|
|
|
|
function IsFireHoseEnabled()
|
|
return (HoseManager.nozzle and not HoseManager.nozzleDropped)
|
|
end
|
|
|
|
exports("IsFireHoseEnabled", IsFireHoseEnabled)
|
|
|
|
function IsFireHoseShooting()
|
|
return HoseManager.pressed
|
|
end
|
|
|
|
exports("IsFireHoseShooting", IsFireHoseShooting)
|
|
|
|
function IsFireHoseShootingWater()
|
|
return ParticleManager.isWaterDecal
|
|
end
|
|
|
|
exports("IsFireHoseShootingWater", IsFireHoseShootingWater)
|
|
|
|
function GetCurrentDecalCoords()
|
|
return ParticleManager.CurrentDecalCoords
|
|
end
|
|
|
|
exports("GetCurrentDecalCoords", GetCurrentDecalCoords)
|
|
|
|
function GetCurrentHosePressure()
|
|
return ParticleManager.particleScale
|
|
end
|
|
|
|
exports("GetCurrentHosePressure", GetCurrentHosePressure)
|
|
|
|
local vehicleModels = getVehicleModelsFromCapacities()
|
|
local interactionId = "menuId"
|
|
if ConfigHose.InteractType.TruckInteraction.Drawtext or ConfigHose.InteractType.TruckInteraction.ScreenPrompt then
|
|
CreateThread(function()
|
|
while true do
|
|
Wait(1)
|
|
local pos = GetEntityCoords(PlayerPedId())
|
|
local vehicle = GetClosestVehicle(pos)
|
|
local inRange = false
|
|
|
|
if vehicle and DoesEntityExist(vehicle) and IsVehicleDriveable(vehicle, false) then
|
|
local vehicleModel = GetEntityModel(vehicle)
|
|
local vehicleSettings = ConfigHose.Rope.VehicleSettings[vehicleModel] or {}
|
|
local useBone = vehicleSettings.useBone or false
|
|
local bones = vehicleSettings.bones or {}
|
|
local offsets = vehicleSettings.offsets or {{x = 0.0, y = 0.0, z = 0.0}}
|
|
|
|
local attachmentPoints = {}
|
|
|
|
if useBone then
|
|
for _, boneName in ipairs(bones) do
|
|
local boneIndex = GetEntityBoneIndexByName(vehicle, boneName)
|
|
if boneIndex ~= -1 then
|
|
local bonePos = GetWorldPositionOfEntityBone(vehicle, boneIndex)
|
|
table.insert(attachmentPoints, bonePos)
|
|
else
|
|
print("Bone " .. boneName .. " not found in vehicle model.")
|
|
end
|
|
end
|
|
else
|
|
for _, offset in ipairs(offsets) do
|
|
local offsetWorldPos = GetOffsetFromEntityInWorldCoords(vehicle, offset.x, offset.y, offset.z)
|
|
table.insert(attachmentPoints, offsetWorldPos)
|
|
end
|
|
end
|
|
|
|
local closestPoint = attachmentPoints[1]
|
|
local minDistance = #(pos - closestPoint)
|
|
|
|
for _, point in ipairs(attachmentPoints) do
|
|
local distance = #(pos - point)
|
|
if distance < minDistance then
|
|
closestPoint = point
|
|
minDistance = distance
|
|
end
|
|
end
|
|
|
|
local promptCoords = closestPoint
|
|
local vehicleDistance = #(pos - promptCoords)
|
|
|
|
if not IsPedInAnyVehicle(PlayerPedId(), false) and vehicleDistance < 3.0 then
|
|
inRange = true
|
|
local text = HoseManager.nozzle and ConfigHose.Translations.storeHoseMessage or ConfigHose.Translations.grabHoseMessage
|
|
|
|
if ConfigHose.InteractType.TruckInteraction.Drawtext then
|
|
drawInstructionalText(text, promptCoords)
|
|
elseif ConfigHose.InteractType.TruckInteraction.ScreenPrompt then
|
|
DisplayHelpText(text)
|
|
end
|
|
|
|
if IsControlJustReleased(0, ConfigHose.Keys.Interact) then
|
|
if not HoseManager.nozzle and isPermissionAllowed() then
|
|
InitializeFireHose()
|
|
AttachRopeToProp()
|
|
else
|
|
UnequipFireHose()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if not inRange then
|
|
Wait(2500)
|
|
end
|
|
end
|
|
end)
|
|
elseif ConfigHose.InteractType.TruckInteraction.ThirdEye.enabled then
|
|
if ConfigHose.InteractType.TruckInteraction.ThirdEye.oxTarget then
|
|
local VehicleOptions = {
|
|
{
|
|
label = ConfigHose.Translations.thirdEyeMessage,
|
|
icon = "fa-solid fa-water",
|
|
onSelect = function()
|
|
if not HoseManager.nozzle and isPermissionAllowed() then
|
|
InitializeFireHose()
|
|
AttachRopeToProp()
|
|
else
|
|
UnequipFireHose()
|
|
end
|
|
end,
|
|
}
|
|
}
|
|
exports.ox_target:addModel(vehicleModels, VehicleOptions)
|
|
end
|
|
|
|
if ConfigHose.InteractType.TruckInteraction.ThirdEye.qbTarget then
|
|
exports['qb-target']:AddTargetModel(vehicleModels, {
|
|
options = {
|
|
{
|
|
label = ConfigHose.Translations.thirdEyeMessage,
|
|
icon = "fa-solid fa-water",
|
|
action = function()
|
|
if not HoseManager.nozzle and isPermissionAllowed() then
|
|
InitializeFireHose()
|
|
AttachRopeToProp()
|
|
else
|
|
UnequipFireHose()
|
|
end
|
|
end,
|
|
},
|
|
},
|
|
distance = 3.0
|
|
})
|
|
end
|
|
elseif ConfigHose.InteractType.TruckInteraction.WorldInteraction then
|
|
CreateThread(function()
|
|
local interactionActive = false
|
|
local idleWait = 1000
|
|
|
|
while true do
|
|
Wait(idleWait)
|
|
|
|
if IsPedInAnyVehicle(PlayerPedId(), false) then
|
|
if interactionActive then
|
|
for _, model in ipairs(vehicleModels) do
|
|
exports.interact:RemoveModelInteraction(model, interactionId)
|
|
end
|
|
interactionActive = false
|
|
end
|
|
idleWait = 1500
|
|
else
|
|
local pos = GetEntityCoords(PlayerPedId())
|
|
local vehicle = GetClosestVehicle(pos)
|
|
|
|
if vehicle and DoesEntityExist(vehicle) then
|
|
local vehicleModel = GetEntityModel(vehicle)
|
|
|
|
local isAllowedModel = false
|
|
for _, model in ipairs(vehicleModels) do
|
|
if model == vehicleModel then
|
|
isAllowedModel = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if isAllowedModel then
|
|
local vehicleSettings = ConfigHose.Rope.VehicleSettings[vehicleModel] or {}
|
|
local useBone = vehicleSettings.useBone or false
|
|
local bones = vehicleSettings.bones or {}
|
|
local offsets = vehicleSettings.offsets or {{x = 0.0, y = 0.0, z = 0.0}}
|
|
|
|
local attachmentPoints = {}
|
|
|
|
if useBone then
|
|
for _, boneName in ipairs(bones) do
|
|
local boneIndex = GetEntityBoneIndexByName(vehicle, boneName)
|
|
if boneIndex ~= -1 then
|
|
local bonePos = GetWorldPositionOfEntityBone(vehicle, boneIndex)
|
|
table.insert(attachmentPoints, bonePos)
|
|
else
|
|
print("Bone " .. boneName .. " not found in vehicle model.")
|
|
end
|
|
end
|
|
else
|
|
for _, offset in ipairs(offsets) do
|
|
local offsetWorldPos = GetOffsetFromEntityInWorldCoords(vehicle, offset.x, offset.y, offset.z)
|
|
table.insert(attachmentPoints, offsetWorldPos)
|
|
end
|
|
end
|
|
|
|
local closestPoint = attachmentPoints[1]
|
|
local minDistance = #(pos - closestPoint)
|
|
|
|
for _, point in ipairs(attachmentPoints) do
|
|
local distance = #(pos - point)
|
|
if distance < minDistance then
|
|
closestPoint = point
|
|
minDistance = distance
|
|
end
|
|
end
|
|
|
|
local promptCoords = closestPoint
|
|
local vehicleDistance = #(pos - promptCoords)
|
|
|
|
if vehicleDistance < 4.0 then
|
|
if not interactionActive then
|
|
exports.interact:AddModelInteraction({
|
|
model = vehicleModel,
|
|
offset = promptCoords - GetEntityCoords(vehicle),
|
|
name = 'Menu',
|
|
id = interactionId,
|
|
distance = 8.0,
|
|
interactDst = 2.5,
|
|
ignoreLos = true,
|
|
bone = 'bodyshell',
|
|
options = {
|
|
{
|
|
label = ConfigHose.Translations.grabHoseWorldInteraction,
|
|
action = function()
|
|
if not HoseManager.nozzle then
|
|
InitializeFireHose()
|
|
AttachRopeToProp()
|
|
else
|
|
UnequipFireHose()
|
|
end
|
|
end,
|
|
},
|
|
}
|
|
})
|
|
interactionActive = true
|
|
end
|
|
idleWait = 0
|
|
else
|
|
if interactionActive then
|
|
exports.interact:RemoveModelInteraction(vehicleModel, interactionId)
|
|
interactionActive = false
|
|
end
|
|
idleWait = 500
|
|
end
|
|
else
|
|
if interactionActive then
|
|
exports.interact:RemoveModelInteraction(vehicleModel, interactionId)
|
|
interactionActive = false
|
|
end
|
|
idleWait = 1000
|
|
end
|
|
else
|
|
if interactionActive then
|
|
for _, model in ipairs(vehicleModels) do
|
|
exports.interact:RemoveModelInteraction(model, interactionId)
|
|
end
|
|
interactionActive = false
|
|
end
|
|
idleWait = 1500
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
else
|
|
warn('Invalid interaction configuration')
|
|
end |