-
Notifications
You must be signed in to change notification settings - Fork 9
Client Systems
Complete technical reference for all client-side systems: wound detection, treatment, infection, healing, and environmental damage.
- Wound System
- Treatment System
- Infection System
- Wound Healing System
- Environmental Damage
- Data Structures
File: client/wound_system.lua (2024 lines)
- Monitors player health every 100ms to detect damage
- Identifies weapon used and body part hit
- Calculates realistic bullet behavior (lodging, penetration, fragmentation)
- Creates wound entries with pain/bleeding levels
- Manages wound progression over time
- Applies bleeding damage every 30 seconds
-- Runs every 100ms (10 times per second)
CreateThread(function()
while true do
Wait(100)
local currentHealth = GetEntityHealth(PlayerPedId())
if currentHealth < PlayerHealth and not ApplyingMedicalDamage then
-- Damage detected! Process wound creation
end
PlayerHealth = currentHealth
end
end)Tip
The ApplyingMedicalDamage flag prevents false wounds from bleeding ticks or infection damage.
Distance affects bullet behavior:
| Distance | Handgun | Rifle | Shotgun |
|---|---|---|---|
| 0-10m | Pass through | Pass through | Pellets (6-12) |
| 10-30m | 5% lodge chance | Pass through | 30% lodge |
| 30-50m | 30% lodge chance | 5% lodge | 60% lodge |
| 50m+ | 60% lodge chance | 30% lodge | 100% lodge |
Lodge Effects:
-
through- Clean wound, normal healing (1.0x infection risk) -
stuck- Bullet lodged, requires surgery (2.0x infection risk) -
fragmented- Bullet shattered, complex surgery needed (2.5x infection risk)
The system maps RedM bone IDs to body parts:
local boneMapping = {
[31086] = 'HEAD', -- SKEL_Head
[14284] = 'SPINE', -- SKEL_Spine3
[11816] = 'STOMACH', -- SKEL_Spine0
[23553] = 'UPPERBODY', -- Left shoulder
[51826] = 'LARM', -- Left upper arm
[61163] = 'LHAND', -- Left hand
-- ... 15 body parts total
}Supported Body Parts: HEAD, NECK, SPINE, UPPERBODY, LOWERBODY, LARM, LHAND, RARM, RHAND, LLEG, LFOOT, RLEG, RFOOT, STOMACH
Warning
Known Issue: Shotgun pellet detection may miss at extreme angles (>80° from center mass).
Every 2 minutes (unified medical progression tick):
- Untreated wounds: Pain and bleeding increase by ~15% chance per tick
- Treated wounds with bandage: Protected from progression
- Expired bandages: 50% of symptoms return, infection risk begins
File: client/treatment_system.lua (787 lines)
- Handles all 4 treatment types
- Manages time-based effects and expiration
- Tracks treatment effectiveness
- Prevents duplicate treatments on same body part
| Type | Heal | Bleed Reduction | Pain Reduction | Duration | Decay |
|---|---|---|---|---|---|
| Cloth | +8 HP | -2 | -2 | 3 min | 60% effectiveness |
| Cotton | +12 HP | -4 | -4 | 5 min | 70% effectiveness |
| Linen | +18 HP | -6 | -6 | 8 min | 80% effectiveness |
| Sterile | +25 HP | -8 | -8 | 12 min | 95% effectiveness |
How Bandages Work:
- Immediate Effect: Restores HP, reduces bleeding/pain
- Active Protection: Prevents wound progression while active
- Expiration: After duration, 50% of reductions return
- Infection Risk: After 60-second grace period, risk begins
Important
Bandage Maintenance Required: Bandages expire (3-12 min) before wounds fully heal (10-40 min). Players must regularly replace bandages to maintain healing. This is intentional design to encourage realistic medical roleplay and ongoing wound care.
Purpose: Stop severe bleeding immediately (limbs only)
| Type | Success Rate | Max Duration | Pain Increase |
|---|---|---|---|
| Rope | 80% | 20 min | +2 |
| Leather | 85% | 25 min | +3 |
| Cloth | 90% | 25 min | +2 |
| Medical | 98% | 30 min | +1 |
Applicable To: LARM, RARM, LLEG, RLEG, LHAND, RHAND, LFOOT, RFOOT
Warning
If a tourniquet is not removed within its max duration, it will start causing damage (simulating tissue death from blood loss).
Applied to ALL body parts with pain (not specific to one wound):
| Type | Effectiveness | Heal | Duration | Side Effects |
|---|---|---|---|---|
| Laudanum | 85% | +25 HP | 5 min | Drowsiness |
| Morphine | 95% | +35 HP | 7.5 min | Euphoria, addiction risk (5%) |
| Whiskey | 60% | +10 HP | 3 min | Intoxication |
| Quinine | 70% | +15 HP | 10 min | Nausea |
| Type | Heal | Duration | Effects |
|---|---|---|---|
| Adrenaline | +40 HP | 5 min | Stamina boost, rapid heartbeat |
| Cocaine | +20 HP | 3 min | Euphoria, anxiety, addiction risk (25%) |
| Strychnine | +10 HP | 2 min | Tremors, convulsions (toxic in high doses) |
| Saline | +15 HP | 10 min | Rehydration |
Note
Addiction risk is currently cosmetic (notification only). Full addiction system planned for v0.3.0.
File: client/infection_system.lua (616 lines)
- Monitors expired bandages for infection risk
- Progresses infections through 4 stages
- Applies stage-based effects (stamina drain, movement penalty)
- Manages cure progression (requires multiple treatments)
| Stage | Percentage | Effects | Cure Required |
|---|---|---|---|
| 1 | 25-49% | Early infection, mild burning | 2-3 antiseptic doses |
| 2 | 50-74% | Redness/swelling, -10 stamina | 3-4 antibiotics |
| 3 | 75-89% | Fever, -20 stamina, -5% speed | 4-5 antibiotics |
| 4 | 90-100% | Severe, -30 stamina, -15% speed, 2 HP/min damage | 5-7 antibiotics OR surgery |
- Bandage is applied (starts fresh)
- Grace period: 60 seconds (no infection risk)
- After grace period: Roll every 2 minutes
- Base chance: 15%
- Multipliers:
- Bullet stuck: 2.0x (30% total)
- Bullet fragmented: 2.5x (37.5% total)
- Clean wound: 1.0x (15% total)
| Item | Cure Progress | Uses Needed | Availability |
|---|---|---|---|
| Antibiotics | 40% per use | 3 uses | Pharmacist (grade 2+) |
| Alcohol | 25% per use | 4 uses | General store |
| Cocaine | 15% per use | 7 uses | Black market |
Tip
After curing an infection, players gain temporary immunity to prevent immediate re-infection.
File: client/wound_healing.lua (231 lines)
- Tracks healing progress when conditions are met
- Converts fully healed wounds into permanent scars
- Maintains medical history
- ✅ Bleeding level = 1 (minimum possible)
- ✅ Active bandage applied
- ✅ Time elapsed (varies by wound type)
- ✅ No new damage to same body part
| Wound Type | Heal Time | Scar Type |
|---|---|---|
| Cutting (knife, machete) | 10 min | Slash scar |
| Shot Through (clean gunshot) | 15 min | Entry/exit scar |
| Post-Surgery (bullet removed) | 25 min | Surgical scar |
| Fragmented (shattered bullet) | 35 min | Complex scar |
| Explosive (dynamite, fire) | 40 min | Burn scar |
| Crushing (animal, trampled) | 20 min | Tissue damage scar |
Tip
Bandage Maintenance Workflow
To successfully heal wounds into scars:
- Apply bandage (sterile recommended for best results)
- Wait for bandage to expire (3-12 minutes)
- Reapply fresh bandage before healing timer resets
- Repeat until wound fully heals (10-40 minutes total)
Example: A gunshot wound (15 min heal time) requires 2-3 bandage changes with sterile bandages (12 min each).
This mechanic encourages realistic medical roleplay and ongoing patient care rather than "set and forget" healing.
File: client/envanim_system.lua (516 lines)
- Detects fall damage with height/velocity calculations
- Creates fractures and bone breaks
- Handles animal attack damage
- Manages leg injury ragdoll effects
| Height | Normal Landing | Ragdoll Landing | Result |
|---|---|---|---|
| < 3m | No damage | No damage | Safe |
| 3-8m | Minor injury | Minor injury | Bruising, pain level 2-3 |
| 8-15m | Fracture | Fracture (6m+) | Bone crack, requires splint |
| 15m+ | Bone Break | Bone Break (10m+) | Complete break, requires surgery |
Fractures are tracked separately from wounds in the player_fractures table:
PlayerFractures[bodyPart] = {
type = "fracture", -- or "bone_break"
severity = 5, -- 1-10 scale
painLevel = 5, -- Pain from fracture
mobilityImpact = 0.2, -- 20% movement reduction
healingProgress = 0.0, -- 0-100%
requiresSurgery = false, -- True for bone breaks
description = "Fractured left leg from 12m fall"
}Dangerous animals within 50m are tracked:
| Animal | Damage Type | Pain | Bleeding | Special |
|---|---|---|---|---|
| Bear | Mauling | 8 | 7 | Multiple wounds |
| Cougar | Clawing | 7 | 6 | Fast attacks |
| Wolf | Biting | 6 | 5 | Pack behavior |
| Alligator | Crushing | 9 | 8 | Limb damage |
| Boar | Goring | 5 | 4 | Charge attacks |
Tip
Leg fractures have a 5-25% chance (based on severity) to cause ragdoll when walking/running, simulating instability.
PlayerWounds = {
['HEAD'] = {
painLevel = 5, -- 0-10 scale
bleedingLevel = 3, -- 0-10 scale
currentHealth = 75.0, -- Current body part HP
maxHealth = 100.0, -- Maximum body part HP
healthPercentage = 75.0, -- Percentage for NUI color
weaponData = "SmallPistol", -- Weapon category
timestamp = 1234567890, -- os.time() when created
isScar = false, -- Is this a healed scar?
scarTime = nil, -- os.time() when healed (if scar)
metadata = {
weaponHash = -1234567, -- Game weapon hash
weaponType = ".45 Colt", -- Display name
bulletStatus = "through", -- "through", "stuck", "fragmented"
requiresSurgery = false, -- Does bullet need removal?
description = "Moderate .45 Colt wound to head...",
shooterDistance = 15.2, -- Distance from shooter (meters)
ballisticType = "handgun" -- Used for distance calculations
},
treatments = {}, -- Treatment history for this wound
infections = {} -- Infection status for this wound
},
['LARM'] = {...},
-- ... other body parts
}ActiveTreatments = {
['HEAD'] = {
treatmentType = "bandage", -- Type: bandage, tourniquet, medicine, injection
itemType = "cotton", -- Specific item used
appliedTime = GetGameTimer(), -- When applied (game time, not os.time)
expirationTime = GetGameTimer() + 300000, -- When expires (5 min later)
appliedBy = 5, -- Server ID who applied it
originalPainLevel = 5, -- Pain level before treatment
originalBleedingLevel = 3, -- Bleeding level before treatment
painReduction = 3, -- Amount of pain reduced
bleedingReduction = 3, -- Amount of bleeding reduced
isActive = true, -- Still active?
metadata = {
label = "Cotton Bandage",
description = "...",
originalEffectiveness = 70, -- Starting effectiveness %
bleedingReduced = 4, -- From config
immediateHeal = 12 -- HP restored on application
}
}
}PlayerInfections = {
['LARM'] = {
stage = 2, -- 1-4 progression level
startTime = GetGameTimer(), -- When infection started
lastProgressCheck = GetGameTimer(), -- Last time we checked for progression
metadata = {
causeDescription = "Dirty bandage infection from cotton bandage",
symptoms = {
"Redness and swelling",
"Mild fever",
"Pain when moving"
},
treatments = {
{item = "antibiotics", timestamp = 1234567890, progress = 40}
}
}
}
}HealingTimers = {
['HEAD'] = {
woundType = "shot_through", -- Type determines heal time
startTime = GetGameTimer(), -- When healing started
healTime = 15, -- Minutes required (from config)
lastCheck = GetGameTimer(), -- Last check time
scarType = "entry_exit_scar", -- What scar it becomes
description = "Clean gunshot wound healing"
}
}PlayerFractures = {
['LLEG'] = {
type = "fracture", -- "fracture" or "bone_break"
severity = 5, -- 1-10 scale
painLevel = 5, -- Pain from fracture
mobilityImpact = 0.2, -- 20% speed reduction
healingProgress = 0.0, -- 0-100% healed
requiresSurgery = false, -- Bone break requires surgery
description = "Left leg fractured from 12m fall",
timestamp = os.time()
}
}v0.3.1-alpha