Bloga Geri Dön
Tutorial8 dk. okuma

FiveM Ambulans Mesleği Script'i: Gerçekçi Bir EMS Sistemi Geliştirin

FiveM sunucunuz için eksiksiz bir ambulans mesleği tasarlayın. Hasta canlandırma, hastane iş akışları, ESX ve QBCore entegrasyonu ve mevcut en iyi EMS scriptleri.

Agency Scripts

Agency Scripts Kurucusu ve Baş Geliştiricisi

Ambulance Job Sistemine Genel Bakış

Bir ambulans meslek scripti, sürükleyici acil durum hizmetleri oynanışını hedefleyen her rol yapma sunucusu için vazgeçilmezdir. EMS sistemi, bir oyuncu yere düştüğünde çağrı almaktan olay yerindeki tedavi mekaniklerine, hastaneye nakle ve tıbbi faturalandırmaya kadar her şeyi yönetir. İyi tasarlanmış bir ambulans scripti, EMS oyuncuları için anlamlı bir oynanış yaratırken yere düşen oyuncuların süresiz olarak beklemesini de önler. Mimari dört ana alt sisteme ayrılır: EMS ekibini olaylar hakkında uyaran çağrı ve bildirim sistemi, sağlıkçılara gerçekleştirecekleri gerçek görevler sunan tedavi ve stabilizasyon mekanikleri, hastane giriş ve iyileşme süreci ve yaralanmalar için ekonomik bir maliyet oluşturan faturalandırma sistemi. Her alt sistemin bağımsız olarak çalışabilmesi gerekir; böylece görevde hiçbir EMS oyuncusu olmadığında, otomatik yedek sistemler oyuncunun iyileşmesini yönetir.

Meslek Yapılandırması ve Mesai Sistemi

Ambulans mesleğinin her seviyede farklı yeteneklere sahip, net bir şekilde tanımlanmış rütbelere ihtiyacı vardır. Stajyerler yalnızca temel ilk yardımı uygulayabilirken, kıdemli paramedikler ileri düzey tedaviler uygulayabilir ve kısıtlı tıbbi malzemelere erişebilir. Meslek rütbelerini kullanılabilir eylemlerle, gerekli öğelerle ve ödeme oranlarıyla eşleştiren bir yapılandırma tablosu kullanın. Duty sistemi, sunucunun otomatik respawn yedeğini kullanıp kullanmayacağını bilmesi için hangi EMS oyuncularının şu anda aktif olduğunu takip etmelidir:

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),
    },
}

The minOnDutyForNoAutoRespawn ayarı, sunucunun EMS'e bağlı iyileşme ile otomatik iyileşme arasında ne zaman geçiş yapacağını kontrol eder. Görevde ikiden az EMS olduğunda, yaralanan oyuncular yapılandırılan saniye kadar bekledikten sonra zamanlayıcı tabanlı bir yeniden doğma seçeneğine sahip olur. Bu durum, oyuncuların asla gelmeyecek bir tıbbi yardımı beklerken takılıp kalmasını önler.

Dispatch ve Bildirim Sistemi

Bir oyuncu etkisiz hale geldiğinde, sistem görevdeki tüm EMS oyuncularına konumu, acil durumun niteliğini ve çağrıyı üstlenme yöntemini gösteren bir bildirim yayını gönderir. Birden fazla EMS oyuncusu bu uyarıyı görebilir, ancak karışıklığı önlemek için yalnızca biri üstlenmelidir. Çağrıyı ilk kabul eden ilk müdahale ekibine atandığı ve diğer EMS görevlilerinin bunu yanıtlayan birimin tanımlayıcısıyla üstlenilmiş olarak gördüğü bir talep sistemi uygulayın:

-- 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)

Müdahale eden EMT personelinin olay yerine varmadan önce uygun tedavi ekipmanlarını hazırlayabilmesi için ölüm nedenini bildirim (dispatch) bilgisine dahil edin. Ateşli silah yaralanmaları, araç çarpışmaları, düşmeler ve boğulma gibi yaygın nedenlerin her biri farklı tedavi yaklaşımları gerektirir ve bu da EMS rol yapma deneyimine derinlik katar.

Tedavi ve Revive Mekanikleri

Tedavi mekanikleri, birini canlandırmak için yalnızca bir tuşa basmaktan daha kapsamlı olmalıdır. EMT'nin asıl revive işlemini gerçekleştirmeden önce hastayı temel tedavilerle stabilize etmesini gerektiren çok adımlı bir süreç oluşturun. Her tedavi adımı, EMT'nin envanterinden bir eşya tüketir ve bir ilerleme çubuğu animasyonuyla birlikte belirli bir süre alır. Hastanın durumu, uygulanan her tedaviyle iyileşen basit bir sağlık durumu ile modellenebilir:

-- 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

