Skip to content

PlayerUtil

QinShenYu edited this page Jun 10, 2026 · 7 revisions

Namespace: ScavLib.util

Safe, null-protected wrappers around the player's Body component. All methods return safe default values (0, false, null) when no world is loaded — they will never throw a NullReferenceException.

Two write paths are provided throughout this API:

  • Recommended writes — respect the game's internal logic where possible (e.g. Feed, HealAll). Use these by default.
  • Raw writes (suffix Raw) — direct field assignment with Mathf.Clamp protection. Bypass game logic intentionally. Use only when you know what you are doing.

0.5.0 structure note: PlayerUtil is a single public static partial class split across several source files for maintainability. The public API is unchanged by the split. The files are:

File Contents
PlayerUtil.cs Inventory shortcuts
PlayerUtil.Vitals.cs Vital sign reads + computed read-only properties
PlayerUtil.States.cs Boolean state queries
PlayerUtil.Drugs.cs Drug component queries / removal, drug-driven modifiers
PlayerUtil.Appearance.cs Disfigurement, eyes, mind-wipe, horrified, claws, weight
PlayerUtil.Sleep.cs Sleep-quality timers
PlayerUtil.LastStand.cs Last-stand state, antibiotic immunity
PlayerUtil.Recovery.cs Feed / Hydrate / HealAll and friends
PlayerUtil.RawWrites.cs Direct field writes (Set*Raw)
PlayerUtil.Thresholds.cs Named threshold constants
PlayerUtil.Compat.cs 0.4.x backward-compatibility aliases

Inventory Shortcuts

Method Returns Description
GiveItem(string id) GameObject Spawn item at player feet and auto-pickup. Returns the spawned GameObject, or null on failure.
TakeItem(string id) bool Drop the first inventory item matching the given ID. Returns true if found and dropped.
HasItem(string id) bool Check if the player has at least one item with the given ID in their surface inventory (slots + wearables).
GetAllItems() List<Item> Get all items currently in the player's slot inventory (not wearables). Returns an empty list if not in game.
FindItemById(string id, out Item item) bool Search full inventory including containers and wearables by ID.
FindItemByTag(string tag, out Item item) bool Search full inventory including containers and wearables by tag.
PlayerUtil.GiveItem("bandage");

if (PlayerUtil.HasItem("rifle"))
    GameUtil.Log("Player has a rifle.");

if (PlayerUtil.FindItemById("medkit", out var kit))
    ItemUtil.Repair(kit);

Vital Sign Reads (Core)

Method Returns Normal range / Notes
GetHunger() float Normal: 100, max 125. Below 0 = starving (muscle loss).
GetThirst() float Normal: 100, max 250. Above 175 = over-hydration. Below 0 = blood viscosity rising.
GetStamina() float 0 ~ 100.
GetEnergy() float 0 ~ 100. Below 7 = exhausted.
GetConsciousness() float 0 ~ 100. Below 30 = incapacitated.
GetBrainHealth() float 0 ~ 100. At 0 = dead.
GetBloodOxygen() float 0 ~ 100. Normal: ~98.
GetBloodVolume() float Normal: 100. Max: 200. Can go negative on heavy bleeding.
GetBloodPressure() float Systolic. Normal: ~120.
GetHeartRate() float Normal: ~70 BPM. Below 20 = cardiac arrest.
GetRespiratoryRate() float 0 ~ 100. Normal: ~100.
GetTemperature() float Celsius. Normal: 36.6 ~ 37.
GetHappiness() float -100 ~ 100. Composite totalHappiness after all modifiers.
GameUtil.Log($"HR: {PlayerUtil.GetHeartRate():F0} BPM  " +
             $"BP: {PlayerUtil.GetBloodPressure():F0}  " +
             $"SpO2: {PlayerUtil.GetBloodOxygen():F0}%");

Vital Sign Reads (Extended)

These cover the full Body field set (expanded in 0.3.0, completed in 0.5.0).

Circulation

Method Returns Notes
GetBloodViscosity() float -100 ~ 100. 0 = normal. Above 90 may trigger pulmonary embolism.
GetBloodVesselSize() float 0.85 ~ 1.15. 1.0 = normal. Affects blood pressure inversely.
GetFibrillationProgress() float 0 ~ 100. At 100 = cardiac arrest.
GetHeartRatePressureOffset() float -30 ~ 80. Internal circulation tuning value.
GetStrokeAmount() float 0 ~ 100. Above 50 = dying. Auto-increments once started.

