Wróć do bloga
Tutorial9 min czytania

System szpitala i EMS w FiveM: oskryptuj realistyczne prace medyczne

Zaprojektuj pełną pętlę szpitala i EMS dla FiveM. Ożywianie, rejestracja pacjentów, apteka, powiązania z karetkami i najlepsze skrypty medyczne do roleplay.

Agency Scripts

Założyciel i główny deweloper w Agency Scripts

Architektura systemu szpitalnego

System szpitala i EMS całkowicie zmienia sposób, w jaki gracze doświadczają zdrowia i obrażeń na serwerze roleplay FiveM. Zamiast zwykłego odrodzenia po powaleniu, gracze trafiają do ścieżki medycznego roleplayu, w której mogą zostać ustabilizowani przez EMS w terenie, przetransportowani karetką, przyjęci do szpitala, zdiagnozowani, wyleczeni i rozliczeni za usługi. Architektura systemu dzieli się na cztery połączone ze sobą warstwy: system obrażeń śledzący co i w jakim miejscu ciała przydarzyło się graczowi, narzędzia dispatchu i działań w terenie dla EMS, proces przyjęcia i leczenia w szpitalu oraz system fakturowania łączący opiekę medyczną z ekonomią serwera. Każda warstwa komunikuje się za pośrednictwem eventów serwerowych, dzięki czemu lekarz zajmujący się pacjentem widzi dokładnie, jakie obrażenia ratownik EMS udokumentował już podczas segregacji medycznej w terenie. Zbudowanie tego jako jednolitego systemu zamiast oddzielnych skryptów gwarantuje, że dane pacjenta przepływają bezproblemowo od momentu zgłoszenia pod 911 aż do chwili opuszczenia szpitala z rachunkiem w dłoni.

System typów obrażeń

Szczegółowy system obrażeń zastępuje binarny stan życia lub śmierci szerokim zakresem stanów wymagających różnego leczenia. Śledź obrażenia według partii ciała, stopnia ciężkości i przyczyny, aby EMS i lekarze mogli odgrywać realistyczne scenariusze medyczne. Gdy gracz odnosi obrażenia, określ typ urazu na podstawie hasha broni lub przyczyny śmierci i przypisz go do odpowiedniej części ciała. Rany postrzałowe tułowia są groźniejsze niż uderzenie pięścią w ramię, a każdy typ obrażeń ma określone wymagania dotyczące leczenia, których lekarze muszą przestrzegać:

Config.InjuryTypes = {
    gunshot = {
        label = 'Gunshot Wound',
        severity = { min = 60, max = 100 },
        bleedRate = 2.5,
        treatments = {'clean_wound', 'remove_bullet', 'stitch', 'bandage'},
        requiredItems = {'tweezers', 'suture_kit', 'bandage'},
        healTime = 120,
    },
    stabbing = {
        label = 'Stab Wound',
        severity = { min = 40, max = 80 },
        bleedRate = 1.8,
        treatments = {'clean_wound', 'stitch', 'bandage'},
        requiredItems = {'suture_kit', 'bandage'},
        healTime = 90,
    },
    blunt = {
        label = 'Blunt Force Trauma',
        severity = { min = 20, max = 60 },
        bleedRate = 0.5,
        treatments = {'examine', 'ice_pack', 'painkillers'},
        requiredItems = {'ice_pack', 'painkillers'},
        healTime = 60,
    },
    burn = {
        label = 'Burn Injury',
        severity = { min = 30, max = 90 },
        bleedRate = 0,
        treatments = {'cool_burn', 'apply_cream', 'bandage'},
        requiredItems = {'burn_cream', 'bandage'},
        healTime = 100,
    },
    fracture = {
        label = 'Bone Fracture',
        severity = { min = 50, max = 70 },
        bleedRate = 0,
        treatments = {'x_ray', 'set_bone', 'apply_cast'},
        requiredItems = {'splint', 'cast_material'},
        healTime = 180,
    },
    vehicle_crash = {
        label = 'Vehicle Collision Injury',
        severity = { min = 30, max = 95 },
        bleedRate = 1.0,
        treatments = {'examine', 'clean_wound', 'stitch', 'bandage', 'painkillers'},
        requiredItems = {'suture_kit', 'bandage', 'painkillers'},
        healTime = 110,
    },
}

Config.BodyRegions = {
    'head', 'torso', 'left_arm', 'right_arm', 'left_leg', 'right_leg'
}

