DRS Advanced Ambulance
Emprego de INEM completo, feito de raiz. Tem ferimentos por zona do corpo com efeitos reais e os estados inconsciente, ferido no chão e morto, cada um com o seu tempo. Tem ainda sinal de socorro e o menu do médico (F6) com painel do corpo, tratamentos, reanimação, desfibrilhador e RCP. Os médicos podem carregar o paciente e metê-lo no veículo, e passar contas. No hospital há check-in com camas. Inclui ainda um INEM por IA (NPC) para quando não há médicos de serviço, maca, colegas no mapa e proteção contra revive. Funciona com Qbox, QBCore (incluindo drs-core) e ESX, e é compatível com os scripts feitos para o qb-ambulancejob.
#Requisitos
| Recurso | Obrigatório |
|---|---|
oxmysql | Sim |
| Qbox, QBCore ou ESX | Sim (deteção automática) |
ox_inventory ou qb-inventory | Sim (itens médicos) |
ox_target ou qb-target | Não — dá opções diretas nos jogadores |
drs_dispatch ou cd_dispatch | Não — sem eles o sinal de socorro usa o alerta próprio |
#Instalação
- Coloca
drs_ambulancejobemresources. - Desliga o
qb-ambulancejob(ou o ambulancejob da tua base): os dois não podem estar ligados ao mesmo tempo. - Se usas um ecrã de morte à parte (ex.:
drs_deathscreen), desliga-o também: o DRS Advanced Ambulance já tem o seu. - Adiciona ao
server.cfg, depois da framework e do inventário:
ensure oxmysql
ensure qb-core
ensure qb-inventory
ensure drs_ambulancejob- Cria os itens (ver abaixo) e copia as imagens de
install/images/para o teu inventário. - Ajusta o
config.lua: empregos, tempos, preços e hospitais.
#Itens
QBCore — dentro de qb-core/shared/items.lua:
-- drs_ambulancejob: cola dentro de qb-core/shared/items.lua (drs-core: drs-core/shared/items.lua)
-- Imagens: copia install/images/*.png para a pasta de imagens do teu inventário (qb-inventory/html/images/)
bandage = { name = 'bandage', label = 'Ligadura', weight = 100, type = 'item', image = 'bandage.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Para hemorragias ligeiras' },
gauze = { name = 'gauze', label = 'Compressas', weight = 80, type = 'item', image = 'gauze.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Estanca hemorragias e feridas de bala' },
tourniquet = { name = 'tourniquet', label = 'Garrote', weight = 150, type = 'item', image = 'tourniquet.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Pára hemorragias graves num braço ou perna' },
splint = { name = 'splint', label = 'Tala', weight = 400, type = 'item', image = 'splint.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Imobiliza fraturas' },
burndressing = { name = 'burndressing', label = 'Penso para queimaduras', weight = 100, type = 'item', image = 'burndressing.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Trata queimaduras' },
painkillers = { name = 'painkillers', label = 'Analgésicos', weight = 50, type = 'item', image = 'painkillers.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Tiram a dor durante uns minutos' },
medkit = { name = 'medkit', label = 'Kit médico', weight = 1500, type = 'item', image = 'medkit.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'INEM: levanta quem está caído' },
defibrillator = { name = 'defibrillator', label = 'Desfibrilhador', weight = 4000, type = 'item', image = 'defibrillator.png', unique = true, useable = true, shouldClose = true, combinable = nil, description = 'INEM: reanima quem não tem pulso' },
firstaid = { name = 'firstaid', label = 'Kit de primeiros socorros', weight = 800, type = 'item', image = 'firstaid.png', unique = false, useable = true, shouldClose = true, combinable = nil, description = 'Levanta alguém que está caído' },ox_inventory / Qbox — dentro de ox_inventory/data/items.lua:
-- drs_ambulancejob: cola dentro de ox_inventory/data/items.lua
-- Imagens: copia install/images/*.png para ox_inventory/web/images/
['bandage'] = { label = 'Ligadura', weight = 100, stack = true, close = true, description = 'Para hemorragias ligeiras', client = { image = 'bandage.png' } },
['gauze'] = { label = 'Compressas', weight = 80, stack = true, close = true, description = 'Estanca hemorragias e feridas de bala', client = { image = 'gauze.png' } },
['tourniquet'] = { label = 'Garrote', weight = 150, stack = true, close = true, description = 'Pára hemorragias graves num braço ou perna', client = { image = 'tourniquet.png' } },
['splint'] = { label = 'Tala', weight = 400, stack = true, close = true, description = 'Imobiliza fraturas', client = { image = 'splint.png' } },
['burndressing'] = { label = 'Penso para queimaduras', weight = 100, stack = true, close = true, description = 'Trata queimaduras', client = { image = 'burndressing.png' } },
['painkillers'] = { label = 'Analgésicos', weight = 50, stack = true, close = true, description = 'Tiram a dor durante uns minutos', client = { image = 'painkillers.png' } },
['medkit'] = { label = 'Kit médico', weight = 1500, stack = true, close = true, description = 'INEM: levanta quem está caído', client = { image = 'medkit.png' } },
['defibrillator'] = { label = 'Desfibrilhador', weight = 4000, stack = false, close = true, description = 'INEM: reanima quem não tem pulso', client = { image = 'defibrillator.png' } },
['firstaid'] = { label = 'Kit de primeiros socorros', weight = 800, stack = true, close = true, description = 'Levanta alguém que está caído', client = { image = 'firstaid.png' } },ESX — importa na base de dados:
-- drs_ambulancejob: itens para ESX (es_extended)
INSERT IGNORE INTO `items` (`name`, `label`, `weight`) VALUES
('bandage', 'Ligadura', 1),
('gauze', 'Compressas', 1),
('tourniquet', 'Garrote', 1),
('splint', 'Tala', 4),
('burndressing', 'Penso para queimaduras', 1),
('painkillers', 'Analgésicos', 1),
('medkit', 'Kit médico', 15),
('defibrillator', 'Desfibrilhador', 40),
('firstaid', 'Kit de primeiros socorros', 8);| Item | O que trata | Quem usa |
|---|---|---|
bandage | Hemorragia ligeira | Qualquer pessoa, em si |
gauze | Hemorragia e ferida de bala | Qualquer pessoa, em si |
tourniquet | Hemorragia grave (só braços e pernas) | Qualquer pessoa, em si |
splint | Fraturas | Qualquer pessoa, em si |
burndressing | Queimaduras | Qualquer pessoa, em si |
painkillers | Tira os efeitos durante uns minutos | Qualquer pessoa, em si |
firstaid | Levanta quem está caído | Qualquer pessoa, noutro jogador |
medkit | Levanta quem está caído | Médicos |
defibrillator | Reanima um morto (dentro do prazo); não se gasta | Médicos |
#Como funciona
#Ferimentos
O tipo de ferimento vem do dano do GTA (bala, lâmina, pancada, queda, fogo, explosão, atropelamento, afogamento) e fica na zona do corpo atingida: cabeça, pescoço, peito, abdómen, braços ou pernas. Há hemorragia, ferida de bala, fratura, queimadura e asfixia, em 4 níveis. O colete protege o tronco das balas.
| Ferimento | Efeito |
|---|---|
| Hemorragia | Perde vida de tempos a tempos, com vinheta vermelha |
| Pernas ou coluna partidas | Coxeia e não corre |
| Braços partidos | A mira treme |
| Cabeça | Visão turva de vez em quando |
Os analgésicos tiram os efeitos durante Config.Injuries.painkillerTime segundos. Qualquer pessoa vê os seus ferimentos com /ferimentos.
#Estados
- Inconsciente: murros e pancadas (as armas de
Config.Knockout) só deixam a pessoa inconsciente durante uns segundos. - Ferido no chão: tem
downTimesegundos até morrer a sangrar. Carrega em G para mandar o sinal de socorro aos médicos de serviço, com ponto no mapa. - Morto: ao fim de
respawnTimesegundos pode renascer no hospital mais perto (segurando E), pagando a contarespawnPrice. Quem sai do jogo morto volta morto.
#Ecrã de morte
Em cada estado aparece o ecrã de morte: tempo que falta, monitor cardíaco com o batimento (abranda à medida que o tempo acaba), causa (tiro, queda, atropelamento…), arma, autor, distância e hora, as teclas G (socorro) e E (hospital) e quantos médicos estão de serviço. Tudo se liga e desliga em Config.DeathScreen.
#Menu do médico (F6)
Examinar (abre o painel do corpo, com os ferimentos de cada zona e os itens que os tratam), tratar, reanimar com o kit médico, desfibrilhador, RCP, carregar, meter e tirar do veículo, dar entrada no hospital e passar contas (o paciente aceita ou recusa).
Dica
O desfibrilhador só resulta nos primeiros defibWindow segundos depois da morte. Fazer RCP pára esse relógio enquanto chega o desfibrilhador.
#Hospital
O balcão de check-in trata quem chega só quando há poucos médicos de serviço (Config.CheckIn.maxDoctorsOnline). O jogador fica numa cama durante o tratamento. As camas e os pontos de cada hospital estão em Config.Hospitals.
#INEM por IA (NPC)
Quando não há médicos de serviço (Config.AIMedic.maxEmsOnline), quem está caído ou morto chama o INEM com G no ecrã de morte ou com /inem:
- No hospital mais perto aparecem dois paramédicos com as malas na mão, que vão a pé até à ambulância e entram.
- A ambulância vem com as luzes e a sirene ligadas até 5 m de ti. Se estiveres longe da estrada (
onFootDistance), deixam-na na estrada e vão a pé. Os carros dos NPC à volta travam para a deixar passar e, se ficar presa, aparece na estrada mais perto. - Um faz RCP e o outro fica de pé com a prancheta. O ecrã de morte mostra o estado: a caminho (com a distância), a pé e a tratar.
- No fim, o servidor reanima-te e cobra
Config.AIMedic.price. Os paramédicos voltam para a ambulância e vão-se embora.
Os pontos de cada hospital estão em Config.Hospitals[].aiMedic: ped (onde aparecem os paramédicos) e vehicle (onde está a ambulância). Com refuseGunshot, o INEM por IA não vai a feridos a tiro. Se um médico ou o staff te reanimar antes, a ambulância vai-se embora.
Nota
O INEM por IA tem ideias do FearX-NpcMedic (AGPL-3.0), usadas com autorização do autor. O código é nosso.
#Maca
O médico de serviço, junto à traseira de uma ambulância (Config.Stretcher.vehicles), carrega H para tirar a maca:
- E pegar ou largar a maca (a empurrar não se corre nem se entra em carros);
- G deitar o doente caído ou morto na maca, ou levantá-lo;
- H junto à traseira da ambulância: guarda a maca e, com doente, põe-no dentro da ambulância.
A maca é a do próprio GTA (prop_ld_binbag_01). As posições da maca e do doente afinam-se em Config.Stretcher.push e lie.
#Mapa e blips
- Hospitais e pedidos de socorro: ícone, cor e tamanho em
Config.Blips.hospitaleConfig.Blips.distress. - Colegas de serviço: cada médico de serviço vê os outros no mapa, mesmo longe (de
intervalemintervalsegundos). O ícone muda quando vão num veículo e desaparece quando saem de serviço.
#Menu do patrão
Contratar, despedir, cargos e dinheiro da empresa ficam no teu script de menu do patrão (drs_bossmenu ou qb-management). Em Config.BossMenu.mode:
'bossmenu'— usa o ponto desse script, com as coordenadas dele;'config'— o ambulance põe os pontos deConfig.BossMenu.pointse, no E, abre o menu do patrão desse script (que confirma se és chefe).
#Comandos
| Comando | Quem | O que faz |
|---|---|---|
/ferimentos | Todos | Ver os teus ferimentos |
/rcp | Todos | Fazer RCP ao jogador mais perto |
/carregar | Todos | Carregar o jogador mais perto |
| F6 | Médicos | Menu do paciente |
| G | Ferido | Sinal de socorro (sem médicos de serviço: chama o INEM por IA) |
/inem | Ferido | Chamar o INEM por IA (sem médicos de serviço) |
| H / E / G | Médicos | Maca: tirar e guardar, pegar e largar, deitar e levantar o doente |
/revive [id] | Staff | Reanimar |
/heal [id] | Staff | Curar |
/reviveall | Staff | Reanimar toda a gente |
#Opções principais
| Opção | Por defeito | Descrição |
|---|---|---|
Config.Locale | 'pt' | Idioma: pt ou en |
Config.Jobs | { 'ambulance' } | Empregos que contam como médicos |
Config.RequireDuty | true | Só de serviço para o menu e os alertas |
Config.Death.downTime | 180 | Segundos no chão até morrer |
Config.Death.respawnTime | 300 | Segundos morto até poder renascer |
Config.Death.respawnPrice | 2500 | Conta do hospital ao renascer |
Config.Death.clearInventory | false | Tirar os itens ao renascer |
Config.Death.defibWindow | 120 | Segundos em que o desfibrilhador resulta |
Config.CheckIn.price | 1500 | Preço do tratamento no balcão |
Config.BillToSociety | true | Contas vão para a conta da empresa |
Config.AIMedic.enabled | true | INEM por IA quando não há médicos de serviço |
Config.AIMedic.price | 2500 | Preço do INEM por IA |
Config.AIMedic.refuseGunshot | true | O INEM por IA não vai a feridos a tiro |
Config.Stretcher.enabled | true | Maca nas ambulâncias |
Config.Blips.colleagues.enabled | true | Médicos de serviço veem os colegas no mapa |
Config.BossMenu.mode | 'bossmenu' | Ponto do menu do patrão: o do teu script ou os do config |
Config.AntiCheat.enabled | true | Proteção contra revive |
#Configuração completa
Config = {}
-- ------------------------------------------------------------------ geral / general
Config.Locale = 'pt' -- 'pt' | 'en'
Config.Framework = 'auto' -- 'auto' | 'qb' | 'qbx' | 'esx' | 'none'
Config.UseOxNotify = false -- usar as notificações do ox_lib (se estiver ligado)
Config.Debug = false
-- empregos que contam como médicos (INEM) / jobs that count as EMS
Config.Jobs = { 'ambulance' }
Config.RequireDuty = true -- os médicos têm de estar de serviço para usar o menu e receber alertas
-- ------------------------------------------------------------------ morte / death
Config.Death = {
downTime = 180, -- segundos caído (ferido) até morrer a sangrar
respawnTime = 300, -- segundos morto até poder renascer no hospital
respawnHold = 3, -- segundos a segurar a tecla para renascer
respawnKey = 38, -- E (controlo do GTA)
distressKey = 47, -- G (controlo do GTA)
distressCooldown = 60, -- segundos entre sinais de socorro
defibWindow = 120, -- segundos depois de morrer em que o desfibrilhador ainda resulta (a RCP pára este relógio)
respawnPrice = 2500, -- conta do hospital ao renascer (0 = grátis)
clearInventory = false, -- tirar os itens ao renascer
keepItems = { 'id_card', 'driver_license', 'phone', 'radio' }, -- itens que nunca se perdem
downHealth = 150, -- vida com que fica caído (100 = morto, 200 = cheia)
reviveHealth = 130, -- vida depois de ser reanimado no local
}
-- Armas que só deixam a pessoa inconsciente (não a matam) / weapons that only knock out
Config.Knockout = {
enabled = true,
seconds = 25,
weapons = { 'WEAPON_UNARMED', 'WEAPON_BAT', 'WEAPON_GOLFCLUB', 'WEAPON_HAMMER', 'WEAPON_KNUCKLE', 'WEAPON_NIGHTSTICK',
'WEAPON_WRENCH', 'WEAPON_POOLCUE', 'WEAPON_FLASHLIGHT', 'WEAPON_CANDYCANE', 'WEAPON_SNOWBALL' },
}
-- ------------------------------------------------------------------ ferimentos / injuries
Config.Injuries = {
minDamage = 6, -- dano mínimo de um golpe para contar como ferimento
bleedTick = 20, -- segundos entre perdas de sangue
bleedDamage = 3, -- vida perdida por nível de hemorragia em cada tick
maxLevel = 4, -- nível máximo de cada ferimento (1 ligeiro · 2 moderado · 3 grave · 4 crítico)
limp = true, -- fraturas nas pernas/coluna: coxeia e não corre
armShake = true, -- fraturas nos braços: a mira treme
headBlur = true, -- ferimentos na cabeça: visão turva de vez em quando
painkillerTime = 300, -- segundos que os analgésicos tiram os efeitos
saveToDatabase = true, -- os ferimentos ficam guardados quando sai do servidor (metadata do QBCore)
}
-- ------------------------------------------------------------------ itens / items
-- cure: o que cada item trata. zone = escolhe a zona (no painel); self = pode usar em si próprio
Config.Items = {
bandage = { cure = { bleeding = 1 }, heal = 15, self = true, time = 4 },
gauze = { cure = { bleeding = 2, gunshot = 1 }, heal = 10, self = true, time = 5 },
tourniquet = { cure = { bleeding = 4 }, limbsOnly = true, self = true, time = 5 },
splint = { cure = { fracture = 4 }, self = true, time = 7 },
burndressing = { cure = { burn = 3 }, self = true, time = 5 },
painkillers = { painkiller = true, heal = 5, self = true, time = 3 },
medkit = { revive = 'down', heal = 40, self = false, time = 8, emsOnly = true }, -- levanta quem está caído
defibrillator = { revive = 'dead', self = false, time = 6, emsOnly = true, keep = true }, -- reanima um morto (dentro do prazo); não gasta
firstaid = { revive = 'down', heal = 20, self = false, time = 12, emsOnly = false }, -- kit de primeiros socorros: qualquer pessoa
}
-- ------------------------------------------------------------------ menu dos médicos / EMS menu
Config.MenuKey = 'F6'
Config.InteractDistance = 3.0
Config.BillMax = 50000
Config.BillToSociety = true -- o dinheiro das contas vai para a conta da empresa (qb-banking / qb-management / Renewed)
-- ------------------------------------------------------------------ hospitais / hospitals
Config.CheckIn = {
price = 1500, -- preço do tratamento no balcão
maxDoctorsOnline = 2, -- com mais médicos de serviço do que isto, o balcão não trata (vai ter com eles)
time = 15, -- segundos na cama
key = 38, -- E
}
Config.Hospitals = {
{
label = 'Pillbox Hill',
checkin = vector3(308.19, -595.35, 43.29),
respawn = vector4(298.74, -584.33, 43.26, 70.0),
blip = vector3(298.74, -584.33, 43.26),
-- INEM por IA: onde aparecem os paramédicos (vão a pé até à ambulância) e onde está a ambulância
aiMedic = { ped = vector4(298.74, -584.33, 43.26, 160.0), vehicle = vector4(294.30, -607.90, 43.33, 70.0) },
beds = {
vector4(353.10, -584.60, 43.11, 152.08), vector4(356.79, -585.86, 43.11, 152.08), vector4(354.12, -593.12, 43.10, 336.32),
vector4(350.79, -591.80, 43.10, 336.32), vector4(346.99, -590.48, 43.10, 336.32), vector4(360.32, -587.19, 43.02, 152.08),
},
},
{
label = 'Paleto Bay',
checkin = vector3(-254.54, 6331.78, 32.43),
respawn = vector4(-248.97, 6331.42, 32.43, 225.0),
blip = vector3(-254.54, 6331.78, 32.43),
aiMedic = { ped = vector4(-248.97, 6331.42, 32.43, 315.0), vehicle = vector4(-262.10, 6346.00, 32.40, 315.0) },
beds = {
vector4(-252.43, 6312.25, 32.34, 313.48), vector4(-247.04, 6317.95, 32.34, 134.64), vector4(-255.98, 6315.67, 32.34, 313.91),
},
},
{
label = 'Sandy Shores',
checkin = vector3(1839.36, 3672.90, 34.28),
respawn = vector4(1836.02, 3670.52, 34.28, 210.0),
blip = vector3(1839.36, 3672.90, 34.28),
aiMedic = { ped = vector4(1836.02, 3670.52, 34.28, 30.0), vehicle = vector4(1828.80, 3693.60, 34.22, 30.0) },
beds = {},
},
}
-- ------------------------------------------------------------------ alertas / alerts
Config.Alerts = {
blipTime = 90, -- segundos que o ponto do pedido de socorro fica no mapa dos médicos
sound = true,
}
-- ------------------------------------------------------------------ menu do patrão (contratar, despedir, cargos, dinheiro)
-- mode = 'bossmenu' -> usa o ponto do teu script de menu do patrão (drs_bossmenu / qb-management), com as coords DELE
-- mode = 'config' -> o ambulance põe os pontos de baixo e, no [E], abre o menu do patrão desse script (só para chefes)
Config.BossMenu = {
mode = 'bossmenu',
points = { vector3(335.46, -594.52, 43.28) }, -- só com mode = 'config'
resource = 'auto', -- 'auto' | 'drs_bossmenu' | 'qb-management'
key = 38, -- E
}
-- ------------------------------------------------------------------ blips (mapa)
Config.Blips = {
hospital = { sprite = 61, color = 2, scale = 0.8, shortRange = true }, -- hospitais (toda a gente)
distress = { sprite = 153, color = 1, scale = 1.1, flash = true }, -- pedido de socorro (médicos de serviço)
-- colegas de serviço: cada médico de serviço vê os outros no mapa (mesmo longe)
colleagues = { enabled = true, sprite = 1, vehicleSprite = 56, color = 1, scale = 0.75, interval = 3, heading = true, label = 'INEM' },
}
-- ------------------------------------------------------------------ maca / stretcher
-- O médico tira a maca da traseira da ambulância, empurra-a até ao doente, deita-o nela e volta a pô-la na ambulância
-- (com o doente lá dentro). Usa a maca do próprio GTA (prop_ld_binbag_01), sem modelos de fora.
Config.Stretcher = {
enabled = true,
emsOnly = true, -- só os médicos de serviço tiram a maca
model = 'prop_ld_binbag_01',
vehicles = { 'ambulance' }, -- veículos que trazem maca (modelos)
rearDistance = 3.0, -- distância à traseira do veículo para tirar / guardar
keys = { grab = 38, patient = 47, vehicle = 74 }, -- E pegar/largar · G deitar/levantar o doente · H tirar/guardar na ambulância
labels = { grab = 'E', patient = 'G', vehicle = 'H' }, -- texto das teclas no ecrã
-- posição da maca à frente de quem empurra e do doente deitado nela (afinar se precisares)
push = { offset = vector3(0.0, 1.45, -0.43), rot = vector3(0.0, 0.0, 180.0) },
lie = { offset = vector3(0.0, 0.0, 1.38), rot = vector3(0.0, 0.0, 180.0) },
}
-- ------------------------------------------------------------------ INEM por IA / AI medic
-- Quando não há médicos de serviço, quem está caído/morto chama uma ambulância do hospital mais perto (Config.Hospitals[].aiMedic):
-- dois paramédicos saem a pé com as malas, entram na ambulância e vão com as luzes ligadas até ti. Se estiveres longe
-- da estrada, deixam a ambulância na estrada e vão a pé. O servidor é que reanima e cobra.
Config.AIMedic = {
enabled = true,
maxEmsOnline = 0, -- só aparece quando os médicos de serviço são no máximo este número
refuseGunshot = true, -- não vai a feridos a tiro (ficam para os médicos a sério ou para o hospital)
onDistress = true, -- o [G] do ecrã de morte chama o INEM por IA quando não há médicos
command = 'inem', -- comando para chamar ('' = sem comando)
price = 2500, -- cobrado do banco (ou do dinheiro) quando és reanimado
pedModel = 's_m_m_paramedic_01',
vehicleModel = 'ambulance',
crew = 2, -- paramédicos na ambulância (1 ou 2)
speed = 35.0, -- m/s (~125 km/h) com as luzes e a sirene ligadas
drivingStyle = 787004, -- condução de emergência (passa os semáforos, contorna os carros)
stopDistance = 5.0, -- pára a esta distância de ti
onFootDistance = 20.0, -- mais longe do que isto da estrada: deixa a ambulância na estrada e vai a pé
maxDriveSeconds = 150, -- se demorar mais (preso no trânsito), a ambulância aparece na estrada mais perto de ti
reviveSeconds = 12, -- tempo do tratamento
minSeconds = 15, -- o servidor não aceita uma reanimação antes disto (desde a chamada)
cooldown = 120, -- segundos entre chamadas
-- mala na mão (prop do jogo base); se não existir usa o kit pequeno
bag = { model = 'xm_prop_x17_bag_med_01a', fallback = 'prop_ld_health_pack', bone = 57005,
offset = vector3(0.28, 0.0, -0.02), rot = vector3(0.0, 270.0, 70.0) },
blip = { sprite = 56, color = 1, label = 'INEM (IA)' },
}
-- ------------------------------------------------------------------ ecrã de morte / death screen
Config.DeathScreen = {
showCause = true, -- causa (tiro, queda, atropelamento…)
showWeapon = true, -- arma que te deitou abaixo
showKiller = true, -- id de quem te deitou abaixo (#12)
showDistance = true, -- distância a que estava quem te atacou
showEms = true, -- quantos médicos estão de serviço
sound = { enabled = true, volume = 0.25 }, -- bip do monitor quando estás caído (sem ficheiros de som)
-- batimento cardíaco (bpm) mostrado no monitor
bpm = { knocked = 64, downStart = 78, downEnd = 36 }, -- caído: começa em downStart e desce até downEnd quando o tempo acaba
keys = { distress = 'G', respawn = 'E' }, -- só o texto das teclas (as teclas são Config.Death.distressKey/respawnKey)
}
-- ------------------------------------------------------------------ proteção contra revive / anti-revive
-- Caído ou morto, só sais desse estado pelo servidor: /revive (staff), médico com o item, cama do hospital,
-- renascer no hospital quando o tempo acaba, ou o "Heal" do txAdmin. Mod menus que se reanimam sozinhos são apanhados.
Config.AntiCheat = {
enabled = true,
-- scripts de outros (TriggerClientEvent('hospital:client:Revive', id)) ainda podem reanimar? false = só os caminhos acima
externalRevive = false,
maxMove = 12.0, -- metros que um jogador caído/morto pode "andar" em 2 s sem estar carregado ou num veículo
blockShooting = true, -- o dano feito por quem está caído/morto é anulado
action = 'log', -- 'log' = só regista e repõe · 'kick' = expulsa ao fim de kickAfter deteções
kickAfter = 3,
}
-- Webhook do Discord para registos (reanimações, contas, check-ins). Vazio = desligado.
Config.Webhook = ''#Compatibilidade com o qb-ambulancejob
O recurso faz provide 'qb-ambulancejob' e responde aos eventos hospital:client:Revive, hospital:client:HealInjuries e hospital:client:KillPlayer, e mantém a metadata isdead e inlaststand. Os scripts feitos para o qb-ambulancejob (HUD, telemóvel, polícia…) funcionam sem mudanças — menos o revive dos menus de admin (ver abaixo).
Importante
O teu menu de admin tem de receber estas linhas para conseguir dar revive. Com a proteção contra revive ligada (Config.AntiCheat), quem está caído ou morto só é reanimado pelo servidor. Os menus de admin que reanimam com TriggerClientEvent('hospital:client:Revive', id) (izzy-admin, ps-adminmenu, qb-adminmenu…) deixam de reanimar quem está caído ou morto, porque um mod menu consegue disparar esse mesmo evento. No ficheiro do servidor do teu menu de admin, troca a linha do revive pela de baixo. O /revive [id] e o "Heal" do txAdmin funcionam sempre, sem mudanças. Se preferires não mexer no menu, põe Config.AntiCheat.externalRevive = true (mas assim um mod menu também se consegue reanimar).
TriggerClientEvent('hospital:client:Revive', id)if GetResourceState('drs_ambulancejob') == 'started' then
TriggerEvent('drs_ambulancejob:revivePlayer', id) -- reanimar um jogador
else
TriggerClientEvent('hospital:client:Revive', id)
endPara reanimar todos:
for _, p in ipairs(GetPlayers()) do TriggerEvent('drs_ambulancejob:revivePlayer', tonumber(p)) end#Proteção contra revive
Caído ou morto, só se sai desse estado pelo servidor: /revive do staff, médico com o item, cama do hospital, renascer no hospital quando o tempo acaba ou o "Heal" do txAdmin.
- Os eventos de reanimação disparados no próprio cliente (mod menus) são ignorados: o cliente só obedece ao estado que o servidor confirma.
- Quem está caído ou morto e se mexe mais de
maxMovemetros em 2 segundos (sem estar a ser carregado nem num veículo) volta para onde estava e o estado é reposto. - O dano feito por quem está caído ou morto é anulado (
blockShooting). - Cada deteção fica no webhook e na consola. Com
action = 'kick'o jogador é expulso ao fim dekickAfterdeteções. O teu anticheat pode ouvirAddEventHandler('drs_ambulancejob:cheatSuspect', function(src, motivo, n) end).
#Para programadores
exports.drs_ambulancejob:GetState(src) -- 'alive' | 'knocked' | 'down' | 'dead'
exports.drs_ambulancejob:IsDead(src)
exports.drs_ambulancejob:Revive(src)
exports.drs_ambulancejob:GetInjuries(src)
exports.drs_ambulancejob:SetInjuries(src, lista)
exports.drs_ambulancejob:SendAlert(src, coords, rua)
AddEventHandler('drs_ambulancejob:stateChanged', function(src, estado, anterior) end)exports.drs_ambulancejob:IsDead()
exports.drs_ambulancejob:GetState()
exports.drs_ambulancejob:GetInjuries()#Segurança
O servidor é dono do estado e dos ferimentos. Valida o emprego, a distância, os itens e os tempos de cada ação: ninguém se reanima a si próprio nem trata quem está longe. Ver também a proteção contra revive.
#Resolução de problemas
Aparecem dois ecrãs de morte — tens outro script de morte ligado (qb-ambulancejob, drs_deathscreen…). Desliga-o.
O F6 não abre — tens de ter um emprego de Config.Jobs e, com Config.RequireDuty, estar de serviço.
Os médicos não recebem o sinal de socorro — têm de estar de serviço. Se usas o drs_dispatch ou o cd_dispatch, o alerta aparece lá.
O desfibrilhador não resulta — passaram mais de defibWindow segundos desde a morte. Faz RCP enquanto o desfibrilhador não chega.
O INEM por IA não vem — há médicos de serviço (maxEmsOnline), tens feridas de bala (refuseGunshot), chamaste há pouco (cooldown) ou o hospital não tem aiMedic no config.
A maca não sai da ambulância — o modelo da tua ambulância tem de estar em Config.Stretcher.vehicles e tens de estar de serviço, junto à traseira.