Adrenaline

Method Returns Notes
GetAdrenaline() float 0 ~ 100. Reserve pool; suppresses pain, raises heart rate.
GetCurAdrenaline() float 0 ~ 100. Active value, lerps toward adrenaline.

Infection / Toxicology / Sepsis

Method Returns Notes
GetSepticShock() float 0 ~ 100. Above 75 = dying.
GetSicknessAmount() float 0 ~ 100. Above 80 = can't sleep naturally.
GetVenomTotal() float 0 ~ 100. Total venom load; decays over time.
GetVenomCurrent() float 0 ~ 100. Active venom; lerps toward venomTotal.

Bleeding

Method Returns Notes
GetInternalBleeding() float 0 ~ 100. Causes hemothorax over time.
GetHemothorax() float 0 ~ 100. Blood in chest cavity; causes breathing issues.
GetAveragePain() float Read-only, per-frame. Highest limb pain after Resilience reduction.
GetTotalBleedSpeed() float Read-only, per-frame. Sum of all limb bleed rates.

Neurology / Psychology

Method Returns Notes
GetShock() float 0 ~ 100. At 100 = forced ragdoll.
GetPainShock() float 0 ~ 1. At 0.66+ = unconscious.
GetTraumaAmount() float 0 ~ 100. From sustained high pain.
GetRadiationSickness() float 0 ~ 100. Above 60 = dying.
GetHorrifiedLevel() float 0 ~ 200. Decays at 20/s. Each point cuts totalHappiness by 0.5%.
GetFocusedLevel() float 0 ~ 200. Opposite of horrified; improves performance. Decays at 20/s.
GetBrainGrowSickness() float 0+. Decays at 1/s. From certain mutations.

Happiness / Weight

Method Returns Notes
GetHappinessBase() float -100 ~ 100. Base value before modifiers. Use GetHappiness() for composite.
GetWeightOffset() float -80 ~ 100. 0 = normal. Affects speed, encumberance, BP, heart rate, insulation. Above |60| may trigger fibrillation.

External Conditions

Method Returns Notes
GetWetness() float 0 ~ 100. Lowers temperature; triggers dog-shake when cold.
GetDirtyness() float 0 ~ 100. Increases infection risk and food sickness chance.
GetSnowAmount() float 0 ~ 100. From cold environments.
GetHearingLoss() float 0 ~ 100. Decays at 0.05/s.

Claws / Immunity

Method Returns Notes
GetClawHealth() float 0 ~ 100. Below 20, claw attacks may damage the attacking limb.
GetClawRegrowTime() float 0+ seconds. Counts down before regrowth boost ends.
GetImmunity() float 0 ~ 200. Normal: ~100. Fights off infections.
GetAntibioticImmunityTime() float 0+ seconds. While > 0, immunity score +70. Decays at 0.5/s.

Stimulants / Drugs (0.5.0)

Method Returns Notes
GetCaffeinated() float 0+ seconds. While > 0: stamina regen ×2, energy drain ×0.55. Decays at 1/s.
GetOpiateHappiness() float Opiate-derived happiness bonus added to totalHappiness. Driven by the Painkillers component; 0 when inactive.
GetAntidepressantHappiness() float Antidepressant-derived happiness bonus added to totalHappiness. Driven by the Antidepressants component; 0 when inactive.

Sleep (0.5.0)

Method Returns Notes
GetBadSleepAmount() float 0+ seconds. While > 0, max consciousness target drops 100→70. Mediocre sleep → 60s, bad sleep → 150s. Decays at 1/s.
GetGoodSleepTime() float Game time of the last good-quality sleep. Used by well-rested moodles.

Last Stand (0.5.0)

Method Returns Notes
GetLastStandTime() float Cooldown timer. -10000 = never triggered; set to 300 on success; decays at 1/s. While > 0, adrenaline drain is suppressed.

Appearance (0.5.0)

Method Returns Notes
IsDisfigured() bool Face disfigured. Permanently caps head muscleHealth at 50; persists across saves.
IsEyeGone() bool At least one eye lost.
IsBothEyesGone() bool Both eyes lost. Auto-cleared by the game if eyeGone is false.
IsMindWiped() bool Active MindwipeScript component. While true, totalHappiness is forced to 0. Read may lag actual state by up to 0.5s.

Computed / Derived Read-Only Properties (0.5.0)