-- Severity multipliers per body region
Config.RegionMultipliers = {
    head = 1.5,
    torso = 1.3,
    left_arm = 0.8,
    right_arm = 0.8,
    left_leg = 0.9,
    right_leg = 0.9,
}

EMS Dispatch i interwencje w terenie

System dispatch EMS łączy powalonych graczy z medykami na służbie. Gdy gracz przechodzi w stan powalenia, może zadzwonić pod 911, co tworzy zgłoszenie dispatch widoczne dla wszystkich funkcjonariuszy EMS na służbie. Zgłoszenie zawiera współrzędne GPS dzwoniącego, krótki opis wygenerowany na podstawie danych o obrażeniach oraz poziom priorytetu zależny od ciężkości urazów. Medycy EMS mogą przyjąć zgłoszenie przez UI dispatch, co oznacza zgłoszenie jako przyjęte i uruchamia nawigację GPS do pacjenta. Wprowadź timer czasu reakcji, który śledzi czas od utworzenia zgłoszenia do kontaktu z pacjentem, przydatny do monitorowania efektywności EMS i dostosowywania obsady. Leczenie polowe to uproszczona wersja leczenia szpitalnego, w której EMS może stabilizować pacjentów za pomocą podstawowych środków medycznych, takich jak bandaże, opaski uciskowe i zastrzyki z adrenaliny, aby zapobiec śmierci podczas transportu:

-- Server-side dispatch handler
local activeDispatches = {}

RegisterNetEvent('hospital:server:call911', function(description)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    local ped = GetPlayerPed(src)
    local coords = GetEntityCoords(ped)
    local injuries = Player.Functions.GetMetaData('injuries') or {}

    -- Determine priority from injury severity
    local maxSeverity = 0
    for _, injury in ipairs(injuries) do
        if injury.severity > maxSeverity then
            maxSeverity = injury.severity
        end
    end

    local priority = maxSeverity >= 80 and 'CRITICAL' or maxSeverity >= 50 and 'URGENT' or 'STANDARD'

    local dispatch = {
        id = #activeDispatches + 1,
        callerId = src,
        citizenid = Player.PlayerData.citizenid,
        callerName = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname,
        coords = { x = coords.x, y = coords.y, z = coords.z },
        description = description or GenerateInjuryDescription(injuries),
        priority = priority,
        injuries = injuries,
        timestamp = os.time(),
        status = 'pending',
        responderId = nil,
    }

    table.insert(activeDispatches, dispatch)

    -- Notify all on-duty EMS
    local emsPlayers = QBCore.Functions.GetQBPlayers()
    for _, emsPlayer in pairs(emsPlayers) do
        if emsPlayer.PlayerData.job.name == 'ambulance' and emsPlayer.PlayerData.job.onduty then
            TriggerClientEvent('hospital:client:newDispatch', emsPlayer.PlayerData.source, dispatch)
        end
    end
end)

RegisterNetEvent('hospital:server:acceptDispatch', function(dispatchId)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player or Player.PlayerData.job.name ~= 'ambulance' then return end

    for i, dispatch in ipairs(activeDispatches) do
        if dispatch.id == dispatchId and dispatch.status == 'pending' then
            dispatch.status = 'responding'
            dispatch.responderId = src
            dispatch.responseTime = os.time()

            -- Notify caller
            TriggerClientEvent('QBCore:Notify', dispatch.callerId, 'EMS is on the way!', 'success')
            -- Set GPS blip for responder
            TriggerClientEvent('hospital:client:setDispatchGPS', src, dispatch.coords)
            break
        end
    end
end)

UI rejestracji i leczenia w szpitalu

System rejestracji w szpitalu zarządza przepływem pacjentów od przyjęcia do wypisu. Gdy ratownik EMS przywozi pacjenta do szpitala lub gracz przychodzi sam, wchodzi w interakcję z NPC w recepcji lub target pointem, aby się zameldować. Proces rejestracji tworzy kartę pacjenta zawierającą aktualne obrażenia, parametry życiowe oraz unikalny visit ID do celów rozliczeniowych. Lekarze na służbie widzą przyjmowanych pacjentów w panelu NUI zarządzania szpitalem, który wyświetla kolejkę w poczekalni, priorytet segregacji medycznej (triage) każdego pacjenta oraz jego udokumentowane obrażenia. Gdy lekarz wybierze pacjenta, otwiera się UI leczenia z diagramem ciała pacjenta i wyróżnionymi miejscami urazów. Lekarz klika poszczególne obrażenia, aby zobaczyć wymagane etapy leczenia, i może wykonywać każdy krok po kolei, co uruchamia animacje oraz zużywa materiały medyczne z ekwipunku. Każdy krok leczenia ma pasek postępu i test powodzenia zależny od metadanych umiejętności lekarza, dodając element progresji do roleplayu medycznego.

