v0.0.5
Fresh install this version. Replace the resource folder rather than overlaying v0.0.5 onto an existing v0.0.4 tree. Database tables are now luxu_medicine_* instead of luxu_ambulancejob_*, blood settings moved under Config.blood, props live in config/props.lua, and disease tuning is a new Config.diseases block. Re-run INSTALL/main.sql (or let Config.database.auto_install create the schema) and merge the configuration diffs below before going live.
Summary
This release adds per-disease outbreak tuning, hospital-respawn inventory keep-lists, nested blood donation/transfusion settings, Spanish locale, and admin commands to spawn or clear virus zones. Staff can delete laboratories, place pharmacy shopkeeper peds, and keep selected items on E-respawn. Fatal headshots can skip last standing. Carry can be handed off to an external system through new client and server startCarry hooks.
On start, the resource renames leftover luxu_ambulancejob_* tables to luxu_medicine_* when the new name does not already exist. If both names are present, data is left untouched and a warning is printed. A fresh install avoids that mixed-schema state.
The shipped default locale is en (Config.locales.lang). Set it to pt or es if you want Portuguese or Spanish.
What's New
Features
Config.diseasesoverlay for infection chance, player spread, symptom interval, HP damage ticks, kill permission, zone spawn chance, rain (cold), and food-poisoning items.enabled = falsealso forcesConfig.features.diseasesoff- Admin outbreak commands:
/ems:clearvirus [virus]and/ems:genvirus <virus> [label] - Hospital E-respawn inventory wipe with
Config.status.dead.clear_inventoryand afiltered_itemskeep-list (*wildcard) - Nested
Config.blooddonation and transfusion settings (replaces the old top-levelblood_donation_*/blood_transfusion_*keys) - Fatal headshots skip last standing when
Config.status.last_standing.headshot_instant_deathis true - Spanish locale (
locales/es.json); default language switched frompttoen - Pharmacy shopkeeper peds (
ped_settingson shops) spawned locally per client - Laboratory delete for bosses
- Hospital supply catalog: microscope slides and typed blood bags (O− through AB+)
- Client and server
hooks.startCarry— returnfalseto bypass the built-in fireman's carry config/props.lua(moved fromshared/props.lua) plus a body-bag prop (xm_prop_body_bag)- Job applications collect a typed phone number; dates are formatted in the UI with
Config.locales.code - Nearby-player menus resolve character names from the server instead of FiveM account names
- Garage refuses to spawn when another vehicle is already in the spawn radius
INSTALL/main.sqlandINSTALL/patches.sqlare included infxmanifestfilesso auto-install can load them- New
luxu_medicine_blood_reservestable
Bug Fixes
- Deathscreen and distress now restore after a fresh join — resource start no longer returns early before framework login
- Carry-to-bed / OrthoScan handoff no longer undoes the patient lie-down pose
- Bed and OrthoScan mounts wait for attach/ownership and use a 6 m proximity check
- Duty clothing menu only opens for the configured EMS job (including
off_<job>) - Wheelchair spawn waits for the model, then unlocks doors, starts the engine, and fills fuel
- ESX job grades, offline player lookup, cash-as-
money, and employee grade/fire paths go through the player bridge instead of QB-onlyplayersSQL - Pharmacy consumes prescription items before completing the purchase
- Stabilize copy now requires last standing with no active bleeding (no longer last standing or dead)
File Changes
⚙️ Configuration & Bridge Files
These files are not encrypted. Review the changes below — you may need to manually apply updates to your server's config files.
config/config.lua
locales = {
- lang = "pt", -- locales/{lang}.json
+ lang = "en", -- locales/{lang}.json
code = "en-US",
symbol_fallback = "$",
unit_system = "metric", -- "metric" | "imperial"
}, features = {
--- Outbreaks, infections (zones, rain, food, player spread), and the tablet Diseases page.
+ --- Legacy master switch; Config.diseases.enabled=false also forces this off (see shared/init.lua).
diseases = true,
},
+ --[[ Diseases (outbreaks & infections) ]]
+ --- Per-disease tuning overlay for the VirusConfig catalog in shared/constants.lua.
+ --- 0 disables that vector; enabled = false disables the whole disease.
+ diseases = {
+ enabled = true, -- master switch (false also forces features.diseases off)
+ zone_duration_days = 7, -- how long generated zones persist (days)
+ damage_tick_seconds = 30, -- how often disease HP damage ticks (0 disables damage globally)
+
+ --- Player-to-player proximity spread (15s / 5m by default).
+ player_spread = {
+ enabled = true,
+ interval_seconds = 15,
+ distance = 5.0,
+ },
+
+ --- Keyed by virus name. Values mirror VirusConfig; only set what you want to change.
+ viruses = {
+ cold = {
+ enabled = true,
+ infection_probability = 35,
+ transmissibility = 50,
+ symptom_interval = 15,
+ damage_per_tick = 0,
+ can_kill = false,
+ spawn_probability = 0, -- rain-only, no zones
+ rain = { enabled = true },
+ },
+ food_poisoning = {
+ enabled = true,
+ infection_probability = 10,
+ transmissibility = 0,
+ symptom_interval = 120,
+ damage_per_tick = 1,
+ can_kill = false,
+ spawn_probability = 0,
+ food = {
+ enabled = true,
+ items = { "burger", "sandwich" },
+ },
+ },
+ covid = {
+ enabled = true,
+ infection_probability = 35,
+ transmissibility = 40,
+ symptom_interval = 15,
+ damage_per_tick = 2,
+ can_kill = false,
+ spawn_probability = 30,
+ },
+ contaminated_water = {
+ enabled = true,
+ infection_probability = 45,
+ transmissibility = 0,
+ symptom_interval = 10,
+ damage_per_tick = 2,
+ can_kill = false,
+ spawn_probability = 50,
+ },
+ tetanus = {
+ enabled = true,
+ infection_probability = 30,
+ transmissibility = 0,
+ symptom_interval = 10,
+ damage_per_tick = 3,
+ can_kill = true,
+ spawn_probability = 25,
+ },
+ radiation = {
+ enabled = true,
+ infection_probability = 12,
+ transmissibility = 0,
+ symptom_interval = 10,
+ damage_per_tick = 5,
+ can_kill = true,
+ spawn_probability = 10,
+ },
+ },
+ }, --- Hospital stash shop catalog. `name` is a Config.items key or a raw item name.
- --- Orders spend society money and add stock to luxu_ambulancejob_hospitals.inventory.
+ --- Orders spend society money and add stock to luxu_medicine_hospitals.inventory.
hospital_supplies = {
{ name = "bandage", label = "Bandage", category = "Consumables", unitPrice = 12, reorderAt = 30 },
{ name = "medical_kit", label = "Medical Bag", category = "Equipment", unitPrice = 85, reorderAt = 10 },
{ name = "adrenaline", label = "Epinephrine Syringe", category = "Medication", unitPrice = 55, reorderAt = 15 },
{ name = "oxymeter", label = "Pulse Oximeter", category = "Equipment", unitPrice = 35, reorderAt = 10 },
{ name = "thermometer", label = "Thermometer", category = "Equipment", unitPrice = 40, reorderAt = 10 },
{ name = "syringe", label = "Syringe", category = "Consumables", unitPrice = 5, reorderAt = 40 },
+ { name = "microscope_slide", label = "Microscope Slide", category = "Consumables", unitPrice = 8, reorderAt = 20 },
{ name = "blood_bag_empty", label = "Empty Blood Bag", category = "Fluids", unitPrice = 22, reorderAt = 20 },
+ { name = "blood_bag_o-", label = "Blood Bag O-", category = "Fluids", unitPrice = 45, reorderAt = 10 },
+ { name = "blood_bag_o+", label = "Blood Bag O+", category = "Fluids", unitPrice = 45, reorderAt = 10 },
+ { name = "blood_bag_a-", label = "Blood Bag A-", category = "Fluids", unitPrice = 45, reorderAt = 10 },
+ { name = "blood_bag_a+", label = "Blood Bag A+", category = "Fluids", unitPrice = 45, reorderAt = 10 },
+ { name = "blood_bag_b-", label = "Blood Bag B-", category = "Fluids", unitPrice = 45, reorderAt = 10 },
+ { name = "blood_bag_b+", label = "Blood Bag B+", category = "Fluids", unitPrice = 45, reorderAt = 10 },
+ { name = "blood_bag_ab-", label = "Blood Bag AB-", category = "Fluids", unitPrice = 45, reorderAt = 10 },
+ { name = "blood_bag_ab+", label = "Blood Bag AB+", category = "Fluids", unitPrice = 45, reorderAt = 10 },
{ name = "defib", label = "Defibrillator", category = "Equipment", unitPrice = 120, reorderAt = 6 }, hospital_respawn_hold_duration = 3000,
condition_damage_interval = 5000,
- blood_donation_minimum = 60,
- blood_donation_amount = 20,
- blood_donation_consent_timeout = 15000, -- ms the patient has to accept/deny
- blood_donation_duration = 15000, -- ms; non-cancelable extraction progress bar
- -- One transfusion unit. Low (31–59) needs 1; Critical (≤30) needs 2.
- blood_transfusion_amount = 30,
- blood_transfusion_duration = 15000, -- ms; server timer + patient progress bar
- -- HP restored to the patient when a transfusion completes (GTA scale: 200 = full).
- blood_transfusion_health = 20,
health_insurance_hours_renewal = 1,
+ --[[ Blood donation & transfusion ]]
+ blood = {
+ donation = {
+ minimum = 60, -- donor needs at least this blood level (0-100)
+ amount = 20, -- blood level taken per donation
+ consent_timeout = 15000, -- ms the patient has to accept/deny
+ duration = 15000, -- ms; non-cancelable extraction progress bar
+ },
+ transfusion = {
+ -- One unit. Low (31–59) needs 1; Critical (≤30) needs 2.
+ amount = 30,
+ duration = 15000, -- ms; server timer + patient progress bar
+ -- HP restored when a transfusion completes (GTA scale: 200 = full). 0 disables healing.
+ health = 20,
+ },
+ }, status = {
last_standing = {
invincible_duration = 10000, -- This can't be set higher than 5000
duration = 10 * 60 * 1000,
instant_death_chance = 0.10, -- 0.0–1.0; 0 disables skip to dead
+ headshot_instant_death = true, -- fatal headshots skip last standing, go straight to dead
-- On-foot last standing uses rpemotes-style move_crawl anims. false = static writhe.
crawl = true,
},
+ dead = {
+ -- Hospital E-respawn inventory wipe. false keeps everything and ignores filtered_items.
+ clear_inventory = true,
+ -- Keep-list used only when clear_inventory is true. Empty = wipe every item.
+ -- Match is against the inventory item name.
+ -- `*` is the only wildcard (any run of characters, including none). Other characters are literal.
+ -- Examples: "phone*" keeps phone and phone1; "*card" keeps idcard; "id_*" keeps id_card.
+ filtered_items = {
+ -- "clothing_*",
+ -- "id_card",
+ },
+ }, ["revive"] = {
enabled = true,
name = "revive",
description = "Revive Player",
params = {
{ name = "target", help = "Server Id of the targeted player", optional = true }
},
restricted = { "group.admin", "group.mod" }
},
+ ["clearvirus"] = {
+ enabled = true,
+ name = "ems:clearvirus",
+ description = "Clear active virus outbreak zones",
+ params = {
+ { name = "virus", help = "Virus name (empty clears all outbreaks)", optional = true }
+ },
+ restricted = { "group.admin" }
+ },
+ ["genvirus"] = {
+ enabled = true,
+ name = "ems:genvirus",
+ description = "Spawn a virus outbreak zone at your position",
+ params = {
+ { name = "virus", help = "Virus name (e.g. covid, radiation)" },
+ { name = "label", help = "Zone label", optional = true }
+ },
+ restricted = { "group.admin" }
+ },
},
}config/hooks/client.lua
function hooks.sendDistressSignal()
return true
end
+--- Called before the built-in carry starts on the transporter side.
+--- Return false to bypass it so an external carry system can take over
+--- (e.g. call your own export here and return false).
+---@param targetServerId number
+---@return boolean
+function hooks.startCarry(targetServerId)
+ return true
+end
+
return hooksconfig/hooks/server.lua
--AddEventHandler("luxu_medicine:server:player_healed", function(targetSource) end)
--AddEventHandler("luxu_medicine:server:player_injured", function(targetSource) end)
+---@class ServerHooks
local hooks = {}
---[[ Todo ]]
+
+--- Called before a built-in carry session is created.
+--- Return false to bypass it so an external carry system can take over.
+---@param source number carrier server id
+---@param targetSource number carried server id
+---@return boolean
+function hooks.startCarry(source, targetSource)
+ return true
+end
return hooksconfig/props.lua (moved from shared/props.lua)
attach = {
- x = 0.39,
- y = -0.06,
- z = -0.06,
- rotx = -100.0,
- roty = -180.0,
- rotz = -78.0,
+ x = 0.4131,
+ y = 0.0465,
+ z = 0.0815,
+ rotx = -66.9871,
+ roty = -142.5557,
+ rotz = -41.8048,
},
},
},
+
+ --[[ THIS MIGHT CHANGE IN THE FUTURE ]]
stretchers = {- lucas2 = {
+ lucas = {
model = "lucas2",
bone = PEDBONES.SKEL_ROOT,
offsets = {
position = vector3(0, 0, 0),
rotation = vector3(0, 0, 0),
},
target = {}
+ },
+ body_bag = {
+ model = "xm_prop_body_bag"
}
}fxmanifest.lua
author "luxu-gg <[email protected]>"
description "Luxu Medicine - Ambulance Job"
-version "0.0.4"
+version "0.0.5"
dependencies {
"oxmysql",
"ox_lib",
"/server:25770"
}
shared_scripts {
"@ox_lib/init.lua",
- "shared/**/*.lua"
+ "shared/**/*.lua",
+ "config/props.lua"
} files {
"web/**/*",
"config/config.lua",
"config/emergency_codes.lua",
"config/clothes.lua",
"config/hooks/client.lua",
"locales/*.json",
+ "INSTALL/main.sql",
+ "INSTALL/patches.sql",
"data/*.json",
"bridge/framework.lua",
"bridge/client/*.lua",
}INSTALL/main.sql
All product tables were renamed luxu_ambulancejob_* → luxu_medicine_* (applications, blood_donations, citizen_tags, conditions, complaints, insurances, medical_records, notes, patient_consultations, stats, tags, treatment_history, health_records, treatment_logs, hospitals, virus_zones, dispatch_history). Example:
-CREATE TABLE IF NOT EXISTS `luxu_ambulancejob_applications` (
+CREATE TABLE IF NOT EXISTS `luxu_medicine_applications` (New table:
+CREATE TABLE IF NOT EXISTS `luxu_medicine_blood_reserves` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `char_id` varchar(255) NOT NULL,
+ `amount` int(11) NOT NULL DEFAULT 0,
+ `donated_at` datetime NOT NULL DEFAULT current_timestamp(),
+ PRIMARY KEY (`id`),
+ KEY `idx_char_id` (`char_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;INSTALL/patches.sql uses the same luxu_medicine_* names. On resource start, leftover luxu_ambulancejob_* tables are renamed when the new name is free.
Full list of files changed
| Change | File |
|---|---|
| Added | INSTALL/items/images/bodybag.png |
| Modified | INSTALL/main.sql |
| Modified | INSTALL/patches.sql |
| Modified | bridge/client/events.lua |
| Modified | bridge/client/target.lua |
| Modified | bridge/server/events.lua |
| Modified | bridge/server/inventory.lua |
| Modified | bridge/server/player.lua |
| Modified | client/cl_main.lua |
| Modified | client/cl_utils.lua |
| Modified | client/handlers/bootstrap.lua |
| Modified | client/handlers/markers.lua |
| Modified | client/handlers/nui.lua |
| Added | client/handlers/shop_peds.lua |
| Modified | client/handlers/targets.lua |
| Modified | client/handlers/virus_zones.lua |
| Modified | client/modules/conditions/blackout_effects.lua |
| Modified | client/modules/conditions/movement_effects.lua |
| Modified | client/modules/conditions/viruses.lua |
| Modified | client/modules/damage.lua |
| Modified | client/modules/experiments/patient_overlay.lua |
| Modified | client/modules/garage.lua |
| Modified | client/modules/items/medical_bag.lua |
| Modified | client/modules/minigames.lua |
| Modified | client/modules/mobility.lua |
| Modified | client/modules/status.lua |
| Modified | client/modules/treatment/blood_transfusion.lua |
| Modified | client/modules/treatment/carry.lua |
| Modified | client/modules/treatment/controls.lua |
| Modified | client/modules/treatment/hospital_beds.lua |
| Modified | client/modules/treatment/hospital_orthoscan.lua |
| Modified | client/modules/treatment/oxymeter.lua |
| Modified | client/modules/treatment/patient_hotbar.lua |
| Modified | client/modules/treatment/stretcher.lua |
| Modified | client/modules/treatment/triage.lua |
| Modified | config/config.lua |
| Modified | config/hooks/client.lua |
| Modified | config/hooks/server.lua |
| Moved | shared/props.lua → config/props.lua |
| Modified | data/shops.json |
| Modified | fxmanifest.lua |
| Modified | locales/en.json |
| Added | locales/es.json |
| Modified | locales/pt.json |
| Modified | server/database_patches.lua |
| Modified | server/features/applications.lua |
| Modified | server/features/citizens.lua |
| Modified | server/features/complaints.lua |
| Modified | server/features/employees.lua |
| Modified | server/features/health_records.lua |
| Modified | server/features/laboratories.lua |
| Modified | server/features/player.lua |
| Modified | server/features/shops.lua |
| Modified | server/features/treatment.lua |
| Modified | server/features/treatment_logs.lua |
| Modified | server/modules/blood_transfusion.lua |
| Modified | server/modules/care.lua |
| Modified | server/modules/conditions.lua |
| Modified | server/modules/hospital_inventory.lua |
| Modified | server/modules/job.lua |
| Modified | server/modules/medical_bag.lua |
| Modified | server/modules/minigames.lua |
| Modified | server/modules/mobility.lua |
| Modified | server/modules/shop.lua |
| Modified | server/modules/statistics.lua |
| Modified | server/modules/viruses.lua |
| Modified | server/services/database.lua |
| Modified | server/sv_main.lua |
| Modified | server/sv_status.lua |
| Modified | server/sv_utils.lua |
| Added | shared/diseases.lua |
| Modified | shared/init.lua |
| Modified | shared/types.lua |
| Modified | web/ |