Présentation du système de tâches d'ambulance
Un script de travail d'ambulance est essentiel pour tout serveur de jeu de rôle visant un gameplay immersif des services d'urgence. Le système EMS gère tout, de la réception des appels lorsqu'un joueur tombe en panne, aux mécaniciens de traitement sur place, au transport hospitalier et à la facturation médicale. Un script d'ambulance bien conçu crée un gameplay significatif pour les joueurs EMS tout en garantissant que les joueurs abattus ne soient pas obligés d'attendre indéfiniment. L'architecture se divise en quatre sous-systèmes principaux : le système de répartition et de notification qui alerte les services médicaux d'urgence en cas d'incidents, les mécanismes de traitement et de stabilisation qui confient aux médecins des tâches réelles à effectuer, le processus d'enregistrement et de récupération à l'hôpital et le système de facturation qui crée un coût économique pour les blessures. Chaque sous-système doit fonctionner indépendamment, de sorte que si aucun joueur EMS n'est en service, des systèmes de secours automatiques gèrent la récupération des joueurs.
Configuration du travail et système de service
Le travail d'ambulance nécessite des grades clairement définis avec des capacités différentes à chaque niveau. Les stagiaires ne seront peut-être capables que d’effectuer les premiers secours de base, tandis que les ambulanciers paramédicaux expérimentés pourront administrer des traitements avancés et accéder à des fournitures médicales restreintes. Utilisez un tableau de configuration qui mappe les niveaux de poste aux actions disponibles, aux éléments requis et aux taux de paiement. Le système de devoir doit suivre quels joueurs EMS sont actuellement actifs afin que le serveur sache s'il doit utiliser la solution de secours de réapparition automatique :
Config.AmbulanceJob = {
name = 'ambulance',
grades = {
[0] = {
label = 'Trainee',
treatments = {'bandage', 'painkillers'},
canRevive = false,
salary = 250,
},
[1] = {
label = 'EMT',
treatments = {'bandage', 'painkillers', 'splint', 'iv_drip'},
canRevive = true,
salary = 400,
},
[2] = {
label = 'Paramedic',
treatments = {'bandage', 'painkillers', 'splint', 'iv_drip',
'defibrillator', 'blood_transfusion'},
canRevive = true,
salary = 550,
},
[3] = {
label = 'Chief',
treatments = {'all'},
canRevive = true,
salary = 750,
},
},
minOnDutyForNoAutoRespawn = 2,
respawnTimer = 300, -- seconds before auto-respawn when no EMS
hospitalCoords = vector3(311.2, -584.3, 43.3),
bedSpawns = {
vector4(309.7, -583.8, 43.3, 70.0),
vector4(313.0, -585.2, 43.3, 70.0),
vector4(316.3, -586.6, 43.3, 70.0),
},
}
Le minOnDutyForNoAutoRespawn Le paramètre contrôle le moment où le serveur bascule entre la récupération dépendante d'EMS et la récupération automatique. Lorsque moins de deux EMS sont en service, les joueurs abattus bénéficient d'une option de réapparition basée sur une minuterie après avoir attendu le nombre de secondes configuré. Cela évite aux joueurs de rester coincés dans l’attente de soins médicaux qui n’arriveront jamais.
Système de répartition et de notification
Lorsqu'un joueur est frappé d'incapacité, le système diffuse une alerte de répartition à tous les joueurs EMS en service indiquant l'emplacement, la nature de l'urgence et le moyen de réclamer l'appel. Plusieurs acteurs EMS peuvent voir l'alerte, mais un seul doit la revendiquer pour éviter toute confusion. Mettez en œuvre un système de réclamation dans lequel le premier intervenant qui accepte l'appel se voit attribuer l'appel, et les autres EMS le voient comme revendiqué avec l'identifiant de l'unité qui a répondu :
-- Server: handle player down event
local ActiveCalls = {}
RegisterNetEvent('ambulance:server:playerDown', function(deathCause)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
local ped = GetPlayerPed(src)
local coords = GetEntityCoords(ped)
local streetHash, _ = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
local streetName = GetStreetNameFromHashKey(streetHash)
local callId = 'EMS-' .. os.time() .. '-' .. src
ActiveCalls[callId] = {
source = src,
patient = Player.PlayerData.charinfo.firstname .. ' ' ..
Player.PlayerData.charinfo.lastname,
coords = coords,
street = streetName,
cause = deathCause,
time = os.time(),
claimed = false,
responder = nil,
}
-- Notify all on-duty EMS
local emsList = QBCore.Functions.GetPlayersOnDuty('ambulance')
for _, emsId in ipairs(emsList) do
TriggerClientEvent('ambulance:client:newCall', emsId, callId, ActiveCalls[callId])
end
end)
RegisterNetEvent('ambulance:server:claimCall', function(callId)
local src = source
local call = ActiveCalls[callId]
if not call or call.claimed then return end
local Player = QBCore.Functions.GetPlayer(src)
if not Player or Player.PlayerData.job.name ~= 'ambulance' then return end
call.claimed = true
call.responder = src
-- Notify all EMS that call is claimed
local emsList = QBCore.Functions.GetPlayersOnDuty('ambulance')
for _, emsId in ipairs(emsList) do
TriggerClientEvent('ambulance:client:callClaimed', emsId, callId, Player.PlayerData.charinfo.firstname)
end
-- Set GPS waypoint for responding EMT
TriggerClientEvent('ambulance:client:setWaypoint', src, call.coords)
end)
Incluez la cause du décès dans les informations de répartition afin que l'ambulancier intervenant puisse préparer les éléments de traitement appropriés avant d'arriver sur place. Les causes courantes telles que les blessures par balle, les collisions de véhicules, les chutes et les noyades nécessitent chacune des approches de traitement différentes, ce qui ajoute de la profondeur à l'expérience de jeu de rôle EMS.
Mécanismes de traitement et de réanimation
Les mécanismes de traitement devraient être plus impliqués que le simple fait d’appuyer sur un bouton pour réanimer quelqu’un. Créez un processus en plusieurs étapes dans lequel l'ambulancier doit d'abord stabiliser le patient avec des traitements de base avant d'effectuer la réanimation proprement dite. Chaque étape de traitement consomme un élément de l'inventaire de l'EMT et prend un temps défini avec une animation de barre de progression. L'état du patient peut être modélisé avec un état de santé simple qui s'améliore à chaque traitement appliqué :
-- Client: treatment system
local TreatmentSteps = {
['bandage'] = {
label = 'Apply Bandage',
duration = 5000,
anim = {dict = 'mini@cpr@char_a@cpr_str', name = 'cpr_pumpchest'},
healthRestore = 10,
item = 'bandage',
},
['painkillers'] = {
label = 'Administer Painkillers',
duration = 3000,
anim = {dict = 'mp_arresting', name = 'a_uncuff'},
healthRestore = 15,
item = 'painkillers',
},
['defibrillator'] = {
label = 'Use Defibrillator',
duration = 8000,
anim = {dict = 'mini@cpr@char_a@cpr_str', name = 'cpr_pumpchest'},
healthRestore = 0,
item = 'defibrillator',
canRevive = true,
},
}
function PerformTreatment(targetId, treatmentType)
local treatment = TreatmentSteps[treatmentType]
if not treatment then return end
-- Check if EMT has required item
if not HasItem(treatment.item) then
QBCore.Functions.Notify('Missing: ' .. treatment.label, 'error')
return
end
-- Play animation and progress bar
TaskPlayAnim(PlayerPedId(), treatment.anim.dict, treatment.anim.name,
8.0, -8.0, treatment.duration, 1, 0, false, false, false)
QBCore.Functions.Progressbar('treatment_' .. treatmentType,
treatment.label, treatment.duration, false, true, {}, {}, {}, {},
function() -- success
TriggerServerEvent('ambulance:server:applyTreatment',
targetId, treatmentType)
ClearPedTasks(PlayerPedId())
end,
function() -- cancel
ClearPedTasks(PlayerPedId())
QBCore.Functions.Notify('Treatment cancelled', 'error')
end
)
end
La barre de progression avec animation crée une scène de traitement réaliste que les autres joueurs peuvent observer, améliorant ainsi l'atmosphère du jeu de rôle. Faites du défibrillateur la dernière étape qui effectue réellement la réanimation, exigeant que l'ambulancier stabilise d'abord le patient avec des bandages et des analgésiques. Cette approche en plusieurs étapes rend le rôle EMS plus attrayant qu'une simple relance en un clic.
Enregistrement et récupération à l'hôpital
Après avoir réanimé un patient sur le terrain ou l'avoir transporté à l'hôpital, un joueur EMS peut l'enregistrer dans un lit d'hôpital pour un rétablissement complet. Le processus d'enregistrement guérit complètement le patient, facture une facture médicale et enregistre la visite. Les lits d’hôpitaux doivent être suivis pour éviter que plusieurs patients ne soient affectés au même lit. Créez un système de gestion des lits qui marque les lits comme occupés et les libère après un temps de récupération configurable :
-- Server: hospital bed management
local OccupiedBeds = {}
RegisterNetEvent('ambulance:server:checkInPatient', function(patientId)
local src = source
local EMT = QBCore.Functions.GetPlayer(src)
local Patient = QBCore.Functions.GetPlayer(patientId)
if not EMT or not Patient then return end
if EMT.PlayerData.job.name ~= 'ambulance' then return end
-- Find available bed
local bedIndex = nil
for i, bed in ipairs(Config.AmbulanceJob.bedSpawns) do
if not OccupiedBeds[i] then
bedIndex = i
break
end
end
if not bedIndex then
TriggerClientEvent('QBCore:Notify', src, 'No beds available', 'error')
return
end
OccupiedBeds[bedIndex] = patientId
-- Calculate and charge medical bill
local bill = CalculateMedicalBill(Patient)
Patient.Functions.RemoveMoney('bank', bill, 'medical-bill')
-- Heal patient and teleport to bed
local bed = Config.AmbulanceJob.bedSpawns[bedIndex]
TriggerClientEvent('ambulance:client:bedRecovery', patientId, bed, bill)
-- Pay EMT for service
local salary = Config.AmbulanceJob.grades[EMT.PlayerData.job.grade.level].salary
EMT.Functions.AddMoney('bank', salary, 'ems-treatment-pay')
-- Release bed after recovery
SetTimeout(60000, function()
OccupiedBeds[bedIndex] = nil
end)
end)
function CalculateMedicalBill(Patient)
local baseCost = 500
local injuryMultiplier = 1.0
-- Could factor in injury severity, treatment count, etc.
return math.floor(baseCost * injuryMultiplier)
end
La facture médicale crée une conséquence économique en cas de décès qui équilibre l'économie des serveurs. Envisagez d'adapter la facture en fonction de la façon dont le joueur a été blessé, avec des coûts plus élevés pour un comportement imprudent comme des accidents à grande vitesse par rapport à des coûts inférieurs pour être victime d'un crime. Cela encourage une conduite prudente et ajoute du poids aux situations dangereuses.
Système de secours à réapparition automatique
Lorsqu'aucun joueur EMS n'est en service, le serveur doit fournir un chemin de récupération alternatif afin que les joueurs à terre ne soient pas bloqués de manière permanente. Implémentez un compte à rebours qui apparaît après un délai configurable, permettant au joueur de réapparaître à l'hôpital avec des frais médicaux forfaitaires déduits automatiquement. Le lieu de réapparition doit être à l’entrée de l’hôpital ou dans une zone de récupération désignée. Vérifiez toujours le nombre EMS actuel avant d'afficher l'option de réapparition automatique et rejetez-la immédiatement si un EMT réclame l'appel pendant le compte à rebours. Ce système à double voie garantit aux joueurs d'avoir toujours un moyen de récupérer tout en donnant la priorité à l'expérience de jeu de rôle de l'interaction EMS lorsque les médecins sont disponibles.
Fournitures médicales et intégration des stocks
Les joueurs EMS doivent avoir accès aux fournitures médicales via une réserve limitée à l'emploi à l'hôpital et via un système d'artisanat ou d'achat. Remplissez la réserve de l'hôpital de bandages, d'analgésiques, d'attelles, de perfusions intraveineuses, de poches de sang et de charges de défibrillateur. Chaque action de traitement consomme l’article correspondant, créant une demande continue de réapprovisionnement. Suivez l'utilisation des fournitures dans la base de données pour surveiller les modèles de consommation et réapprovisionner automatiquement les réserves hospitalières à des intervalles configurables. Pensez à fabriquer certaines fournitures pouvant être fabriquées par les joueurs ayant le rôle de pharmacien ou de médecin, créant ainsi des opportunités de jeu de rôle supplémentaires et des liens économiques entre les différents emplois du serveur.
Journalisation et surveillance des performances
Enregistrez chaque interaction EMS pour examen administratif, y compris qui a été traité, quels traitements ont été appliqués, l'EMT qui a répondu et la facture médicale finale. Stockez ces journaux dans une table de base de données dédiée et envoyez éventuellement des résumés à un webhook Discord pour une surveillance du personnel en temps réel. Ces journaux aident à résoudre les litiges, à identifier les acteurs EMS qui n'exécutent pas leurs tâches et à suivre l'état général du système. Du côté des performances, gardez la logique du contrôle de mort légère en l'exécutant uniquement sur les joueurs dont la santé est tombée à zéro, et non sur chaque joueur à chaque image. Utilisez une architecture basée sur les événements dans laquelle l'état de mort déclenche un événement sur un seul serveur plutôt qu'une interrogation. Le système de notification de répartition doit regrouper les alertes plutôt que d'envoyer des événements individuels à chaque acteur EMS, réduisant ainsi la surcharge du réseau lors de scénarios de pertes massives où plusieurs acteurs tombent simultanément.