Przebieg leczenia

Zaprojektuj przebieg leczenia jako proces krok po kroku, w którym każdy uraz wymaga określonych działań wykonywanych w odpowiedniej kolejności. Rana postrzałowa tułowia może wymagać oczyszczenia rany, wyciągnięcia kuli pęsetą, zszycia rany zestawem chirurgicznym i nałożenia bandaża. Każdy krok zużywa odpowiedni przedmiot z ekwipunku lekarza i odtwarza animację leczenia. Pominięcie kroków lub wykonanie ich w złej kolejności powinno zakończyć się niepowodzeniem lub zmniejszyć skuteczność, zachęcając do właściwego medical roleplay. Po wyleczeniu wszystkich obrażeń pacjent wchodzi w okres rekonwalescencji, w którym jego zdrowie stopniowo się regeneruje, zamiast natychmiastowego przywrócenia:

RegisterNetEvent('hospital:server:treatInjury', function(patientId, injuryIndex, treatmentStep)
    local src = source
    local Doctor = QBCore.Functions.GetPlayer(src)
    local Patient = QBCore.Functions.GetPlayer(patientId)

    if not Doctor or not Patient then return end
    if Doctor.PlayerData.job.name ~= 'ambulance' or not Doctor.PlayerData.job.onduty then
        TriggerClientEvent('QBCore:Notify', src, 'You must be on duty', 'error')
        return
    end

    local injuries = Patient.Functions.GetMetaData('injuries') or {}
    local injury = injuries[injuryIndex]
    if not injury then return end

    local injuryConfig = Config.InjuryTypes[injury.type]
    if not injuryConfig then return end

    -- Validate treatment step order
    local expectedStep = injury.currentStep or 1
    if treatmentStep ~= expectedStep then
        TriggerClientEvent('QBCore:Notify', src, 'Complete previous treatment steps first', 'error')
        return
    end

    local stepName = injuryConfig.treatments[treatmentStep]
    if not stepName then return end

    -- Check required item
    local requiredItem = Config.TreatmentItems[stepName]
    if requiredItem then
        local hasItem = Doctor.Functions.GetItemByName(requiredItem.name)
        if not hasItem or hasItem.amount < 1 then
            TriggerClientEvent('QBCore:Notify', src, 'Missing: ' .. requiredItem.label, 'error')
            return
        end
        Doctor.Functions.RemoveItem(requiredItem.name, 1)
    end

    -- Apply treatment
    injury.currentStep = treatmentStep + 1
    injury.treated = treatmentStep >= #injuryConfig.treatments

    if injury.treated then
        injury.bleedRate = 0
        injury.healStartTime = os.time()
    end

    injuries[injuryIndex] = injury
    Patient.Functions.SetMetaData('injuries', injuries)

    -- Notify both parties
    TriggerClientEvent('QBCore:Notify', src, 'Treatment step complete: ' .. stepName, 'success')
    TriggerClientEvent('QBCore:Notify', patientId, 'You received treatment: ' .. stepName, 'success')
    TriggerClientEvent('hospital:client:updateInjuries', patientId, injuries)
end)

System On-Duty i Off-Duty

System służby kontroluje, kiedy personel EMS i szpitala jest aktywny oraz może odbierać zgłoszenia dispatch. Gdy gracz z pracą medyka rozpoczyna służbę w punkcie na terenie szpitala, uzyskuje dostęp do komend medycznych, otrzymuje powiadomienia dispatch i pojawia się na aktywnej liście EMS widocznej dla reszty personelu. System służby powinien rejestrować czas wejścia i zejścia ze służby na potrzeby naliczania wypłat, jeśli twój serwer korzysta z automatycznych wynagrodzeń. Wprowadź różne role w ramach pracy EMS, takie jak ratownik medyczny, lekarz i chirurg, gdzie każda rola ma dostęp do innych możliwości leczenia. Ratownik medyczny może stabilizować pacjentów w terenie i przeprowadzać podstawowe zabiegi, lekarz radzi sobie ze standardowymi procedurami szpitalnymi, a chirurg wykonuje skomplikowane operacje, takie jak wyciąganie kul czy nastawianie kości. Zapisuj listę obecności we wspólnym stanie serwera, aby system dispatch mógł dokładnie zliczać dostępnych ratowników i dostosowywać licznik auto-respawnu dla powalonych graczy na podstawie dostępności EMS.