Method Returns Notes
GetTempDiffFromNormal() float Per-frame: temperature - 37.
GetBloodVolumePercentage() float 0 ~ 1.5. Normal 0.5 ~ 1.0. Computed: 0.5 + bloodVolume/200.
IsFibrillationRising() bool True if fibrillation is actively worsening (low O₂/BP, high HR, etc.).
IsBrainDying() bool True if bloodPressure < 10 AND consciousness < 5.
GetCurrentWeightMovementMult() float Weight-driven movement multiplier (updated per-second).
GetCurrentTemperatureMovementMult() float Temperature-driven movement multiplier (updated per-second).
GetBleedClottingSpeed() float Clotting speed multiplier. Affected by viscosity and venom.
GetBleedingSpeedMultiplier() float Bleeding speed multiplier. Affected by viscosity.
GetThirstBloodPressure() float Thirst-driven BP multiplier (per-second).
GetHungerLimbHealCurrent() float Current hunger-driven limb heal rate (per-frame).
GetCurImmunityMult() float Current immunity-to-infection-speed multiplier (per-second).
GetDesensitizedMult() float 0 ~ 1. 1 = fully sensitive, lower = desensitized to gore/horror.
GetCorpsesSeen() int Corpses seen this run. Drives desensitization.
GetBloodPressureReadout() string Formatted BP readout for UI, e.g. "120/80".
GetRespiratoryRateReadout() string Formatted respiratory rate readout for UI, e.g. "25/m".

Drug Component Queries & Removal (0.5.0)

Each drug effect is implemented as a separate MonoBehaviour component the game adds to the player Body. These helpers check for and remove them.

Method Returns Description
HasPainkillers() bool True if the Painkillers component is active (opiates in effect).
HasAntidepressants() bool True if the Antidepressants component is active.
HasSleepingPills() bool True if the SleepingPills component is active.
RemovePainkillers() void Destroy the Painkillers component if present. Ends opiate effects; opiateHappiness decays back to 0. No-op if absent.
RemoveAntidepressants() void Destroy the Antidepressants component if present. No-op if absent.
RemoveSleepingPills() void Destroy the SleepingPills component if present. No-op if absent.
if (PlayerUtil.HasSleepingPills())
    PlayerUtil.RemoveSleepingPills(); // force the player awake-capable again

State Queries (Core)

Method Returns Condition
IsAlive() bool brainHealth > 0
IsConscious() bool Alive AND consciousness > 30
IsDying() bool Any critical vital threshold breached
IsCriticallyDying() bool Stricter version of IsDying — gates the last-stand roll
IsInCardiacArrest() bool heartRate < 20
IsSleeping() bool Player is currently asleep
IsExercising() bool Player is performing a workout (pushups/squats/plank)

State Queries (Extended, 0.5.0)

Method Returns Condition
IsBreathing() bool Alive AND respiratoryRate > 10
IsInWater() bool Player is submerged in water
HasScubaGear() bool Player has functional scuba gear (can breathe underwater)
IsStanding() bool Standing (not ragdolled)
IsCrouching() bool Currently crouching
IsOnHardStimulants() bool Under low/mid/high-grade hard stimulants
UsedNeuralBooster() bool Used a neural booster (permanent flag for the run)
IsUsingSleepingBag() bool Using a sleeping bag (improves sleep quality / insulation)
IsBothHandsUnusable() bool Both hands have force < 0.08 (unable to grip)
IsAboveMedicalCutoff() bool totalHappiness > -75 (above medical treatment cutoff)
CanTakeNap() bool (energy < 35 AND avgPain < 31 AND sickness < 80) OR holding SleepingPills
AllowUseItem() bool totalHappiness > -20, or passes a depression chance roll
HasPulmonaryEmbolism() bool Has a pulmonary embolism (from high blood viscosity); triggers isDying
IsFibrillationForced() bool Fibrillation forced on — will not auto-recover even if vitals stabilize
HasTriedLastStand() bool Already attempted the last-stand recovery roll this run
HasSuccessfullyRolledLastStand() bool Successfully triggered last-stand recovery this run

Note on naming: States.cs exposes HasTriedLastStand() and HasSuccessfullyRolledLastStand(). LastStand.cs exposes the equivalent TriedRollingLastStand() and SuccessfullyRolledLastStand(). They read the same underlying fields. The game's own field succesfullyRolledLastStand is misspelled (one s missing); ScavLib exposes it under the corrected name — use the original spelling only when interoping with raw JSON save data.


Last Stand State Queries (0.5.0)

