Page cover image

🚑Envi-Medic

Envi-Medic Official Documentation

Prerequisites

  • A working FiveM Server

  • Basic understanding of FiveM server setup and resource management

  • An up-to-date version of ox_lib

1. Introduction

Envi-Medic is a comprehensive medical assistance system for FiveM servers. It offers a wide range of customizable features to create a realistic and immersive emergency medical service experience.

Config Preview

2. Commands and Exports

Commands

  • /callmedic [server id]: Call an ambulance for yourself or another player

  • /cancelmedic: Cancel an ambulance that's on the way to you

Client Exports

exports['envi-medic']:SendHelp(): Sends an ambulance to the player
exports['envi-medic']:CancelHelp(): Cancels the ambulance if it's on the way
exports['envi-medic']:IsWalkingToAmbulance(): Returns true if the player is walking to the ambulance
exports['envi-medic']:IsInAmbulance(): Returns true if the player is in the ambulance
exports['envi-medic']:IsOnCooldown(): Returns true if the player is on cooldown
exports['envi-medic']:GetMedicPedNetID(): Returns the net ID of the medic ped
exports['envi-medic']:GetAmbulanceNetID(): Returns the net ID of the ambulance

3. Debug and Failsafe Settings

  • Config.DebugZones: Enable to visualize zones for testing

  • Config.CommandsDisabled: Disable built-in commands

  • Config.FailSafeMode: Enable timeouts for actions to prevent stuck scenarios

Configurable timeouts for various stages of the medical assistance process

4. Core Configuration

  • Config.AutoMedicCleanUp: Automatically delete medic and ambulances after a set time

  • Config.UltimateTimeOut: Force despawn ambulance and use a "magic ped" to revive player

  • Config.RemoveAllItemsOnMedicRevive: Option to remove all items on revive

  • Config.RemoveCertainItemsOnMedicRevive: Option to remove specific items on revive

5. Medic and Ambulance Settings

  • Configurable ambulance and medic models

  • Customizable spawn distance and arrival parameters

  • Options for invincible medics and ambulances

  • Ambulance driving style configuration

Config.AmbulanceModel = `ambulance` -- Model to spawn for the ambulance [ must be in `ticks` like `ambulance` (not 'ambulance') ]
Config.MedicModel = `s_m_m_paramedic_01` -- Model to spawn for the medic [ must be in `ticks` like `s_m_m_paramedic_01` (not 's_m_m_paramedic_01') ]
Config.InvincibleMedic = true -- Set to true if you want the medic/ambulance to be invincible

Config.AmbulanceDriveFlag = 787004 -- Driving style for the ambulance to get to the player -- see more here: https://vespura.com/fivem/drivingstyle/   -- [[ NEW - UPDATED FLAG ]]

6. Hospital and Revive Settings

  • Configurable hospital slow-down and parking area radius

  • Option to always take players to the hospital or revive on the spot

  • Wasabi Crutch system integration for post-revive effects

Config.HospitalSlowDownAreaRadius = 40.0 -- Radius to check for the ambulance arriving at the hospital - if the player enters this radius the ambulance will slow down
Config.HospitalParkingAreaRadius = 15.0 -- Radius to check for the ambulance pulling into the hospital - if the player enters this radius they will revive (should be smaller than the slow down radius)

Config.AlwaysTakeToHosptial = false -- Set to true if you want to always take the player to the closest hospital when they are revived
                                    -- Set to false if you want to take the player to be revived on the spot and free to walk away
                                    
Config.WasabiCrutch = {
  enabled = false, -- Set to true if you want to use the wasabi-crutch system on final revive (edit in ReviveEvent below)
  type = 'crutch', -- 'crutch' or 'chair'
  time = 10, -- Time in mins before the crutch/chair despawns
}

7. Job and Payment Settings

  • Job-locked functionality with configurable job list

  • Online job check to prevent calling when real medics are available

  • Configurable payment types and costs for revival

  • Society fund integration

Config.JobLocked = false -- Set to true if you want to lock the command to only allow jobs in the Config.Jobs table below
                        -- If set to false it will allow anyone to use it to call EMS
Config.Jobs = {          -- ['job_name'] = MinimumGrade,
  ['police'] = 2,
  ['ambulance'] = 2,
}

Config.JobToCheck = 'ambulance' -- The job to check for
Config.JobToCheckAmountOnline = 1 -- If there is this amount of people online with the job, you can't call a medic.

Config.PaymentType = 'bank'   -- 'cash' / 'bank'

Config.ReviveCostSuccessfulSkillCheck  = 3000      -- How much it costs to be revived if you spawn back in the hospital (if AlwaysTakeToHosptial is set to true and you pass the minigame)
Config.ReviveCostFailedSkillCheck  = 5000      -- How much it costs to be revived if you spawn back in the hospital (if you fail the minigame)  -- will default to this if you do not use skillcheck or if AlwaysTakeToHosptial is set to false

Config.Society = 'ambulance' -- Name of Society to send funds to  - set to false to disable

8. Animation and Cinematic Settings

  • Toggle for cinematic mode during revival

  • Advanced animation options with customizable offsets

  • Player control disable option during transport