System rozliczeń medycznych

Rozliczenia medyczne łączą system szpitalny z ekonomią serwera i tworzą finansowe konsekwencje ryzykownych zachowań. Gdy pacjent jest leczony, system generuje szczegółowy rachunek zawierający każdy wykonany zabieg, zużyte materiały oraz opłaty placówki. Rachunki można opłacić przy wypisie w recepcji, pobrać bezpośrednio z konta bankowego pacjenta lub wysłać jako fakturę, którą pacjent musi uregulować w określonym terminie. Wdróż system ubezpieczeń medycznych, w którym gracze mogą wykupić polisy pokrywające określony procent kosztów leczenia, zmniejszając finansowy ciężar częstych wizyt w szpitalu. Składki ubezpieczeniowe mogą być cykliczną opłatą wzbogacającą symulację ekonomii serwera. Dla graczy, którzy nie mogą zapłacić, wdróż system zadłużenia medycznego, w którym niezapłacone rachunki naliczają odsetki i ostatecznie wywołują konsekwencje, takie jak zajęcie części wypłaty z pracy lub ograniczony dostęp do niektórych usług aż do spłaty długu. Przechowuj wszystkie rekordy rozliczeń do wglądu dla administratorów i połącz je z systemem logowania transakcji, aby przepływ pieniędzy od pacjenta do szpitala mógł być kontrolowany.

Pojazd i wyposażenie pogotowia

Karetka powinna być czymś więcej niż tylko szybkim pojazdem na sygnale. Wprowadź funkcje dedykowane dla pojazdu, które przekształcą ambulans w mobilny punkt medyczny. Gdy ratownik EMS otworzy tylne drzwi karetki za pomocą interakcji z pojazdem, uzyskuje dostęp do mobilnego menu leczenia z częścią funkcji szpitalnych, takich jak bandażowanie, podawanie leków przeciwbólowych, zakładanie szyn i użycie defibrylatora. Przechowuj artykuły medyczne w bagażniku karetki (trunk inventory), aby ratownicy musieli uzupełniać zapasy w szpitalu między wezwaniami. Defibrylator to specjalny przedmiot, który może ożywić graczy w stanie śmierci (death state), ale powinien wymagać minigry opartej na wyczuciu czasu, symulującej poprawną technikę resuscytacji. Zaimplementuj system noszy, na których EMS może umieścić powalonego gracza przy karetce, co blokuje pacjenta w animacji leżącej wewnątrz pojazdu podczas transportu. Użyj AttachEntityToEntity aby obsłużyć umieszczanie noszy i SetPedIntoVehicle do ładowania pacjenta.

Integracja i Quality of Life

Twój system szpitala powinien integrować się z zasobem telefonu na serwerze, aby gracze mogli dzwonić pod numer 911 bezpośrednio z aplikacji w telefonie, przeglądać swoją historię medyczną oraz nieopłacone rachunki i sprawdzać czas oczekiwania na EMS przed podjęciem decyzji, czy wezwać pomoc, czy leczyć się samemu podstawowymi przedmiotami z apteki. Połącz system obrażeń z karami do poruszania się, tak aby urazy nóg zmniejszały prędkość ruchu, a urazy rąk wpływały na celność, tworząc odczuwalne konsekwencje w rozgrywce, które motywują graczy do szukania leczenia zamiast ignorowania obrażeń. Wdróż system dokumentacji medycznej dostępny przez szpitalny MDT, w którym lekarze mogą przeglądać pełną historię leczenia pacjenta, alergie odnotowane przez innych lekarzy oraz aktualnie przyjmowane leki. Wyeksportuj swoje funkcje obrażeń i leczenia, aby inne zasoby, takie jak efekty narkotyków, zatrucia pokarmowe czy zagrożenia środowiskowe, mogły trafiać do tego samego systemu medycznego. Dodaj system auto-respawnu z konfigurowalnym czasem, który aktywuje się, gdy na służbie nie ma żadnych EMS, dzięki czemu gracze nigdy nie utkną w stanie powalenia w nieskończoność, jednocześnie stawiając na pierwszym miejscu roleplay medyczny tworzony przez graczy, gdy personel jest dostępny.

Pasujący skrypt

Gotowe na twój serwer, aktualizacje w zestawie.

Gotowy, aby zacząć?

Kup skrypty w naszym sklepie lub dołącz do Discorda, aby uzyskać wsparcie, aktualizacje i sprawdzić nadchodzące nowości.