Method Returns Description
TriedRollingLastStand() bool True if the game has attempted a last-stand roll this life. Once true, no further roll occurs. Reset on new life (new Body).
SuccessfullyRolledLastStand() bool True if the player survived via last stand this life.

Recommended Writes

These methods respect the game's clamping and logic where meaningful.

Method Description
Feed(float amount) Add to hunger. Clamped to -100 ~ 100. Negative values allowed.
Hydrate(float amount) Add to thirst. Clamped to 0 ~ 200.
RestoreStamina(float amount) Add to stamina. Clamped to 0 ~ 100.
RestoreEnergy(float amount) Add to energy. Clamped to 0 ~ 100.
HealAll() Reset all vitals to safe values and heal every non-dismembered limb. Does not regrow dismembered limbs. 0.5.0: also clears active Painkillers/Antidepressants/SleepingPills components, resets badSleepAmount, and zeroes opiateHappiness/antidepressantHappiness — mirroring Body.TryLastStand() cleanup.
// Fully restore the player
PlayerUtil.HealAll();

// Partial restore
PlayerUtil.Feed(50f);
PlayerUtil.Hydrate(50f);
PlayerUtil.RestoreStamina(100f);

Raw Writes

Direct field assignments with Mathf.Clamp protection. These bypass game logic — use only when intentional. "0+" denotes a lower clamp at 0 with no upper bound; "—" denotes a boolean with no range; "no clamp" denotes a drug-driven value written verbatim.

Core vitals

Method Range
SetHungerRaw(float) -50 ~ 125
SetThirstRaw(float) -50 ~ 250
SetStaminaRaw(float) 0 ~ 100
SetEnergyRaw(float) 0 ~ 100
SetConsciousnessRaw(float) 0 ~ 100
SetBrainHealthRaw(float) 0 ~ 100 — setting to 0 kills the player
SetTemperatureRaw(float) 20 ~ 50 (°C)
SetHappinessRaw(float) -100 ~ 100 (base happiness)
SetHappinessBaseRaw(float) -100 ~ 100 (alias for base happiness)

Note: SetHungerRaw / SetThirstRaw use the game's wider raw clamps (-50 ~ 125 and -50 ~ 250). The recommended Feed / Hydrate writes clamp to the narrower gameplay ranges (-100 ~ 100 and 0 ~ 200) instead.

Circulation

Method Range
SetBloodVolumeRaw(float) -100 ~ 200
SetBloodOxygenRaw(float) 0 ~ 100
SetBloodPressureRaw(float) 0 ~ 250
SetHeartRateRaw(float) 0 ~ 300
SetRespiratoryRateRaw(float) 0 ~ 100
SetBloodViscosityRaw(float) -100 ~ 100
SetBloodVesselSizeRaw(float) 0.85 ~ 1.15
SetFibrillationProgressRaw(float) 0 ~ 100
SetHeartRatePressureOffsetRaw(float) -30 ~ 80
SetFibrillationForcedRaw(bool)
SetHasPulmonaryEmbolismRaw(bool) — (causes immediate dying state)
SetStrokeAmountRaw(float) 0 ~ 100

Adrenaline

Method Range
SetAdrenalineRaw(float) 0 ~ 100
SetCurAdrenalineRaw(float) 0 ~ 100

Infection / Toxicology / Sepsis

Method Range
SetSepticShockRaw(float) 0 ~ 100
SetSicknessAmountRaw(float) 0 ~ 100
SetVenomTotalRaw(float) 0 ~ 100
SetVenomCurrentRaw(float) 0 ~ 100

Bleeding

Method Range
SetInternalBleedingRaw(float) 0 ~ 100
SetHemothoraxRaw(float) 0 ~ 100

Neurology / Psychology

Method Range
SetShockRaw(float) 0 ~ 100
SetPainShockRaw(float) 0 ~ 1
SetTraumaAmountRaw(float) 0 ~ 100
SetRadiationSicknessRaw(float) 0 ~ 100
SetHorrifiedLevelRaw(float) 0 ~ 200
SetFocusedLevelRaw(float) 0 ~ 200
SetBrainGrowSicknessRaw(float) 0+
SetStrokeAmountRaw(float) 0 ~ 100

External Conditions

Method Range
SetWetnessRaw(float) 0 ~ 100
SetDirtynessRaw(float) 0 ~ 100
SetSnowAmountRaw(float) 0 ~ 100
SetHearingLossRaw(float) 0 ~ 100

Weight

Method Range
SetWeightOffsetRaw(float) -80 ~ 100

Claws / Immunity / Stimulants

