Visão geral do sistema de trabalho de ambulância
Um script de trabalho de ambulância é essencial para qualquer servidor de roleplay que pretenda uma jogabilidade imersiva de serviços de emergência. O sistema EMS cuida de tudo, desde o recebimento de chamadas de despacho quando um jogador cai até a mecânica de tratamento no local, transporte hospitalar e cobrança médica. Um script de ambulância bem projetado cria uma jogabilidade significativa para jogadores EMS, ao mesmo tempo que garante que jogadores abatidos não fiquem esperando indefinidamente. A arquitetura se divide em quatro subsistemas principais: o sistema de despacho e notificação que alerta o EMS sobre incidentes, a mecânica de tratamento e estabilização que dá aos médicos tarefas reais para executar, o processo de check-in e recuperação do hospital e o sistema de cobrança que cria um custo econômico para lesões. Cada subsistema precisa funcionar de forma independente para que, se nenhum jogador do EMS estiver de serviço, os sistemas de fallback automáticos cuidem da recuperação do jogador.
Configuração de trabalho e sistema de serviço
O trabalho de ambulância requer graus claramente definidos com diferentes capacidades em cada nível. Os estagiários podem apenas realizar primeiros socorros básicos, enquanto os paramédicos seniores podem administrar tratamentos avançados e ter acesso a suprimentos médicos restritos. Use uma tabela de configuração que mapeie as classificações de cargos para ações disponíveis, itens obrigatórios e taxas de pagamento. O sistema de serviço deve rastrear quais jogadores EMS estão ativos no momento para que o servidor saiba se deve usar o retorno automático de respawn:
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),
},
}A configuração minOnDutyForNoAutoRespawn controla quando o servidor alterna entre recuperação automática e dependente de EMS. Quando menos de dois EMS estão em serviço, os jogadores abatidos recebem uma opção de reaparecimento baseada em cronômetro após esperar o número configurado de segundos. Isso evita que os jogadores fiquem presos à espera de cuidados médicos que nunca chegarão.
Sistema de Despacho e Notificação
Quando um jogador está incapacitado, o sistema transmite um alerta de despacho para todos os jogadores do EMS em serviço, mostrando a localização, a natureza da emergência e uma forma de reivindicar a chamada. Vários jogadores do EMS podem ver o alerta, mas apenas um deve reivindicá-lo para evitar confusão. Implemente um sistema de reclamação em que o primeiro atendente que aceitar a chamada receba a atribuição e outros EMS a vejam como reivindicada com o identificador da unidade respondente:
-- 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)Inclua a causa da morte nas informações de despacho para que o paramédico responsável possa preparar os itens de tratamento apropriados antes de chegar ao local. Causas comuns, como ferimentos a bala, colisões de veículos, quedas e afogamentos, exigem diferentes abordagens de tratamento, o que acrescenta profundidade à experiência de RPG do EMS.
Mecânica de Tratamento e Revitalização
A mecânica do tratamento deveria envolver mais do que simplesmente apertar um botão para reanimar alguém. Crie um processo de várias etapas em que o paramédico deve primeiro estabilizar o paciente com tratamentos básicos antes de realizar a reanimação real. Cada etapa do tratamento consome um item do inventário do paramédico e leva um determinado período de tempo com uma animação de barra de progresso. A condição do paciente pode ser modelada com um estado de saúde simples que melhora com cada tratamento aplicado:
-- 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
)
endA barra de progresso com animação cria uma cena de tratamento realista que outros jogadores podem observar, melhorando a atmosfera do RPG. Faça do desfibrilador a etapa final que realmente realiza a revivificação, exigindo que o paramédico primeiro estabilize o paciente com curativos e analgésicos. Essa abordagem de várias etapas torna a função do EMS mais envolvente do que uma simples revitalização com um clique.
Check-in e recuperação hospitalar
Depois de reanimar um paciente em campo ou transportá-lo para o hospital, um jogador do EMS pode colocá-lo em uma cama de hospital para recuperação total. O processo de check-in cura completamente o paciente, cobra uma conta médica e registra a consulta. Os leitos hospitalares devem ser rastreados para evitar que vários pacientes sejam alocados no mesmo leito. Crie um sistema de gerenciamento de leitos que marque os leitos como ocupados e os libere após um tempo de recuperação configurável:
-- 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)
endA conta médica cria uma consequência econômica para a morte que equilibra a economia do servidor. Considere dimensionar a conta com base em como o jogador foi ferido, com custos mais elevados por comportamento imprudente, como colisões em alta velocidade, versus custos mais baixos por ser vítima de um crime. Isto incentiva uma condução cuidadosa e acrescenta peso a situações perigosas.
Sistema substituto de reaparecimento automático
Quando nenhum jogador EMS estiver de serviço, o servidor deve fornecer um caminho de recuperação alternativo para que os jogadores caídos não fiquem permanentemente presos. Implemente um cronômetro de contagem regressiva que aparece após um atraso configurável, permitindo ao jogador reaparecer no hospital com uma taxa médica fixa deduzida automaticamente. O local de reaparecimento deve ser na entrada do hospital ou em uma área de recuperação designada. Sempre verifique a contagem atual do EMS antes de mostrar a opção de reaparecimento automático e descarte-a imediatamente se um paramédico reivindicar a chamada durante a contagem regressiva. Este sistema de caminho duplo garante que os jogadores sempre tenham uma maneira de se recuperar, ao mesmo tempo que prioriza a experiência de roleplay da interação EMS quando os médicos estão disponíveis.
Suprimentos médicos e integração de estoque
Os jogadores do EMS precisam de acesso a suprimentos médicos por meio de um estoque com restrição de trabalho no hospital e por meio de um sistema de elaboração ou compra. Abasteça o estoque do hospital com bandagens, analgésicos, talas, soro intravenoso, bolsas de sangue e cargas de desfibrilador. Cada ação de tratamento consome o item correspondente, criando uma demanda contínua por reabastecimento. Rastreie o uso de suprimentos no banco de dados para monitorar padrões de consumo e reabastecer automaticamente os estoques hospitalares em intervalos configuráveis. Considere tornar alguns suprimentos fabricáveis por jogadores com funções de farmacêutico ou médico, criando oportunidades adicionais de interpretação e conexões econômicas entre diferentes trabalhos no servidor.
Registro em log e monitoramento de desempenho
Registre todas as interações do EMS para revisão administrativa, incluindo quem foi tratado, quais tratamentos foram aplicados, o EMT respondente e a conta médica final. Armazene esses logs em uma tabela de banco de dados dedicada e, opcionalmente, envie resumos para um webhook do Discord para monitoramento da equipe em tempo real. Esses registros ajudam a resolver disputas, identificar os participantes do EMS que não estão desempenhando suas funções e monitorar a integridade geral do sistema. Do lado do desempenho, mantenha a lógica de verificação de morte leve, executando-a apenas em jogadores cuja saúde caiu para zero, e não em todos os jogadores a cada frame. Use uma arquitetura orientada a eventos onde o estado de morte aciona um único evento de servidor em vez de uma pesquisa. O sistema de notificação de despacho deve enviar alertas em lote, em vez de enviar eventos individuais para cada jogador do EMS, reduzindo a sobrecarga da rede durante cenários de vítimas em massa, onde vários jogadores caem simultaneamente.