Config.CinematicMode = true -- Set to true if you want the camera to go into cinematic mode when you are being revived
                            -- Set to false if you want the camera to stay where it is when you are being revived
Config.AdvancedAnimations = true -- Set to true if you want to use the advanced animations  (sometimes onesync will break these)
                                 -- Set to false if you want to use the basic animations
Config.DisablePlayerControls = true -- Set to true if you want to disable player controls when they are being revived and transported to the hospital
                                    -- Set to false if you want to allow players to move around when they are being transported to the hospital

9. Minigame and Skill Check

  • Optional minigame for revival process

Config.MiniGame = false -- Set to true if you want to use the minigame when you are being revived

Config.ReviveCostSuccessfulSkillCheck  = 3000      -- How much it costs to be revived if you spawn back in the hospital (if AlwaysTakeToHosptial is set to true and you pass the minigame)
Config.ReviveCostFailedSkillCheck  = 5000      -- How much it costs to be revived if you spawn back in the hospital (if you fail the minigame)  -- will default to this if you do not use skillcheck or if AlwaysTakeToHosptial is set to false

10. Blacklist Areas and Drop-off Spots

  • Define areas where ambulances won't respond

  • Configurable hospital drop-off and respawn locations

Config.BlacklistAreas = {  -- Areas that are blacklisted, ambulance will NOT come to a player in these areas
  ['Hospital Area'] = { area = vec4(1140.0322, -1446.7982, 34.3813, 192.7532), radius = 50.0 },
  ['Cayo Perico']   = { area = vec4(5034.0801, -5110.3999, 4.9121, 258.0274), radius = 1500.0 }, 

}

Config.DropOffSpots = {  -- Where the ambulance will take you - it should always find the closest one
  --['St Feiacre Hospital'] = { dropOff = vec4(1140.0322, -1446.7982, 34.3813, 192.7532), respawnSpot = vec4(1125.2919, -1527.3180, 35.3501, 258.0274)},
  ['St Feiacre Hospital']   = { dropOff = vec4(1120.0826, -1517.0491, 34.6926, 86.2999), respawnSpot = vec4(1149.4230, -1529.0354, 35.3748, 324.1485)}, 

}

11. Config Animation Settings

Config.AnimationOffsetZ = -0.9 -- This is the offset for the animation when the medic is reviving the player - play with this setting to get the right position if you ambulancejob causes the medic to be high or low during anims - default is -0.9 -  negative number for lower, number for higher
Config.AnimationTime = 1000 -- This is an addition for the Wait time for animation syncing issues. Adjust this for your server if the animations are out of sync

12. Arrival Settings

Config.ArrivalZoneRadius = 100.0 -- Radius to check for the ambulance arriving at the player - if the player leaves this radius the ambulance will leave -- [[ MUST HAVE THE .0 AT THE END ]]
Config.ArrivalDistance = 18.0 -- How close the ambulance needs to be to the player before it stops and the medic gets out

13. Language Configuration

Extensive language configuration for all script messages and prompts.

Config.Lang = {

  ambulance_called = "An ambulance has been called for you!",
  ambulance_timeout = "The ambulance has timed out",
  ambulance_busy = "We're too busy right now.. Call back later!",
  ambulance_area_blacklisted = "Doesn't look like we can come to that area!",
  ambulance_area_blacklisted2 = "Sorry, we can\'t go to that area. Call back later.",
  ambulance_water = "Sorry, we hate water! - Try again later!",
  ambulance_dispatched = "An ambulance has been dispatched!",
  ambulance_help_arrived = "Help has arrived!",
  ambulance_resuscitated = "You have been successfully resuscitated!",
  ambulance_transported = "You have been resuscitated and need to be transported to the hospital!",
  ambulance_next_stop = "Next Stop - ",
  too_many_medics = "There are too many Medical Professionals on duty to call for local medical assistance",
  unauthorized_medical_call = "You are not authorized to call for medical",
  invalid_server_id = "We can\'t find any active citizens from the ID you provided! Please call back later.",
  medical_treatment_paid = 'You paid $%s for Medical Treatment',
  ambulance_no_pay = 'You can\'t afford your Medical Bills.. Get a job, you bum!',
  ambulance_left_area = 'You left the area and the ambulance has left!',
  ambulance_not_dead = 'It doesn\'t sound like the patient needs Emergency Medical Assistance?!',
  no_phone = 'You don\'t have a phone to call for help!',
  ambulance_ultimate_failsafe = 'KIFFLOM! The ambulance has failed to arrive, you will be revived by the power of Epsilon!',
  ambulance_ultimate_failsafe_healing = 'Baninishing Demons...',

  -- NEW --
  keep_items = 'You have been revived but have lost some items.',

}

14. ESX_Ambulance replacement

