338 lines
No EOL
14 KiB
Lua
338 lines
No EOL
14 KiB
Lua
--[[
|
|
-- Author: Tim Plate
|
|
-- Project: Advanced Roleplay Environment
|
|
-- Copyright (c) 2022 Tim Plate Solutions
|
|
--]]
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_APPLY_TOURNIQUET, function(bodyPart, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if ClientHealthBuffer.bodyParts[bodyPart].tourniquetApplied then return end
|
|
|
|
ClientHealthBuffer.bodyParts[bodyPart].tourniquetApplied = true
|
|
ClientHealthBuffer.bodyParts[bodyPart].tourniquetAppliedTime = GetGameTimer()
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_REMOVE_TOURNIQUET, function(bodyPart, authToken)
|
|
if not ClientHealthBuffer.bodyParts[bodyPart].tourniquetApplied then return end
|
|
ClientHealthBuffer.bodyParts[bodyPart].tourniquetApplied = false
|
|
ClientHealthBuffer.bodyParts[bodyPart].tourniquetAppliedTime = 0
|
|
|
|
for k, v in ipairs(ClientHealthBuffer.bodyParts[bodyPart].blocked_medications) do
|
|
table.remove(ClientHealthBuffer.bodyParts[bodyPart].blocked_medications, k)
|
|
AddMedicationLocal(bodyPart, v)
|
|
end
|
|
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_INJECT_MEDICATION, function(bodyPart, medication, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if medication == "morphine" or medication == "epinephrine" then SpawnGameObject("visn_injector_" .. medication, ClientData.coords.x, ClientData.coords.y, ClientData.coords.z - 0.95) end
|
|
AddMedicationLocal(bodyPart, medication)
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_APPLY_BANDAGE, function(bodyPart, bandageType, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
local targetWound, effectiveness = FindMostEffectiveWound(ClientHealthBuffer, bandageType, bodyPart)
|
|
|
|
if effectiveness == -1 or not targetWound then -- No wounds on this body part
|
|
SpawnGameObject("visn_bandage", ClientData.coords.x, ClientData.coords.y, ClientData.coords.z - 0.95)
|
|
return
|
|
end
|
|
|
|
local woundIndex, finalWound = FindInjuryInHealthBuffer(ClientHealthBuffer, bodyPart, targetWound.id)
|
|
if woundIndex == -1 or not finalWound then return end
|
|
|
|
local amount = GetInjuryLevelAsNumber(finalWound.level)
|
|
local impact = math.min(effectiveness, amount)
|
|
local woundWillOpenAgain = false
|
|
|
|
amount = amount - impact
|
|
finalWound.level = GetInjuryLevelFromNumber(amount)
|
|
SpawnGameObject("visn_bandage_blood", ClientData.coords.x, ClientData.coords.y, ClientData.coords.z - 0.95)
|
|
|
|
if amount <= 0 or finalWound.level == "none" and not woundWillOpenAgain then
|
|
|
|
if ClientConfig.m_enableSewings then
|
|
woundWillOpenAgain = HandleBandageOpening(bodyPart, targetWound.key, bandageType, targetWound.id)
|
|
end
|
|
|
|
if not woundWillOpenAgain then
|
|
ClientHealthBuffer.bodyParts[bodyPart].injuries[targetWound.key] = nil
|
|
ClientHealthBuffer.bodyParts[bodyPart].injuryAmount = math.max(0, ClientHealthBuffer.bodyParts[bodyPart].injuryAmount - 1)
|
|
if bodyPart == "LEFT_LEG" or bodyPart == "RIGHT_LEG" then ResetPedMovementClipset(ClientData.ped, 0.0) end
|
|
end
|
|
end
|
|
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_APPLY_SURGICAL_KIT, function(bodyPart, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
for k, v in pairs(ClientHealthBuffer.bodyParts[bodyPart].injuries) do
|
|
if v.needSewing then
|
|
ClientHealthBuffer.bodyParts[bodyPart].injuries[k] = nil
|
|
ClientHealthBuffer.bodyParts[bodyPart].injuryAmount = math.max(0, ClientHealthBuffer.bodyParts[bodyPart].injuryAmount - 1)
|
|
end
|
|
end
|
|
|
|
SpawnGameObject("visn_gloves", ClientData.coords.x, ClientData.coords.y, ClientData.coords.z - 0.95)
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_APPLY_INFUSION, function(bodyPart, infusion, volume, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
|
|
for i, v in ipairs(ClientHealthBuffer.infusions) do
|
|
if v.bodyPart == bodyPart and v.name == infusion then
|
|
ClientHealthBuffer.infusions[i].remainingVolume = ClientHealthBuffer.infusions[i].remainingVolume + volume
|
|
ClientHealthBuffer.infusions[i].totalVolume = ClientHealthBuffer.infusions[i].totalVolume + volume
|
|
ReportHealthBufferUpdate()
|
|
LogDebug(TableContains(ClientConfig.m_debugModeModules, "infusions"), "Infusion (" .. infusion .. "; " .. volume .. "ml) updated at " .. bodyPart .. ".")
|
|
return
|
|
end
|
|
end
|
|
|
|
table.insert(ClientHealthBuffer.infusions, {
|
|
name = infusion,
|
|
remainingVolume = volume,
|
|
totalVolume = volume,
|
|
bodyPart = bodyPart
|
|
})
|
|
|
|
LogDebug(TableContains(ClientConfig.m_debugModeModules, "infusions"), "Infusion (" .. infusion .. "; " .. volume .. "ml) applied at " .. bodyPart .. ".")
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_APPLY_CPR, function(bodyPart, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer.unconscious then return end
|
|
|
|
if not ClientHealthBuffer.non_recovery_mode then
|
|
if math.random(0, 100) >= 50 then
|
|
ClientHealthBuffer.heartRate = ClientHealthBuffer.heartRate + math.random(3, 30)
|
|
end
|
|
end
|
|
|
|
ClientHealthBuffer.unconsciousTimeUntilDeath = ClientHealthBuffer.unconsciousTimeUntilDeath + 150
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_APPLY_DEFIBRILLATOR, function(bodyPart, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer.unconscious then return end
|
|
if math.random(0, 100) > 50 then return end
|
|
if ClientHealthBuffer.non_recovery_mode then return end
|
|
|
|
ClientHealthBuffer.heartRate = ClientHealthBuffer.heartRate + math.random(0, 55)
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_APPLY_EMERGENCY_REVIVE_KIT, function(bodyPart, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
|
|
SpawnGameObject("visn_gloves", ClientData.coords.x, ClientData.coords.y, ClientData.coords.z - 0.95)
|
|
ResetHealthBuffer()
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_RESPAWN_PLAYER, function(authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer then return end
|
|
|
|
local nearestLocation, nearestDistance = nil, 9000000
|
|
for _, v in pairs(ClientConfig.m_respawnConfiguration.m_respawnLocations) do
|
|
local distance = #(ClientData.coords - vector3(v.x, v.y, v.z))
|
|
if distance < nearestDistance then
|
|
nearestLocation = v
|
|
nearestDistance = distance
|
|
end
|
|
end
|
|
|
|
RespawnPed(ClientData.ped, { x = nearestLocation.x, y = nearestLocation.y, z = nearestLocation.z }, nearestLocation.hospital)
|
|
RemoveAllPedWeapons(ClientData.ped, true)
|
|
|
|
SetUnconsciousState(false)
|
|
ResetHealthBuffer()
|
|
|
|
if CarryAnimationData ~= nil then
|
|
ClearPedTasks(ClientData.ped)
|
|
DetachEntity(ClientData.ped, true, false)
|
|
CarryAnimationData = nil
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_SAVE_LOG, function(logs, authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer then return end
|
|
|
|
ClientHealthBuffer.logs = logs
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_PUT_IN_VEHICLE, function(authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer then return end
|
|
if not ClientHealthBuffer.unconscious and not ClientHealthBuffer.anesthesia then return end
|
|
|
|
local vehicle, distance = GetCustomClosestVehicle(ClientData.coords)
|
|
if distance > ClientConfig.m_vehicleScanRadius then return end
|
|
if not IsEntityAVehicle(vehicle) then return end
|
|
local maxPassengers = GetVehicleMaxNumberOfPassengers(vehicle)
|
|
local freeSeat = -1
|
|
|
|
local startIndex = 0
|
|
if maxPassengers >= 3 then startIndex = 1 end
|
|
|
|
for i = startIndex, (maxPassengers - 1) - startIndex do
|
|
if IsVehicleSeatFree(vehicle, i) then
|
|
freeSeat = i
|
|
break
|
|
end
|
|
end
|
|
|
|
if freeSeat then
|
|
TaskWarpPedIntoVehicle(ClientData.ped, vehicle, freeSeat)
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_PUT_IN_BODYBAG, function(authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer then return end
|
|
if not ClientHealthBuffer.unconscious and not ClientHealthBuffer.anesthesia then return end
|
|
|
|
SetEntityAlpha(PlayerPedId(), 0, false)
|
|
SetEntityVisible(PlayerPedId(), false, false)
|
|
|
|
RequestModel(GetHashKey("xm_prop_body_bag"))
|
|
while not HasModelLoaded(GetHashKey("xm_prop_body_bag")) do
|
|
Citizen.Wait(0)
|
|
end
|
|
|
|
local bodyBag = CreateObject(GetHashKey("xm_prop_body_bag"), ClientData.coords.x, ClientData.coords.y, ClientData.coords.z, true, true, false)
|
|
AttachEntityToEntity(bodyBag, ClientData.ped, 0, -0.2, 0.75, -0.2, 0.0, 0.0, 0.0, false, false, false, false, 20, false)
|
|
BodyBagObject = bodyBag
|
|
|
|
ClientHealthBuffer.bodybag = true
|
|
ClientHealthBuffer.unconsciousTimeUntilDeath = math.min(ClientHealthBuffer.unconsciousTimeUntilDeath, ClientConfig.m_bodybagUnconsciousTime)
|
|
ClientHealthBuffer.activeECG = false
|
|
|
|
SendNUIMessage({
|
|
payload = "showManualRespawnText",
|
|
payloadData = {
|
|
value = true,
|
|
key = ClientConfig.m_configurableKeys.m_useInputMapper
|
|
and GetControlStringFromKeyMapping("manual_respawn")
|
|
or GetControlStringFromKeyMappingNoInputMapper(ClientConfig.m_configurableKeys.keys.MANUAL_RESPAWN.control_id)
|
|
}
|
|
})
|
|
AllowManualRespawn = true
|
|
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_START_ECG, function(authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer then return end
|
|
|
|
ClientHealthBuffer.activeECG = true
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_STOP_ECG, function(authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer then return end
|
|
|
|
ClientHealthBuffer.activeECG = false
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_PULL_OUT_VEHICLE, function(authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer then return end
|
|
if not ClientHealthBuffer.unconscious and not ClientHealthBuffer.anesthesia then return end
|
|
if not IsPedSittingInAnyVehicle(ClientData.ped) then return end
|
|
|
|
local vehicle = GetVehiclePedIsIn(ClientData.ped, false)
|
|
TaskLeaveVehicle(ClientData.ped, vehicle, 16)
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_SYNC_LOCAL, function(authToken, animationData)
|
|
if authToken ~= TempAuthToken then return end
|
|
RequestAnimDict(animationData.lib)
|
|
while not HasAnimDictLoaded(animationData.lib) do Citizen.Wait(0) end
|
|
|
|
TaskPlayAnim(ClientData.ped, animationData.lib, animationData.name, 8.0, -8.0, animationData.length, animationData.flag, 0, false, false, false)
|
|
CarryAnimationData = {
|
|
lib = animationData.lib,
|
|
name = animationData.name,
|
|
flag = animationData.flag
|
|
}
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_SYNC_TARGET, function(authToken, targetSource, animationData)
|
|
if authToken ~= TempAuthToken then return end
|
|
local targetPed = GetPlayerPed(GetPlayerFromServerId(targetSource))
|
|
if not targetPed or targetPed == -1 then return end
|
|
|
|
RequestAnimDict(animationData.lib)
|
|
while not HasAnimDictLoaded(animationData.lib) do Citizen.Wait(0) end
|
|
if animationData.zRotation == nil then animationData.zRotation = 180.0 end
|
|
if animationData.flag == nil then animationData.flag = 0 end
|
|
|
|
AttachEntityToEntity(ClientData.ped, targetPed, 0, animationData.xDistance, animationData.yDistance, animationData.zDistance, 0.5, 0.5, animationData.zRotation, false, false, false, false, 2, false)
|
|
TaskPlayAnim(ClientData.ped, animationData.lib, animationData.name, 8.0, -8.0, animationData.length, animationData.flag, 0, false, false, false)
|
|
CarryAnimationData = {
|
|
lib = animationData.lib,
|
|
name = animationData.name,
|
|
flag = animationData.flag
|
|
}
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_STOP_CARRY, function(authToken)
|
|
if authToken ~= TempAuthToken then return end
|
|
|
|
ClearPedTasks(ClientData.ped)
|
|
DetachEntity(ClientData.ped, true, false)
|
|
CarryAnimationData = nil
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.EVENT_SET_HEALTH_BUFFER, function(authToken, healthBuffer)
|
|
if authToken ~= TempAuthToken then return end
|
|
|
|
for k, v in pairs(healthBuffer) do
|
|
if k ~= "unconscious" then
|
|
ClientHealthBuffer[k] = v
|
|
end
|
|
end
|
|
|
|
if healthBuffer.unconscious == true then
|
|
SetUnconsciousState(true)
|
|
end
|
|
end)
|
|
|
|
RegisterNetEvent(ENUM_EVENT_TYPES.PROCEDURE_UPDATE_TRIAGE, function(authToken, triageSelection)
|
|
if authToken ~= TempAuthToken then return end
|
|
if not ClientHealthBuffer then return end
|
|
|
|
if triageSelection == "black" then
|
|
if not ClientHealthBuffer.unconscious then return end
|
|
end
|
|
|
|
SendNUIMessage({
|
|
payload = "showManualRespawnText",
|
|
payloadData = {
|
|
value = ClientConfig.m_configurableKeys.keys.MANUAL_RESPAWN.enabled and triageSelection == "black",
|
|
key = ClientConfig.m_configurableKeys.m_useInputMapper
|
|
and GetControlStringFromKeyMapping("manual_respawn")
|
|
or GetControlStringFromKeyMappingNoInputMapper(ClientConfig.m_configurableKeys.keys.MANUAL_RESPAWN.control_id)
|
|
}
|
|
})
|
|
|
|
AllowManualRespawn = triageSelection == "black"
|
|
ClientHealthBuffer.triageSelection = triageSelection
|
|
ReportHealthBufferUpdate()
|
|
end)
|
|
|
|
RegisterNetEvent("visn_are:resetHealthBuffer", function()
|
|
ResetHealthBuffer()
|
|
end) |