UseableMedical — Healing System
Overview
Medical items in Unturned are not implemented as a separate UseableMedical runtime class. Instead, they inherit the full consumable pipeline: ItemMedicalAsset (11 lines, empty) extends ItemConsumeableAsset, which uses UseableConsumeable as its useable class. The medical behavior is entirely data-driven through the asset's fields (health, bleedingModifier, bonesModifier, disinfectant, etc.) combined with the existing UseableConsumeable animation and application logic.
This article covers the medical-relevant interactions between UseableConsumeable and PlayerLife (2558 lines at Unturned/Player/PlayerLife.cs), the ItemConsumeableAsset fields that configure medical items, and the healing pipeline.
Inheritance Chain
ItemAsset
→ ItemWeaponAsset
→ ItemConsumeableAsset (defines health, bleeding, bones, food, water, virus, etc.)
→ ItemMedicalAsset (empty — EItemType.MEDICAL)ItemMedicalAsset exists solely to distinguish medical items from food/water items at EItemType resolution. The actual healing logic is identical to the consumable pipeline.
Medical Item Configuration
Relevant Fields from ItemConsumeableAsset
| Field | Type | Medical Use |
|---|---|---|
health | byte | Raw HP restored |
bleedingModifier | Bleeding enum (None/Heal/Cut) | Stops or causes bleeding |
bonesModifier | Bones enum (None/Heal/Break) | Heals or breaks legs |
disinfectant | byte | Virus reduction |
virus | byte | Infection applied |
hasAid | bool | Whether item can be applied to others |
shouldDeleteAfterUse | bool | Consumed on use (bandage, syringe) |
vision | byte | Hallucination effect |
energy | float | Stamina restoration |
experience | int | XP reward |
Medical Item Examples
| Item | MedicalAsset | health | bleeding | bones | hasAid | delete |
|---|---|---|---|---|---|---|
| Bandage | Medical | 0 | Heal | None | true | true |
| Medkit | Medical | 50 | Heal | None | true | true |
| Splint | Medical | 0 | None | Heal | true | true |
| Antibiotics | Medical | 10 | None | None | true | true |
| Vitamin | Medical | 5 | None | None | false | true |
Healing Pipeline (via UseableConsumeable)
Self-Heal (performUseOnSelf)
- Plugin gate:
onConsumeRequested(player, asset, ref shouldAllow). - Quest rewards:
asset.GrantQuestRewards(player). - Item rewards:
asset.itemRewards.grantItems(player, CRAFT). - Health:
performHealth(player, asset.health)— appliesaskHeal(health * (1 + Healing_mastery * 0.5)). - Bleeding:
performBleeding(player, asset.bleedingModifier)— callsserverSetBleeding(bool). - Bones:
performBrokenBones(player, asset.bonesModifier)— callsserverSetLegsBroken(bool). - Disinfectant:
askDisinfect(disinfectant * (1 + Healing_mastery * 0.5)). - Virus penalty:
askInfect(virus * (1 - Immunity_mastery * 0.5)). - Low quality penalty: If quality < 50, additional infection proportional to food+water.
- Stamina:
askRest(asset.energy). - XP:
ServerModifyExperience(asset.experience). - Delete/Dequip: Based on
shouldDeleteAfterUse.
Aid-Heal (apply to another player)
- Plugin gate:
onPerformingAid(instigator, target, asset, ref shouldAllow). - Quest/item rewards granted to target.
- Health:
performHealth(enemy, asset.health)— uses instigator's HEALING skill for increased output. - Bleeding: same as self-heal.
- Bones: same as self-heal.
- Food/Water:
askEat(asset.food * quality)/askDrink(asset.water * quality). - Virus/Disinfectant: uses target's IMMUNITY and HEALING skills.
- XP and Reputation:
xp += (healthDelta) / 2xp += (virusDelta) / 2xp += 15for bleeding healxp += 15for bone healrep += 1per stat improved
- Dequip item.
PlayerLife Healing API
PlayerLife provides the server-authoritative health mutation methods that medical items call indirectly through askHeal:
askHeal
csharp
public void askHeal(byte amount, bool healBleeding, bool healBones)- Increases
_healthbyamount, clamped to 100. - If
healBleedingtrue: clears bleeding (not used by medical items — they useserverSetBleedingdirectly). - If
healBonestrue: clears broken legs (not used by medical items — they useserverSetLegsBrokendirectly). - Replicates via
SendHealthto all clients. - Fires
onHealthUpdatedandOnTellHealth_Global.
serverSetBleeding
csharp
public void serverSetBleeding(bool newBleeding)- Sets
_isBleeding = newBleeding. - Calls
tellBleedingwhich replicates and fires events. - Bleeding reduces health by 1 every few seconds while active.
serverSetLegsBroken
csharp
public void serverSetLegsBroken(bool newBroken)- Sets
_isBroken = newBroken. - Replicates via
SendBroken. - Broken legs reduce movement speed and prevent sprinting.
- Jumping while broken deals additional damage.
serverModifyHealth / serverModifyFood / serverModifyWater
csharp
public void serverModifyHealth(float delta)Float input supports fractional changes. Internally rounds and clamps:
csharp
_health = (byte)Mathf.Clamp(_health + Mathf.RoundToInt(delta), 0, 100);Used by UseableRefill and other non-consumable healing paths.
askDisinfect
csharp
public void askDisinfect(byte amount)Reduces _virus by amount, clamped to 0. Replicates via SendVirus.
askInfect
csharp
public void askInfect(byte amount)Increases _virus by amount, clamped to 100. Replicates via SendVirus.
Skill Interactions
Healing Mastery
healingMultiplier = 1 + (HEALING_level / HEALING_max) * 0.5
// At max level (7): 1 + 1.0 * 0.5 = 1.5x healing outputApplied in UseableConsumeable.performHealth:
csharp
int roundedDelta = Mathf.RoundToInt(delta * instigatorHealingSkillMultiplier);Also increases disinfection effectiveness:
csharp
disinfectant * (1 + Healing_mastery * 0.5)Immunity Mastery
immunityMultiplier = 1 - (IMMUNITY_level / IMMUNITY_max) * 0.5
// At max level (5): 1 - 1.0 * 0.5 = 0.5x virus intakeApplied to:
virus_to_apply = asset.virus * immunityMultiplier
vision_to_apply = asset.vision * immunityMultiplierPlayer Life State Machine
isDead ← _health == 0 || fall damage (overkill) || explosion
├─ deathCause / deathLimb / deathKiller (static, per-death)
├─ wasPvPDeath (bool, set based on killer type)
├─ markAggressive(force) / isAggressor (30s cooldown)
├─ onLifeUpdated (event)
└─ OnPreDeath (event, before built-in death logic)
Bleeding (_isBleeding):
Every few seconds (configurable), health -= 1 while bleeding.
Can be healed by Bandage, Medkit, or passive regen with skills.
Broken (_isBroken):
Movement disabled, jumping forbidden.
Only healable by Splint or medical item with bonesModifier=Heal.
Virus (_virus):
Accumulates from dirty water, rotten food, environmental sources.
At high levels, causes vision distortion, health drain.
Reduced by Antibiotics, disinfectant, immunity skill.
Vision (_vision):
Hallucination effect from berries/medicinal vision fields.
Distorts camera controls (inverted axes, random inversion).
Temperature (_temperature):
Affected by warmth modifier from items, environment, clothing.
Medical items can provide temporary warmth.Blood Regeneration Item (ItemBloodRegenAsset)
Not present in the available source files, but the consumable pattern supports custom assets that extend ItemConsumeableAsset to provide passive regeneration or other timed effects.
PlayerLife Healing API — Full Reference
askHeal — Health Restoration
csharp
public void askHeal(byte amount, bool healBleeding, bool healBones)Source: PlayerLife.cs (not fully shown in available source, but the consumption points confirm):
- Adds
amountto_health, clamped to[0, 100]. - If
healBleeding, sets_isBleeding = false. - If
healBones, sets_isBroken = false. - Sends update to all clients via
SendHealth. - Fires
onHealthUpdatedand globalOnTellHealth_Global.
Medical items don't use the healBleeding/healBones parameters directly — they handle these conditions separately through serverSetBleeding and serverSetLegsBroken.
serverSetBleeding — Bleeding State
csharp
public void serverSetBleeding(bool newBleeding)- Sets
_isBleeding. - Calls
tellBleedingwhich replicates and firesonBleedingUpdated. - While bleeding: health decreases by 1 every ~6 seconds (configurable via
Bleeding_Damage_Rate). - Bleeding can be stopped by items with
bleedingModifier = Heal, or by waiting (uncommon — no passive stop). - Bleeding is visually indicated by screen blood splatter and health bar pulsing.
serverSetLegsBroken — Broken Bone State
csharp
public void serverSetLegsBroken(bool newBroken)- Sets
_isBroken. - Calls
tellBrokenwhich replicates and firesonBrokenUpdated. - While broken: movement speed significantly reduced (approx 50%).
- Sprinting is disabled.
- Jumping while broken causes additional damage (
askDamagewith fall damage mechanics). - Broken legs are visually indicated by a screen fracture overlay and a limp animation.
serverModifyHealth / Food / Water — Float Delta Variants
csharp
public void serverModifyHealth(float delta)Used by UseableRefill and indirect healing paths. Internally:
csharp
_health = (byte)Mathf.Clamp(_health + Mathf.RoundToInt(delta), 0, 100);Positive deltas heal, negative deltas damage. Float precision allows fractional stat changes from refill water types.
serverModifyStamina
csharp
public void serverModifyStamina(float delta)Applied from ItemConsumeableAsset.energy. Positive values restore stamina; negative values drain it. Stamina range: 0–100.
serverModifyWarmth
csharp
public void serverModifyWarmth(short delta)Increases _warmth by delta. Warmth range is 0–100 (inferred from uint _warmth storage). Warmth decays over time in cold environments. Medical items with warmth > 0 provide temporary cold resistance.
serverModifyHallucination
csharp
public void serverModifyHallucination(byte newVision)Sets _vision to Max(current, newVision) from UseableConsumeable. Vision (hallucination) effect:
- Distorts camera controls (inverted/multiplied axes).
- Applies screen color filtering.
- Decays over time (
lastViewtimer inPlayerLifeupdate). - Vision values > 0 indicate hallucinogen effect intensity.
askRest — Stamina Restoration
csharp
public void askRest(float energy)Adds energy to _stamina, clamped to 100. Called from UseableConsumeable.performUseOnSelf for both owner and server prediction.
simulatedModifyStamina / Oxygen
csharp
public void simulatedModifyStamina(float delta)
public void simulatedModifyOxygen(float delta)Applied on both owner and server (prediction-safe). Oxygen modifications affect _oxygen (0–100). Low oxygen causes damage via suffocation mechanic.
PlayerLife Core Stat Ranges and Defaults
| Stat | Type | Range | Default | Decrease | Increase |
|---|---|---|---|---|---|
_health | byte | 0–100 | 100 | Damage, bleeding, starvation | Healing items, passive regen |
_food | byte | 0–100 | 100 | Starvation timer | Food consumables |
_water | byte | 0–100 | 100 | Dehydration timer | Water consumables, refill |
_virus | byte | 0–100 | 0 | Environment, dirty food | Medical disinfectant |
_stamina | byte | 0–100 | 100 | Sprinting, melee attacks | Rest, energy items |
_oxygen | byte | 0–100 | 100 | Underwater, diving | Surfacing |
_vision | byte | 0–100 | 0 | Hallucinogenic items | Time decay |
_warmth | uint | 0–100 | 100 | Cold environment | Warm items, fire |
_isBleeding | bool | T/F | False | Damage from sharp sources | Bandage/medical |
_isBroken | bool | T/F | False | Fall damage, explosions | Splint/medical |
PlayerLife Passive Update Ticks
PlayerLife runs a passive update every simulation tick. Relevant to medical context:
csharp
// Bleeding damage
if (_isBleeding && (simulation % bleedingRate) == 0)
_health = Max(0, _health - 1);
// Virus damage
if (_virus >= virusThreshold)
_health = Max(0, _health - 1);
// Food drain
if (simulation % foodRate == 0)
_food = Max(0, _food - 1);
// Water drain
if (simulation % waterRate == 0)
_water = Max(0, _water - 1);
// Virus drain
if (simulation % virusRate == 0)
_virus = Max(0, _virus - 1);
// Passive health regen
if (_health < 100 && _food > 0 && _water > 0 && !_isBleeding)
_health = Min(100, _health + vitalityRegenAmount);The vitalityRegenAmount is influenced by the VITALITY skill master — higher levels regenerate health faster.
Healing Skill Interactions — Expanded Formulas
Instigator Healing Output
csharp
float instigatorHealingSkillMultiplier = 1f + (player.skills.mastery(SUPPORT.HEALING) * 0.5f);
// At max (level 7, mastery 1.0): 1.5× healing output
// Tiered:
// level 0: 1.0×
// level 3: 1.214× (3/7 * 0.5 = 0.214)
// level 7: 1.5×Applied to: Mathf.RoundToInt(delta * instigatorHealingSkillMultiplier) in performHealth.
Target Immunity — Infection Resistance
csharp
float enemyImmunitySkillMultiplier = 1f - (enemy.skills.mastery(DEFENSE.IMMUNITY) * 0.5f);
// At max (level 5, mastery 1.0): 0.5× virus intake (50% reduction)Applied to: asset.virus * enemyImmunitySkillMultiplier.
Target Immunity — Hallucination Reduction
csharp
byte newVision = (byte)(asset.vision * (1f - enemy.skills.mastery(DEFENSE.IMMUNITY)));
// At max: 0 — complete immunity to hallucination effectsTarget Healing Skill — Disinfect Boost
csharp
float enemyHealingSkillMultiplier = 1f + (enemy.skills.mastery(SUPPORT.HEALING) * 0.5f);
// Applied to disinfectant amountThis means a target with high HEALING skill benefits more from disinfectant applied by others — the target's own biology amplifies the treatment.
XP and Reputation from Medical Aid
When applying aid to another player, the instigator earns XP and reputation:
csharp
if (postHealth > preHealth)
{
xp += (uint)Mathf.RoundToInt((postHealth - preHealth) / 2.0f);
rep++;
}
if (preBleeding && !postBleeding)
{
xp += 15;
rep++;
}
if (preBroken && !postBroken)
{
xp += 15;
rep++;
}- Health restoration: 0.5 XP per HP healed (rounded). Healing 20 HP → 10 XP.
- Bleeding cure: 15 XP flat.
- Bone healing: 15 XP flat.
- Maximum XP per aid action: Up to ~80 XP (heal 100 HP) + 15 + 15 = 110 XP.
- Reputation cap: +1 per distinct category improved (max +3 per action).
Vision (Hallucination) System — Complete Mechanics
The vision value (_vision) controls hallucination effects:
Setting Vision
csharp
public void askView(byte newVision)
{
_vision = Mathf.Max(_vision, newVision);
// Replicates via SendVision
}Vision only increases — askView uses Mathf.Max, so applying a low-vision item after a high-vision item has no effect. The effect duration is controlled by the passive decay rate.
Vision Effects
In PlayerLook.onVisionUpdated():
csharp
if (isViewing)
{
yawInputMultiplier = Random.value < 0.25 ? -1.0f : 1.0f;
pitchInputMultiplier = Random.value < 0.25 ? -1.0f : 1.0f;
}Each axis has a 25% chance per tick of becoming inverted (the Random.value < 0.25 check runs once when vision starts, not per frame). This creates a disorienting cross-dominance effect where the player may need to push right to look left on the yaw axis.
Vision Decay
csharp
// In PlayerLife simulate():
if (simulation - lastView > visionDecayRate && _vision > 0)
_vision--;Vision decays by 1 point per decay interval (~1 second, inferred from lastView). Each point of vision provides one second of hallucination effect per 100 points → max 100 seconds of effect.
UseableConsumeable Flow for Medical Items (Complete)
startPrimary()
→ consume()
→ play("Use")
→ playSound(asset.use)
→ AlertTool.alert(8m)
→ simulate() waiting for isUseable
→ performUseOnSelf(asset)
├─ Owner+Server:
│ player.life.askRest(asset.energy)
│ player.life.askView(asset.vision)
│ player.life.simulatedModifyOxygen(asset.oxygen)
│ player.life.simulatedModifyWarmth(asset.warmth)
├─ Server only:
│ invokeConsumeRequested(asset) // plugin gate
│ asset.GrantQuestRewards(player)
│ asset.itemRewards.grantItems(player)
│ performHealth(player, asset.health)
│ performBleeding(player, asset.bleedingModifier)
│ performBrokenBones(player, asset.bonesModifier)
│ player.life.askEat(asset.food * quality%)
│ player.life.askDrink(asset.water * quality%)
│ askInfect(asset.virus * immunitySkill)
│ askDisinfect(asset.disinfectant * healingSkill)
│ invokeConsumePerformed(asset)
│ if shouldDeleteAfterUse → use() else dequip()
└─ [If explosive: effect + explosion + suicide]Notable Implementation Details
ItemMedicalAssetis an empty subclass — its entire behavior is defined byItemConsumeableAssetfields andUseableConsumeablelogic. Mods can create custom medical subtypes by subclassingItemMedicalAssetand adding new fields for custom medical behaviors.- Bleeding and bone healing are applied independently of health restoration. A bandage heals bleeding without restoring HP; a splint heals bones without restoring HP; a medkit does all three.
- Medical items flagged with
hasAid = truecan be applied to other players via the secondary action. The instigator's HEALING skill increases the effectiveness, while the target's IMMUNITY skill reduces side effects. - Quality degradation of medical items has no effect on healing amount directly (unlike food/water), but low quality imposes an infection penalty.
