using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using UnityEngine; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyVersion("0.0.0.0")] namespace YoureInjured; [BepInPlugin("com.marccunningham.youreinjured", "You're Injured", "1.7.3")] [BepInProcess("valheim.exe")] public sealed class YoureInjuredPlugin : BaseUnityPlugin { private enum HitSoundKind { None, Axe, Sword, Arrow } public const string PluginGuid = "com.marccunningham.youreinjured"; public const string PluginName = "You're Injured"; public const string PluginVersion = "1.7.3"; private const float MinimumValue = 0f; private const float MaximumValue = 100f; private const float TickIntervalSeconds = 1f; private const float SaveIntervalSeconds = 5f; private const float MinimumHealthLeft = 1f; private const float InjuryPanelHeight = 150f; private const float InjuryPanelMinimumBottomMargin = 12f; private const int LiquidBloodTextureSize = 192; private const int LiquidBloodTextureVariantCount = 7; private const float VanillaDayLengthSeconds = 1800f; private const float CompactHudReferenceWidth = 2048f; private const float CompactHudReferenceHeight = 1152f; private const float CompactInjuryReferenceLeft = 248f; private const float CompactInjuryReferenceBottom = 22f; private const float CompactInjuryReferenceWidth = 220f; private const float CompactInjuryReferenceHeight = 88f; private const string ZdoHead = "YoureInjured_Head"; private const string ZdoTorso = "YoureInjured_Torso"; private const string ZdoLeftArm = "YoureInjured_LeftArm"; private const string ZdoRightArm = "YoureInjured_RightArm"; private const string ZdoLeftLeg = "YoureInjured_LeftLeg"; private const string ZdoRightLeg = "YoureInjured_RightLeg"; private const string ZdoBleeding = "YoureInjured_Bleeding"; private const string ZdoInfection = "YoureInjured_Infection"; private const string ZdoInfectionRisk = "YoureInjured_InfectionRisk"; internal static YoureInjuredPlugin Instance; private ConfigEntry modEnabled; private ConfigEntry treatmentKey; private ConfigEntry diagnosticKey; private ConfigEntry sessionToggleKey; private ConfigEntry difficultyPreset; private ConfigEntry lastAppliedDifficultyPreset; private ConfigEntry minimumStaminaRegenMultiplier; private ConfigEntry showHud; private ConfigEntry hideHudWithCtrlF3; private ConfigEntry useCompactSurvivalHud; private ConfigEntry useSafeHudLayout; private ConfigEntry hudPanelLeft; private ConfigEntry hudPanelBottomOffset; private ConfigEntry stackBelowTemperatureHud; private ConfigEntry autoLiftTemperatureHudForInjuryPanel; private ConfigEntry temperatureHudGapPixels; private ConfigEntry temperatureHudFallbackLeft; private ConfigEntry temperatureHudFallbackBottomOffset; private ConfigEntry verboseLogging; private ConfigEntry minimumDamageForInjury; private ConfigEntry injuryPerHealthLost; private ConfigEntry fallInjuryMultiplier; private ConfigEntry physicalBleedingThreshold; private ConfigEntry bleedingPerHealthLost; private ConfigEntry brokenBoneThreshold; private ConfigEntry bleedingDamageAt100PerSecond; private ConfigEntry naturalClottingPerSecond; private ConfigEntry infectionRiskPerSecond; private ConfigEntry wetInfectionRiskMultiplier; private ConfigEntry infectionOnsetSeverity; private ConfigEntry infectionGrowthPerSecond; private ConfigEntry infectionRecoveryInBedPerSecond; private ConfigEntry infectionDamageAt100PerSecond; private ConfigEntry enableSwimmingRinse; private ConfigEntry swimmingRinseRequiredSeconds; private ConfigEntry shelterRecoveryPerSecond; private ConfigEntry bedRecoveryMultiplier; private ConfigEntry recoveryStillSpeedLimit; private ConfigEntry brokenLegRunPenalty; private ConfigEntry legInjuryRunPenalty; private ConfigEntry armInjuryAttackStaminaPenalty; private ConfigEntry brokenArmAttackStaminaPenalty; private ConfigEntry legInjuryRunStaminaPenalty; private ConfigEntry headTorsoStaminaRegenPenalty; private ConfigEntry infectionStaminaRegenPenalty; private ConfigEntry legInjuryJumpStaminaPenalty; private ConfigEntry bandageItemSharedName; private ConfigEntry bandageItemCost; private ConfigEntry bandageBleedingReduction; private ConfigEntry bandageInfectionRiskReduction; private ConfigEntry bandageInfectionReduction; private ConfigEntry bandageWoundRelief; private ConfigEntry fullHealOnBandage; private ConfigEntry treatmentCooldownSeconds; private ConfigEntry enableBleedingVisuals; private ConfigEntry spawnBloodFromSharpHits; private ConfigEntry enableBleedingTrail; private ConfigEntry visibleBloodMinimumHealthLoss; private ConfigEntry trailMinimumBleeding; private ConfigEntry walkingTrailIntervalSeconds; private ConfigEntry runningTrailIntervalSeconds; private ConfigEntry groundBloodLifetimeSeconds; private ConfigEntry maximumGroundBloodSplats; private ConfigEntry maximumHitBloodDroplets; private ConfigEntry bloodDropletGravity; private ConfigEntry bloodSplatMinimumSize; private ConfigEntry bloodSplatMaximumSize; private ConfigEntry bloodLiquidSpreadSeconds; private ConfigEntry enableHitImpactSprites; private ConfigEntry maximumImpactSpriteTextures; private ConfigEntry enableHitAudio; private ConfigEntry hitAudioVolume; private ConfigEntry hitAudioCooldownSeconds; private ConfigEntry axeHitAudioFile; private ConfigEntry swordHitAudioFile; private ConfigEntry arrowHitAudioFile; private ConfigEntry enableBandageAudio; private ConfigEntry bandageAudioVolume; private ConfigEntry bandageAudioFile; private ConfigEntry enableDramaticHitSpray; private ConfigEntry dramaticHitSprayDurationSeconds; private ConfigEntry dramaticHitSprayMinimumSize; private ConfigEntry dramaticHitSprayMaximumSize; private ConfigEntry dramaticHitSprayMinimumHealthLoss; private ConfigEntry enableWoundMarks; private ConfigEntry maximumWoundMarks; private ConfigEntry woundMarkMinimumSize; private ConfigEntry woundMarkMaximumSize; private ConfigEntry enableClothStaining; private ConfigEntry clothStainMinimumHealthLoss; private ConfigEntry maximumClothStains; private ConfigEntry clothStainMinimumSize; private ConfigEntry clothStainMaximumSize; private ConfigEntry enableSeaRinseForStains; private ConfigEntry seaRinseRequiredSeconds; private static readonly Color BloodTintColor = new Color(0.4f, 0.01f, 0.016f, 0.78f); private Harmony harmony; private readonly InjuryState state = new InjuryState(); private GUIStyle injuryHeaderStyle; private GUIStyle injuryDetailStyle; private GUIStyle compactInjuryHeaderStyle; private GUIStyle compactInjuryDetailStyle; private bool hudHiddenByCtrlF3; private bool runtimeEnabled = true; private bool stateLoaded; private float tickTimer; private float saveTimer; private float treatmentCooldown; private int localDamageHookCalls; private int injuryEventsRecorded; private float lastDetectedHealthLoss; private HitType lastDetectedHitType; private readonly List activeGroundBlood = new List(); private Transform bloodVisualRoot; private Material bloodDropMaterial; private Material[] bloodLiquidMaterials; private Texture2D[] bloodLiquidTextures; private float bleedingTrailTimer; private float swimmingRinseTimer; private int hitBloodAttempts; private int trailBloodAttempts; private int hitBloodDropletsSpawned; private int trailBloodDropletsSpawned; private int groundBloodSplatsSpawned; private int directTrailSplatsSpawned; private int groundProbeSuccesses; private int groundProbeFailures; private int dropletFallbackLandings; private string pluginDirectory; private readonly List impactSpriteTextures = new List(); private readonly List impactSpriteMaterials = new List(); private readonly List dripSpriteTextures = new List(); private readonly List dripSpriteMaterials = new List(); private Component hitAudioSource; private object axeHitAudioClip; private object swordHitAudioClip; private object arrowHitAudioClip; private object bandageAudioClip; private float bleedDripTimer; private float nextAllowedRecognizedHitAudioTime; private readonly List activeWoundMarks = new List(); private readonly List activeClothStains = new List(); private Transform playerDecalRoot; private float seaRinseTimer; private readonly List activeBleedSources = new List(); private int nextBleedSourceCycleIndex; private static readonly string[] HeadBoneNames = new string[2] { "head", "jaw" }; private static readonly string[] LeftArmBoneNames = new string[2] { "leftarm", "lefthand" }; private static readonly string[] RightArmBoneNames = new string[2] { "rightarm", "righthand" }; private static readonly string[] LeftLegBoneNames = new string[2] { "leftleg", "leftfoot" }; private static readonly string[] RightLegBoneNames = new string[2] { "rightleg", "rightfoot" }; private static readonly string[] TorsoBoneNames = new string[3] { "chest", "spine", "hips" }; private const int MaximumActiveBleedSources = 6; private const float BleedSourceOffsetFromBone = 0.1f; private const float BodyDecalMaximumOffsetFromBone = 0.12f; private void RemoveLegacyHudResizeConfigEntries() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("HUD Layout Editor", "ToggleInjuriesLayoutEditorKey")); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("HUD Layout", "CompactInjuriesXNormalized")); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("HUD Layout", "CompactInjuriesYNormalized")); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("HUD Layout", "CompactInjuriesWidthNormalized")); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("HUD Layout", "CompactInjuriesHeightNormalized")); } private void Awake() { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_1281: Unknown result type (might be due to invalid IL or missing references) //IL_128b: Expected O, but got Unknown Instance = this; pluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); modEnabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Set false to disable the entire injury system, including wounds, penalties, treatment and injury HUD."); treatmentKey = ((BaseUnityPlugin)this).Config.Bind("General", "UseBandageKey", (KeyCode)103, "Press this key to use a bandage material and treat wounds. Change it if G conflicts with another mod."); diagnosticKey = ((BaseUnityPlugin)this).Config.Bind("General", "DiagnosticKey", (KeyCode)283, "Writes the current injury state to BepInEx/LogOutput.log."); sessionToggleKey = ((BaseUnityPlugin)this).Config.Bind("General", "SessionToggleKey", (KeyCode)284, "Emergency session toggle. This pauses or resumes injury effects without removing the DLL."); difficultyPreset = ((BaseUnityPlugin)this).Config.Bind("Difficulty", "Preset", "Normal", new ConfigDescription("Pick a difficulty from the dropdown. This one setting tunes every injury rate, bleeding, infection, recovery and bandage value together for a balanced experience. Change this, then restart Valheim to apply it. Hand-tune individual values afterward if you want a custom mix.", (AcceptableValueBase)(object)new AcceptableValueList(new string[4] { "Easy", "Normal", "Hard", "Extreme" }), Array.Empty())); lastAppliedDifficultyPreset = ((BaseUnityPlugin)this).Config.Bind("Difficulty", "LastAppliedPreset", "Normal", "Internal preset tracking. Leave this alone; it records the last difficulty preset applied."); minimumStaminaRegenMultiplier = ((BaseUnityPlugin)this).Config.Bind("Difficulty", "MinimumStaminaRegenMultiplier", 0.82f, "Safety floor for this mod's own injury and infection stamina-regeneration penalty. It prevents wounds from combining with other Scavengers penalties into a no-escape state."); showHud = ((BaseUnityPlugin)this).Config.Bind("HUD", "ShowInjuryPanel", true, "Set false to hide only the Injuries HUD while injury calculations and treatment continue running."); hideHudWithCtrlF3 = ((BaseUnityPlugin)this).Config.Bind("HUD", "HideHudWithCtrlF3", true, "When enabled, Ctrl+F3 hides or restores this mod's HUD along with Valheim's HUD toggle. The injury system keeps running."); useCompactSurvivalHud = ((BaseUnityPlugin)this).Config.Bind("HUD", "UseCompactSurvivalHud", true, "Places the injury panel beneath the Body Temp panel, under Nourishment and directly left of the Tired meter."); useSafeHudLayout = ((BaseUnityPlugin)this).Config.Bind("HUD", "UseSafeLayout", true, "Uses the fixed stacked layout beneath the temperature gauge. It automatically keeps enough room for the full injury panel."); hudPanelLeft = ((BaseUnityPlugin)this).Config.Bind("HUD", "PanelLeftPixels", 392f, "Manual panel left edge in pixels when UseSafeLayout is false."); hudPanelBottomOffset = ((BaseUnityPlugin)this).Config.Bind("HUD", "PanelBottomOffsetPixels", 18f, "Manual clearance from the bottom of the screen in pixels when UseSafeLayout is false."); stackBelowTemperatureHud = ((BaseUnityPlugin)this).Config.Bind("HUD", "StackDirectlyBelowTemperatureBar", true, "Keeps the injury panel directly below You're Cold's temperature bar, with an even gap. This is enabled by default so the two survival panels remain aligned."); autoLiftTemperatureHudForInjuryPanel = ((BaseUnityPlugin)this).Config.Bind("HUD", "AutoLiftTemperatureHudForInjuryPanel", true, "Moves the temperature panel upward only when needed so the larger injury panel can remain directly beneath it without clipping off the bottom of the screen."); temperatureHudGapPixels = ((BaseUnityPlugin)this).Config.Bind("HUD", "TemperatureHudGapPixels", 12f, "Even vertical gap between the bottom of the temperature panel and the top of the larger injury panel."); temperatureHudFallbackLeft = ((BaseUnityPlugin)this).Config.Bind("HUD", "TemperatureHudFallbackLeftPixels", 460f, "Fallback temperature-panel left edge used only when You're Cold is not currently loaded."); temperatureHudFallbackBottomOffset = ((BaseUnityPlugin)this).Config.Bind("HUD", "TemperatureHudFallbackBottomOffsetPixels", 330f, "Fallback temperature-panel bottom offset used only when You're Cold is not currently loaded."); verboseLogging = ((BaseUnityPlugin)this).Config.Bind("Debug", "VerboseLogging", false, "Writes injury update details to LogOutput.log every tick. Keep disabled unless testing."); minimumDamageForInjury = ((BaseUnityPlugin)this).Config.Bind("Damage", "MinimumHealthLossForInjury", 1f, "Actual health loss required before a hit can create an injury. V1.0.3 defaults to 1 so ordinary enemy hits are visible during testing."); injuryPerHealthLost = ((BaseUnityPlugin)this).Config.Bind("Damage", "InjuryPointsPerHealthLost", 1.4f, "Injury points applied for each point of health actually lost after armour and resistances."); fallInjuryMultiplier = ((BaseUnityPlugin)this).Config.Bind("Damage", "FallInjuryMultiplier", 1.25f, "Extra injury multiplier for fall damage. Fall injuries are applied to both legs."); physicalBleedingThreshold = ((BaseUnityPlugin)this).Config.Bind("Damage", "PhysicalDamageForBleeding", 1f, "Actual health loss required before slash, pierce or chop damage can start a bleeding wound. Lowered from 5 so normal armor-mitigated hits actually trigger visible bleeding."); bleedingPerHealthLost = ((BaseUnityPlugin)this).Config.Bind("Damage", "BleedingPointsPerHealthLost", 1.8f, "Bleeding points applied per health lost beyond the bleeding threshold."); brokenBoneThreshold = ((BaseUnityPlugin)this).Config.Bind("Damage", "BrokenBoneThreshold", 78f, "An arm or leg at or above this injury value is treated as broken."); bleedingDamageAt100PerSecond = ((BaseUnityPlugin)this).Config.Bind("Bleeding", "DamageAt100BleedingPerSecond", 0.24f, "Health lost each second at 100 bleeding. Bleeding will not reduce health below 1 in V1."); naturalClottingPerSecond = ((BaseUnityPlugin)this).Config.Bind("Bleeding", "NaturalClottingPerSecond", 0.06f, "Bleeding naturally decreases this much per second. Bandages are much faster."); infectionRiskPerSecond = ((BaseUnityPlugin)this).Config.Bind("Infection", "RiskGainPerSecond", 0.1f, "Infection risk gained per second from untreated serious wounds."); wetInfectionRiskMultiplier = ((BaseUnityPlugin)this).Config.Bind("Infection", "WetRiskMultiplier", 2f, "Multiplier applied to infection risk while Wet."); infectionOnsetSeverity = ((BaseUnityPlugin)this).Config.Bind("Infection", "OnsetSeverity", 25f, "Infection severity created when infection risk reaches 100."); infectionGrowthPerSecond = ((BaseUnityPlugin)this).Config.Bind("Infection", "GrowthPerSecond", 0.04f, "How quickly an untreated infection worsens outside a bed."); infectionRecoveryInBedPerSecond = ((BaseUnityPlugin)this).Config.Bind("Infection", "RecoveryInBedPerSecond", 0.14f, "How quickly infection improves while sheltered in bed with no active bleeding."); infectionDamageAt100PerSecond = ((BaseUnityPlugin)this).Config.Bind("Infection", "DamageAt100InfectionPerSecond", 0.12f, "Health lost each second at 100 infection. Infection will not reduce health below 1 in V1."); enableSwimmingRinse = ((BaseUnityPlugin)this).Config.Bind("Infection", "EnableColdWaterRinse", true, "Allows one continuous minute of swimming to rinse infection risk from a closed, non-infected wound. It does not cure an established infection and cannot be used while actively bleeding."); swimmingRinseRequiredSeconds = ((BaseUnityPlugin)this).Config.Bind("Infection", "ColdWaterRinseSeconds", 60f, "Continuous swimming time required to clear infection risk from a closed wound. Leaving the water resets the rinse timer."); shelterRecoveryPerSecond = ((BaseUnityPlugin)this).Config.Bind("Recovery", "ShelterRecoveryPerSecond", 0.045f, "Injury points recovered per second while sheltered and still, with no bleeding or infection."); bedRecoveryMultiplier = ((BaseUnityPlugin)this).Config.Bind("Recovery", "BedRecoveryMultiplier", 4.5f, "Recovery multiplier while resting in bed."); recoveryStillSpeedLimit = ((BaseUnityPlugin)this).Config.Bind("Recovery", "StillSpeedLimit", 0.25f, "Maximum movement speed that counts as resting for sheltered recovery."); brokenLegRunPenalty = ((BaseUnityPlugin)this).Config.Bind("Penalties", "BrokenLegRunPenalty", 0.18f, "Speed penalty per broken leg. Two broken legs are capped so movement remains possible."); legInjuryRunPenalty = ((BaseUnityPlugin)this).Config.Bind("Penalties", "LegInjuryRunPenaltyAt100", 0.22f, "Maximum speed penalty from non-broken leg injuries."); armInjuryAttackStaminaPenalty = ((BaseUnityPlugin)this).Config.Bind("Penalties", "ArmInjuryAttackStaminaPenaltyAt100", 0.28f, "Maximum extra attack stamina cost from arm injuries."); brokenArmAttackStaminaPenalty = ((BaseUnityPlugin)this).Config.Bind("Penalties", "BrokenArmAttackStaminaPenalty", 0.15f, "Extra attack stamina cost per broken arm."); legInjuryRunStaminaPenalty = ((BaseUnityPlugin)this).Config.Bind("Penalties", "LegInjuryRunStaminaPenaltyAt100", 0.22f, "Maximum extra run stamina drain from leg injuries."); headTorsoStaminaRegenPenalty = ((BaseUnityPlugin)this).Config.Bind("Penalties", "HeadTorsoStaminaRegenPenaltyAt100", 0.22f, "Maximum stamina regeneration reduction from head and torso injuries."); infectionStaminaRegenPenalty = ((BaseUnityPlugin)this).Config.Bind("Penalties", "InfectionStaminaRegenPenaltyAt100", 0.18f, "Maximum stamina regeneration reduction from infection."); legInjuryJumpStaminaPenalty = ((BaseUnityPlugin)this).Config.Bind("Penalties", "LegInjuryJumpStaminaPenaltyAt100", 0.2f, "Maximum extra jump stamina cost from leg injuries."); bandageItemSharedName = ((BaseUnityPlugin)this).Config.Bind("Bandages", "BandageItemSharedName", "$item_leatherscraps", "Valheim shared item name consumed as a bandage. Default is Leather Scraps, so treatment is available from the early game. This is a material-based bandage system in V1, not a new custom item prefab."); bandageItemCost = ((BaseUnityPlugin)this).Config.Bind("Bandages", "BandageItemCost", 1, "How many bandage material items are consumed per treatment."); bandageBleedingReduction = ((BaseUnityPlugin)this).Config.Bind("Bandages", "BleedingReduction", 100f, "A successful bandage fully closes active bleeding and stops the blood trail."); bandageInfectionRiskReduction = ((BaseUnityPlugin)this).Config.Bind("Bandages", "InfectionRiskReduction", 40f, "Infection risk removed by one treatment."); bandageInfectionReduction = ((BaseUnityPlugin)this).Config.Bind("Bandages", "InfectionReduction", 5f, "Existing infection reduced by one treatment. Sleeping while sheltered is the main recovery method."); bandageWoundRelief = ((BaseUnityPlugin)this).Config.Bind("Bandages", "WoundRelief", 7f, "Small injury reduction applied to each body part by one treatment when FullHealOnBandage is false. Bandages do not immediately fix broken bones in this partial-relief mode."); fullHealOnBandage = ((BaseUnityPlugin)this).Config.Bind("Bandages", "FullHealOnBandage", true, "Temporary simplified mode: one bandage fully clears all injuries, bleeding, infection, and infection risk at once, including broken bones. This is an easier placeholder until a fuller per-wound treatment system is built; set to false to use the original partial WoundRelief amount instead."); treatmentCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind("Bandages", "TreatmentCooldownSeconds", 1f, "Prevents accidental repeated bandage use from one key press."); enableBleedingVisuals = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "Enabled", false, "DEFAULT OFF: Crimson Blood now owns all blood visuals (impact spray, wound marks, trails, 2-day ground blood). Leave this false when Crimson Blood is installed to avoid double blood. Set true only if you want You're Injured to draw its own legacy blood instead."); spawnBloodFromSharpHits = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "SpawnBloodFromSharpHits", true, "Spawns a small blood burst from qualifying slash or pierce hits, even before a wound becomes severe enough to leave a trail."); enableBleedingTrail = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "EnableBleedingTrail", true, "Leaves intermittent drops while walking or running with meaningful active bleeding."); visibleBloodMinimumHealthLoss = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "MinimumHealthLossForVisibleBlood", 1f, "Health loss required from slash, pierce or chop damage before a visible outward wound spray is created."); trailMinimumBleeding = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "MinimumBleedingForTrail", 0.01f, "Any active untreated bleeding leaves a trail. A successful bandage closes the wound and stops it."); walkingTrailIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "WalkingTrailIntervalSeconds", 0.65f, "Time between blood drops while walking with an untreated bleeding wound."); runningTrailIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "RunningTrailIntervalSeconds", 0.3f, "Time between blood drops while running with an untreated bleeding wound."); groundBloodLifetimeSeconds = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "GroundBloodLifetimeSeconds", 3600f, "How long landed blood remains visible on the ground before fading. Defaults to 2 in-game days (1 vanilla Valheim day = 1800 real seconds, so 2 days = 3600 seconds = 1 real hour)."); maximumGroundBloodSplats = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "MaximumGroundBloodSplats", 900, "Safety cap for active ground blood visuals. The oldest splat is removed when this limit is reached. Raised well above the old default so a 2-day lifetime is actually honoured during active play instead of being cut short by the cap."); maximumHitBloodDroplets = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "MaximumHitBloodDroplets", 20, "Maximum droplets produced by one strong slash, axe or arrow hit."); bloodDropletGravity = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "DropletGravity", 2.4f, "Multiplier on real-world gravity for falling blood droplets. The old default of 14 made every droplet's flight last roughly 0.07 seconds, too brief to actually see; this pulls droplets down quickly enough to feel like blood, while staying airborne long enough (roughly a third to half a second) to read as a visible arc instead of an instant splat."); bloodSplatMinimumSize = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "GroundSplatMinimumSize", 0.2f, "Smallest ground blood splat diameter in metres."); bloodSplatMaximumSize = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "GroundSplatMaximumSize", 0.72f, "Largest ground blood splat diameter in metres."); bloodLiquidSpreadSeconds = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "BloodLiquidSpreadSeconds", 0.65f, "Seconds for a fresh blood splat to settle and spread across the ground. Short but visible, so blood feels liquid rather than stamped on."); enableHitImpactSprites = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "EnableHitImpactSprites", false, "Legacy setting kept only so an old config file cannot silently re-enable the removed camera-facing hit sprite. The dramatic hit spray (see the Dramatic Hit Spray section) is the supported replacement and is always world-space."); maximumImpactSpriteTextures = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "MaximumImpactSpriteTextures", 4, "Maximum number of supplied blood-spray textures loaded from assets/bleeding/impact_frames."); enableHitAudio = ((BaseUnityPlugin)this).Config.Bind("Hit Audio", "Enabled", true, "Plays one local hit sound for qualifying player hits. Axe, sword, and arrow MP3 files are loaded externally beside the DLL."); hitAudioVolume = ((BaseUnityPlugin)this).Config.Bind("Hit Audio", "Volume", 0.65f, "Volume for externally loaded hit sounds."); hitAudioCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind("Hit Audio", "RecognizedHitSoundCooldownSeconds", 0.18f, "Minimum gap between correctly recognized axe, sword or arrow hit sounds. This prevents duplicate sounds from a single combat event."); axeHitAudioFile = ((BaseUnityPlugin)this).Config.Bind("Hit Audio", "AxeHitFile", "axe_hit.mp3", "MP3 filename expected in assets/audio beside the You're Injured DLL."); swordHitAudioFile = ((BaseUnityPlugin)this).Config.Bind("Hit Audio", "SwordHitFile", "sword_hit.mp3", "MP3 filename expected in assets/audio beside the You're Injured DLL."); arrowHitAudioFile = ((BaseUnityPlugin)this).Config.Bind("Hit Audio", "ArrowHitFile", "arrow_hit.mp3", "MP3 filename expected in assets/audio beside the You're Injured DLL."); enableBandageAudio = ((BaseUnityPlugin)this).Config.Bind("Bandage Audio", "Enabled", true, "Plays the supplied cloth-wrap sound only after a bandage is successfully applied and its material is consumed."); bandageAudioVolume = ((BaseUnityPlugin)this).Config.Bind("Bandage Audio", "Volume", 0.68f, "Volume for the externally loaded bandage-wrap sound."); bandageAudioFile = ((BaseUnityPlugin)this).Config.Bind("Bandage Audio", "BandageWrapFile", "bandage.mp3", "MP3 filename expected in assets/audio beside the You're Injured DLL."); enableDramaticHitSpray = ((BaseUnityPlugin)this).Config.Bind("Dramatic Hit Spray", "Enabled", true, "Adds a larger, more dramatic directional blood-spray burst at the wound on a qualifying hit, on top of the existing 3D droplets. World-space and oriented to the wound, never camera-facing, so it cannot flash across the screen."); dramaticHitSprayDurationSeconds = ((BaseUnityPlugin)this).Config.Bind("Dramatic Hit Spray", "DurationSeconds", 1.5f, "How long the dramatic spray burst remains visible before fading out completely."); dramaticHitSprayMinimumSize = ((BaseUnityPlugin)this).Config.Bind("Dramatic Hit Spray", "MinimumSize", 0.55f, "Smallest world-space size of the dramatic spray burst, used for lighter qualifying hits."); dramaticHitSprayMaximumSize = ((BaseUnityPlugin)this).Config.Bind("Dramatic Hit Spray", "MaximumSize", 1.35f, "Largest world-space size of the dramatic spray burst, used for heavy wounds."); dramaticHitSprayMinimumHealthLoss = ((BaseUnityPlugin)this).Config.Bind("Dramatic Hit Spray", "MinimumHealthLoss", 1f, "Actual health loss required from a cutting hit before the larger dramatic spray plays. Matches MinimumHealthLossForVisibleBlood by default so the dramatic spray fires alongside the droplet burst rather than requiring a separately, more severe hit. Raise this if you want the dramatic spray reserved for heavier wounds only."); enableWoundMarks = ((BaseUnityPlugin)this).Config.Bind("Wound Marks", "Enabled", true, "Leaves small persistent red wound-mark decals on the character's body at the hit location. These move with the character and stay until washed off or treated."); maximumWoundMarks = ((BaseUnityPlugin)this).Config.Bind("Wound Marks", "MaximumActiveMarks", 24, "Safety cap for total wound marks on the body at once. The oldest mark is removed to make room for a new one."); woundMarkMinimumSize = ((BaseUnityPlugin)this).Config.Bind("Wound Marks", "MinimumSize", 0.05f, "Smallest wound-mark decal size in metres."); woundMarkMaximumSize = ((BaseUnityPlugin)this).Config.Bind("Wound Marks", "MaximumSize", 0.13f, "Largest wound-mark decal size in metres, used for heavier wounds."); enableClothStaining = ((BaseUnityPlugin)this).Config.Bind("Cloth Staining", "Enabled", true, "Adds a blood-coloured stain patch over the character's clothing near a sufficiently serious wound. This is a separate decal layered over the equipped armor visual; it never edits the actual armor or clothing texture, so it is always safe alongside other texture or model mods."); clothStainMinimumHealthLoss = ((BaseUnityPlugin)this).Config.Bind("Cloth Staining", "MinimumHealthLoss", 4f, "Actual health loss required before a hit leaves a stain on clothing, in addition to a smaller skin-level wound mark."); maximumClothStains = ((BaseUnityPlugin)this).Config.Bind("Cloth Staining", "MaximumActiveStains", 12, "Safety cap for total cloth stains at once. The oldest stain is removed to make room for a new one."); clothStainMinimumSize = ((BaseUnityPlugin)this).Config.Bind("Cloth Staining", "MinimumSize", 0.12f, "Smallest cloth stain decal size in metres."); clothStainMaximumSize = ((BaseUnityPlugin)this).Config.Bind("Cloth Staining", "MaximumSize", 0.3f, "Largest cloth stain decal size in metres, used for heavier wounds."); enableSeaRinseForStains = ((BaseUnityPlugin)this).Config.Bind("Cloth Staining", "EnableSeaRinse", true, "Allows one continuous minute of swimming in open water to wash every wound mark and cloth stain off the character. This is purely visual and does not affect bleeding, infection, or injury healing."); seaRinseRequiredSeconds = ((BaseUnityPlugin)this).Config.Bind("Cloth Staining", "SeaRinseRequiredSeconds", 60f, "Continuous swimming time required to wash off wound marks and cloth stains. Leaving the water resets the rinse timer, matching the existing infection-risk rinse."); if (string.Equals(bandageItemSharedName.Value, "$item_linen", StringComparison.Ordinal)) { bandageItemSharedName.Value = "$item_leatherscraps"; } if (Mathf.Abs(minimumDamageForInjury.Value - 5f) < 0.01f) { minimumDamageForInjury.Value = 1f; } if (Mathf.Abs(hudPanelLeft.Value - 460f) < 0.01f || Mathf.Abs(hudPanelLeft.Value - 417f) < 0.01f || Mathf.Abs(hudPanelLeft.Value - 406f) < 0.01f) { hudPanelLeft.Value = 392f; } if (Mathf.Abs(hudPanelBottomOffset.Value - 165f) < 0.01f || Mathf.Abs(hudPanelBottomOffset.Value - 170f) < 0.01f || Mathf.Abs(hudPanelBottomOffset.Value - 140f) < 0.01f || Mathf.Abs(hudPanelBottomOffset.Value - 100f) < 0.01f) { hudPanelBottomOffset.Value = 18f; } if (Mathf.Abs(walkingTrailIntervalSeconds.Value - 1.35f) < 0.01f) { walkingTrailIntervalSeconds.Value = 0.82f; } if (Mathf.Abs(runningTrailIntervalSeconds.Value - 0.68f) < 0.01f) { runningTrailIntervalSeconds.Value = 0.44f; } if (maximumGroundBloodSplats.Value == 160) { maximumGroundBloodSplats.Value = 240; } if (maximumHitBloodDroplets.Value == 5) { maximumHitBloodDroplets.Value = 14; } if (Mathf.Abs(bloodSplatMinimumSize.Value - 0.11f) < 0.01f) { bloodSplatMinimumSize.Value = 0.17f; } if (Mathf.Abs(bloodSplatMaximumSize.Value - 0.28f) < 0.01f) { bloodSplatMaximumSize.Value = 0.52f; } if (Mathf.Abs(physicalBleedingThreshold.Value - 8f) < 0.01f) { physicalBleedingThreshold.Value = 5f; } if (Mathf.Abs(bandageBleedingReduction.Value - 55f) < 0.01f || Mathf.Abs(bandageBleedingReduction.Value - 60f) < 0.01f) { bandageBleedingReduction.Value = 100f; } if (Mathf.Abs(visibleBloodMinimumHealthLoss.Value - 2f) < 0.01f) { visibleBloodMinimumHealthLoss.Value = 1f; } if (Mathf.Abs(trailMinimumBleeding.Value - 5f) < 0.01f) { trailMinimumBleeding.Value = 0.01f; } if (Mathf.Abs(walkingTrailIntervalSeconds.Value - 0.82f) < 0.01f) { walkingTrailIntervalSeconds.Value = 0.65f; } if (Mathf.Abs(runningTrailIntervalSeconds.Value - 0.44f) < 0.01f) { runningTrailIntervalSeconds.Value = 0.3f; } if (Mathf.Abs(groundBloodLifetimeSeconds.Value - 120f) < 0.01f) { groundBloodLifetimeSeconds.Value = 150f; } if (maximumGroundBloodSplats.Value == 240) { maximumGroundBloodSplats.Value = 300; } if (maximumHitBloodDroplets.Value == 14) { maximumHitBloodDroplets.Value = 20; } if (Mathf.Abs(bloodSplatMinimumSize.Value - 0.17f) < 0.01f) { bloodSplatMinimumSize.Value = 0.2f; } if (Mathf.Abs(bloodSplatMaximumSize.Value - 0.52f) < 0.01f) { bloodSplatMaximumSize.Value = 0.72f; } if (string.Equals(bandageAudioFile.Value, "bandage wrap.mp3", StringComparison.OrdinalIgnoreCase)) { bandageAudioFile.Value = "bandage.mp3"; } if (Mathf.Abs(groundBloodLifetimeSeconds.Value - 150f) < 0.01f) { groundBloodLifetimeSeconds.Value = 3600f; } if (maximumGroundBloodSplats.Value == 300) { maximumGroundBloodSplats.Value = 900; } enableHitImpactSprites.Value = false; RemoveLegacyHudResizeConfigEntries(); ((BaseUnityPlugin)this).Config.Save(); MigrateLegacyDefaultsToNormal(); ApplyDifficultyPresetIfChanged(); LoadExternalImpactSprites(); ((MonoBehaviour)this).StartCoroutine(LoadHitAudioFiles()); harmony = new Harmony("com.marccunningham.youreinjured"); harmony.PatchAll(typeof(YoureInjuredPlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"You're Injured 1.7.3 loaded. V1.7.2 removes the old O-key HUD editor completely, clears its old config entries, keeps the compact Injuries panel fixed, and gives every compact text line enough vertical room to avoid clipped letters."); } private void MigrateLegacyDefaultsToNormal() { if (Mathf.Abs(injuryPerHealthLost.Value - 1.6f) < 0.001f && Mathf.Abs(fallInjuryMultiplier.Value - 1.4f) < 0.001f && Mathf.Abs(bleedingPerHealthLost.Value - 1.8f) < 0.001f && Mathf.Abs(brokenBoneThreshold.Value - 75f) < 0.001f && Mathf.Abs(headTorsoStaminaRegenPenalty.Value - 0.35f) < 0.001f && Mathf.Abs(infectionStaminaRegenPenalty.Value - 0.3f) < 0.001f) { ApplyDifficultyPreset("Normal"); ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"You're Injured: migrated untouched legacy injury defaults to the balanced Normal preset."); } } private void ApplyDifficultyPresetIfChanged() { string text = NormalizeDifficultyPreset(difficultyPreset.Value); if (!string.Equals(difficultyPreset.Value, text, StringComparison.OrdinalIgnoreCase)) { difficultyPreset.Value = text; } if (!string.Equals(lastAppliedDifficultyPreset.Value, text, StringComparison.OrdinalIgnoreCase)) { ApplyDifficultyPreset(text); lastAppliedDifficultyPreset.Value = text; ((BaseUnityPlugin)this).Config.Save(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("You're Injured: applied " + text + " difficulty preset.")); } } private static string NormalizeDifficultyPreset(string value) { if (string.Equals(value, "Easy", StringComparison.OrdinalIgnoreCase)) { return "Easy"; } if (string.Equals(value, "Hard", StringComparison.OrdinalIgnoreCase)) { return "Hard"; } if (string.Equals(value, "Extreme", StringComparison.OrdinalIgnoreCase)) { return "Extreme"; } return "Normal"; } private void ApplyDifficultyPreset(string preset) { switch (preset) { case "Easy": injuryPerHealthLost.Value = 1f; fallInjuryMultiplier.Value = 1.1f; bleedingPerHealthLost.Value = 1.1f; brokenBoneThreshold.Value = 85f; bleedingDamageAt100PerSecond.Value = 0.16f; naturalClottingPerSecond.Value = 0.08f; infectionRiskPerSecond.Value = 0.07f; wetInfectionRiskMultiplier.Value = 1.7f; infectionGrowthPerSecond.Value = 0.025f; infectionRecoveryInBedPerSecond.Value = 0.18f; infectionDamageAt100PerSecond.Value = 0.09f; shelterRecoveryPerSecond.Value = 0.06f; bedRecoveryMultiplier.Value = 5f; brokenLegRunPenalty.Value = 0.14f; legInjuryRunPenalty.Value = 0.16f; legInjuryRunStaminaPenalty.Value = 0.16f; headTorsoStaminaRegenPenalty.Value = 0.16f; infectionStaminaRegenPenalty.Value = 0.12f; minimumStaminaRegenMultiplier.Value = 0.9f; bandageBleedingReduction.Value = 68f; bandageInfectionRiskReduction.Value = 48f; bandageInfectionReduction.Value = 7f; bandageWoundRelief.Value = 9f; break; case "Hard": injuryPerHealthLost.Value = 1.85f; fallInjuryMultiplier.Value = 1.55f; bleedingPerHealthLost.Value = 2f; brokenBoneThreshold.Value = 70f; bleedingDamageAt100PerSecond.Value = 0.34f; naturalClottingPerSecond.Value = 0.035f; infectionRiskPerSecond.Value = 0.15f; wetInfectionRiskMultiplier.Value = 3f; infectionGrowthPerSecond.Value = 0.07f; infectionRecoveryInBedPerSecond.Value = 0.09f; infectionDamageAt100PerSecond.Value = 0.22f; shelterRecoveryPerSecond.Value = 0.025f; bedRecoveryMultiplier.Value = 3f; brokenLegRunPenalty.Value = 0.25f; legInjuryRunPenalty.Value = 0.34f; legInjuryRunStaminaPenalty.Value = 0.34f; headTorsoStaminaRegenPenalty.Value = 0.32f; infectionStaminaRegenPenalty.Value = 0.28f; minimumStaminaRegenMultiplier.Value = 0.75f; bandageBleedingReduction.Value = 48f; bandageInfectionRiskReduction.Value = 30f; bandageInfectionReduction.Value = 3f; bandageWoundRelief.Value = 4f; break; case "Extreme": injuryPerHealthLost.Value = 2.3f; fallInjuryMultiplier.Value = 1.8f; bleedingPerHealthLost.Value = 2.4f; brokenBoneThreshold.Value = 65f; bleedingDamageAt100PerSecond.Value = 0.42f; naturalClottingPerSecond.Value = 0.025f; infectionRiskPerSecond.Value = 0.2f; wetInfectionRiskMultiplier.Value = 3.6f; infectionGrowthPerSecond.Value = 0.095f; infectionRecoveryInBedPerSecond.Value = 0.065f; infectionDamageAt100PerSecond.Value = 0.3f; shelterRecoveryPerSecond.Value = 0.018f; bedRecoveryMultiplier.Value = 2.4f; brokenLegRunPenalty.Value = 0.3f; legInjuryRunPenalty.Value = 0.4f; legInjuryRunStaminaPenalty.Value = 0.4f; headTorsoStaminaRegenPenalty.Value = 0.38f; infectionStaminaRegenPenalty.Value = 0.34f; minimumStaminaRegenMultiplier.Value = 0.68f; bandageBleedingReduction.Value = 38f; bandageInfectionRiskReduction.Value = 22f; bandageInfectionReduction.Value = 2f; bandageWoundRelief.Value = 3f; break; default: injuryPerHealthLost.Value = 1.4f; fallInjuryMultiplier.Value = 1.25f; bleedingPerHealthLost.Value = 1.5f; brokenBoneThreshold.Value = 78f; bleedingDamageAt100PerSecond.Value = 0.24f; naturalClottingPerSecond.Value = 0.06f; infectionRiskPerSecond.Value = 0.1f; wetInfectionRiskMultiplier.Value = 2f; infectionGrowthPerSecond.Value = 0.04f; infectionRecoveryInBedPerSecond.Value = 0.14f; infectionDamageAt100PerSecond.Value = 0.12f; shelterRecoveryPerSecond.Value = 0.045f; bedRecoveryMultiplier.Value = 4.5f; brokenLegRunPenalty.Value = 0.18f; legInjuryRunPenalty.Value = 0.22f; legInjuryRunStaminaPenalty.Value = 0.22f; headTorsoStaminaRegenPenalty.Value = 0.22f; infectionStaminaRegenPenalty.Value = 0.18f; minimumStaminaRegenMultiplier.Value = 0.82f; bandageBleedingReduction.Value = 60f; bandageInfectionRiskReduction.Value = 40f; bandageInfectionReduction.Value = 5f; bandageWoundRelief.Value = 7f; break; } } private void OnDestroy() { if (harmony != null) { harmony.UnpatchSelf(); } DestroyBloodVisuals(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (TryToggleHudWithCtrlF3()) { return; } if (Input.GetKeyDown(diagnosticKey.Value)) { WriteDiagnostic(); } if (Input.GetKeyDown(sessionToggleKey.Value)) { runtimeEnabled = !runtimeEnabled; ShowMessage("You're Injured: " + (runtimeEnabled ? "ON" : "OFF")); } if (!runtimeEnabled || !modEnabled.Value) { return; } Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { EnsureStateLoaded(localPlayer); if (Input.GetKeyDown(treatmentKey.Value)) { TryUseBandage(localPlayer); } float deltaTime = Time.deltaTime; treatmentCooldown = Mathf.Max(0f, treatmentCooldown - deltaTime); UpdateBleedingTrail(localPlayer, deltaTime); UpdateBleedingDrips(localPlayer, deltaTime); UpdateSeaRinse(localPlayer, deltaTime); tickTimer += deltaTime; saveTimer += deltaTime; if (tickTimer >= 1f) { float elapsedSeconds = Mathf.Min(tickTimer, 3f); tickTimer = 0f; TickInjuries(localPlayer, elapsedSeconds); } if (saveTimer >= 5f) { saveTimer = 0f; SaveState(localPlayer); } } } internal bool IsActiveFor(Player player) { if (runtimeEnabled && modEnabled.Value && (Object)(object)player != (Object)null && (Object)(object)player == (Object)(object)Player.m_localPlayer) { return stateLoaded; } return false; } internal float GetRunSpeedMultiplier() { float threshold = Mathf.Clamp(brokenBoneThreshold.Value, 1f, 100f); float num = state.GetAverageLegInjury() / 100f; float num2 = 1f - num * Mathf.Clamp01(legInjuryRunPenalty.Value); if (state.IsBroken(Limb.LeftLeg, threshold)) { num2 -= Mathf.Clamp01(brokenLegRunPenalty.Value); } if (state.IsBroken(Limb.RightLeg, threshold)) { num2 -= Mathf.Clamp01(brokenLegRunPenalty.Value); } return Mathf.Clamp(num2, 0.3f, 1f); } internal float GetAttackStaminaMultiplier() { float threshold = Mathf.Clamp(brokenBoneThreshold.Value, 1f, 100f); float num = state.GetAverageArmInjury() / 100f; float num2 = 1f + num * Mathf.Max(0f, armInjuryAttackStaminaPenalty.Value); if (state.IsBroken(Limb.LeftArm, threshold)) { num2 += Mathf.Max(0f, brokenArmAttackStaminaPenalty.Value); } if (state.IsBroken(Limb.RightArm, threshold)) { num2 += Mathf.Max(0f, brokenArmAttackStaminaPenalty.Value); } return Mathf.Max(1f, num2); } internal float GetRunStaminaMultiplier() { float num = state.GetAverageLegInjury() / 100f; return Mathf.Max(1f, 1f + num * Mathf.Max(0f, legInjuryRunStaminaPenalty.Value)); } internal float GetJumpStaminaMultiplier() { float num = state.GetAverageLegInjury() / 100f; return Mathf.Max(1f, 1f + num * Mathf.Max(0f, legInjuryJumpStaminaPenalty.Value)); } internal float GetStaminaRegenMultiplier() { float num = (state.Head + state.Torso) / 200f * Mathf.Clamp01(headTorsoStaminaRegenPenalty.Value); float num2 = state.Infection / 100f * Mathf.Clamp01(infectionStaminaRegenPenalty.Value); float num3 = Mathf.Clamp(minimumStaminaRegenMultiplier.Value, 0.1f, 1f); return Mathf.Clamp(1f - num - num2, num3, 1f); } internal void RecordAppliedDamage(Player player, HitData hit, float healthBefore) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Invalid comparison between Unknown and I4 if (!IsActiveFor(player) || hit == null) { return; } float num = Mathf.Max(0f, healthBefore - ((Character)player).GetHealth()); localDamageHookCalls++; lastDetectedHealthLoss = num; lastDetectedHitType = hit.m_hitType; if (verboseLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Damage hook: health loss=" + num.ToString("0.0") + ", type=" + ((object)Unsafe.As(ref hit.m_hitType)/*cast due to .constrained prefix*/).ToString() + ", threshold=" + minimumDamageForInjury.Value.ToString("0.0"))); } if (!(num < Mathf.Max(0f, minimumDamageForInjury.Value)) && !ShouldIgnoreInjuryHit(hit.m_hitType)) { float num2 = num * Mathf.Max(0f, injuryPerHealthLost.Value); Limb limb; if ((int)hit.m_hitType == 3) { num2 *= Mathf.Max(0f, fallInjuryMultiplier.Value); state.Add(Limb.LeftLeg, num2 * 0.5f); state.Add(Limb.RightLeg, num2 * 0.5f); limb = Limb.LeftLeg; } else { limb = ResolveHitLimb(player, hit); state.Add(limb, num2); } float bleedingAdded = ApplyBleedingFromHit(hit, num); state.ClampAll(); TrySpawnHitBlood(player, hit, num, bleedingAdded, limb); TryPlayHitAudio(hit); injuryEventsRecorded++; SaveState(player); ShowMessage(BuildDamageMessage(num)); if (verboseLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Applied damage " + num.ToString("0.0") + ", hitType=" + ((object)Unsafe.As(ref hit.m_hitType)/*cast due to .constrained prefix*/).ToString() + ", injuries=" + state.ToDiagnosticText())); } } } private void TickInjuries(Player player, float elapsedSeconds) { if (((Character)player).IsDead()) { state.Bleeding = 0f; activeBleedSources.Clear(); return; } ProcessBleeding(player, elapsedSeconds); ProcessInfection(player, elapsedSeconds); ProcessRecovery(player, elapsedSeconds); state.ClampAll(); if (verboseLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Tick: " + state.ToDiagnosticText())); } } private void ProcessBleeding(Player player, float elapsedSeconds) { if (!(state.Bleeding <= 0f)) { float healthLoss = state.Bleeding / 100f * Mathf.Max(0f, bleedingDamageAt100PerSecond.Value) * elapsedSeconds; ApplyNonLethalHealthLoss(player, healthLoss); float num = Mathf.Max(0f, naturalClottingPerSecond.Value) * elapsedSeconds; if (player.InShelter() && !IsWet(player)) { num *= 2f; } state.Bleeding = Mathf.Max(0f, state.Bleeding - num); } } private void ProcessInfection(Player player, float elapsedSeconds) { bool flag = IsWet(player); bool flag2 = state.Bleeding >= 5f || state.GetAverageLimbInjury() >= 35f || state.Torso >= 35f; bool flag3 = UpdateColdWaterRinse(player, elapsedSeconds); if (flag2 && state.Infection <= 0f && !flag3) { float num = Mathf.Max(0f, infectionRiskPerSecond.Value) * elapsedSeconds; if (flag) { num *= Mathf.Max(1f, wetInfectionRiskMultiplier.Value); } if (player.InShelter()) { num *= 0.5f; } state.InfectionRisk += num; if (state.InfectionRisk >= 100f) { state.InfectionRisk = 0f; state.Infection = Mathf.Max(state.Infection, Mathf.Clamp(infectionOnsetSeverity.Value, 1f, 100f)); ShowMessage("An untreated wound has become infected."); } } else if (!flag2 && state.Infection <= 0f) { state.InfectionRisk = Mathf.Max(0f, state.InfectionRisk - elapsedSeconds * 0.25f); } if (!(state.Infection <= 0f)) { if (((Character)player).InBed() && player.InShelter() && !flag && state.Bleeding <= 0.01f) { state.Infection = Mathf.Max(0f, state.Infection - Mathf.Max(0f, infectionRecoveryInBedPerSecond.Value) * elapsedSeconds); return; } state.Infection += Mathf.Max(0f, infectionGrowthPerSecond.Value) * elapsedSeconds; float healthLoss = state.Infection / 100f * Mathf.Max(0f, infectionDamageAt100PerSecond.Value) * elapsedSeconds; ApplyNonLethalHealthLoss(player, healthLoss); } } private bool UpdateColdWaterRinse(Player player, float elapsedSeconds) { if (!enableSwimmingRinse.Value || (Object)(object)player == (Object)null || state.Infection > 0.01f) { swimmingRinseTimer = 0f; return false; } if (!((Character)player).IsSwimming() || !(state.Bleeding <= 0.01f) || !(state.InfectionRisk > 0.01f)) { swimmingRinseTimer = 0f; return false; } swimmingRinseTimer += elapsedSeconds; if (swimmingRinseTimer >= Mathf.Max(1f, swimmingRinseRequiredSeconds.Value)) { state.InfectionRisk = 0f; swimmingRinseTimer = 0f; ShowMessage("Cold water has rinsed the infection risk. Dry off and bandage the wound."); return false; } return true; } private void ProcessRecovery(Player player, float elapsedSeconds) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (state.Bleeding > 0.01f || state.Infection > 0.01f || IsWet(player) || !player.InShelter()) { return; } bool flag = ((Character)player).InBed(); Vector3 velocity = ((Character)player).GetVelocity(); bool flag2 = ((Vector3)(ref velocity)).magnitude <= Mathf.Max(0.01f, recoveryStillSpeedLimit.Value); if (flag || flag2) { float num = Mathf.Max(0f, shelterRecoveryPerSecond.Value) * elapsedSeconds; if (flag) { num *= Mathf.Max(1f, bedRecoveryMultiplier.Value); } state.ReduceAllInjuries(num); } } private float ApplyBleedingFromHit(HitData hit, float actualHealthLoss) { if (Mathf.Max(0f, hit.m_damage.m_slash) + Mathf.Max(0f, hit.m_damage.m_pierce) + Mathf.Max(0f, hit.m_damage.m_chop) <= 0f || actualHealthLoss < Mathf.Max(0f, physicalBleedingThreshold.Value)) { return 0f; } float num = (actualHealthLoss - Mathf.Max(0f, physicalBleedingThreshold.Value)) * Mathf.Max(0f, bleedingPerHealthLost.Value); state.Bleeding += num; return num; } private void UpdateBleedingTrail(Player player, float deltaSeconds) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) if (!enableBleedingVisuals.Value || !enableBleedingTrail.Value || (Object)(object)player == (Object)null || ((Character)player).IsSwimming()) { bleedingTrailTimer = 0f; return; } if (state.Bleeding <= 0.01f) { bleedingTrailTimer = 0f; return; } Vector3 velocity = ((Character)player).GetVelocity(); velocity.y = 0f; if (((Vector3)(ref velocity)).sqrMagnitude <= 0.1f) { return; } float num = (((Character)player).IsRunning() ? Mathf.Max(0.1f, runningTrailIntervalSeconds.Value) : Mathf.Max(0.1f, walkingTrailIntervalSeconds.Value)); bleedingTrailTimer += deltaSeconds; if (!(bleedingTrailTimer < num)) { bleedingTrailTimer = 0f; trailBloodAttempts++; Vector3 val = ((((Vector3)(ref velocity)).sqrMagnitude > 0.01f) ? ((Vector3)(ref velocity)).normalized : ((Component)player).transform.forward); if (!TryGetNextBleedSourcePosition(player, out var worldPosition)) { worldPosition = ((Character)player).GetCenterPoint() - Vector3.up * 0.22f - val * 0.1f; } worldPosition -= val * 0.1f; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Random.Range(-0.16f, 0.16f), 0f, Random.Range(-0.16f, 0.16f)); bool flag = TryPlaceBloodOnGround(player, worldPosition + val2, trailDrop: true); if (flag) { directTrailSplatsSpawned++; } SpawnBloodDroplet(((Component)player).transform, worldPosition + val2, val * -0.3f + val2 * 1.65f + Vector3.up * 0.46f, 0.052f, 0.95f, trailDrop: true, !flag); trailBloodDropletsSpawned++; } } private void UpdateBleedingDrips(Player player, float deltaSeconds) { //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) if (!enableBleedingVisuals.Value || (Object)(object)player == (Object)null || ((Character)player).IsSwimming() || state.Bleeding <= 0.01f) { bleedDripTimer = 0f; return; } float num = Mathf.InverseLerp(0f, 100f, state.Bleeding); float num2 = Mathf.Lerp(0.58f, 0.3f, num); bleedDripTimer += deltaSeconds; if (bleedDripTimer < num2) { return; } bleedDripTimer = 0f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Random.Range(-0.16f, 0.16f), 0f, Random.Range(-0.16f, 0.16f)); if (!TryGetNextBleedSourcePosition(player, out var worldPosition)) { worldPosition = ((Character)player).GetCenterPoint() - Vector3.up * Random.Range(0.18f, 0.48f); } worldPosition += val; Vector3 velocity = ((Character)player).GetVelocity(); velocity.y = 0f; bool flag = TryPlaceBloodOnGround(player, worldPosition, trailDrop: true); if (flag) { directTrailSplatsSpawned++; } if (num >= 0.35f) { if (!TryGetNextBleedSourcePosition(player, out var worldPosition2)) { worldPosition2 = worldPosition; } Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Random.Range(-0.26f, 0.26f), 0f, Random.Range(-0.26f, 0.26f)); if (TryPlaceBloodOnGround(player, worldPosition2 + val2, trailDrop: true)) { directTrailSplatsSpawned++; } } SpawnBloodDroplet(((Component)player).transform, worldPosition, velocity * 0.2f + val * 0.95f + Vector3.up * Random.Range(0.12f, 0.36f), Mathf.Lerp(0.055f, 0.082f, num), 1.7f, trailDrop: true, !flag); trailBloodDropletsSpawned++; } private void TrySpawnHitBlood(Player player, HitData hit, float actualHealthLoss, float bleedingAdded, Limb hitLimb) { //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) if (!enableBleedingVisuals.Value || !spawnBloodFromSharpHits.Value || (Object)(object)player == (Object)null || hit == null || Mathf.Max(0f, hit.m_damage.m_slash) + Mathf.Max(0f, hit.m_damage.m_pierce) + Mathf.Max(0f, hit.m_damage.m_chop) <= 0f || actualHealthLoss < Mathf.Max(0f, visibleBloodMinimumHealthLoss.Value)) { return; } hitBloodAttempts++; Vector3 val = ResolvePlayerImpactPoint(player, hit); Vector3 val2 = ResolveOutwardBloodDirection(player, hit, val); float num = Mathf.Clamp01((actualHealthLoss - visibleBloodMinimumHealthLoss.Value) / 10f); bool flag = actualHealthLoss >= 4f || bleedingAdded > 0.01f; if (actualHealthLoss >= Mathf.Max(0f, dramaticHitSprayMinimumHealthLoss.Value)) { SpawnDramaticHitSpray(player, val, val2, num); } SpawnWoundMark(player, hitLimb, val, num); if (actualHealthLoss >= Mathf.Max(0f, clothStainMinimumHealthLoss.Value)) { SpawnClothStain(player, hitLimb, val, num); } if (bleedingAdded > 0.01f) { RegisterBleedSource(player, hitLimb, val); } int num2 = Mathf.Clamp(maximumHitBloodDroplets.Value, 8, 26); int num3 = 8 + Mathf.RoundToInt(Mathf.Lerp(3f, (float)num2 - 8f, num)); if (bleedingAdded > 0.01f) { num3 += 3; } if (flag) { num3 += 4; } num3 = Mathf.Clamp(num3, 8, num2); ((MonoBehaviour)this).StartCoroutine(PlaceDelayedFallbackGroundBlood(player, val + val2 * Random.Range(0.34f, 0.72f), 0.18f)); if (flag) { Vector3 val3 = Vector3.Cross(Vector3.up, val2); Vector3 normalized = ((Vector3)(ref val3)).normalized; ((MonoBehaviour)this).StartCoroutine(PlaceDelayedFallbackGroundBlood(player, val + val2 * Random.Range(0.65f, 1.2f) + normalized * Random.Range(-0.34f, 0.34f), 0.26f)); } for (int i = 0; i < num3; i++) { float num4 = (flag ? 0.86f : 0.62f); Vector3 val4 = val2 + new Vector3(Random.Range(0f - num4, num4), Random.Range(-0.06f, 0.42f), Random.Range(0f - num4, num4)); if (((Vector3)(ref val4)).sqrMagnitude < 0.01f) { val4 = ((Component)player).transform.forward; } ((Vector3)(ref val4)).Normalize(); float num5 = (flag ? Random.Range(4.4f, 7.2f) : Random.Range(3.1f, 5.55f)); Vector3 initialVelocity = val4 * num5 + Vector3.up * Random.Range(2.1f, flag ? 4.8f : 3.9f); float size = (flag ? Random.Range(0.052f, 0.105f) : Random.Range(0.042f, 0.084f)); SpawnBloodDroplet(((Component)player).transform, val, initialVelocity, size, 2.35f, trailDrop: false, createSplatWhenLanding: true); hitBloodDropletsSpawned++; } } private static Vector3 ResolvePlayerImpactPoint(Player player, HitData hit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) Vector3 centerPoint = ((Character)player).GetCenterPoint(); Vector3 val = hit?.m_point ?? Vector3.zero; if (!(((Vector3)(ref val)).sqrMagnitude < 0.0001f)) { Vector3 val2 = val - centerPoint; if (!(((Vector3)(ref val2)).sqrMagnitude > 9f)) { goto IL_003e; } } val = centerPoint; goto IL_003e; IL_003e: return val + Vector3.up * 0.035f; } private static Vector3 ResolveOutwardBloodDirection(Player player, HitData hit, Vector3 impactPoint) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = hit?.m_dir ?? Vector3.zero; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)player).transform.forward; } ((Vector3)(ref val)).Normalize(); Vector3 val2 = impactPoint - ((Character)player).GetCenterPoint(); val2.y *= 0.55f; if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { val2 = val; } else { ((Vector3)(ref val2)).Normalize(); if (Vector3.Dot(val2, val) < 0f) { val2 = -val2; } } Vector3 val3 = val * 0.78f + val2 * 0.32f + Vector3.up * 0.08f; if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = ((Component)player).transform.forward; } val3.y = Mathf.Clamp(val3.y, -0.1f, 0.38f); return ((Vector3)(ref val3)).normalized; } private void SpawnHitImpactSprite(Vector3 source, Vector3 direction, float severity) { } private void SpawnBloodDroplet(Transform owner, Vector3 source, Vector3 initialVelocity, float size, float lifetime, bool trailDrop, bool createSplatWhenLanding) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) if (enableBleedingVisuals.Value) { EnsureBloodVisualRoot(); bool flag = trailDrop && dripSpriteMaterials.Count > 0; GameObject val = GameObject.CreatePrimitive((PrimitiveType)(flag ? 5 : 0)); ((Object)val).name = (flag ? "YoureInjured_BloodDripSprite" : "YoureInjured_BloodDroplet"); val.transform.SetParent(bloodVisualRoot, true); val.transform.position = source; val.transform.localScale = (Vector3)(flag ? new Vector3(Mathf.Max(0.026f, size * 2.5f), Mathf.Max(0.026f, size * 2.5f), 1f) : (Vector3.one * Mathf.Max(0.018f, size))); Camera main = Camera.main; if (flag && (Object)(object)main != (Object)null) { val.transform.rotation = ((Component)main).transform.rotation; } Collider component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sharedMaterial = (flag ? dripSpriteMaterials[Random.Range(0, dripSpriteMaterials.Count)] : GetBloodDropMaterial()); component2.shadowCastingMode = (ShadowCastingMode)0; component2.receiveShadows = false; } val.AddComponent().Initialize(this, owner, initialVelocity, Mathf.Max(0.2f, lifetime), Mathf.Max(1f, bloodDropletGravity.Value), trailDrop, createSplatWhenLanding); } } internal void LandBloodDroplet(Vector3 point, Vector3 normal, bool trailDrop) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!(normal.y < 0.18f)) { CreateGroundBloodSplat(point, ((Vector3)(ref normal)).normalized, trailDrop); } } internal bool TryLandBloodAtFallback(Transform owner, Vector3 source, bool trailDrop) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)owner == (Object)null || (Object)(object)owner != (Object)(object)((Component)localPlayer).transform) { return false; } bool num = TryPlaceBloodOnGround(localPlayer, source, trailDrop); if (num) { dropletFallbackLandings++; } return num; } private bool TryPlaceBloodOnGround(Player player, Vector3 source, bool trailDrop) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!TryFindGroundBelow(player, source, out var point, out var normal)) { groundProbeFailures++; return false; } groundProbeSuccesses++; CreateGroundBloodSplat(point, normal, trailDrop); return true; } private IEnumerator PlaceDelayedFallbackGroundBlood(Player player, Vector3 source, float delaySeconds) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) yield return (object)new WaitForSeconds(Mathf.Max(0f, delaySeconds)); if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)Player.m_localPlayer)) { TryPlaceBloodOnGround(player, source, trailDrop: false); } } private bool TryFindGroundBelow(Player player, Vector3 source, out Vector3 point, out Vector3 normal) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) point = Vector3.zero; normal = Vector3.up; if ((Object)(object)player == (Object)null) { return false; } RaycastHit[] array = Physics.RaycastAll(source + Vector3.up * 1.8f, Vector3.down, 7f, -1, (QueryTriggerInteraction)1); float num = float.MaxValue; Vector3 val; for (int i = 0; i < array.Length; i++) { Collider collider = ((RaycastHit)(ref array[i])).collider; if (!((Object)(object)collider == (Object)null) && !((Component)collider).transform.IsChildOf(((Component)player).transform) && !(((RaycastHit)(ref array[i])).normal.y < 0.18f) && !(((RaycastHit)(ref array[i])).distance >= num)) { num = ((RaycastHit)(ref array[i])).distance; point = ((RaycastHit)(ref array[i])).point; val = ((RaycastHit)(ref array[i])).normal; normal = ((Vector3)(ref val)).normalized; } } if (num < float.MaxValue) { return true; } Collider lastGroundCollider = ((Character)player).GetLastGroundCollider(); Vector3 lastGroundNormal = ((Character)player).GetLastGroundNormal(); if ((Object)(object)lastGroundCollider != (Object)null && lastGroundNormal.y >= 0.18f) { Vector3 val2 = lastGroundCollider.ClosestPoint(((Component)player).transform.position + Vector3.up * 0.3f); val = val2 - ((Component)player).transform.position; if (((Vector3)(ref val)).sqrMagnitude <= 36f) { point = val2; normal = ((Vector3)(ref lastGroundNormal)).normalized; return true; } } return false; } private void CreateGroundBloodSplat(Vector3 point, Vector3 normal, bool trailDrop) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) if (!enableBleedingVisuals.Value) { return; } CleanupDeadBloodSplats(); int num = Mathf.Max(10, maximumGroundBloodSplats.Value); while (activeGroundBlood.Count >= num) { GroundBloodSplat groundBloodSplat = activeGroundBlood[0]; activeGroundBlood.RemoveAt(0); if ((Object)(object)groundBloodSplat != (Object)null) { Object.Destroy((Object)(object)((Component)groundBloodSplat).gameObject); } } EnsureBloodVisualRoot(); GameObject val = new GameObject("YoureInjured_LiquidGroundBlood"); val.transform.SetParent(bloodVisualRoot, true); val.transform.position = point + normal * 0.011f; val.transform.rotation = Quaternion.FromToRotation(Vector3.up, normal); float num2 = Mathf.Max(0.03f, bloodSplatMinimumSize.Value); float num3 = Mathf.Max(num2, bloodSplatMaximumSize.Value); float num4 = (trailDrop ? Random.Range(Mathf.Lerp(num2, num3, 0.25f), Mathf.Lerp(num2, num3, 0.76f)) : Random.Range(Mathf.Lerp(num2, num3, 0.5f), num3)); float aspect = (trailDrop ? Random.Range(0.55f, 2.25f) : Random.Range(0.72f, 1.95f)); float yaw = Random.Range(0f, 360f); List list = new List(); CreateBloodDecalMesh(val.transform, "YoureInjured_LiquidBloodPool", Vector3.zero, num4, aspect, yaw, 4, 0f, GetBloodLiquidMaterial(Random.Range(0, 7)), list); int num5 = (trailDrop ? Random.Range(1, 4) : Random.Range(2, 5)); for (int i = 0; i < num5; i++) { float num6 = Random.Range(0f, MathF.PI * 2f); Vector3 val2 = new Vector3(Mathf.Cos(num6), 0f, Mathf.Sin(num6)); float num7 = num4 * Random.Range(0.48f, trailDrop ? 0.82f : 1.2f); Vector3 localPosition = val2 * num7 + Vector3.up * 0.0015f; CreateBloodDecalMesh(val.transform, "YoureInjured_LiquidBloodDrop", localPosition, num4 * Random.Range(0.11f, 0.28f), Random.Range(0.5f, 1.75f), Random.Range(0f, 360f), 4, 0f, GetBloodLiquidMaterial(Random.Range(0, 7)), list); } GroundBloodSplat groundBloodSplat2 = val.AddComponent(); groundBloodSplat2.Initialize(this, Mathf.Max(5f, groundBloodLifetimeSeconds.Value), Mathf.Clamp(bloodLiquidSpreadSeconds.Value, 0.1f, 2f), list); activeGroundBlood.Add(groundBloodSplat2); groundBloodSplatsSpawned++; } private static void CreateBloodDecalMesh(Transform parent, string name, Vector3 localPosition, float diameter, float aspect, float yaw, int edgeCount, float irregularity, Material material, List ownedMeshes) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.transform.localPosition = localPosition; val.transform.localRotation = Quaternion.AngleAxis(yaw, Vector3.up); val.transform.localScale = new Vector3(Mathf.Max(0.01f, diameter * aspect), 1f, Mathf.Max(0.01f, diameter / Mathf.Max(0.05f, aspect))); MeshFilter val2 = val.AddComponent(); MeshRenderer obj = val.AddComponent(); Mesh item = (val2.sharedMesh = BuildIrregularBloodMesh(edgeCount, irregularity)); ((Renderer)obj).sharedMaterial = material; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)obj).receiveShadows = false; ownedMeshes?.Add(item); } private static Mesh BuildIrregularBloodMesh(int requestedEdgeCount, float irregularity) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown Vector3[] vertices = (Vector3[])(object)new Vector3[4] { new Vector3(-0.5f, 0f, -0.5f), new Vector3(-0.5f, 0f, 0.5f), new Vector3(0.5f, 0f, 0.5f), new Vector3(0.5f, 0f, -0.5f) }; Vector3[] normals = (Vector3[])(object)new Vector3[4] { Vector3.up, Vector3.up, Vector3.up, Vector3.up }; Vector2[] uv = (Vector2[])(object)new Vector2[4] { new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(1f, 0f) }; int[] triangles = new int[6] { 0, 1, 2, 0, 2, 3 }; Mesh val = new Mesh { name = "YoureInjured_LiquidBloodDecalQuad", vertices = vertices, normals = normals, uv = uv, triangles = triangles }; val.RecalculateBounds(); return val; } internal void UnregisterGroundBlood(GroundBloodSplat splat) { activeGroundBlood.Remove(splat); } private void CleanupDeadBloodSplats() { for (int num = activeGroundBlood.Count - 1; num >= 0; num--) { if ((Object)(object)activeGroundBlood[num] == (Object)null) { activeGroundBlood.RemoveAt(num); } } } private void EnsureBloodVisualRoot() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (!((Object)(object)bloodVisualRoot != (Object)null)) { GameObject val = new GameObject("YoureInjured_BloodVisuals"); bloodVisualRoot = val.transform; } } private void EnsurePlayerDecalRoot() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown if (!((Object)(object)playerDecalRoot != (Object)null)) { GameObject val = new GameObject("YoureInjured_PlayerBodyDecals"); playerDecalRoot = val.transform; } } private static Transform FindAttachmentBone(Player player, Limb limb) { if ((Object)(object)player == (Object)null) { return null; } string[] array = limb switch { Limb.Head => HeadBoneNames, Limb.LeftArm => LeftArmBoneNames, Limb.RightArm => RightArmBoneNames, Limb.LeftLeg => LeftLegBoneNames, Limb.RightLeg => RightLegBoneNames, _ => TorsoBoneNames, }; Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren(true); for (int i = 0; i < array.Length; i++) { foreach (Transform val in componentsInChildren) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, array[i], StringComparison.OrdinalIgnoreCase)) { return val; } } } for (int k = 0; k < array.Length; k++) { foreach (Transform val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name.IndexOf(array[k], StringComparison.OrdinalIgnoreCase) >= 0) { return val2; } } } return ((Component)player).transform; } private void SpawnWoundMark(Player player, Limb limb, Vector3 worldPoint, float severity) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if (!enableWoundMarks.Value || (Object)(object)player == (Object)null) { return; } EnsurePlayerDecalRoot(); CleanupDeadPlayerDecals(activeWoundMarks); int num = Mathf.Max(4, maximumWoundMarks.Value); while (activeWoundMarks.Count >= num) { PlayerBodyDecal playerBodyDecal = activeWoundMarks[0]; activeWoundMarks.RemoveAt(0); if ((Object)(object)playerBodyDecal != (Object)null) { Object.Destroy((Object)(object)((Component)playerBodyDecal).gameObject); } } Transform bone = FindAttachmentBone(player, limb); float num2 = Mathf.Max(0.01f, woundMarkMinimumSize.Value); float num3 = Mathf.Max(num2, woundMarkMaximumSize.Value); float size = Mathf.Lerp(num2, num3, Mathf.Clamp01(severity)); PlayerBodyDecal playerBodyDecal2 = CreateBodyDecalObject("YoureInjured_WoundMark", bone, ((Component)player).transform, worldPoint, size, isClothStain: false); if ((Object)(object)playerBodyDecal2 != (Object)null) { activeWoundMarks.Add(playerBodyDecal2); } } private void SpawnClothStain(Player player, Limb limb, Vector3 worldPoint, float severity) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if (!enableClothStaining.Value || (Object)(object)player == (Object)null) { return; } EnsurePlayerDecalRoot(); CleanupDeadPlayerDecals(activeClothStains); int num = Mathf.Max(2, maximumClothStains.Value); while (activeClothStains.Count >= num) { PlayerBodyDecal playerBodyDecal = activeClothStains[0]; activeClothStains.RemoveAt(0); if ((Object)(object)playerBodyDecal != (Object)null) { Object.Destroy((Object)(object)((Component)playerBodyDecal).gameObject); } } Transform bone = FindAttachmentBone(player, limb); float num2 = Mathf.Max(0.02f, clothStainMinimumSize.Value); float num3 = Mathf.Max(num2, clothStainMaximumSize.Value); float size = Mathf.Lerp(num2, num3, Mathf.Clamp01(severity)); PlayerBodyDecal playerBodyDecal2 = CreateBodyDecalObject("YoureInjured_ClothStain", bone, ((Component)player).transform, worldPoint, size, isClothStain: true); if ((Object)(object)playerBodyDecal2 != (Object)null) { activeClothStains.Add(playerBodyDecal2); } } private void RegisterBleedSource(Player player, Limb limb, Vector3 worldPoint) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) Transform val = FindAttachmentBone(player, limb); if ((Object)(object)val == (Object)null) { return; } Vector3 val2 = worldPoint - val.position; Vector3 val3 = val2; val3.y *= 0.4f; if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = ((Component)player).transform.forward; } ((Vector3)(ref val3)).Normalize(); float num = Mathf.Min(((Vector3)(ref val2)).magnitude, 0.1f); Vector3 val4 = val.position + val3 * num; Vector3 localOffset = val.InverseTransformPoint(val4); for (int i = 0; i < activeBleedSources.Count; i++) { if ((Object)(object)activeBleedSources[i].Bone == (Object)(object)val) { activeBleedSources[i] = new BleedSource(val, localOffset); return; } } if (activeBleedSources.Count >= 6) { activeBleedSources.RemoveAt(0); } activeBleedSources.Add(new BleedSource(val, localOffset)); } private bool TryGetNextBleedSourcePosition(Player player, out Vector3 worldPosition) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) for (int num = activeBleedSources.Count - 1; num >= 0; num--) { if ((Object)(object)activeBleedSources[num].Bone == (Object)null) { activeBleedSources.RemoveAt(num); } } if (activeBleedSources.Count == 0) { worldPosition = (((Object)(object)player != (Object)null) ? ((Character)player).GetCenterPoint() : Vector3.zero); return false; } nextBleedSourceCycleIndex = (nextBleedSourceCycleIndex + 1) % activeBleedSources.Count; if (activeBleedSources[nextBleedSourceCycleIndex].TryGetWorldPosition(out worldPosition)) { return true; } worldPosition = (((Object)(object)player != (Object)null) ? ((Character)player).GetCenterPoint() : Vector3.zero); return false; } private PlayerBodyDecal CreateBodyDecalObject(string name, Transform bone, Transform playerTransform, Vector3 worldPoint, float size, bool isClothStain) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bone == (Object)null) { return null; } GameObject obj = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)obj).name = name; obj.transform.SetParent(playerDecalRoot, true); Collider component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Vector3 val = worldPoint - bone.position; Vector3 val2 = val; val2.y *= 0.4f; if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f) { val2 = playerTransform.forward; } ((Vector3)(ref val2)).Normalize(); float num = Mathf.Min(((Vector3)(ref val)).magnitude, 0.12f); obj.transform.position = bone.position + val2 * num; obj.transform.rotation = Quaternion.LookRotation(-val2, Vector3.up) * Quaternion.Euler(0f, Random.Range(0f, 360f), 0f); obj.transform.localScale = Vector3.one * Mathf.Max(0.01f, size); Renderer component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sharedMaterial = ((dripSpriteMaterials.Count > 0) ? dripSpriteMaterials[Random.Range(0, dripSpriteMaterials.Count)] : GetBloodDropMaterial()); component2.shadowCastingMode = (ShadowCastingMode)0; component2.receiveShadows = false; } obj.transform.SetParent(bone, true); PlayerBodyDecal playerBodyDecal = obj.AddComponent(); playerBodyDecal.Initialize(this, isClothStain, 0.35f); return playerBodyDecal; } internal void UnregisterPlayerBodyDecal(PlayerBodyDecal decal, bool isClothStain) { if (isClothStain) { activeClothStains.Remove(decal); } else { activeWoundMarks.Remove(decal); } } private static void CleanupDeadPlayerDecals(List decals) { for (int num = decals.Count - 1; num >= 0; num--) { if ((Object)(object)decals[num] == (Object)null) { decals.RemoveAt(num); } } } private void SpawnDramaticHitSpray(Player player, Vector3 source, Vector3 outwardDirection, float severity) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Expected O, but got Unknown if (enableDramaticHitSpray.Value && impactSpriteMaterials.Count != 0) { EnsureBloodVisualRoot(); GameObject obj = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)obj).name = "YoureInjured_DramaticHitSpray"; obj.transform.SetParent(bloodVisualRoot, true); Collider component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Vector3 val = outwardDirection; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)player).transform.forward; } ((Vector3)(ref val)).Normalize(); obj.transform.position = source + outwardDirection * 0.06f; obj.transform.rotation = Quaternion.LookRotation(-val, Vector3.up) * Quaternion.Euler(0f, 0f, Random.Range(0f, 360f)); float num = Mathf.Max(0.1f, dramaticHitSprayMinimumSize.Value); float num2 = Mathf.Max(num, dramaticHitSprayMaximumSize.Value); float num3 = Mathf.Lerp(num, num2, Mathf.Clamp01(severity)); obj.transform.localScale = Vector3.one * num3; Renderer component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { Material material = new Material(impactSpriteMaterials[Random.Range(0, impactSpriteMaterials.Count)]); component2.material = material; component2.shadowCastingMode = (ShadowCastingMode)0; component2.receiveShadows = false; } obj.AddComponent().Initialize(Mathf.Max(0.1f, dramaticHitSprayDurationSeconds.Value)); } } private void UpdateSeaRinse(Player player, float elapsedSeconds) { if (!enableSeaRinseForStains.Value || (Object)(object)player == (Object)null) { seaRinseTimer = 0f; return; } bool flag = activeWoundMarks.Count > 0 || activeClothStains.Count > 0; if (!((Character)player).IsSwimming() || !flag) { seaRinseTimer = 0f; return; } seaRinseTimer += elapsedSeconds; if (seaRinseTimer >= Mathf.Max(1f, seaRinseRequiredSeconds.Value)) { ClearAllPlayerBodyDecals(); seaRinseTimer = 0f; ShowMessage("The sea has washed the blood from your body and clothes."); } } private void ClearAllPlayerBodyDecals() { for (int num = activeWoundMarks.Count - 1; num >= 0; num--) { if ((Object)(object)activeWoundMarks[num] != (Object)null) { Object.Destroy((Object)(object)((Component)activeWoundMarks[num]).gameObject); } } activeWoundMarks.Clear(); for (int num2 = activeClothStains.Count - 1; num2 >= 0; num2--) { if ((Object)(object)activeClothStains[num2] != (Object)null) { Object.Destroy((Object)(object)((Component)activeClothStains[num2]).gameObject); } } activeClothStains.Clear(); } private void LoadExternalImpactSprites() { string path = Path.Combine(pluginDirectory ?? string.Empty, "assets", "bleeding", "impact_frames"); if (!Directory.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"You're Injured: no optional impact-frame folder found. The dramatic hit spray will be skipped; droplets and ground blood still work."); } else { try { int num = Mathf.Clamp(maximumImpactSpriteTextures.Value, 1, 8); string[] files = Directory.GetFiles(path, "*.png", SearchOption.TopDirectoryOnly); Array.Sort(files, (IComparer?)StringComparer.OrdinalIgnoreCase); for (int i = 0; i < files.Length; i++) { if (impactSpriteTextures.Count >= num) { break; } if (!InjuryAssetLoader.TryLoadAlphaMaskPng(files[i], out var texture, out var error)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: skipped impact sprite " + Path.GetFileName(files[i]) + ". " + error)); continue; } ((Object)texture).name = "YoureInjured_HitSpray_" + Path.GetFileNameWithoutExtension(files[i]); impactSpriteTextures.Add(texture); impactSpriteMaterials.Add(CreateImpactSpriteMaterial(texture)); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: could not enumerate impact sprite files. " + ex.Message)); } if (impactSpriteMaterials.Count > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("You're Injured: loaded " + impactSpriteMaterials.Count + " dramatic hit-spray frames. These render world-space and outward-facing, never toward the camera.")); } } string path2 = Path.Combine(pluginDirectory ?? string.Empty, "assets", "bleeding", "drip_frames"); if (!Directory.Exists(path2)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"You're Injured: no optional drip-frame folder found. Physical droplets and ground blood still work."); return; } try { string[] files2 = Directory.GetFiles(path2, "*.png", SearchOption.TopDirectoryOnly); Array.Sort(files2, (IComparer?)StringComparer.OrdinalIgnoreCase); for (int j = 0; j < files2.Length; j++) { if (dripSpriteTextures.Count >= 4) { break; } if (!InjuryAssetLoader.TryLoadAlphaMaskPng(files2[j], out var texture2, out var error2)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: skipped drip sprite " + Path.GetFileName(files2[j]) + ". " + error2)); continue; } ((Object)texture2).name = "YoureInjured_TrailDrip_" + Path.GetFileNameWithoutExtension(files2[j]); dripSpriteTextures.Add(texture2); dripSpriteMaterials.Add(CreateImpactSpriteMaterial(texture2)); } } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: could not enumerate drip sprite files. " + ex2.Message)); } if (dripSpriteMaterials.Count > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("You're Injured: loaded " + dripSpriteMaterials.Count + " selected blood-trail drip frames. Camera-facing hit sprites are disabled.")); } } private static Material CreateImpactSpriteMaterial(Texture2D texture) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Unlit/Transparent"); if ((Object)(object)val == (Object)null) { val = Shader.Find("Sprites/Default"); } if ((Object)(object)val == (Object)null) { val = Shader.Find("Legacy Shaders/Transparent/Diffuse"); } Material val2 = new Material(val); val2.mainTexture = (Texture)(object)texture; if (val2.HasProperty("_Color")) { val2.SetColor("_Color", BloodTintColor); } val2.renderQueue = 3002; return val2; } private IEnumerator LoadHitAudioFiles() { yield return ((MonoBehaviour)this).StartCoroutine(LoadExternalMp3(Path.Combine(pluginDirectory ?? string.Empty, "assets", "audio", axeHitAudioFile.Value.Trim()), delegate(object clip) { axeHitAudioClip = clip; }, "axe hit")); yield return ((MonoBehaviour)this).StartCoroutine(LoadExternalMp3(Path.Combine(pluginDirectory ?? string.Empty, "assets", "audio", swordHitAudioFile.Value.Trim()), delegate(object clip) { swordHitAudioClip = clip; }, "sword hit")); yield return ((MonoBehaviour)this).StartCoroutine(LoadExternalMp3(Path.Combine(pluginDirectory ?? string.Empty, "assets", "audio", arrowHitAudioFile.Value.Trim()), delegate(object clip) { arrowHitAudioClip = clip; }, "arrow hit")); yield return ((MonoBehaviour)this).StartCoroutine(LoadExternalMp3(Path.Combine(pluginDirectory ?? string.Empty, "assets", "audio", bandageAudioFile.Value.Trim()), delegate(object clip) { bandageAudioClip = clip; }, "bandage wrap")); } private IEnumerator LoadExternalMp3(string path, Action onLoaded, string label) { object request; object operation; if (string.IsNullOrEmpty(path) || !File.Exists(path)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: " + label + " audio file was not found at " + path)); } else if (TryBeginExternalMp3Request(path, label, out request, out operation)) { yield return operation; CompleteExternalMp3Request(request, onLoaded, label); } } private bool TryBeginExternalMp3Request(string path, string label, out object request, out object operation) { request = null; operation = null; try { Type type = FindRuntimeType("UnityEngine.Networking.UnityWebRequestMultimedia"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: UnityWebRequestMultimedia was unavailable; could not load " + label + " audio.")); return false; } MethodInfo methodInfo = null; MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo2 in methods) { if (methodInfo2.Name == "GetAudioClip" && methodInfo2.GetParameters().Length == 2) { methodInfo = methodInfo2; break; } } if (methodInfo == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: no compatible GetAudioClip method was found for " + label + " audio.")); return false; } object obj = Enum.Parse(methodInfo.GetParameters()[1].ParameterType, "MPEG"); request = methodInfo.Invoke(null, new object[2] { new Uri(path).AbsoluteUri, obj }); if (request == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: could not create the request for " + label + " audio.")); return false; } MethodInfo method = request.GetType().GetMethod("SendWebRequest", Type.EmptyTypes); if (method == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: no SendWebRequest method was found for " + label + " audio.")); DisposeRequest(request); request = null; return false; } operation = method.Invoke(request, null); if (operation == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: SendWebRequest returned no operation for " + label + " audio.")); DisposeRequest(request); request = null; return false; } return true; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: could not start loading " + label + " audio. " + ex.Message)); DisposeRequest(request); request = null; operation = null; return false; } } private void CompleteExternalMp3Request(object request, Action onLoaded, string label) { try { if (request == null) { return; } PropertyInfo property = request.GetType().GetProperty("error", BindingFlags.Instance | BindingFlags.Public); string text = ((property != null) ? (property.GetValue(request, null) as string) : null); if (!string.IsNullOrEmpty(text)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: failed to load " + label + " audio. " + text)); return; } PropertyInfo property2 = request.GetType().GetProperty("downloadHandler", BindingFlags.Instance | BindingFlags.Public); object obj = ((property2 != null) ? property2.GetValue(request, null) : null); PropertyInfo propertyInfo = obj?.GetType().GetProperty("audioClip", BindingFlags.Instance | BindingFlags.Public); object obj2 = ((propertyInfo != null) ? propertyInfo.GetValue(obj, null) : null); if (obj2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: the " + label + " MP3 decoded without an AudioClip.")); return; } onLoaded?.Invoke(obj2); ((BaseUnityPlugin)this).Logger.LogInfo((object)("You're Injured: loaded " + label + " audio from " + Path.GetFileName(GetRequestUrl(request)) + ".")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: could not finish loading " + label + " audio. " + ex.Message)); } finally { DisposeRequest(request); } } private static string GetRequestUrl(object request) { if (request == null) { return string.Empty; } try { PropertyInfo property = request.GetType().GetProperty("url", BindingFlags.Instance | BindingFlags.Public); string text = ((property != null) ? (property.GetValue(request, null) as string) : null); return string.IsNullOrEmpty(text) ? string.Empty : text; } catch { return string.Empty; } } private static void DisposeRequest(object request) { if (request is IDisposable disposable) { disposable.Dispose(); } } private void TryPlayBandageAudio() { if (enableBandageAudio != null && enableBandageAudio.Value && bandageAudioClip != null) { TryPlayOneShot(bandageAudioClip, Mathf.Clamp01(bandageAudioVolume.Value)); } } private void TryPlayHitAudio(HitData hit) { if (enableHitAudio == null || !enableHitAudio.Value || hit == null) { return; } HitSoundKind hitSoundKind = ResolveHitSoundKind(hit); if (hitSoundKind != HitSoundKind.None && !(Time.unscaledTime < nextAllowedRecognizedHitAudioTime)) { object obj = null; switch (hitSoundKind) { case HitSoundKind.Axe: obj = axeHitAudioClip; break; case HitSoundKind.Arrow: obj = arrowHitAudioClip; break; case HitSoundKind.Sword: obj = swordHitAudioClip; break; } if (obj != null && TryPlayOneShot(obj, Mathf.Clamp01(hitAudioVolume.Value))) { float num = ((hitAudioCooldownSeconds == null) ? 0.18f : hitAudioCooldownSeconds.Value); nextAllowedRecognizedHitAudioTime = Time.unscaledTime + Mathf.Clamp(num, 0.05f, 1f); } } } private HitSoundKind ResolveHitSoundKind(HitData hit) { string text = ResolveHitAttackerName(hit).ToLowerInvariant(); string text2 = ResolveHitSkillName(hit).ToLowerInvariant(); if (text.Contains("arrow") || text.Contains("bow") || text2.Contains("bow")) { return HitSoundKind.Arrow; } if (text.Contains("draugr") && !text.Contains("elite")) { return HitSoundKind.Axe; } if (text.Contains("draugr_elite") || text.Contains("draugr elite") || text.Contains("skeleton")) { return HitSoundKind.Sword; } return HitSoundKind.None; } private static string ResolveHitAttackerName(HitData hit) { object hitAttackerObject = GetHitAttackerObject(hit); if (hitAttackerObject == null) { return string.Empty; } GameObject val = ResolveAttackerGameObject(hitAttackerObject); if ((Object)(object)val != (Object)null) { string obj = ((Object)val).name ?? string.Empty; Transform val2 = (((Object)(object)val.transform != (Object)null) ? val.transform.root : null); string text = (((Object)(object)val2 != (Object)null && (Object)(object)((Component)val2).gameObject != (Object)null) ? ((Object)((Component)val2).gameObject).name : string.Empty); return obj + " " + text; } return string.Empty; } private static object GetHitAttackerObject(HitData hit) { try { MethodInfo method = ((object)hit).GetType().GetMethod("GetAttacker", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null); return (method != null) ? method.Invoke(hit, null) : null; } catch { return null; } } private static GameObject ResolveAttackerGameObject(object attacker) { GameObject val = (GameObject)((attacker is GameObject) ? attacker : null); if ((Object)(object)val != (Object)null) { return val; } Component val2 = (Component)((attacker is Component) ? attacker : null); if ((Object)(object)val2 != (Object)null) { return val2.gameObject; } try { Type typeFromHandle = typeof(ZNetScene); FieldInfo field = typeFromHandle.GetField("instance", BindingFlags.Static | BindingFlags.Public); object obj = ((field != null) ? field.GetValue(null) : null); if (obj == null) { PropertyInfo property = typeFromHandle.GetProperty("instance", BindingFlags.Static | BindingFlags.Public); obj = ((property != null) ? property.GetValue(null, null) : null); } if (obj == null) { return null; } MethodInfo[] methods = obj.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "FindInstance") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType.IsInstanceOfType(attacker)) { object obj2 = methodInfo.Invoke(obj, new object[1] { attacker }); GameObject val3 = (GameObject)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)val3 != (Object)null) { return val3; } Component val4 = (Component)((obj2 is Component) ? obj2 : null); if ((Object)(object)val4 != (Object)null) { return val4.gameObject; } } } } catch { } return null; } private static string ResolveHitSkillName(HitData hit) { try { FieldInfo field = ((object)hit).GetType().GetField("m_skill", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); object obj = ((field != null) ? field.GetValue(hit) : null); return (obj != null) ? obj.ToString() : string.Empty; } catch { return string.Empty; } } private bool TryPlayOneShot(object clip, float volume) { if (clip == null) { return false; } Component val = EnsureHitAudioSource(); if ((Object)(object)val == (Object)null) { return false; } try { MethodInfo[] methods = ((object)val).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "PlayOneShot" && methodInfo.GetParameters().Length == 2) { methodInfo.Invoke(val, new object[2] { clip, volume }); return true; } } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: failed to play external audio. " + ex.Message)); } return false; } private Component EnsureHitAudioSource() { if ((Object)(object)hitAudioSource != (Object)null) { return hitAudioSource; } Type type = FindRuntimeType("UnityEngine.AudioSource"); if (type == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"You're Injured: Unity AudioSource was unavailable."); return null; } hitAudioSource = ((Component)this).gameObject.GetComponent(type); if ((Object)(object)hitAudioSource == (Object)null) { hitAudioSource = ((Component)this).gameObject.AddComponent(type); } if ((Object)(object)hitAudioSource != (Object)null) { SetAudioProperty(hitAudioSource, "playOnAwake", false); SetAudioProperty(hitAudioSource, "spatialBlend", 0f); SetAudioProperty(hitAudioSource, "loop", false); } return hitAudioSource; } private static void SetAudioProperty(Component source, string name, object value) { if (!((Object)(object)source == (Object)null)) { PropertyInfo property = ((object)source).GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public); if (property != null && property.CanWrite) { property.SetValue(source, value, null); } } } private static Type FindRuntimeType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType(fullName, throwOnError: false); if (type != null) { return type; } } string text = null; if (string.Equals(fullName, "UnityEngine.AudioSource", StringComparison.Ordinal)) { text = "UnityEngine.AudioModule"; } else if (fullName.StartsWith("UnityEngine.Networking.", StringComparison.Ordinal)) { text = "UnityEngine.UnityWebRequestAudioModule"; } if (!string.IsNullOrEmpty(text)) { try { Assembly assembly = Assembly.Load(text); Type type2 = ((assembly != null) ? assembly.GetType(fullName, throwOnError: false) : null); if (type2 != null) { return type2; } } catch { } } return null; } private Material GetBloodDropMaterial() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bloodDropMaterial == (Object)null) { bloodDropMaterial = CreateBloodMaterial(new Color(0.38f, 0.003f, 0.008f, 1f), 0.62f, transparent: false, 0.006f); } return bloodDropMaterial; } private Material GetBloodLiquidMaterial(int requestedVariant) { EnsureBloodLiquidMaterials(); if (bloodLiquidMaterials == null || bloodLiquidMaterials.Length == 0) { return GetBloodDropMaterial(); } int num = Mathf.Abs(requestedVariant) % bloodLiquidMaterials.Length; return bloodLiquidMaterials[num]; } private void EnsureBloodLiquidMaterials() { if (bloodLiquidMaterials == null || bloodLiquidMaterials.Length != 7) { DestroyBloodLiquidMaterials(); bloodLiquidMaterials = (Material[])(object)new Material[7]; bloodLiquidTextures = (Texture2D[])(object)new Texture2D[7]; for (int i = 0; i < 7; i++) { Texture2D val = CreateLiquidBloodTexture(i); bloodLiquidTextures[i] = val; bloodLiquidMaterials[i] = CreateLiquidBloodDecalMaterial(val); } } } private static Material CreateLiquidBloodDecalMaterial(Texture2D texture) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Standard"); if ((Object)(object)val == (Object)null) { val = Shader.Find("Legacy Shaders/Transparent/Diffuse"); } if ((Object)(object)val == (Object)null) { val = Shader.Find("Unlit/Transparent"); } if ((Object)(object)val == (Object)null) { val = Shader.Find("Sprites/Default"); } Material val2 = new Material(val); val2.mainTexture = (Texture)(object)texture; if (val2.HasProperty("_Color")) { val2.SetColor("_Color", Color.white); } if (val2.HasProperty("_Glossiness")) { val2.SetFloat("_Glossiness", 0.93f); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0f); } if (val2.HasProperty("_Mode")) { val2.SetFloat("_Mode", 3f); val2.SetInt("_SrcBlend", 5); val2.SetInt("_DstBlend", 10); val2.SetInt("_ZWrite", 0); val2.DisableKeyword("_ALPHATEST_ON"); val2.EnableKeyword("_ALPHABLEND_ON"); val2.DisableKeyword("_ALPHAPREMULTIPLY_ON"); } val2.renderQueue = 3001; return val2; } private static Texture2D CreateLiquidBloodTexture(int variant) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03ac: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03c1: Unknown result type (might be due to invalid IL or missing references) //IL_03c8: Unknown result type (might be due to invalid IL or missing references) //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) Texture2D val = new Texture2D(192, 192, (TextureFormat)4, false); ((Object)val).name = "YoureInjured_LiquidBloodTexture_" + variant; ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; Color[] array = (Color[])(object)new Color[36864]; float num = Hash01(variant * 41 + 7) * MathF.PI * 2f; float num2 = Mathf.Cos(num); float num3 = Mathf.Sin(num); float num4 = Hash01(variant * 83 + 4) * MathF.PI * 2f; float num5 = Mathf.Cos(num4); float num6 = Mathf.Sin(num4); Color val3 = default(Color); for (int i = 0; i < 192; i++) { for (int j = 0; j < 192; j++) { float num7 = ((float)j / 191f - 0.5f) * 2f; float num8 = ((float)i / 191f - 0.5f) * 2f; float num9 = num7 * num2 - num8 * num3; float num10 = num7 * num3 + num8 * num2; float num11 = Mathf.Atan2(num10, num9); float num12 = Mathf.Sqrt(num9 / 0.74f * (num9 / 0.74f) + num10 / 0.47f * (num10 / 0.47f)); float num13 = 0.88f + 0.075f * Mathf.Sin(num11 * 4f + (float)variant * 0.7f) + 0.045f * Mathf.Sin(num11 * 9f + (float)variant * 2.4f) + 0.025f * Mathf.Sin(num11 * 15f + (float)variant * 4.8f) - num12; float num14 = num9 * num5 + num10 * num6; float num15 = (0f - num9) * num6 + num10 * num5; float num16 = 1f - Mathf.Sqrt((num14 - 0.48f) / 0.5f * ((num14 - 0.48f) / 0.5f) + num15 / 0.14f * (num15 / 0.14f)); float num17 = Mathf.Max(num13, num16 * 0.62f); float num18 = Hash01(variant * 57 + 11) * MathF.PI * 2f; float num19 = Mathf.Cos(num18) * 0.48f; float num20 = Mathf.Sin(num18) * 0.25f; float num21 = Mathf.Sqrt((num9 - num19) / 0.26f * ((num9 - num19) / 0.26f) + (num10 - num20) / 0.18f * ((num10 - num20) / 0.18f)); float num22 = Mathf.Max(num17, (1f - num21) * 0.45f); float num23 = SmoothLiquidStep((num22 + 0.015f) / 0.1f) * 0.9f; float num24 = Mathf.Clamp01((num22 + 0.2f) / 1.05f); Color val2 = new Color(0.15f, 0.002f, 0.004f, 1f); ((Color)(ref val3))..ctor(0.47f, 0.006f, 0.013f, 1f); Color val4 = Color.Lerp(val2, val3, num24); float num25 = 0f; for (int k = 0; k < 2; k++) { int num26 = variant * 151 + k * 29 + 101; float num27 = Mathf.Lerp(-0.2f, 0.2f, Hash01(num26)); float num28 = Mathf.Lerp(-0.16f, 0.16f, Hash01(num26 + 1)); float num29 = (num9 - num27) / Mathf.Lerp(0.15f, 0.23f, Hash01(num26 + 2)); float num30 = (num10 - num28) / Mathf.Lerp(0.018f, 0.036f, Hash01(num26 + 3)); num25 += Mathf.Exp((0f - (num29 * num29 + num30 * num30)) * 2f); } num25 = Mathf.Clamp01(num25) * num23 * 0.14f; val4 = Color.Lerp(val4, new Color(0.68f, 0.045f, 0.03f, 1f), num25); array[i * 192 + j] = new Color(val4.r, val4.g, val4.b, num23); } } val.SetPixels(array); val.Apply(); return val; } private static float SmoothLiquidStep(float value) { value = Mathf.Clamp01(value); return value * value * (3f - 2f * value); } private static float Hash01(int seed) { float num = Mathf.Sin((float)seed * 12.9898f) * 43758.547f; return num - Mathf.Floor(num); } private static Material CreateBloodMaterial(Color color, float smoothness, bool transparent, float emissionStrength) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) Shader val = Shader.Find("Standard"); if ((Object)(object)val == (Object)null) { val = Shader.Find("Unlit/Color"); } if ((Object)(object)val == (Object)null) { val = Shader.Find("Legacy Shaders/Diffuse"); } if ((Object)(object)val == (Object)null) { val = Shader.Find("Sprites/Default"); } Material val2 = new Material(val); if (val2.HasProperty("_Color")) { val2.SetColor("_Color", color); } if (val2.HasProperty("_Glossiness")) { val2.SetFloat("_Glossiness", Mathf.Clamp01(smoothness)); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", 0.01f); } if (transparent && val2.HasProperty("_Mode")) { val2.SetFloat("_Mode", 3f); val2.SetInt("_SrcBlend", 5); val2.SetInt("_DstBlend", 10); val2.SetInt("_ZWrite", 0); val2.DisableKeyword("_ALPHATEST_ON"); val2.EnableKeyword("_ALPHABLEND_ON"); val2.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val2.renderQueue = 3000; } if (emissionStrength > 0f && val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", new Color(color.r * emissionStrength, color.g * emissionStrength, color.b * emissionStrength, 1f)); val2.EnableKeyword("_EMISSION"); } return val2; } private void DestroyBloodLiquidMaterials() { if (bloodLiquidMaterials != null) { for (int i = 0; i < bloodLiquidMaterials.Length; i++) { if ((Object)(object)bloodLiquidMaterials[i] != (Object)null) { Object.Destroy((Object)(object)bloodLiquidMaterials[i]); } } bloodLiquidMaterials = null; } if (bloodLiquidTextures == null) { return; } for (int j = 0; j < bloodLiquidTextures.Length; j++) { if ((Object)(object)bloodLiquidTextures[j] != (Object)null) { Object.Destroy((Object)(object)bloodLiquidTextures[j]); } } bloodLiquidTextures = null; } private void DestroyExternalHitAssets() { for (int i = 0; i < impactSpriteMaterials.Count; i++) { if ((Object)(object)impactSpriteMaterials[i] != (Object)null) { Object.Destroy((Object)(object)impactSpriteMaterials[i]); } } impactSpriteMaterials.Clear(); for (int j = 0; j < impactSpriteTextures.Count; j++) { if ((Object)(object)impactSpriteTextures[j] != (Object)null) { Object.Destroy((Object)(object)impactSpriteTextures[j]); } } impactSpriteTextures.Clear(); for (int k = 0; k < dripSpriteMaterials.Count; k++) { if ((Object)(object)dripSpriteMaterials[k] != (Object)null) { Object.Destroy((Object)(object)dripSpriteMaterials[k]); } } dripSpriteMaterials.Clear(); for (int l = 0; l < dripSpriteTextures.Count; l++) { if ((Object)(object)dripSpriteTextures[l] != (Object)null) { Object.Destroy((Object)(object)dripSpriteTextures[l]); } } dripSpriteTextures.Clear(); DestroyExternalAudioClip(ref axeHitAudioClip); DestroyExternalAudioClip(ref swordHitAudioClip); DestroyExternalAudioClip(ref arrowHitAudioClip); DestroyExternalAudioClip(ref bandageAudioClip); } private void DestroyExternalAudioClip(ref object clip) { object obj = clip; Object val = (Object)((obj is Object) ? obj : null); if (val != (Object)null) { Object.Destroy(val); } clip = null; } private void DestroyBloodVisuals() { DestroyExternalHitAssets(); if ((Object)(object)bloodVisualRoot != (Object)null) { Object.Destroy((Object)(object)((Component)bloodVisualRoot).gameObject); bloodVisualRoot = null; } if ((Object)(object)playerDecalRoot != (Object)null) { Object.Destroy((Object)(object)((Component)playerDecalRoot).gameObject); playerDecalRoot = null; } if ((Object)(object)bloodDropMaterial != (Object)null) { Object.Destroy((Object)(object)bloodDropMaterial); bloodDropMaterial = null; } DestroyBloodLiquidMaterials(); activeGroundBlood.Clear(); activeWoundMarks.Clear(); activeClothStains.Clear(); activeBleedSources.Clear(); seaRinseTimer = 0f; } private Limb ResolveHitLimb(Player player, HitData hit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) Vector3 point = hit.m_point; if (point == Vector3.zero) { return Limb.Torso; } float num = ((Character)player).GetHeadPoint().y - 0.22f; float y = ((Character)player).GetCenterPoint().y; Vector3 val = ((Component)player).transform.InverseTransformPoint(point); if (point.y >= num) { return Limb.Head; } if (point.y <= y - 0.35f) { if (!(val.x < 0f)) { return Limb.RightLeg; } return Limb.LeftLeg; } if (Mathf.Abs(val.x) >= 0.34f) { if (!(val.x < 0f)) { return Limb.RightArm; } return Limb.LeftArm; } return Limb.Torso; } private bool ShouldIgnoreInjuryHit(HitType hitType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Invalid comparison between Unknown and I4 //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 if ((int)hitType != 4 && (int)hitType != 5 && (int)hitType != 6 && (int)hitType != 7 && (int)hitType != 8 && (int)hitType != 9 && (int)hitType != 10) { return (int)hitType == 21; } return true; } private void TryUseBandage(Player player) { if (treatmentCooldown > 0f) { return; } if (!state.HasAnyCondition()) { ShowMessage("You have no wounds to treat."); return; } if (IsWet(player)) { ShowMessage("You need to dry off before applying a bandage."); return; } int num = Mathf.Max(1, bandageItemCost.Value); Inventory inventory = ((Humanoid)player).GetInventory(); string value = bandageItemSharedName.Value; if (inventory == null || !inventory.HaveItem(value, false) || inventory.CountItems(value, -1, false) < num) { ShowMessage("You need " + num + " " + GetBandageMaterialLabel(value) + " to make a bandage."); return; } inventory.RemoveItem(value, num, -1, false); state.Bleeding = 0f; bleedingTrailTimer = 0f; bleedDripTimer = 0f; activeBleedSources.Clear(); state.InfectionRisk = Mathf.Max(0f, state.InfectionRisk - Mathf.Max(0f, bandageInfectionRiskReduction.Value)); state.Infection = Mathf.Max(0f, state.Infection - Mathf.Max(0f, bandageInfectionReduction.Value)); if (fullHealOnBandage.Value) { state.Head = 0f; state.Torso = 0f; state.LeftArm = 0f; state.RightArm = 0f; state.LeftLeg = 0f; state.RightLeg = 0f; state.Infection = 0f; state.InfectionRisk = 0f; } else { ApplyBandageWoundRelief(Mathf.Max(0f, bandageWoundRelief.Value)); } state.ClampAll(); TryPlayBandageAudio(); treatmentCooldown = Mathf.Max(0f, treatmentCooldownSeconds.Value); SaveState(player); ShowMessage(fullHealOnBandage.Value ? "You apply a bandage. All wounds are healed." : "You apply a bandage. The bleeding has stopped."); } private static string GetBandageMaterialLabel(string sharedName) { if (string.Equals(sharedName, "$item_leatherscraps", StringComparison.Ordinal)) { return "Leather Scraps"; } return sharedName; } private void ApplyBandageWoundRelief(float relief) { float num = Mathf.Clamp(brokenBoneThreshold.Value, 1f, 100f); state.Head = Mathf.Max(0f, state.Head - relief); state.Torso = Mathf.Max(0f, state.Torso - relief); if (state.LeftArm < num) { state.LeftArm = Mathf.Max(0f, state.LeftArm - relief); } if (state.RightArm < num) { state.RightArm = Mathf.Max(0f, state.RightArm - relief); } if (state.LeftLeg < num) { state.LeftLeg = Mathf.Max(0f, state.LeftLeg - relief); } if (state.RightLeg < num) { state.RightLeg = Mathf.Max(0f, state.RightLeg - relief); } } private void EnsureStateLoaded(Player player) { if (!stateLoaded) { ZDO ownedPlayerZdo = GetOwnedPlayerZdo(player); if (ownedPlayerZdo != null) { state.Head = ownedPlayerZdo.GetFloat("YoureInjured_Head", 0f); state.Torso = ownedPlayerZdo.GetFloat("YoureInjured_Torso", 0f); state.LeftArm = ownedPlayerZdo.GetFloat("YoureInjured_LeftArm", 0f); state.RightArm = ownedPlayerZdo.GetFloat("YoureInjured_RightArm", 0f); state.LeftLeg = ownedPlayerZdo.GetFloat("YoureInjured_LeftLeg", 0f); state.RightLeg = ownedPlayerZdo.GetFloat("YoureInjured_RightLeg", 0f); state.Bleeding = ownedPlayerZdo.GetFloat("YoureInjured_Bleeding", 0f); state.Infection = ownedPlayerZdo.GetFloat("YoureInjured_Infection", 0f); state.InfectionRisk = ownedPlayerZdo.GetFloat("YoureInjured_InfectionRisk", 0f); state.ClampAll(); stateLoaded = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)("Loaded injury state: " + state.ToDiagnosticText())); } } } private void SaveState(Player player) { if (stateLoaded && !((Object)(object)player == (Object)null)) { ZDO ownedPlayerZdo = GetOwnedPlayerZdo(player); if (ownedPlayerZdo != null) { ownedPlayerZdo.Set("YoureInjured_Head", state.Head); ownedPlayerZdo.Set("YoureInjured_Torso", state.Torso); ownedPlayerZdo.Set("YoureInjured_LeftArm", state.LeftArm); ownedPlayerZdo.Set("YoureInjured_RightArm", state.RightArm); ownedPlayerZdo.Set("YoureInjured_LeftLeg", state.LeftLeg); ownedPlayerZdo.Set("YoureInjured_RightLeg", state.RightLeg); ownedPlayerZdo.Set("YoureInjured_Bleeding", state.Bleeding); ownedPlayerZdo.Set("YoureInjured_Infection", state.Infection); ownedPlayerZdo.Set("YoureInjured_InfectionRisk", state.InfectionRisk); } } } private static ZDO GetOwnedPlayerZdo(Player player) { ZNetView component = ((Component)player).GetComponent(); if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner()) { return null; } return component.GetZDO(); } private static bool IsWet(Player player) { SEMan sEMan = ((Character)player).GetSEMan(); if (sEMan != null) { return sEMan.HaveStatusEffect(SEMan.s_statusEffectWet); } return false; } private static void ApplyNonLethalHealthLoss(Player player, float healthLoss) { if (!((Object)(object)player == (Object)null) && !(healthLoss <= 0f) && !IsGodModeActive(player) && !(((Character)player).GetHealth() <= 1f)) { float num = Mathf.Max(0f, ((Character)player).GetHealth() - 1f); if (num > 0f) { ((Character)player).UseHealth(Mathf.Min(healthLoss, num)); } } } private static bool IsGodModeActive(Player player) { if ((Object)(object)player == (Object)null) { return false; } try { Type type = ((object)player).GetType(); MethodInfo method = type.GetMethod("InGodMode", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method != null && method.ReturnType == typeof(bool)) { object obj = method.Invoke(method.IsStatic ? null : player, null); if (obj is bool && (bool)obj) { return true; } } FieldInfo field = type.GetField("m_godMode", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { object value = field.GetValue(field.IsStatic ? null : player); if (value is bool && (bool)value) { return true; } } PropertyInfo property = type.GetProperty("GodMode", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(bool) && property.CanRead) { MethodInfo getMethod = property.GetGetMethod(nonPublic: true); object value2 = property.GetValue((getMethod != null && getMethod.IsStatic) ? null : player, null); if (value2 is bool && (bool)value2) { return true; } } } catch { } return false; } private void WriteDiagnostic() { ((BaseUnityPlugin)this).Logger.LogInfo((object)("You're Injured diagnostic: enabled=" + runtimeEnabled + ", loaded=" + stateLoaded + ", hookCalls=" + localDamageHookCalls + ", injuryEvents=" + injuryEventsRecorded + ", lastLoss=" + lastDetectedHealthLoss.ToString("0.0") + ", lastType=" + ((object)Unsafe.As(ref lastDetectedHitType)/*cast due to .constrained prefix*/).ToString() + ", threshold=" + minimumDamageForInjury.Value.ToString("0.0") + ", rinse=" + swimmingRinseTimer.ToString("0") + "/" + swimmingRinseRequiredSeconds.Value.ToString("0") + ", seaRinse=" + seaRinseTimer.ToString("0") + "/" + seaRinseRequiredSeconds.Value.ToString("0") + ", blood=[hitAttempts=" + hitBloodAttempts + ", trailAttempts=" + trailBloodAttempts + ", hitDrops=" + hitBloodDropletsSpawned + ", trailDrops=" + trailBloodDropletsSpawned + ", directTrailSplats=" + directTrailSplatsSpawned + ", splats=" + groundBloodSplatsSpawned + ", probesOk=" + groundProbeSuccesses + ", probesFailed=" + groundProbeFailures + ", fallbackLandings=" + dropletFallbackLandings + ", active=" + activeGroundBlood.Count + "], body=[woundMarks=" + activeWoundMarks.Count + "/" + maximumWoundMarks.Value + ", clothStains=" + activeClothStains.Count + "/" + maximumClothStains.Value + ", bleedSources=" + activeBleedSources.Count + "/" + 6 + "], " + state.ToDiagnosticText())); } private void ShowMessage(string text) { if ((Object)(object)MessageHud.instance != (Object)null) { MessageHud.instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false); } } private string BuildDamageMessage(float actualHealthLoss) { string mostSevereLimbName = state.GetMostSevereLimbName(Mathf.Clamp(brokenBoneThreshold.Value, 1f, 100f)); return "Injured: " + mostSevereLimbName + " (" + actualHealthLoss.ToString("0") + " damage)"; } private void OnGUI() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (runtimeEnabled && modEnabled.Value && showHud.Value && !IsHudHiddenByCtrlF3() && !((Object)(object)Player.m_localPlayer == (Object)null) && stateLoaded) { if (useCompactSurvivalHud.Value) { Rect compactInjuryRect = GetCompactInjuryRect(); DrawCompactInjuryHud(compactInjuryRect); } else { DrawLegacyInjuryHud(); } } } private void DrawCompactInjuryHud(Rect panelRect) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0387: Unknown result type (might be due to invalid IL or missing references) float compactInjuryContentScale = GetCompactInjuryContentScale(panelRect); EnsureHudStyles(); compactInjuryHeaderStyle.fontSize = Mathf.Max(10, Mathf.RoundToInt(12f * compactInjuryContentScale)); compactInjuryDetailStyle.fontSize = Mathf.Max(9, Mathf.RoundToInt(10f * compactInjuryContentScale)); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.84f); GUI.DrawTexture(panelRect, (Texture)(object)Texture2D.whiteTexture); GUI.color = new Color(0.78f, 0.72f, 0.53f, 0.68f); GUI.DrawTexture(new Rect(((Rect)(ref panelRect)).x, ((Rect)(ref panelRect)).y, ((Rect)(ref panelRect)).width, 1f * compactInjuryContentScale), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref panelRect)).x, ((Rect)(ref panelRect)).yMax - 1f * compactInjuryContentScale, ((Rect)(ref panelRect)).width, 1f * compactInjuryContentScale), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref panelRect)).x, ((Rect)(ref panelRect)).y, 1f * compactInjuryContentScale, ((Rect)(ref panelRect)).height), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref panelRect)).xMax - 1f * compactInjuryContentScale, ((Rect)(ref panelRect)).y, 1f * compactInjuryContentScale, ((Rect)(ref panelRect)).height), (Texture)(object)Texture2D.whiteTexture); GUI.color = GetInjuryColor(); GUI.Label(new Rect(((Rect)(ref panelRect)).x + 7f * compactInjuryContentScale, ((Rect)(ref panelRect)).y + 4f * compactInjuryContentScale, ((Rect)(ref panelRect)).width - 14f * compactInjuryContentScale, 18f * compactInjuryContentScale), "Injuries: " + state.GetOverallLabel(), compactInjuryHeaderStyle); GUI.color = Color.white; GUI.Label(new Rect(((Rect)(ref panelRect)).x + 7f * compactInjuryContentScale, ((Rect)(ref panelRect)).y + 23f * compactInjuryContentScale, ((Rect)(ref panelRect)).width - 14f * compactInjuryContentScale, 16f * compactInjuryContentScale), "Bleeding: " + state.Bleeding.ToString("0") + "% Infection: " + state.Infection.ToString("0") + "%", compactInjuryDetailStyle); GUI.Label(new Rect(((Rect)(ref panelRect)).x + 7f * compactInjuryContentScale, ((Rect)(ref panelRect)).y + 42f * compactInjuryContentScale, ((Rect)(ref panelRect)).width - 14f * compactInjuryContentScale, 16f * compactInjuryContentScale), "Head: " + state.Head.ToString("0") + " Torso: " + state.Torso.ToString("0"), compactInjuryDetailStyle); string text = "Arms: " + state.GetAverageArmInjury().ToString("0") + " Legs: " + state.GetAverageLegInjury().ToString("0"); if (swimmingRinseTimer > 0.01f) { text = text + " Rinse: " + swimmingRinseTimer.ToString("0") + "s"; } GUI.Label(new Rect(((Rect)(ref panelRect)).x + 7f * compactInjuryContentScale, ((Rect)(ref panelRect)).y + 61f * compactInjuryContentScale, ((Rect)(ref panelRect)).width - 14f * compactInjuryContentScale, 18f * compactInjuryContentScale), text, compactInjuryDetailStyle); GUI.color = color; } private void DrawLegacyInjuryHud() { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) float num = 420f; float num2; float num3; if (stackBelowTemperatureHud.Value) { ResolveTemperatureHudRect(out var x, out var y, out var width, out var height); num = width; num2 = x; num3 = y + height + Mathf.Max(4f, temperatureHudGapPixels.Value); } else { num2 = (useSafeHudLayout.Value ? 392f : hudPanelLeft.Value); num3 = (float)Screen.height - Mathf.Max(0f, useSafeHudLayout.Value ? 12f : hudPanelBottomOffset.Value) - 150f; } num2 = Mathf.Clamp(num2, 12f, (float)Screen.width - num - 12f); num3 = Mathf.Clamp(num3, 12f, (float)Screen.height - 150f - 12f); EnsureHudStyles(); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.84f); GUI.DrawTexture(new Rect(num2, num3, num, 150f), (Texture)(object)Texture2D.whiteTexture); GUI.color = new Color(0.78f, 0.72f, 0.53f, 0.62f); GUI.DrawTexture(new Rect(num2, num3, num, 1f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(num2, num3 + 150f - 1f, num, 1f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(num2, num3, 1f, 150f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(num2 + num - 1f, num3, 1f, 150f), (Texture)(object)Texture2D.whiteTexture); GUI.color = GetInjuryColor(); GUI.Label(new Rect(num2 + 14f, num3 + 9f, num - 28f, 27f), "Injuries: " + state.GetOverallLabel(), injuryHeaderStyle); GUI.color = Color.white; GUI.Label(new Rect(num2 + 14f, num3 + 42f, num - 28f, 21f), "Bleeding: " + state.Bleeding.ToString("0") + "% Infection: " + state.Infection.ToString("0") + "%", injuryDetailStyle); GUI.Label(new Rect(num2 + 14f, num3 + 67f, num - 28f, 21f), BuildRinseStatusLine(), injuryDetailStyle); GUI.Label(new Rect(num2 + 14f, num3 + 92f, num - 28f, 21f), "Head: " + state.Head.ToString("0") + " Torso: " + state.Torso.ToString("0"), injuryDetailStyle); GUI.Label(new Rect(num2 + 14f, num3 + 117f, num - 28f, 21f), "Arms: " + state.GetAverageArmInjury().ToString("0") + " Legs: " + state.GetAverageLegInjury().ToString("0"), injuryDetailStyle); GUI.color = color; } private static float GetCompactHudScale() { return Mathf.Max(0.7f, Mathf.Min((float)Screen.width / 2048f, (float)Screen.height / 1152f)); } private Rect GetCompactInjuryRect() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) float compactHudScale = GetCompactHudScale(); float num = 220f * compactHudScale; float num2 = 88f * compactHudScale; float num3 = 248f * compactHudScale; float num4 = (float)Screen.height - 110f * compactHudScale; return new Rect(num3, num4, num, num2); } private static float GetCompactInjuryContentScale(Rect panelRect) { return GetCompactHudScale(); } private bool IsHudHiddenByCtrlF3() { if (hideHudWithCtrlF3 != null && hideHudWithCtrlF3.Value) { return hudHiddenByCtrlF3; } return false; } private bool TryToggleHudWithCtrlF3() { if (!IsCtrlF3Pressed()) { return false; } if (hideHudWithCtrlF3 == null || !hideHudWithCtrlF3.Value) { return true; } hudHiddenByCtrlF3 = !hudHiddenByCtrlF3; ((BaseUnityPlugin)this).Logger.LogInfo((object)("You're Injured: Ctrl+F3 HUD " + (hudHiddenByCtrlF3 ? "hidden." : "restored."))); return true; } private static bool IsCtrlF3Pressed() { if (Input.GetKeyDown((KeyCode)284)) { if (!Input.GetKey((KeyCode)306)) { return Input.GetKey((KeyCode)305); } return true; } return false; } private void ResolveTemperatureHudRect(out float x, out float y, out float width, out float height) { x = temperatureHudFallbackLeft.Value; width = 420f; height = 128f; float value = temperatureHudFallbackBottomOffset.Value; try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { if (!(type == null)) { break; } type = assemblies[i].GetType("BepInEx.Bootstrap.Chainloader", throwOnError: false); } PropertyInfo propertyInfo = ((type != null) ? type.GetProperty("PluginInfos", BindingFlags.Static | BindingFlags.Public) : null); object obj = ((((propertyInfo != null) ? propertyInfo.GetValue(null, null) : null) is IDictionary dictionary && dictionary.Contains("com.marccunningham.yourecold")) ? dictionary["com.marccunningham.yourecold"] : null); if (obj != null) { PropertyInfo property = obj.GetType().GetProperty("Instance", BindingFlags.Instance | BindingFlags.Public); object obj2 = ((property != null) ? property.GetValue(obj, null) : null); if (obj2 != null) { FieldInfo field = obj2.GetType().GetField("hudPanelLeft", BindingFlags.Instance | BindingFlags.NonPublic); FieldInfo field2 = obj2.GetType().GetField("hudPanelBottomOffset", BindingFlags.Instance | BindingFlags.NonPublic); ConfigEntry val = ((field != null) ? (field.GetValue(obj2) as ConfigEntry) : null); ConfigEntry val2 = ((field2 != null) ? (field2.GetValue(obj2) as ConfigEntry) : null); if (val != null) { x = val.Value; } if (val2 != null) { float num = height + Mathf.Max(4f, temperatureHudGapPixels.Value) + 150f + 12f; if (stackBelowTemperatureHud.Value && autoLiftTemperatureHudForInjuryPanel.Value && val2.Value < num) { val2.Value = num; BaseUnityPlugin val3 = (BaseUnityPlugin)((obj2 is BaseUnityPlugin) ? obj2 : null); if ((Object)(object)val3 != (Object)null) { val3.Config.Save(); } } value = val2.Value; } } } } catch { } x = Mathf.Clamp(x, 12f, (float)Screen.width - width - 12f); y = Mathf.Clamp((float)Screen.height - value, 12f, (float)Screen.height - height - 12f); } private string BuildRinseStatusLine() { string text = "Risk: " + state.InfectionRisk.ToString("0") + "%"; if (!enableSwimmingRinse.Value || state.InfectionRisk <= 0.01f || state.Infection > 0.01f) { return text; } if (state.Bleeding > 0.01f) { return text + " Rinse blocked: bleeding"; } if (swimmingRinseTimer > 0.01f) { return text + " Rinse: " + swimmingRinseTimer.ToString("0") + "/" + swimmingRinseRequiredSeconds.Value.ToString("0") + "s"; } return text + " Swim 60s to rinse"; } private void EnsureHudStyles() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown if (injuryHeaderStyle == null) { injuryHeaderStyle = new GUIStyle(GUI.skin.label); injuryHeaderStyle.fontSize = 20; injuryHeaderStyle.fontStyle = (FontStyle)1; } if (injuryDetailStyle == null) { injuryDetailStyle = new GUIStyle(GUI.skin.label); injuryDetailStyle.fontSize = 16; } if (compactInjuryHeaderStyle == null) { compactInjuryHeaderStyle = new GUIStyle(GUI.skin.label); compactInjuryHeaderStyle.fontStyle = (FontStyle)1; compactInjuryHeaderStyle.wordWrap = false; compactInjuryHeaderStyle.clipping = (TextClipping)1; compactInjuryHeaderStyle.alignment = (TextAnchor)0; } if (compactInjuryDetailStyle == null) { compactInjuryDetailStyle = new GUIStyle(GUI.skin.label); compactInjuryDetailStyle.wordWrap = false; compactInjuryDetailStyle.clipping = (TextClipping)1; compactInjuryDetailStyle.alignment = (TextAnchor)0; compactInjuryDetailStyle.padding = new RectOffset(0, 0, 0, 0); } } private Color GetInjuryColor() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) float overallSeverity = state.GetOverallSeverity(); if (state.Bleeding > 0.01f || state.Infection > 0.01f) { return new Color(1f, 0.35f, 0.2f, 1f); } if (overallSeverity >= Mathf.Clamp(brokenBoneThreshold.Value, 1f, 100f)) { return new Color(0.92f, 0.15f, 0.15f, 1f); } if (overallSeverity >= 35f) { return new Color(1f, 0.7f, 0.18f, 1f); } return new Color(0.35f, 0.85f, 0.42f, 1f); } } internal enum Limb { Head, Torso, LeftArm, RightArm, LeftLeg, RightLeg } internal struct BleedSource { public readonly Transform Bone; public readonly Vector3 LocalOffset; public BleedSource(Transform bone, Vector3 localOffset) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) Bone = bone; LocalOffset = localOffset; } public bool TryGetWorldPosition(out Vector3 worldPosition) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Bone == (Object)null) { worldPosition = Vector3.zero; return false; } worldPosition = Bone.TransformPoint(LocalOffset); return true; } } internal struct DamageSnapshot { public bool IsLocalPlayer; public float HealthBefore; } internal sealed class InjuryState { public float Head; public float Torso; public float LeftArm; public float RightArm; public float LeftLeg; public float RightLeg; public float Bleeding; public float Infection; public float InfectionRisk; public void Add(Limb limb, float amount) { switch (limb) { case Limb.Head: Head += amount; break; case Limb.Torso: Torso += amount; break; case Limb.LeftArm: LeftArm += amount; break; case Limb.RightArm: RightArm += amount; break; case Limb.LeftLeg: LeftLeg += amount; break; case Limb.RightLeg: RightLeg += amount; break; } } public void ReduceAllInjuries(float amount) { Head = Mathf.Max(0f, Head - amount); Torso = Mathf.Max(0f, Torso - amount); LeftArm = Mathf.Max(0f, LeftArm - amount); RightArm = Mathf.Max(0f, RightArm - amount); LeftLeg = Mathf.Max(0f, LeftLeg - amount); RightLeg = Mathf.Max(0f, RightLeg - amount); } public bool IsBroken(Limb limb, float threshold) { return limb switch { Limb.LeftArm => LeftArm >= threshold, Limb.RightArm => RightArm >= threshold, Limb.LeftLeg => LeftLeg >= threshold, Limb.RightLeg => RightLeg >= threshold, _ => false, }; } public float GetAverageArmInjury() { return (LeftArm + RightArm) * 0.5f; } public float GetAverageLegInjury() { return (LeftLeg + RightLeg) * 0.5f; } public float GetAverageLimbInjury() { return (Head + Torso + LeftArm + RightArm + LeftLeg + RightLeg) / 6f; } public float GetOverallSeverity() { return Mathf.Max(new float[3] { GetMaximumLimbInjury(), Bleeding, Infection }); } public float GetMaximumLimbInjury() { return Mathf.Max(Head, Mathf.Max(Torso, Mathf.Max(LeftArm, Mathf.Max(RightArm, Mathf.Max(LeftLeg, RightLeg))))); } public bool HasAnyCondition() { if (!(Head > 0.01f) && !(Torso > 0.01f) && !(LeftArm > 0.01f) && !(RightArm > 0.01f) && !(LeftLeg > 0.01f) && !(RightLeg > 0.01f) && !(Bleeding > 0.01f) && !(Infection > 0.01f)) { return InfectionRisk > 0.01f; } return true; } public string GetOverallLabel() { float overallSeverity = GetOverallSeverity(); if (overallSeverity < 1f) { return "Fine"; } if (overallSeverity < 25f) { return "Bruised"; } if (overallSeverity < 60f) { return "Wounded"; } return "Severely Injured"; } public string GetMostSevereLimbName(float brokenThreshold) { Limb current = Limb.Head; float currentValue = Head; Consider(Limb.Torso, Torso, ref current, ref currentValue); Consider(Limb.LeftArm, LeftArm, ref current, ref currentValue); Consider(Limb.RightArm, RightArm, ref current, ref currentValue); Consider(Limb.LeftLeg, LeftLeg, ref current, ref currentValue); Consider(Limb.RightLeg, RightLeg, ref current, ref currentValue); string text = LimbToLabel(current); if (IsBroken(current, brokenThreshold)) { text += " broken"; } return text; } public void ClampAll() { Head = Mathf.Clamp(Head, 0f, 100f); Torso = Mathf.Clamp(Torso, 0f, 100f); LeftArm = Mathf.Clamp(LeftArm, 0f, 100f); RightArm = Mathf.Clamp(RightArm, 0f, 100f); LeftLeg = Mathf.Clamp(LeftLeg, 0f, 100f); RightLeg = Mathf.Clamp(RightLeg, 0f, 100f); Bleeding = Mathf.Clamp(Bleeding, 0f, 100f); Infection = Mathf.Clamp(Infection, 0f, 100f); InfectionRisk = Mathf.Clamp(InfectionRisk, 0f, 100f); } public string ToDiagnosticText() { return "head=" + Head.ToString("0.0") + ", torso=" + Torso.ToString("0.0") + ", leftArm=" + LeftArm.ToString("0.0") + ", rightArm=" + RightArm.ToString("0.0") + ", leftLeg=" + LeftLeg.ToString("0.0") + ", rightLeg=" + RightLeg.ToString("0.0") + ", bleeding=" + Bleeding.ToString("0.0") + ", infection=" + Infection.ToString("0.0") + ", infectionRisk=" + InfectionRisk.ToString("0.0"); } private static void Consider(Limb candidate, float value, ref Limb current, ref float currentValue) { if (value > currentValue) { current = candidate; currentValue = value; } } private static string LimbToLabel(Limb limb) { return limb switch { Limb.Head => "head", Limb.Torso => "torso", Limb.LeftArm => "left arm", Limb.RightArm => "right arm", Limb.LeftLeg => "left leg", Limb.RightLeg => "right leg", _ => "body", }; } } internal static class InjuryAssetLoader { private static MethodInfo textureLoadImageMethod; private static MethodInfo imageConversionLoadImageMethod; private static bool searchedImageLoadMethods; internal static bool TryLoadAlphaMaskPng(string path, out Texture2D texture, out string error) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) texture = null; error = null; if (string.IsNullOrEmpty(path) || !File.Exists(path)) { error = "File not found."; return false; } Texture2D val = null; try { byte[] array = File.ReadAllBytes(path); if (array == null || array.Length == 0) { error = "File was empty."; return false; } ResolveImageLoadMethods(); val = new Texture2D(2, 2, (TextureFormat)4, false); bool flag = false; if (imageConversionLoadImageMethod != null) { object obj = imageConversionLoadImageMethod.Invoke(null, new object[3] { val, array, false }); flag = obj is bool && (bool)obj; } if (!flag && textureLoadImageMethod != null) { object obj2 = textureLoadImageMethod.Invoke(val, new object[2] { array, false }); flag = obj2 is bool && (bool)obj2; } if (!flag) { DestroyUnityObject((Object)(object)val); error = ((imageConversionLoadImageMethod == null && textureLoadImageMethod == null) ? "No Unity PNG decoder was found." : "Unity rejected this PNG."); return false; } Color32[] pixels = val.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { pixels[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, pixels[i].a); } val.SetPixels32(pixels); ((Texture)val).wrapMode = (TextureWrapMode)1; ((Texture)val).filterMode = (FilterMode)1; val.Apply(false, true); texture = val; return true; } catch (TargetInvocationException ex) { DestroyUnityObject((Object)(object)val); error = ((ex.InnerException != null) ? ex.InnerException.Message : ex.Message); return false; } catch (Exception ex2) { DestroyUnityObject((Object)(object)val); error = ex2.Message; return false; } } private static void ResolveImageLoadMethods() { if (searchedImageLoadMethods) { return; } searchedImageLoadMethods = true; try { textureLoadImageMethod = typeof(Texture2D).GetMethod("LoadImage", BindingFlags.Instance | BindingFlags.Public, null, new Type[2] { typeof(byte[]), typeof(bool) }, null); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { if (!(imageConversionLoadImageMethod == null)) { break; } Type type = assemblies[i].GetType("UnityEngine.ImageConversion", throwOnError: false); if (!(type == null)) { imageConversionLoadImageMethod = type.GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(Texture2D), typeof(byte[]), typeof(bool) }, null); } } } catch { } } private static void DestroyUnityObject(Object value) { if (value != (Object)null) { Object.Destroy(value); } } } internal sealed class BloodDroplet : MonoBehaviour { private YoureInjuredPlugin plugin; private Transform owner; private Vector3 velocity; private float remainingLifetime; private float gravity; private bool trailDrop; private bool createSplatWhenLanding; public void Initialize(YoureInjuredPlugin sourcePlugin, Transform sourceOwner, Vector3 startVelocity, float lifetime, float gravityStrength, bool isTrailDrop, bool createSplat) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) plugin = sourcePlugin; owner = sourceOwner; velocity = startVelocity; remainingLifetime = lifetime; gravity = gravityStrength; trailDrop = isTrailDrop; createSplatWhenLanding = createSplat; } private void Update() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) float deltaTime = Time.deltaTime; remainingLifetime -= deltaTime; if ((Object)(object)plugin == (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } velocity += Physics.gravity * gravity * deltaTime; Vector3 val = velocity * deltaTime; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude > 1E-05f) { RaycastHit[] array = Physics.RaycastAll(((Component)this).transform.position, val / magnitude, magnitude + 0.025f, -1, (QueryTriggerInteraction)1); RaycastHit val2 = default(RaycastHit); bool flag = false; float num = float.MaxValue; for (int i = 0; i < array.Length; i++) { Collider collider = ((RaycastHit)(ref array[i])).collider; if (!((Object)(object)collider == (Object)null) && (!((Object)(object)owner != (Object)null) || !((Component)collider).transform.IsChildOf(owner)) && !(((RaycastHit)(ref array[i])).normal.y < 0.18f) && !(((RaycastHit)(ref array[i])).distance >= num)) { val2 = array[i]; num = ((RaycastHit)(ref array[i])).distance; flag = true; } } if (flag) { if (createSplatWhenLanding) { plugin.LandBloodDroplet(((RaycastHit)(ref val2)).point, ((RaycastHit)(ref val2)).normal, trailDrop); } Object.Destroy((Object)(object)((Component)this).gameObject); return; } } Transform transform = ((Component)this).transform; transform.position += val; if (remainingLifetime <= 0f) { if (createSplatWhenLanding) { plugin.TryLandBloodAtFallback(owner, ((Component)this).transform.position, trailDrop); } Object.Destroy((Object)(object)((Component)this).gameObject); } } } internal sealed class GroundBloodSplat : MonoBehaviour { private YoureInjuredPlugin plugin; private float remainingLifetime; private float fullLifetime; private float spreadSeconds; private float ageSeconds; private Vector3 originalScale; private List ownedMeshes; public void Initialize(YoureInjuredPlugin sourcePlugin, float lifetime, float settleSeconds, List meshes) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) plugin = sourcePlugin; remainingLifetime = lifetime; fullLifetime = lifetime; spreadSeconds = Mathf.Max(0.05f, settleSeconds); ageSeconds = 0f; originalScale = ((Component)this).transform.localScale; ((Component)this).transform.localScale = originalScale * 0.32f; ownedMeshes = meshes; } private void Update() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) float deltaTime = Time.deltaTime; remainingLifetime -= deltaTime; ageSeconds += deltaTime; if (remainingLifetime <= 0f) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } float num = Mathf.Clamp01(ageSeconds / spreadSeconds); float num2 = Mathf.Lerp(0.32f, 1f, num * num * (3f - 2f * num)); float num3 = Mathf.Max(12f, fullLifetime * 0.1f); float num4 = 1f; if (remainingLifetime < num3) { float num5 = Mathf.Clamp01(remainingLifetime / num3); num4 = Mathf.Lerp(0.72f, 1f, num5); } ((Component)this).transform.localScale = originalScale * num2 * num4; } private void OnDestroy() { if (ownedMeshes != null) { for (int i = 0; i < ownedMeshes.Count; i++) { if ((Object)(object)ownedMeshes[i] != (Object)null) { Object.Destroy((Object)(object)ownedMeshes[i]); } } ownedMeshes.Clear(); } if ((Object)(object)plugin != (Object)null) { plugin.UnregisterGroundBlood(this); } } } internal sealed class PlayerBodyDecal : MonoBehaviour { private YoureInjuredPlugin plugin; private bool isClothStain; private float fadeInRemaining; private float fadeInDuration; private Vector3 targetScale; public void Initialize(YoureInjuredPlugin sourcePlugin, bool stain, float fadeSeconds) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) plugin = sourcePlugin; isClothStain = stain; fadeInDuration = Mathf.Max(0.05f, fadeSeconds); fadeInRemaining = fadeInDuration; targetScale = ((Component)this).transform.localScale; ((Component)this).transform.localScale = Vector3.zero; } private void Update() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)this).transform.parent == (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); } else if (fadeInRemaining > 0f) { fadeInRemaining -= Time.deltaTime; float num = 1f - Mathf.Clamp01(fadeInRemaining / fadeInDuration); ((Component)this).transform.localScale = targetScale * (num * num * (3f - 2f * num)); } } private void OnDestroy() { if ((Object)(object)plugin != (Object)null) { plugin.UnregisterPlayerBodyDecal(this, isClothStain); } } } internal sealed class DramaticHitSpray : MonoBehaviour { private float remainingLifetime; private float fullLifetime; public void Initialize(float lifetime) { fullLifetime = Mathf.Max(0.05f, lifetime); remainingLifetime = fullLifetime; } private void Update() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) remainingLifetime -= Time.deltaTime; if (remainingLifetime <= 0f) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } Renderer component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.material != (Object)null) { float num = Mathf.Clamp01(remainingLifetime / fullLifetime); Color color = component.material.color; color.a = num * 0.85f; component.material.color = color; } } } [HarmonyPatch(typeof(Character), "ApplyDamage")] internal static class CharacterApplyDamagePatch { [HarmonyPrefix] private static void Prefix(Character __instance, out DamageSnapshot __state) { __state = new DamageSnapshot { IsLocalPlayer = ((Object)(object)YoureInjuredPlugin.Instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer), HealthBefore = (((Object)(object)__instance != (Object)null) ? __instance.GetHealth() : 0f) }; } [HarmonyPostfix] private static void Postfix(Character __instance, HitData __0, DamageSnapshot __state) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown YoureInjuredPlugin instance = YoureInjuredPlugin.Instance; if (!((Object)(object)instance == (Object)null) && __state.IsLocalPlayer && !((Object)(object)__instance == (Object)null)) { instance.RecordAppliedDamage((Player)__instance, __0, __state.HealthBefore); } } } [HarmonyPatch(typeof(Character), "GetJogSpeedFactor")] internal static class CharacterGetJogSpeedFactorPatch { [HarmonyPostfix] private static void Postfix(Character __instance, ref float __result) { YoureInjuredPlugin instance = YoureInjuredPlugin.Instance; if ((Object)(object)instance != (Object)null && instance.IsActiveFor((Player)(object)((__instance is Player) ? __instance : null))) { __result *= instance.GetRunSpeedMultiplier(); } } } [HarmonyPatch(typeof(Character), "GetRunSpeedFactor")] internal static class CharacterGetRunSpeedFactorPatch { [HarmonyPostfix] private static void Postfix(Character __instance, ref float __result) { YoureInjuredPlugin instance = YoureInjuredPlugin.Instance; if ((Object)(object)instance != (Object)null && instance.IsActiveFor((Player)(object)((__instance is Player) ? __instance : null))) { __result *= instance.GetRunSpeedMultiplier(); } } } [HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")] internal static class SEManModifyStaminaRegenPatch { [HarmonyPostfix] private static void Postfix(Character ___m_character, ref float __0) { YoureInjuredPlugin instance = YoureInjuredPlugin.Instance; if ((Object)(object)instance != (Object)null && instance.IsActiveFor((Player)(object)((___m_character is Player) ? ___m_character : null))) { __0 *= instance.GetStaminaRegenMultiplier(); } } } [HarmonyPatch(typeof(SEMan), "ModifyRunStaminaDrain")] internal static class SEManModifyRunStaminaDrainPatch { [HarmonyPostfix] private static void Postfix(Character ___m_character, ref float __1) { YoureInjuredPlugin instance = YoureInjuredPlugin.Instance; if ((Object)(object)instance != (Object)null && instance.IsActiveFor((Player)(object)((___m_character is Player) ? ___m_character : null))) { __1 *= instance.GetRunStaminaMultiplier(); } } } [HarmonyPatch(typeof(SEMan), "ModifyJumpStaminaUsage")] internal static class SEManModifyJumpStaminaUsagePatch { [HarmonyPostfix] private static void Postfix(Character ___m_character, ref float __1) { YoureInjuredPlugin instance = YoureInjuredPlugin.Instance; if ((Object)(object)instance != (Object)null && instance.IsActiveFor((Player)(object)((___m_character is Player) ? ___m_character : null))) { __1 *= instance.GetJumpStaminaMultiplier(); } } } [HarmonyPatch(typeof(SEMan), "ModifyAttackStaminaUsage")] internal static class SEManModifyAttackStaminaUsagePatch { [HarmonyPostfix] private static void Postfix(Character ___m_character, ref float __1) { YoureInjuredPlugin instance = YoureInjuredPlugin.Instance; if ((Object)(object)instance != (Object)null && instance.IsActiveFor((Player)(object)((___m_character is Player) ? ___m_character : null))) { __1 *= instance.GetAttackStaminaMultiplier(); } } }