Skip to content

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 ​

FieldTypeMedical Use
healthbyteRaw HP restored
bleedingModifierBleeding enum (None/Heal/Cut)Stops or causes bleeding
bonesModifierBones enum (None/Heal/Break)Heals or breaks legs
disinfectantbyteVirus reduction
virusbyteInfection applied
hasAidboolWhether item can be applied to others
shouldDeleteAfterUseboolConsumed on use (bandage, syringe)
visionbyteHallucination effect
energyfloatStamina restoration
experienceintXP reward

Medical Item Examples ​

ItemMedicalAssethealthbleedingboneshasAiddelete
BandageMedical0HealNonetruetrue
MedkitMedical50HealNonetruetrue
SplintMedical0NoneHealtruetrue
AntibioticsMedical10NoneNonetruetrue
VitaminMedical5NoneNonefalsetrue

Healing Pipeline (via UseableConsumeable) ​

Self-Heal (performUseOnSelf) ​

  1. Plugin gate: onConsumeRequested(player, asset, ref shouldAllow).
  2. Quest rewards: asset.GrantQuestRewards(player).
  3. Item rewards: asset.itemRewards.grantItems(player, CRAFT).
  4. Health: performHealth(player, asset.health) — applies askHeal(health * (1 + Healing_mastery * 0.5)).
  5. Bleeding: performBleeding(player, asset.bleedingModifier) — calls serverSetBleeding(bool).
  6. Bones: performBrokenBones(player, asset.bonesModifier) — calls serverSetLegsBroken(bool).
  7. Disinfectant: askDisinfect(disinfectant * (1 + Healing_mastery * 0.5)).
  8. Virus penalty: askInfect(virus * (1 - Immunity_mastery * 0.5)).
  9. Low quality penalty: If quality < 50, additional infection proportional to food+water.
  10. Stamina: askRest(asset.energy).
  11. XP: ServerModifyExperience(asset.experience).
  12. Delete/Dequip: Based on shouldDeleteAfterUse.

Aid-Heal (apply to another player) ​

  1. Plugin gate: onPerformingAid(instigator, target, asset, ref shouldAllow).
  2. Quest/item rewards granted to target.
  3. Health: performHealth(enemy, asset.health) — uses instigator's HEALING skill for increased output.
  4. Bleeding: same as self-heal.
  5. Bones: same as self-heal.
  6. Food/Water: askEat(asset.food * quality) / askDrink(asset.water * quality).
  7. Virus/Disinfectant: uses target's IMMUNITY and HEALING skills.
  8. XP and Reputation:
    • xp += (healthDelta) / 2
    • xp += (virusDelta) / 2
    • xp += 15 for bleeding heal
    • xp += 15 for bone heal
    • rep += 1 per stat improved
  9. 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 _health by amount, clamped to 100.
  • If healBleeding true: clears bleeding (not used by medical items — they use serverSetBleeding directly).
  • If healBones true: clears broken legs (not used by medical items — they use serverSetLegsBroken directly).
  • Replicates via SendHealth to all clients.
  • Fires onHealthUpdated and OnTellHealth_Global.

serverSetBleeding ​

csharp
public void serverSetBleeding(bool newBleeding)
  • Sets _isBleeding = newBleeding.
  • Calls tellBleeding which 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 output

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

Applied to:

virus_to_apply = asset.virus * immunityMultiplier
vision_to_apply = asset.vision * immunityMultiplier

Player 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 amount to _health, clamped to [0, 100].
  • If healBleeding, sets _isBleeding = false.
  • If healBones, sets _isBroken = false.
  • Sends update to all clients via SendHealth.
  • Fires onHealthUpdated and global OnTellHealth_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 tellBleeding which replicates and fires onBleedingUpdated.
  • 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 tellBroken which replicates and fires onBrokenUpdated.
  • While broken: movement speed significantly reduced (approx 50%).
  • Sprinting is disabled.
  • Jumping while broken causes additional damage (askDamage with 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 (lastView timer in PlayerLife update).
  • 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 ​

StatTypeRangeDefaultDecreaseIncrease
_healthbyte0–100100Damage, bleeding, starvationHealing items, passive regen
_foodbyte0–100100Starvation timerFood consumables
_waterbyte0–100100Dehydration timerWater consumables, refill
_virusbyte0–1000Environment, dirty foodMedical disinfectant
_staminabyte0–100100Sprinting, melee attacksRest, energy items
_oxygenbyte0–100100Underwater, divingSurfacing
_visionbyte0–1000Hallucinogenic itemsTime decay
_warmthuint0–100100Cold environmentWarm items, fire
_isBleedingboolT/FFalseDamage from sharp sourcesBandage/medical
_isBrokenboolT/FFalseFall damage, explosionsSplint/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 effects

Target Healing Skill — Disinfect Boost ​

csharp
float enemyHealingSkillMultiplier = 1f + (enemy.skills.mastery(SUPPORT.HEALING) * 0.5f);
// Applied to disinfectant amount

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

  • ItemMedicalAsset is an empty subclass — its entire behavior is defined by ItemConsumeableAsset fields and UseableConsumeable logic. Mods can create custom medical subtypes by subclassing ItemMedicalAsset and 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 = true can 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.