RegisterNetEvent('esx_ambulancejob:revive')
AddEventHandler('esx_ambulancejob:revive', function(fromMedic)
  local playerPed = PlayerPedId()
  local coords = GetEntityCoords(playerPed)
  TriggerServerEvent('esx_ambulancejob:setDeathStatus', false)

  DoScreenFadeOut(800)

  while not IsScreenFadedOut() do
    Wait(50)
  end

  local formattedCoords = {x = ESX.Math.Round(coords.x, 1), y = ESX.Math.Round(coords.y, 1), z = ESX.Math.Round(coords.z, 1)}

  RespawnPed(playerPed, formattedCoords, 0.0)
  isDead = false
  ClearTimecycleModifier()
  SetPedMotionBlur(playerPed, false)
  ClearExtraTimecycleModifier()
  EndDeathCam()
  DoScreenFadeIn(800)
  if fromMedic then
    FreezeEntityPosition(playerPed, true)
    Wait(3000)
    FreezeEntityPosition(playerPed, false)
  end
end)

15. Additional Features

  • Phone requirement check for calling ambulance

  • QBVehicleKeys integration

  • Custom vehicle lock/unlock functions

  • Automatic resource detection for revive and fuel events

  • Wasabi Crutch system integration for post-revive effects

Config.CheckForPhone = false -- Set to true if you want to check if the player has a phone before they can call for help
                            -- Set to false if you want to allow anyone to call for help regardless if they have a phone or not
Config.PhoneItems = { 'phone', 'phone2', } -- Items to check for if CheckForPhone is set to true (supports multiple items)

Config.QBVehicleKeys = true -- Set to true if you want to use the QBVehicleKeys script to lock/unlock the ambulance
                             -- Set to false if you want to use the custom lock/unlock functions below

function CustomUnlockVehicleEvent(ambulance)
  
end

function CustomLockVehicleEvent(ambulance)

end


local reviveEvent = nil
local fuelEvent = nil

CreateThread(function()
  if GetResourceState('qb-ambulancejob') == 'started' then
     reviveEvent = 'hospital:client:Revive'
     return
  end
  if GetResourceState('esx_ambulancejob') == 'started' then
    reviveEvent = 'esx_ambulancejob:revive'
    return
  end
  if GetResourceState('wasabi_ambulance') == 'started' then
    reviveEvent = 'wasabi_ambulance:revive'
    return
  end
  if GetResourceState('brutal_ambulancejob') == 'started' then
    reviveEvent = 'brutal_ambulancejob:revive'
    return
  end
  if GetResourceState('qbx_medical') == 'started' then
    reviveEvent = 'qbx_medical:client:playerRevived'
    return
  end
  if GetResourceState('ak47_ambulancejob') == 'started' then
    reviveEvent = 'ak47_ambulancejob:revive'
    return
  end
  if GetResourceState('osp_ambulance') == 'started' then
    reviveEvent = 'hospital:client:Revive'
    return
  end
  print('ERROR: No Ambulance Job Detected - Please add custom ReviveEvent in config.lua')
  reviveEvent = nil
end)

CreateThread(function()
  if GetResourceState('LegacyFuel') == 'started' then
     fuelEvent = 'LegacyFuel'
     return
  end
  if GetResourceState('cdn-fuel') == 'started' then
    fuelEvent = 'cdn-fuel'
    return
  end
  if GetResourceState('BigDaddy-Fuel') == 'started' then
    fuelEvent = 'BigDaddy-Fuel'
    return
  end
  if GetResourceState('ps-fuel') == 'started' then
    fuelEvent = 'ps-fuel'
    return
  end
  if GetResourceState('okokGasStation') == 'started' then
    fuelEvent = 'okokGasStation'
    return
  end
  if GetResourceState('qs-fuelstations') == 'started' then
    fuelEvent = 'qs-fuelstations'
    return
  end
end)

function ReviveEvent(finalRevive)
  if reviveEvent == nil then
      print('ERROR: No Ambulance Job Detected - Please add custom Revive Event in config.lua')
      return
  end
  if Config.FreezeOnRevive then
    FreezeEntityPosition(cache.ped, true)
  end
  TriggerEvent(reviveEvent, cache.ped)
  if finalRevive then
    -- do additional things here
    if Config.WasabiCrutch.enabled then
      if Config.WasabiCrutch.enabled then
        if Config.WasabiCrutch.type == 'crutch' then
          exports.wasabi_crutch:SetCrutchTime(PlayerId(), Config.WasabiCrutch.time)
        elseif Config.WasabiCrutch.type == 'chair' then
          exports.wasabi_crutch:SetChairTime(PlayerId(), Config.WasabiCrutch.time)
        end
      end
    end
  end
end

function FuelEvent(ambulance)
  if fuelEvent and GetResourceState('ox_fuel') ~= 'started' then
    exports[fuelEvent]:SetFuel(ambulance, 100)
    return
  elseif GetResourceState('ox_fuel') == 'started' then
    Entity(ambulance).state.fuel = 100.0
    return
  end
  print('ERROR: No Fuel Resource Detected - Please add custom Fuel Event in config.lua')
  fuelEvent = nil
end

Remember to adjust these settings carefully to balance your server's gameplay experience. This comprehensive documentation covers the main features of the Envi-Medic system, providing both server administrators and players with a detailed understanding of its capabilities and configuration options.

Last updated