696 lines
24 KiB
Lua
696 lines
24 KiB
Lua
local ESX = nil
|
|
|
|
CreateThread(function()
|
|
while not ESX do
|
|
Wait(10)
|
|
ESX = exports['es_extended']:getSharedObject()
|
|
end
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- STATE
|
|
-- ============================================================
|
|
|
|
local deathState = 'ALIVE' -- ALIVE | UNCONSCIOUS | BLEEDING_OUT
|
|
local unconsciousTimer = 0
|
|
local bleedoutTimer = 0
|
|
local emsCallHoldTime = 0
|
|
local emsCalled = false
|
|
local isReviving = false
|
|
local isTreating = false
|
|
local canGiveUp = false
|
|
local giveUpTimer = 0
|
|
|
|
-- Tabelle mit bewusstlosen Spielern (vom Server synchronisiert, für ox_target)
|
|
local DownedPlayers = {}
|
|
|
|
-- ============================================================
|
|
-- HELPER: Ist der lokale Spieler EMS?
|
|
-- (Muss VOR ox_target Registrierung stehen!)
|
|
-- ============================================================
|
|
|
|
local function IsLocalPlayerEMS()
|
|
local playerData = ESX.GetPlayerData()
|
|
if not playerData or not playerData.job then return false end
|
|
|
|
for _, jobName in ipairs(Config.EMSJobNames) do
|
|
if playerData.job.name == jobName then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
-- ============================================================
|
|
-- UTILS
|
|
-- ============================================================
|
|
|
|
local function GetNearestHospital()
|
|
local playerCoords = GetEntityCoords(PlayerPedId())
|
|
local nearest = nil
|
|
local nearestDist = math.huge
|
|
|
|
for _, loc in ipairs(Config.RespawnLocations) do
|
|
local dist = #(playerCoords - vector3(loc.x, loc.y, loc.z))
|
|
if dist < nearestDist then
|
|
nearestDist = dist
|
|
nearest = loc
|
|
end
|
|
end
|
|
|
|
return nearest or Config.RespawnLocations[1]
|
|
end
|
|
|
|
local function SetHudVisible(visible)
|
|
DisplayRadar(visible)
|
|
pcall(function()
|
|
if visible then
|
|
exports['l2_hud']:ShowHUD()
|
|
else
|
|
exports['l2_hud']:HideHUD()
|
|
end
|
|
end)
|
|
end
|
|
|
|
local function LoadAnimDict(dict)
|
|
RequestAnimDict(dict)
|
|
local timeout = 0
|
|
while not HasAnimDictLoaded(dict) and timeout < 1000 do
|
|
Wait(10)
|
|
timeout = timeout + 10
|
|
end
|
|
end
|
|
|
|
local function PlayDeadAnimation(ped)
|
|
if not IsPedRagdoll(ped) then
|
|
SetPedToRagdoll(ped, -1, -1, 0, false, false, false)
|
|
end
|
|
end
|
|
|
|
local function PlayAnimation(dict, anim, duration, flag)
|
|
if isTreating then return false end
|
|
isTreating = true
|
|
|
|
local ped = PlayerPedId()
|
|
|
|
LoadAnimDict(dict)
|
|
TaskPlayAnim(ped, dict, anim, 8.0, -8.0, duration, flag or 1, 0, false, false, false)
|
|
|
|
local startTime = GetGameTimer()
|
|
while (GetGameTimer() - startTime) < duration do
|
|
Wait(100)
|
|
if not DoesEntityExist(ped) or IsPedDeadOrDying(ped, true) then
|
|
isTreating = false
|
|
return false
|
|
end
|
|
end
|
|
|
|
ClearPedTasks(ped)
|
|
RemoveAnimDict(dict)
|
|
isTreating = false
|
|
return true
|
|
end
|
|
|
|
-- Wiederbeleben: CPR Animation (auf dem Boden knien, ganzer Körper)
|
|
local function PlayReviveAnimation(duration)
|
|
return PlayAnimation('mini@cpr@char_a@cpr_str', 'cpr_pumpchest', duration, 1)
|
|
end
|
|
|
|
-- Heilen / Bandage: Verband-Animation (im Stehen, nur Oberkörper)
|
|
local function PlayHealAnimation(duration)
|
|
return PlayAnimation('anim@heists@narcotics@funding@gang_idle', 'gang_chatting_idle01', duration, 49)
|
|
end
|
|
|
|
-- GTA Health-System: 0=tot, 100=minimum sichtbar, 200=voll
|
|
-- Diese Funktion rechnet Prozent in GTA-HP um (Bereich 100-200)
|
|
local function PercentToHealth(percent)
|
|
local health = 100 + math.floor(100 * percent)
|
|
if health < 110 then health = 110 end -- Sicherheitspuffer über "dying" Grenze
|
|
if health > 200 then health = 200 end
|
|
return health
|
|
end
|
|
|
|
-- ============================================================
|
|
-- NUI COMMUNICATION
|
|
-- ============================================================
|
|
|
|
local function ShowDeathscreen(state, timer)
|
|
SendNUIMessage({
|
|
action = 'show',
|
|
state = state,
|
|
timer = timer,
|
|
locale = Config.Locale
|
|
})
|
|
end
|
|
|
|
local function UpdateNUI(state, timer)
|
|
SendNUIMessage({
|
|
action = 'update',
|
|
state = state,
|
|
timer = timer
|
|
})
|
|
end
|
|
|
|
local function HideDeathscreen()
|
|
SendNUIMessage({ action = 'hide' })
|
|
end
|
|
|
|
-- ============================================================
|
|
-- DEATH STATE MANAGEMENT
|
|
-- ============================================================
|
|
|
|
local function SetUnconsciousState()
|
|
if deathState ~= 'ALIVE' or isReviving then return end
|
|
|
|
deathState = 'UNCONSCIOUS'
|
|
unconsciousTimer = Config.UnconsciousTime
|
|
emsCalled = false
|
|
canGiveUp = false
|
|
giveUpTimer = 0
|
|
|
|
local ped = PlayerPedId()
|
|
|
|
if IsPedDeadOrDying(ped, true) then
|
|
-- Ped ist bereits tot - muss resurrectet werden
|
|
local coords = GetEntityCoords(ped)
|
|
NetworkResurrectLocalPlayer(coords.x, coords.y, coords.z, GetEntityHeading(ped), true, false)
|
|
Wait(0)
|
|
ped = PlayerPedId()
|
|
SetEntityAlpha(ped, 0, false) -- Unsichtbar während Übergang
|
|
end
|
|
|
|
SetEntityHealth(ped, 200)
|
|
SetEntityInvincible(ped, true)
|
|
SetPedToRagdoll(ped, -1, -1, 0, false, false, false)
|
|
|
|
-- Kurz warten dann wieder sichtbar (Ragdoll hat bereits gestartet)
|
|
CreateThread(function()
|
|
Wait(100)
|
|
SetEntityAlpha(PlayerPedId(), 255, false)
|
|
end)
|
|
|
|
SetHudVisible(false)
|
|
ShowDeathscreen('UNCONSCIOUS', unconsciousTimer)
|
|
TriggerServerEvent('mercyv-deathscreen:server:updateState', 'UNCONSCIOUS')
|
|
end
|
|
|
|
local function SetBleedingOutState()
|
|
deathState = 'BLEEDING_OUT'
|
|
bleedoutTimer = Config.BleedoutTime
|
|
UpdateNUI('BLEEDING_OUT', bleedoutTimer)
|
|
TriggerServerEvent('mercyv-deathscreen:server:updateState', 'BLEEDING_OUT')
|
|
end
|
|
|
|
local function ResetToAlive(skipResurrect, reviveHealthPercent)
|
|
isReviving = true
|
|
|
|
unconsciousTimer = 0
|
|
bleedoutTimer = 0
|
|
emsCallHoldTime = 0
|
|
emsCalled = false
|
|
canGiveUp = false
|
|
giveUpTimer = 0
|
|
|
|
local ped = PlayerPedId()
|
|
|
|
-- Ragdoll / Animation stoppen
|
|
SetPedCanRagdoll(ped, false)
|
|
ClearPedTasksImmediately(ped)
|
|
SetPedCanRagdoll(ped, true)
|
|
|
|
if not skipResurrect then
|
|
NetworkResurrectLocalPlayer(GetEntityCoords(ped), GetEntityHeading(ped), true, false)
|
|
|
|
local health = PercentToHealth(reviveHealthPercent or Config.ReviveHealthPercent or 0.5)
|
|
SetEntityHealth(ped, health)
|
|
ClearPedBloodDamage(ped)
|
|
end
|
|
|
|
SetEntityInvincible(ped, false)
|
|
HideDeathscreen()
|
|
|
|
deathState = 'ALIVE'
|
|
|
|
-- HUD-Restore in eigenem Thread damit es garantiert ausgeführt wird
|
|
CreateThread(function()
|
|
Wait(1500)
|
|
SetHudVisible(true)
|
|
isReviving = false
|
|
end)
|
|
end
|
|
|
|
local function DoRespawn()
|
|
TriggerServerEvent('mercyv-deathscreen:server:respawn')
|
|
end
|
|
|
|
-- ============================================================
|
|
-- SERVER CALLBACKS
|
|
-- ============================================================
|
|
|
|
RegisterNetEvent('mercyv-deathscreen:client:doRespawn')
|
|
AddEventHandler('mercyv-deathscreen:client:doRespawn', function()
|
|
isReviving = true
|
|
local hospital = GetNearestHospital()
|
|
|
|
-- Beim Respawn MUSS resurrectet werden (Teleport zum Krankenhaus)
|
|
NetworkResurrectLocalPlayer(hospital.x, hospital.y, hospital.z, hospital.heading, true, false)
|
|
Wait(300)
|
|
|
|
local ped = PlayerPedId()
|
|
SetEntityCoords(ped, hospital.x, hospital.y, hospital.z, false, false, false, true)
|
|
SetEntityHeading(ped, hospital.heading)
|
|
SetEntityHealth(ped, 200) -- Volle HP beim Respawn
|
|
ClearPedBloodDamage(ped)
|
|
SetPedCanRagdoll(ped, false)
|
|
SetEntityInvincible(ped, false)
|
|
ClearPedTasksImmediately(ped)
|
|
SetPedCanRagdoll(ped, true)
|
|
HideDeathscreen()
|
|
|
|
deathState = 'ALIVE'
|
|
unconsciousTimer = 0
|
|
bleedoutTimer = 0
|
|
emsCallHoldTime = 0
|
|
emsCalled = false
|
|
canGiveUp = false
|
|
giveUpTimer = 0
|
|
|
|
TriggerServerEvent('mercyv-deathscreen:server:updateState', 'ALIVE')
|
|
|
|
-- HUD-Restore in eigenem Thread damit es garantiert ausgeführt wird
|
|
CreateThread(function()
|
|
Wait(500)
|
|
SetHudVisible(true)
|
|
isReviving = false
|
|
end)
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- DOWNED PLAYERS SYNC
|
|
-- ============================================================
|
|
|
|
RegisterNetEvent('mercyv-deathscreen:client:syncDownedPlayers')
|
|
AddEventHandler('mercyv-deathscreen:client:syncDownedPlayers', function(downedList)
|
|
DownedPlayers = downedList or {}
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- ESX EVENT HANDLERS
|
|
-- ============================================================
|
|
|
|
AddEventHandler('esx:onPlayerDeath', function(data)
|
|
SetUnconsciousState()
|
|
end)
|
|
|
|
RegisterNetEvent('esx:playerLoaded')
|
|
AddEventHandler('esx:playerLoaded', function(xPlayer)
|
|
ESX.PlayerData = xPlayer
|
|
ResetToAlive()
|
|
end)
|
|
|
|
RegisterNetEvent('esx:setJob')
|
|
AddEventHandler('esx:setJob', function(job)
|
|
if ESX.PlayerData then
|
|
ESX.PlayerData.job = job
|
|
end
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- EIGENE TOD-ERKENNUNG (ohne esx_ambulancejob)
|
|
-- ============================================================
|
|
|
|
CreateThread(function()
|
|
while true do
|
|
if isReviving then
|
|
Wait(500)
|
|
elseif deathState == 'ALIVE' then
|
|
local ped = PlayerPedId()
|
|
local health = GetEntityHealth(ped)
|
|
if IsPedDeadOrDying(ped, true) or health <= 101 then
|
|
SetUnconsciousState()
|
|
end
|
|
Wait(0)
|
|
else
|
|
-- Im Death-State: Falls GTA den Ped nochmal killt, erneut resurrecten
|
|
local ped = PlayerPedId()
|
|
if IsPedDeadOrDying(ped, true) then
|
|
local coords = GetEntityCoords(ped)
|
|
NetworkResurrectLocalPlayer(coords.x, coords.y, coords.z, GetEntityHeading(ped), true, false)
|
|
Wait(0)
|
|
ped = PlayerPedId()
|
|
SetEntityAlpha(ped, 0, false)
|
|
SetEntityHealth(ped, 200)
|
|
SetEntityInvincible(ped, true)
|
|
SetPedToRagdoll(ped, -1, -1, 0, false, false, false)
|
|
CreateThread(function()
|
|
Wait(100)
|
|
SetEntityAlpha(PlayerPedId(), 255, false)
|
|
end)
|
|
end
|
|
Wait(1000)
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- EIGENES REVIVE SYSTEM
|
|
-- ============================================================
|
|
|
|
RegisterNetEvent('mercyv-deathscreen:client:revived')
|
|
AddEventHandler('mercyv-deathscreen:client:revived', function()
|
|
if deathState == 'ALIVE' then return end
|
|
|
|
ResetToAlive(false, Config.ReviveHealthPercent)
|
|
TriggerServerEvent('mercyv-deathscreen:server:updateState', 'ALIVE')
|
|
ESX.ShowNotification(Config.Locale.revived)
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- OX_TARGET: Wundenbehandlung auf lebende Spieler (nur EMS)
|
|
-- ============================================================
|
|
|
|
CreateThread(function()
|
|
while not ESX do Wait(100) end
|
|
|
|
local ok, err = pcall(function()
|
|
exports.ox_target:addGlobalPlayer({
|
|
{
|
|
name = 'mercyv_revive',
|
|
icon = 'fas fa-heart-pulse',
|
|
label = Config.Locale.reviveTargetLabel or 'Wiederbeleben',
|
|
distance = Config.ReviveDistance or 3.0,
|
|
canInteract = function(entity)
|
|
if isTreating then return false end
|
|
|
|
local targetPlayer = NetworkGetPlayerIndexFromPed(entity)
|
|
if targetPlayer == -1 then return false end
|
|
local targetServerId = GetPlayerServerId(targetPlayer)
|
|
|
|
-- Nur bei am Boden liegenden Spielern anzeigen
|
|
if not DownedPlayers[targetServerId] then return false end
|
|
|
|
if IsLocalPlayerEMS() then return true end
|
|
return Config.CitizenRevive
|
|
end,
|
|
onSelect = function(data)
|
|
local targetPlayer = NetworkGetPlayerIndexFromPed(data.entity)
|
|
if targetPlayer == -1 then return end
|
|
local targetServerId = GetPlayerServerId(targetPlayer)
|
|
if not targetServerId or targetServerId <= 0 then return end
|
|
|
|
local success = PlayReviveAnimation(Config.ReviveAnimDuration or 5000)
|
|
if success then
|
|
TriggerServerEvent('mercyv-deathscreen:server:revivePlayer', targetServerId)
|
|
end
|
|
end,
|
|
},
|
|
{
|
|
name = 'mercyv_heal_big',
|
|
icon = 'fas fa-kit-medical',
|
|
label = Config.Locale.healBigLabel or 'Große Wunden behandeln',
|
|
distance = Config.ReviveDistance or 3.0,
|
|
canInteract = function(entity)
|
|
if isTreating then return false end
|
|
if not IsLocalPlayerEMS() then return false end
|
|
|
|
local targetPlayer = NetworkGetPlayerIndexFromPed(entity)
|
|
if targetPlayer == -1 then return false end
|
|
local targetServerId = GetPlayerServerId(targetPlayer)
|
|
if DownedPlayers[targetServerId] then return false end
|
|
|
|
return true
|
|
end,
|
|
onSelect = function(data)
|
|
local targetPlayer = NetworkGetPlayerIndexFromPed(data.entity)
|
|
if targetPlayer == -1 then return end
|
|
local targetServerId = GetPlayerServerId(targetPlayer)
|
|
if not targetServerId or targetServerId <= 0 then return end
|
|
|
|
local success = PlayHealAnimation(Config.HealBigDuration or 8000)
|
|
if success then
|
|
TriggerServerEvent('mercyv-deathscreen:server:healPlayer', targetServerId, 'big')
|
|
end
|
|
end,
|
|
},
|
|
{
|
|
name = 'mercyv_heal_small',
|
|
icon = 'fas fa-bandage',
|
|
label = Config.Locale.healSmallLabel or 'Kleine Wunden behandeln',
|
|
distance = Config.ReviveDistance or 3.0,
|
|
canInteract = function(entity)
|
|
if isTreating then return false end
|
|
if not IsLocalPlayerEMS() then return false end
|
|
|
|
local targetPlayer = NetworkGetPlayerIndexFromPed(entity)
|
|
if targetPlayer == -1 then return false end
|
|
local targetServerId = GetPlayerServerId(targetPlayer)
|
|
if DownedPlayers[targetServerId] then return false end
|
|
|
|
return true
|
|
end,
|
|
onSelect = function(data)
|
|
local targetPlayer = NetworkGetPlayerIndexFromPed(data.entity)
|
|
if targetPlayer == -1 then return end
|
|
local targetServerId = GetPlayerServerId(targetPlayer)
|
|
if not targetServerId or targetServerId <= 0 then return end
|
|
|
|
local success = PlayHealAnimation(Config.HealSmallDuration or 5000)
|
|
if success then
|
|
TriggerServerEvent('mercyv-deathscreen:server:healPlayer', targetServerId, 'small')
|
|
end
|
|
end,
|
|
},
|
|
})
|
|
end)
|
|
|
|
if not ok then
|
|
print('[mercyv-deathscreen] ox_target Heal fehlgeschlagen: ' .. tostring(err))
|
|
end
|
|
end)
|
|
|
|
-- Wundenbehandlung: Client bekommt HP-Update
|
|
RegisterNetEvent('mercyv-deathscreen:client:healed')
|
|
AddEventHandler('mercyv-deathscreen:client:healed', function(newHealth, healType)
|
|
local ped = PlayerPedId()
|
|
SetEntityHealth(ped, newHealth)
|
|
ClearPedBloodDamage(ped)
|
|
ESX.ShowNotification(Config.Locale.healedByEMS or 'Du wurdest behandelt')
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- SELBSTHEILUNG (Bandage)
|
|
-- ============================================================
|
|
|
|
RegisterNetEvent('mercyv-deathscreen:client:selfHeal')
|
|
AddEventHandler('mercyv-deathscreen:client:selfHeal', function()
|
|
if deathState ~= 'ALIVE' then return end
|
|
if isTreating then return end
|
|
|
|
local success = PlayHealAnimation(Config.SelfHealDuration or 4000)
|
|
if success then
|
|
local ped = PlayerPedId()
|
|
local currentHealth = GetEntityHealth(ped)
|
|
local maxHealth = GetEntityMaxHealth(ped)
|
|
local newHealth = currentHealth + (Config.SelfHealAmount or 50)
|
|
if newHealth > maxHealth then newHealth = maxHealth end
|
|
|
|
SetEntityHealth(ped, newHealth)
|
|
ClearPedBloodDamage(ped)
|
|
ESX.ShowNotification(Config.Locale.selfHealUsed or 'Du hast dich mit einer Bandage verarztet')
|
|
end
|
|
end)
|
|
|
|
|
|
-- ============================================================
|
|
-- MAIN TIMER THREAD
|
|
-- ============================================================
|
|
|
|
CreateThread(function()
|
|
while true do
|
|
if deathState == 'UNCONSCIOUS' then
|
|
unconsciousTimer = unconsciousTimer - 1
|
|
giveUpTimer = giveUpTimer + 1
|
|
UpdateNUI('UNCONSCIOUS', unconsciousTimer)
|
|
if unconsciousTimer <= 0 then
|
|
SetBleedingOutState()
|
|
end
|
|
if not canGiveUp and giveUpTimer >= (Config.GiveUpTime or 60) then
|
|
canGiveUp = true
|
|
SendNUIMessage({ action = 'enableGiveUp' })
|
|
end
|
|
elseif deathState == 'BLEEDING_OUT' then
|
|
bleedoutTimer = bleedoutTimer - 1
|
|
giveUpTimer = giveUpTimer + 1
|
|
UpdateNUI('BLEEDING_OUT', bleedoutTimer)
|
|
if bleedoutTimer <= 0 then
|
|
DoRespawn()
|
|
end
|
|
if not canGiveUp and giveUpTimer >= (Config.GiveUpTime or 60) then
|
|
canGiveUp = true
|
|
SendNUIMessage({ action = 'enableGiveUp' })
|
|
end
|
|
end
|
|
Wait(1000)
|
|
end
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- INPUT & ANIMATION THREAD
|
|
-- ============================================================
|
|
|
|
CreateThread(function()
|
|
while true do
|
|
if deathState ~= 'ALIVE' and not isReviving then
|
|
local ped = PlayerPedId()
|
|
|
|
DisableAllControlActions(0)
|
|
PlayDeadAnimation(ped)
|
|
|
|
-- Aufgeben (ausbluten) per E-Taste → direkt Respawn
|
|
if canGiveUp and (deathState == 'UNCONSCIOUS' or deathState == 'BLEEDING_OUT') then
|
|
if IsDisabledControlJustPressed(0, Config.RespawnKey) then
|
|
DoRespawn()
|
|
end
|
|
end
|
|
|
|
-- EMS rufen per G-Taste
|
|
if (deathState == 'UNCONSCIOUS' or deathState == 'BLEEDING_OUT') and not emsCalled then
|
|
if IsDisabledControlPressed(0, Config.EMSCallKey) then
|
|
emsCallHoldTime = emsCallHoldTime + 1
|
|
|
|
-- Balken oder Fortschritt könnte hier visualisiert werden (ca. 1-2 Sek gedrückt halten)
|
|
if emsCallHoldTime >= 60 then
|
|
emsCalled = true
|
|
emsCallHoldTime = 0
|
|
|
|
local coords = GetEntityCoords(ped)
|
|
|
|
-- Straßenname ermitteln
|
|
local streetHash, crossingHash = GetStreetNameAtCoord(coords.x, coords.y, coords.z, 0, 0)
|
|
local streetName = GetStreetNameFromHashKey(streetHash)
|
|
|
|
-- CD_DISPATCH INTEGRATION
|
|
TriggerServerEvent('cd_dispatch:AddNotification', {
|
|
job_table = {'ambulance'},
|
|
coords = coords,
|
|
title = '10-15 - Bewusstlose Person',
|
|
message = 'Notruf: Verletzte Person bei ' .. tostring(streetName),
|
|
flash = 0,
|
|
unique_id = tostring(math.random(1111, 9999)),
|
|
sound = 1,
|
|
blip = {
|
|
sprite = 153,
|
|
scale = 1.2,
|
|
colour = 1,
|
|
flashes = true,
|
|
text = 'Notruf: Bewusstlose Person',
|
|
time = 5,
|
|
radius = 0,
|
|
}
|
|
})
|
|
|
|
SendNUIMessage({ action = 'emsCalled' })
|
|
ESX.ShowNotification('Der Rettungsdienst wurde alarmiert.')
|
|
end
|
|
else
|
|
emsCallHoldTime = 0
|
|
end
|
|
end
|
|
|
|
Wait(0)
|
|
else
|
|
Wait(500)
|
|
end
|
|
end
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- CLEANUP
|
|
-- ============================================================
|
|
|
|
AddEventHandler('onResourceStop', function(resourceName)
|
|
if resourceName ~= GetCurrentResourceName() then return end
|
|
|
|
if deathState ~= 'ALIVE' then
|
|
local ped = PlayerPedId()
|
|
SetPedCanRagdoll(ped, false)
|
|
SetEntityInvincible(ped, false)
|
|
ClearPedTasksImmediately(ped)
|
|
SetPedCanRagdoll(ped, true)
|
|
SetHudVisible(true)
|
|
HideDeathscreen()
|
|
end
|
|
end)
|
|
|
|
-- ============================================================
|
|
-- MEDICAL NPC SYSTEM (AUTO-MEDIC)
|
|
-- ============================================================
|
|
|
|
local MedicNPC = {
|
|
model = `s_m_m_doctor_01`, -- Der Skin des Arztes
|
|
coords = vector4(-327.2433, -588.2013, 31.7755, 211.5617), -- Z leicht gesenkt für Bodenhaftung
|
|
}
|
|
|
|
CreateThread(function()
|
|
-- NPC Erstellen
|
|
RequestModel(MedicNPC.model)
|
|
while not HasModelLoaded(MedicNPC.model) do Wait(10) end
|
|
|
|
local npcEntity = CreatePed(4, MedicNPC.model, MedicNPC.coords.x, MedicNPC.coords.y, MedicNPC.coords.z, MedicNPC.coords.w, false, true)
|
|
SetEntityHeading(npcEntity, MedicNPC.coords.w)
|
|
FreezeEntityPosition(npcEntity, true)
|
|
SetEntityInvincible(npcEntity, true)
|
|
SetBlockingOfNonTemporaryEvents(npcEntity, true)
|
|
|
|
-- ox_target Optionen für den NPC
|
|
-- ox_target Optionen für den NPC
|
|
exports.ox_target:addLocalEntity(npcEntity, {
|
|
{
|
|
name = 'medic_npc_heal',
|
|
icon = 'fas fa-kit-medical',
|
|
label = 'Sich selbst heilen ($1000)', -- Text angepasst
|
|
canInteract = function()
|
|
return deathState == 'ALIVE' and GetEntityHealth(PlayerPedId()) < 200
|
|
end,
|
|
onSelect = function()
|
|
TriggerServerEvent('mercyv-deathscreen:server:npcHealSelf')
|
|
exports['hex_4_hud']:Notify('Dr.Klaus', 'Du hast dich behandeln lassen', success, 5000)
|
|
end
|
|
},
|
|
{
|
|
name = 'medic_npc_revive',
|
|
icon = 'fas fa-heart-pulse',
|
|
label = 'Person in der Nähe wiederbeleben ($1500)', -- Text angepasst
|
|
canInteract = function()
|
|
local coords = GetEntityCoords(PlayerPedId())
|
|
local players = ESX.Game.GetPlayersInArea(coords, 5.0)
|
|
|
|
for _, player in ipairs(players) do
|
|
local serverId = GetPlayerServerId(player)
|
|
if DownedPlayers[serverId] and player ~= PlayerId() then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end,
|
|
onSelect = function()
|
|
local coords = GetEntityCoords(PlayerPedId())
|
|
local players = ESX.Game.GetPlayersInArea(coords, 5.0)
|
|
local closestPlayer = nil
|
|
|
|
for _, player in ipairs(players) do
|
|
local serverId = GetPlayerServerId(player)
|
|
if DownedPlayers[serverId] and player ~= PlayerId() then
|
|
closestPlayer = serverId
|
|
break
|
|
end
|
|
end
|
|
|
|
if closestPlayer then
|
|
TriggerServerEvent('mercyv-deathscreen:server:npcReviveOther', closestPlayer)
|
|
else
|
|
exports['hex_4_hud']:Notify('Dr.Klaus', 'Keine bewusstlose Person in der nähe', error, 5000)
|
|
end
|
|
end
|
|
}
|
|
}) -- Diese Zeile schließt den ox_target Block
|
|
end) -- Diese Zeile schließt den CreateThread |