Animasyonlu ilerleme çubuğu, diğer oyuncuların da izleyebileceği gerçekçi bir tedavi sahnesi oluşturarak rol yapma atmosferini güçlendirir. Defibrilatörü canlandırma işlemini gerçekleştiren son adım haline getirin: böylece EMT görevlisinin hastayı önce bandaj ve ağrı kesicilerle stabilize etmesi gerekir. Bu çok adımlı yaklaşım, EMS rolünü tek tıklamayla canlandırmaktan çok daha ilgi çekici kılar.

Hastane Girişi ve İyileşme

Bir hastayı sahada canlandırdıktan veya hastaneye naklettikten sonra bir EMS oyuncusu tam iyileşme için hastayı bir hastane yatağına yatırabilir. Giriş işlemi hastayı tamamen iyileştirir, tıbbi fatura keser ve ziyareti kaydeder. Birden fazla hastanın aynı yatağa atanmasını önlemek için hastane yatakları takip edilmelidir. Yatakları dolu olarak işaretleyen ve yapılandırılabilir bir iyileşme süresinden sonra serbest bırakan bir yatak yönetim sistemi oluşturun:

-- 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

Hastane faturası, ölmenin sunucu ekonomisini dengeleyen ekonomik bir sonucunu yaratır. Faturayı oyuncunun nasıl yaralandığına göre ölçeklendirmeyi değerlendirin; örneğin yüksek hızlı kazalar gibi dikkatsiz davranışlar için daha yüksek maliyetler, bir suçun mağduru olmak için ise daha düşük maliyetler belirleyin. Bu, dikkatli araç kullanmayı teşvik eder ve tehlikeli durumlara ağırlık kazandırır.

Otomatik Yeniden Canlanma Fallback Sistemi

Nöbette hiçbir EMS oyuncusu olmadığında, yaralı oyuncuların kalıcı olarak mahsur kalmaması için sunucunun alternatif bir iyileşme yolu sunması gerekir. Yapılandırılabilir bir gecikmenin ardından görünen bir geri sayım sayacı uygulayın: bu sayede oyuncu, sabit bir tıbbi ücret otomatik olarak kesilerek hastanede yeniden doğabilir. Yeniden doğma konumu hastane girişinde veya belirlenmiş bir iyileşme alanında olmalıdır. Otomatik yeniden doğma seçeneğini göstermeden önce her zaman mevcut EMS sayısını kontrol edin ve geri sayım sırasında bir sağlık görevlisi çağrıyı kabul ederse bu seçeneği derhal kapatın. Bu ikili yol sistemi, sağlık görevlileri mevcut olduğunda EMS etkileşiminin roleplay deneyimine öncelik verirken, oyuncuların her zaman toparlanma yoluna sahip olmasını sağlar.

Tıbbi Malzemeler ve Envanter Entegrasyonu

EMS oyuncularının hastanedeki mesleğe özel bir depo ile bir üretim veya satın alma sistemi üzerinden tıbbi malzemelere erişmesi gerekir. Hastane deposunu bandajlar, ağrı kesiciler, ateller, serumlar, kan torbaları ve defibrilatör şarjlarıyla doldurun. Her tedavi işlemi ilgili eşyayı tüketerek sürekli bir ikmal talebi oluşturur. Tüketim alışkanlıklarını izlemek ve yapılandırılabilir aralıklarla hastane depolarını otomatik olarak yenilemek için veritabanındaki malzeme kullanımını takip edin. Bazı malzemelerin eczacı veya doktor rolündeki oyuncular tarafından üretilebilir olmasını sağlayarak sunucudaki farklı meslekler arasında ek rol yapma fırsatları ve ekonomik bağlar oluşturmayı düşünebilirsiniz.

Log Kaydı ve Performans İzleme

Kimin tedavi edildiği, hangi tedavilerin uygulandığı, müdahale eden sağlık personeli ve nihai tıbbi fatura dahil olmak üzere tüm EMS etkileşimlerini yönetimsel inceleme için kaydedin. Bu kayıtları özel bir veritabanı tablosunda saklayın ve yetkililerin gerçek zamanlı takibi için özetleri isteğe bağlı olarak bir Discord webhook'una gönderin. Bu kayıtlar anlaşmazlıkları çözmeye, görevini yerine getirmeyen EMS oyuncularını tespit etmeye ve genel sistem sağlığını izlemeye yardımcı olur. Performans tarafında, ölüm kontrolü mantığını her karede her oyuncu yerine yalnızca canı sıfıra düşen oyuncular üzerinde çalıştırarak hafif tutun. Yoklama yapmak yerine ölüm durumunun tek bir sunucu olayını tetiklediği olaya dayalı mimariyi kullanın. Dispatch bildirim sistemi, her bir EMS oyuncusuna ayrı ayrı olaylar göndermek yerine uyarıları toplu halde iletmeli, böylece birden fazla oyuncunun aynı anda yere düştüğü kitlesel yaralanma senaryolarında ağ yükünü azaltmalıdır.

Eşleşen script

Sunucunuz için hazır, güncellemeler dahil.

Başlamaya Hazır mısınız?

Scriptleri mağazamızdan edinin veya destek, güncellemeler ve gelecek yeniliklere göz atmak için Discord'a katılın.