Method Range
SetClawHealthRaw(float) 0 ~ 100
SetClawRegrowTimeRaw(float) 0+ (seconds)
SetImmunityRaw(float) 0 ~ 200
SetAntibioticImmunityTimeRaw(float) 0+ (seconds)
SetCaffeinatedRaw(float) 0+ (seconds)

Sleep

Method Range
SetBadSleepAmountRaw(float) 0+ (seconds)
SetGoodSleepTimeRaw(float) no clamp (a Time.time timestamp)

Last Stand

Method Range
SetLastStandTimeRaw(float) -10000 ~ 300
SetTriedRollingLastStandRaw(bool) — (set false to allow another attempt)
SetSuccessfullyRolledLastStandRaw(bool) — (statistics tracking)

Drug-driven modifiers

Method Range
SetOpiateHappinessRaw(float) no clamp
SetAntidepressantHappinessRaw(float) no clamp
SetBloodPressureChangeFromMedicineRaw(float) no clamp (offset)

Boolean flags (appearance / state)

Method Notes
SetSleepingRaw(bool) Does not trigger the sleep animation.
SetDisfiguredRaw(bool)
SetEyeGoneRaw(bool) Single eye lost.
SetBothEyesGoneRaw(bool) Full blindness. Auto-cleared by the game if eyeGone is false.
SetUsedNeuralBoosterRaw(bool) Permanent for the run.
SetUsingSleepingBagRaw(bool) Improves sleep quality and insulation.

Desensitization

Method Range
SetDesensitizedMultRaw(float) 0 ~ 1
SetCorpsesSeenRaw(int) 0+

Backward-Compatibility Aliases (Compat)

The 0.5.0 partial-class split renamed several boolean accessors from Get* to Is* / Has*. The old names are preserved as thin aliases in PlayerUtil.Compat.cs so mods written against 0.4.x still compile. Prefer the canonical names in new code.

Alias (old) Canonical (use this)
GetDisfigured() IsDisfigured()
GetEyeGone() IsEyeGone()
GetBothEyesGone() IsBothEyesGone()
GetSleeping() IsSleeping()
GetFibrillationForced() IsFibrillationForced()
GetHasPulmonaryEmbolism() HasPulmonaryEmbolism()

PlayerUtil.Thresholds

Named constants for every threshold used by the game's moodle system. Use these instead of hard-coding magic numbers to keep your mod consistent with the game's own UI. All values were extracted directly from MoodleManager.AddAllMoodles().

if (PlayerUtil.GetBloodOxygen() < PlayerUtil.Thresholds.BLOOD_OXYGEN_SEVERE)
    GameUtil.Alert("Low blood oxygen!", important: true);

Blood Pressure

Constant Value
BLOOD_PRESSURE_CRITICAL_LOW 60
BLOOD_PRESSURE_LOW_3 83
BLOOD_PRESSURE_LOW_2 96
BLOOD_PRESSURE_LOW_1 110
BLOOD_PRESSURE_HIGH_1 130
BLOOD_PRESSURE_HIGH_2 145
BLOOD_PRESSURE_HIGH_3 162
BLOOD_PRESSURE_CRITICAL_HIGH 180

Blood Oxygen

Constant Value
BLOOD_OXYGEN_CRITICAL 45
BLOOD_OXYGEN_SEVERE 60
BLOOD_OXYGEN_LOW 75
BLOOD_OXYGEN_MILD 90

Heart Rate (BPM)

Constant Value
HEART_RATE_CARDIAC_ARREST 20
HEART_RATE_BRADYCARDIA_SEVERE 40
HEART_RATE_BRADYCARDIA_MILD 60
HEART_RATE_TACHYCARDIA_MILD 110
HEART_RATE_TACHYCARDIA_SEVERE 160
HEART_RATE_TACHYCARDIA_CRITICAL 200

Temperature (°C)

Constant Value
TEMPERATURE_HYPOTHERMIA_CRITICAL 28.0
TEMPERATURE_HYPOTHERMIA_SEVERE 32.5
TEMPERATURE_HYPOTHERMIA_MILD 34.0
TEMPERATURE_COLD 35.5
TEMPERATURE_NORMAL 37.0
TEMPERATURE_WARM 38.0
TEMPERATURE_HYPERTHERMIA_MILD 39.0
TEMPERATURE_HYPERTHERMIA_SEVERE 40.25
TEMPERATURE_HYPERTHERMIA_CRITICAL 41.5

Bleeding Speed (per second)

Constant Value
BLEED_SPEED_CRITICAL 0.30
BLEED_SPEED_HEAVY 0.15
BLEED_SPEED_MEDIUM 0.06

Hunger

Constant Value
HUNGER_STARVING 15
HUNGER_VERY_HUNGRY 35
HUNGER_HUNGRY 50
HUNGER_PECKISH 75
HUNGER_OVERFED_1 100
HUNGER_OVERFED_2 120

Thirst

Constant Value
THIRST_CRITICAL 20
THIRST_VERY_THIRSTY 35
THIRST_THIRSTY 55
THIRST_MILDLY_THIRSTY 75
THIRST_OVERHYDRATED_1 100
THIRST_OVERHYDRATED_2 125
THIRST_OVERHYDRATED_3 175

Stamina

Constant Value
STAMINA_EXHAUSTED 15
STAMINA_VERY_TIRED 35
STAMINA_TIRED 50
STAMINA_MILDLY_TIRED 70

Energy

Constant Value
ENERGY_EXHAUSTED 7
ENERGY_VERY_TIRED 15
ENERGY_TIRED 25
ENERGY_MILDLY_TIRED 35

Consciousness

Constant Value
CONSCIOUSNESS_UNCONSCIOUS 20
CONSCIOUSNESS_INCAPACITATED 30
CONSCIOUSNESS_CONFUSED_3 55
CONSCIOUSNESS_CONFUSED_2 72
CONSCIOUSNESS_CONFUSED_1 90

Pain

Constant Value
PAIN_AGONY 80
PAIN_SEVERE 55
PAIN_MODERATE 30
PAIN_MILD 10

Brain Damage

Constant Value
BRAIN_DAMAGE_SEVERE 30
BRAIN_DAMAGE_MODERATE 60
BRAIN_DAMAGE_MILD 80
BRAIN_DAMAGE_SLIGHT 95

Systemic Conditions

Constant Value
STROKE_CRITICAL 70
SEPSIS_CRITICAL 80
SEPSIS_MODERATE 50
SEPSIS_MILD 10
RADIATION_CRITICAL 80
RADIATION_SEVERE 50
RADIATION_MODERATE 30
RADIATION_MILD 10

Internal Bleeding / Hemothorax

Constant Value
INTERNAL_BLEEDING_CRITICAL 50
HEMOTHORAX_HEAVY 70
HEMOTHORAX_PRESENT 40

Happiness (totalHappiness, -100 ~ 100)

Constant Value
HAPPINESS_MISERABLE -75
HAPPINESS_DEPRESSED -50
HAPPINESS_GLOOMY -30
HAPPINESS_SAD -10
HAPPINESS_HAPPY_1 10
HAPPINESS_HAPPY_2 30
HAPPINESS_HAPPY_3 50
HAPPINESS_HAPPY_4 75

Weight Offset

Constant Value
WEIGHT_UNDERWEIGHT_4 -50
WEIGHT_UNDERWEIGHT_3 -40
WEIGHT_UNDERWEIGHT_2 -30
WEIGHT_UNDERWEIGHT_1 -15
WEIGHT_OVERWEIGHT_1 15
WEIGHT_OVERWEIGHT_2 30
WEIGHT_OVERWEIGHT_3 40
WEIGHT_OVERWEIGHT_4 50

Usage Example

using ScavLib.util;
using ScavLib.event_bus;
using ScavLib.event_bus.events;

[BepInDependency("com.kanisuko.scavlib", BepInDependency.DependencyFlags.SoftDependency)]
[BepInPlugin("com.yourname.yourmod", "YourMod", "1.0.0")]
public class YourPlugin : BaseUnityPlugin
{
    private void Awake()
    {
        EventBus.Register(this);
    }

    [Subscribe]
    private void OnWorldLoaded(WorldLoadedEvent e)
    {
        if (!PlayerUtil.IsAlive()) return;

        // Vital sign check using Thresholds constants
        if (PlayerUtil.GetBloodOxygen() < PlayerUtil.Thresholds.BLOOD_OXYGEN_LOW)
            GameUtil.Alert("Blood oxygen is low!", important: true);

        // Clear active drug components before a full heal
        if (PlayerUtil.HasPainkillers())
            PlayerUtil.RemovePainkillers();

        if (PlayerUtil.IsDying() && !PlayerUtil.HasTriedLastStand())
            PlayerUtil.HealAll();

        // Give the player a starting item
        PlayerUtil.GiveItem("bandage");
    }
}

Clone this wiki locally