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(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.0.0.0")] namespace YoureInjured; [BepInPlugin("com.marccunningham.youreinjured", "You're Injured", "1.5.0")] [BepInProcess("valheim.exe")] public sealed class YoureInjuredPlugin : BaseUnityPlugin { private enum HudResizeHandle { None, TopLeft, TopRight, BottomLeft, BottomRight } 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.5.0"; 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 CompactHudReferenceWidth = 2048f; private const float CompactHudReferenceHeight = 1152f; private const float CompactInjuryReferenceLeft = 248f; private const float CompactInjuryReferenceBottom = 30f; private const float CompactInjuryReferenceWidth = 220f; private const float CompactInjuryReferenceHeight = 80f; 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 hudLayoutEditorKey; private ConfigEntry compactHudXNormalized; private ConfigEntry compactHudYNormalized; private ConfigEntry compactHudWidthNormalized; private ConfigEntry compactHudHeightNormalized; 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 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 cameraSafeHitSprites; private ConfigEntry hitImpactSpriteLifetime; private ConfigEntry hitImpactSpriteMaximumSize; 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 Harmony harmony; private readonly InjuryState state = new InjuryState(); private GUIStyle injuryHeaderStyle; private GUIStyle injuryDetailStyle; private GUIStyle compactInjuryHeaderStyle; private GUIStyle compactInjuryDetailStyle; private bool hudLayoutEditorActive; private bool hudLayoutDragging; private HudResizeHandle hudResizeHandle; private Vector2 hudEditStartMouse; private Rect hudEditStartRect; private CursorLockMode hudPreviousCursorLockMode; private bool hudPreviousCursorVisible; private bool hudCursorStateCaptured; 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 void Awake() { //IL_0e99: Unknown result type (might be due to invalid IL or missing references) //IL_0ea3: 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", "Choose Easy, Normal, Hard, or Extreme. Change this setting, then restart Valheim to apply that mod's matching survival balance."); 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."); hudLayoutEditorKey = ((BaseUnityPlugin)this).Config.Bind("HUD Layout Editor", "ToggleInjuriesLayoutEditorKey", (KeyCode)111, "Press O to enter or leave Injuries HUD layout mode. In layout mode, drag the panel and drag a gold corner handle to resize it."); compactHudXNormalized = ((BaseUnityPlugin)this).Config.Bind("HUD Layout", "CompactInjuriesXNormalized", 0.12109375f, "Saved left position of the compact Injuries panel as a fraction of screen width."); compactHudYNormalized = ((BaseUnityPlugin)this).Config.Bind("HUD Layout", "CompactInjuriesYNormalized", 0.9045139f, "Saved top position of the compact Injuries panel as a fraction of screen height."); compactHudWidthNormalized = ((BaseUnityPlugin)this).Config.Bind("HUD Layout", "CompactInjuriesWidthNormalized", 0.107421875f, "Saved width of the compact Injuries panel as a fraction of screen width."); compactHudHeightNormalized = ((BaseUnityPlugin)this).Config.Bind("HUD Layout", "CompactInjuriesHeightNormalized", 5f / 72f, "Saved height of the compact Injuries panel as a fraction of screen height."); 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", 8f, "Actual health loss required before slash or pierce damage can cause bleeding."); bleedingPerHealthLost = ((BaseUnityPlugin)this).Config.Bind("Damage", "BleedingPointsPerHealthLost", 1.5f, "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", 60f, "Bleeding removed by one treatment."); 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. Bandages do not immediately fix broken bones."); 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", true, "Creates local visual blood droplets and glossy two-minute ground splats for the player when wounded. It does not alter damage, terrain, saves or networking."); 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", 2f, "Health loss required from slash or pierce damage before a visible hit blood burst is created."); trailMinimumBleeding = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "MinimumBleedingForTrail", 5f, "Bleeding severity required before movement leaves a visible trail."); walkingTrailIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "WalkingTrailIntervalSeconds", 0.82f, "Time between trail drops while walking. The default leaves a clearly readable but safe blood trail."); runningTrailIntervalSeconds = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "RunningTrailIntervalSeconds", 0.44f, "Time between trail drops while running."); groundBloodLifetimeSeconds = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "GroundBloodLifetimeSeconds", 120f, "How long landed blood remains visible on the ground. Default is two minutes and the final fade only begins in the last twelve seconds."); maximumGroundBloodSplats = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "MaximumGroundBloodSplats", 240, "Safety cap for active ground blood visuals. The oldest splat is removed when this limit is reached."); maximumHitBloodDroplets = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "MaximumHitBloodDroplets", 14, "Maximum droplets produced by one strong slash, axe or arrow hit."); bloodDropletGravity = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "DropletGravity", 14f, "Downward acceleration for visual blood droplets. Slightly above real gravity keeps the fall readable in-game."); bloodSplatMinimumSize = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "GroundSplatMinimumSize", 0.17f, "Smallest ground blood splat diameter in metres."); bloodSplatMaximumSize = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "GroundSplatMaximumSize", 0.52f, "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, "Optional world-space hit burst using supplied blood-spray frames. Disabled by default because the player-hit burst is not needed and can read like a red screen flash."); cameraSafeHitSprites = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "CameraSafeHitSprites", true, "Skips a hit-sprite if the wound is too close to the gameplay camera, preventing a red full-screen blink."); hitImpactSpriteLifetime = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "HitImpactSpriteLifetimeSeconds", 0.14f, "How long the small sprite-based blood burst remains visible."); hitImpactSpriteMaximumSize = ((BaseUnityPlugin)this).Config.Bind("Visual Bleeding", "HitImpactSpriteMaximumSize", 0.38f, "Largest world-space size of a hit blood-spray sprite."); 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 wrap.mp3", "MP3 filename expected in assets/audio beside the You're Injured DLL."); 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; } ((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.5.0 loaded. G uses Leather Scraps as bandage material, F2 logs diagnostics, and F3 toggles injury effects for this session. V1.3.5 adds a heavier directional wound spray, larger persistent blood pools, and strict weapon-recognized hit audio."); } 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() { RestoreHudCursor(); if (harmony != null) { harmony.UnpatchSelf(); } DestroyBloodVisuals(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_00e9: Unknown result type (might be due to invalid IL or missing references) if (TryToggleHudWithCtrlF3()) { return; } if (hudLayoutEditorActive && (!showHud.Value || IsHudHiddenByCtrlF3())) { CloseHudLayoutEditorForHiddenHud(); } if (Input.GetKeyDown(hudLayoutEditorKey.Value) && showHud.Value && !IsHudHiddenByCtrlF3()) { ToggleHudLayoutEditor(); } 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); 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_00d5: 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_0101: 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); 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); } else { state.Add(ResolveHitLimb(player, hit), num2); } float bleedingAdded = ApplyBleedingFromHit(hit, num); state.ClampAll(); TrySpawnHitBlood(player, hit, num, bleedingAdded); 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; 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0134: 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_0136: 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_015d: 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_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017d: 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 < Mathf.Max(0f, trailMinimumBleeding.Value)) { 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 = ((Character)player).GetCenterPoint() - Vector3.up * 0.18f; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(Random.Range(-0.12f, 0.12f), 0f, Random.Range(-0.12f, 0.12f)); bool flag = TryPlaceBloodOnGround(player, val + val2, trailDrop: true); if (flag) { directTrailSplatsSpawned++; } SpawnBloodDroplet(((Component)player).transform, val + val2, val2 * 1.25f + Vector3.up * 0.35f, 0.04f, 0.72f, trailDrop: false, !flag); trailBloodDropletsSpawned++; } } private void UpdateBleedingDrips(Player player, float deltaSeconds) { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_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_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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0172: 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_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0182: 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_019b: 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_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0148: 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.72f, 0.4f, num); bleedDripTimer += deltaSeconds; if (bleedDripTimer < num2) { return; } bleedDripTimer = 0f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Random.Range(-0.13f, 0.13f), 0f, Random.Range(-0.13f, 0.13f)); Vector3 val2 = ((Character)player).GetCenterPoint() - Vector3.up * Random.Range(0.16f, 0.42f) + val; Vector3 velocity = ((Character)player).GetVelocity(); velocity.y = 0f; bool flag = TryPlaceBloodOnGround(player, val2, trailDrop: true); if (flag) { directTrailSplatsSpawned++; } if (num >= 0.45f) { Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(Random.Range(-0.2f, 0.2f), 0f, Random.Range(-0.2f, 0.2f)); if (TryPlaceBloodOnGround(player, val2 + val3, trailDrop: true)) { directTrailSplatsSpawned++; } } SpawnBloodDroplet(((Component)player).transform, val2, velocity * 0.16f + val * 0.7f + Vector3.up * Random.Range(0.08f, 0.26f), Mathf.Lerp(0.045f, 0.07f, num), 1.5f, trailDrop: true, !flag); trailBloodDropletsSpawned++; } private void TrySpawnHitBlood(Player player, HitData hit, float actualHealthLoss, float bleedingAdded) { //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_012d: 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_013e: 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_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: 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_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: 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_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: 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_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: 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) / 12f); bool flag = actualHealthLoss >= 6f || bleedingAdded > 0.01f; int num2 = Mathf.Clamp(maximumHitBloodDroplets.Value, 4, 22); int num3 = 5 + Mathf.RoundToInt(Mathf.Lerp(2f, (float)num2 - 5f, num)); if (bleedingAdded > 0.01f) { num3 += 2; } if (flag) { num3 += 2; } num3 = Mathf.Clamp(num3, 5, num2); TryPlaceBloodOnGround(player, val + val2 * Random.Range(0.25f, 0.48f), trailDrop: false); if (flag) { Vector3 val3 = Vector3.Cross(Vector3.up, val2); Vector3 normalized = ((Vector3)(ref val3)).normalized; TryPlaceBloodOnGround(player, val + val2 * Random.Range(0.42f, 0.72f) + normalized * Random.Range(-0.22f, 0.22f), trailDrop: false); } SpawnHitImpactSprite(val, val2, num); for (int i = 0; i < num3; i++) { float num4 = (flag ? 0.72f : 0.52f); Vector3 val4 = val2 + new Vector3(Random.Range(0f - num4, num4), Random.Range(-0.05f, 0.32f), 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(2.7f, 5.1f) : Random.Range(2f, 4f)); Vector3 initialVelocity = val4 * num5 + Vector3.up * Random.Range(1.7f, flag ? 3.85f : 3.1f); float size = (flag ? Random.Range(0.04f, 0.082f) : Random.Range(0.034f, 0.066f)); SpawnBloodDroplet(((Component)player).transform, val, initialVelocity, size, 1.8f, 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) { //IL_0087: 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_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_0044: 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_012d: 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) if (!enableHitImpactSprites.Value || impactSpriteMaterials.Count == 0) { return; } EnsureBloodVisualRoot(); Camera main = Camera.main; if (cameraSafeHitSprites.Value && (Object)(object)main != (Object)null) { Vector3 val = source - ((Component)main).transform.position; if (((Vector3)(ref val)).sqrMagnitude < 0.48f) { return; } } GameObject obj = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)obj).name = "YoureInjured_HitBloodSprite"; obj.transform.SetParent(bloodVisualRoot, true); obj.transform.position = source + direction * 0.045f; obj.transform.localScale = Vector3.one * Mathf.Lerp(0.2f, Mathf.Max(0.2f, hitImpactSpriteMaximumSize.Value), severity); Collider component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sharedMaterial = impactSpriteMaterials[Random.Range(0, impactSpriteMaterials.Count)]; component2.shadowCastingMode = (ShadowCastingMode)0; component2.receiveShadows = false; } obj.AddComponent().Initialize(direction * Mathf.Lerp(0.45f, 1.1f, severity), Mathf.Clamp(hitImpactSpriteLifetime.Value, 0.06f, 0.3f), component2); } 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 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, (float)Math.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 LoadExternalImpactSprites() { string text = Path.Combine(pluginDirectory ?? string.Empty, "assets", "bleeding", "impact_frames"); if (!Directory.Exists(text)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: no impact-sprite folder found at " + text + ". Hit droplets will still work.")); return; } string[] files; try { files = Directory.GetFiles(text, "*.png", SearchOption.TopDirectoryOnly); Array.Sort(files, (IComparer?)StringComparer.OrdinalIgnoreCase); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("You're Injured: could not enumerate impact sprite files. " + ex.Message)); return; } int num = Mathf.Clamp(maximumImpactSpriteTextures.Value, 1, 12); 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_ImpactSprite_" + Path.GetFileNameWithoutExtension(files[i]); impactSpriteTextures.Add(texture); impactSpriteMaterials.Add(CreateImpactSpriteMaterial(texture)); } string path = Path.Combine(pluginDirectory ?? string.Empty, "assets", "bleeding", "drip_frames"); if (Directory.Exists(path)) { try { string[] files2 = Directory.GetFiles(path, "*.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_DripSprite_" + 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 (impactSpriteMaterials.Count > 0 || dripSpriteMaterials.Count > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("You're Injured: loaded " + impactSpriteMaterials.Count + " camera-safe impact sprites and " + dripSpriteMaterials.Count + " falling drip sprites.")); } } 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_0068: 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", new Color(0.4f, 0.01f, 0.016f, 0.78f)); } 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) * (float)Math.PI * 2f; float num2 = Mathf.Cos(num); float num3 = Mathf.Sin(num); float num4 = Hash01(variant * 83 + 4) * (float)Math.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) * (float)Math.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)bloodDropMaterial != (Object)null) { Object.Destroy((Object)(object)bloodDropMaterial); bloodDropMaterial = null; } DestroyBloodLiquidMaterials(); activeGroundBlood.Clear(); } 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."); } else { inventory.RemoveItem(value, num, -1, false); state.Bleeding = Mathf.Max(0f, state.Bleeding - Mathf.Max(0f, bandageBleedingReduction.Value)); state.InfectionRisk = Mathf.Max(0f, state.InfectionRisk - Mathf.Max(0f, bandageInfectionRiskReduction.Value)); state.Infection = Mathf.Max(0f, state.Infection - Mathf.Max(0f, bandageInfectionReduction.Value)); ApplyBandageWoundRelief(Mathf.Max(0f, bandageWoundRelief.Value)); state.ClampAll(); TryPlayBandageAudio(); treatmentCooldown = Mathf.Max(0f, treatmentCooldownSeconds.Value); SaveState(player); ShowMessage("You apply a bandage."); } } 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 (!(healthLoss <= 0f) && !(((Character)player).GetHealth() <= 1f)) { float num = Mathf.Max(0f, ((Character)player).GetHealth() - 1f); if (num > 0f) { ((Character)player).UseHealth(Mathf.Min(healthLoss, num)); } } } 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") + ", blood=[hitAttempts=" + hitBloodAttempts + ", trailAttempts=" + trailBloodAttempts + ", hitDrops=" + hitBloodDropletsSpawned + ", trailDrops=" + trailBloodDropletsSpawned + ", directTrailSplats=" + directTrailSplatsSpawned + ", splats=" + groundBloodSplatsSpawned + ", probesOk=" + groundProbeSuccesses + ", probesFailed=" + groundProbeFailures + ", fallbackLandings=" + dropletFallbackLandings + ", active=" + activeGroundBlood.Count + "], " + 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) //IL_005c: 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); DrawHudLayoutEditor(compactInjuryRect); } else { DrawLegacyInjuryHud(); } } } private void DrawCompactInjuryHud(Rect panelRect) { //IL_0001: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_0111: 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_0154: 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_01b7: 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_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0388: 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, 16f * compactInjuryContentScale), "Injuries: " + state.GetOverallLabel(), compactInjuryHeaderStyle); GUI.color = Color.white; GUI.Label(new Rect(((Rect)(ref panelRect)).x + 7f * compactInjuryContentScale, ((Rect)(ref panelRect)).y + 22f * compactInjuryContentScale, ((Rect)(ref panelRect)).width - 14f * compactInjuryContentScale, 13f * 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 + 39f * compactInjuryContentScale, ((Rect)(ref panelRect)).width - 14f * compactInjuryContentScale, 13f * 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 + 56f * compactInjuryContentScale, ((Rect)(ref panelRect)).width - 14f * compactInjuryContentScale, 13f * 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_005e: 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) float compactHudScale = GetCompactHudScale(); float minimumWidth = 180f * compactHudScale; float minimumHeight = 70f * compactHudScale; return ClampHudRect(new Rect(compactHudXNormalized.Value * (float)Screen.width, compactHudYNormalized.Value * (float)Screen.height, compactHudWidthNormalized.Value * (float)Screen.width, compactHudHeightNormalized.Value * (float)Screen.height), minimumWidth, minimumHeight); } private float GetCompactInjuryContentScale(Rect panelRect) { float compactHudScale = GetCompactHudScale(); float num = 220f * compactHudScale; float num2 = 80f * compactHudScale; float num3 = Mathf.Min(((Rect)(ref panelRect)).width / num, ((Rect)(ref panelRect)).height / num2); return Mathf.Max(0.55f, compactHudScale * Mathf.Clamp(num3, 0.55f, 3f)); } private void StoreCompactInjuryRect(Rect rect) { //IL_0000: 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_001c: Unknown result type (might be due to invalid IL or missing references) Rect val = ClampHudRect(rect, 180f * GetCompactHudScale(), 70f * GetCompactHudScale()); compactHudXNormalized.Value = ((Rect)(ref val)).x / Mathf.Max(1f, (float)Screen.width); compactHudYNormalized.Value = ((Rect)(ref val)).y / Mathf.Max(1f, (float)Screen.height); compactHudWidthNormalized.Value = ((Rect)(ref val)).width / Mathf.Max(1f, (float)Screen.width); compactHudHeightNormalized.Value = ((Rect)(ref val)).height / Mathf.Max(1f, (float)Screen.height); } private static Rect ClampHudRect(Rect rect, float minimumWidth, float minimumHeight) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Clamp(((Rect)(ref rect)).width, minimumWidth, Mathf.Max(minimumWidth, (float)Screen.width - 4f)); float num2 = Mathf.Clamp(((Rect)(ref rect)).height, minimumHeight, Mathf.Max(minimumHeight, (float)Screen.height - 4f)); float num3 = Mathf.Clamp(((Rect)(ref rect)).x, 0f, Mathf.Max(0f, (float)Screen.width - num)); float num4 = Mathf.Clamp(((Rect)(ref rect)).y, 0f, Mathf.Max(0f, (float)Screen.height - num2)); return new Rect(num3, num4, num, num2); } 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; if (hudHiddenByCtrlF3) { CloseHudLayoutEditorForHiddenHud(); } ((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 CloseHudLayoutEditorForHiddenHud() { if (hudLayoutEditorActive) { hudLayoutEditorActive = false; hudLayoutDragging = false; hudResizeHandle = HudResizeHandle.None; RestoreHudCursor(); ((BaseUnityPlugin)this).Config.Save(); } } private void ToggleHudLayoutEditor() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) hudLayoutEditorActive = !hudLayoutEditorActive; hudLayoutDragging = false; hudResizeHandle = HudResizeHandle.None; if (hudLayoutEditorActive) { hudPreviousCursorLockMode = Cursor.lockState; hudPreviousCursorVisible = Cursor.visible; hudCursorStateCaptured = true; Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; ShowMessage("Injuries layout mode: drag panel or a gold corner. Press O again to save."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"You're Injured: Injuries HUD layout editor enabled."); } else { RestoreHudCursor(); ((BaseUnityPlugin)this).Config.Save(); ShowMessage("Injuries layout saved."); ((BaseUnityPlugin)this).Logger.LogInfo((object)"You're Injured: Injuries HUD layout editor saved and closed."); } } private void RestoreHudCursor() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (hudCursorStateCaptured) { Cursor.lockState = hudPreviousCursorLockMode; Cursor.visible = hudPreviousCursorVisible; hudCursorStateCaptured = false; } } private void DrawHudLayoutEditor(Rect panelRect) { //IL_0198: 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_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: 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_0027: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Invalid comparison between Unknown and I4 //IL_0038: 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_006c: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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_0086: 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_008d: 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_0112: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_0146: 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) if (!hudLayoutEditorActive) { return; } Cursor.lockState = (CursorLockMode)0; Cursor.visible = true; Event current = Event.current; if (current != null) { Vector2 mousePosition = current.mousePosition; if ((int)current.type == 0 && current.button == 0) { HudResizeHandle resizeHandle = GetResizeHandle(panelRect, mousePosition); if (resizeHandle != HudResizeHandle.None) { hudResizeHandle = resizeHandle; hudLayoutDragging = false; hudEditStartMouse = mousePosition; hudEditStartRect = panelRect; current.Use(); } else if (((Rect)(ref panelRect)).Contains(mousePosition)) { hudLayoutDragging = true; hudResizeHandle = HudResizeHandle.None; hudEditStartMouse = mousePosition; hudEditStartRect = panelRect; current.Use(); } } else if ((int)current.type == 3 && current.button == 0 && (hudLayoutDragging || hudResizeHandle != HudResizeHandle.None)) { Vector2 val = mousePosition - hudEditStartMouse; Rect rect = (Rect)(hudLayoutDragging ? new Rect(((Rect)(ref hudEditStartRect)).x + val.x, ((Rect)(ref hudEditStartRect)).y + val.y, ((Rect)(ref hudEditStartRect)).width, ((Rect)(ref hudEditStartRect)).height) : ResizeRect(hudEditStartRect, val, hudResizeHandle, 180f * GetCompactHudScale(), 70f * GetCompactHudScale())); StoreCompactInjuryRect(rect); current.Use(); } else if ((int)current.type == 1 && current.button == 0 && (hudLayoutDragging || hudResizeHandle != HudResizeHandle.None)) { hudLayoutDragging = false; hudResizeHandle = HudResizeHandle.None; ((BaseUnityPlugin)this).Config.Save(); current.Use(); } } DrawEditorOutline(panelRect); Color color = GUI.color; GUI.color = new Color(1f, 0.78f, 0.22f, 1f); GUI.Label(new Rect(12f, 36f, 820f, 24f), "O — Injuries layout mode: drag panel; drag any gold corner to resize; press O again to save."); GUI.color = color; } private static HudResizeHandle GetResizeHandle(Rect rect, Vector2 mouse) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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) Rect val = new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 14f, 14f); if (((Rect)(ref val)).Contains(mouse)) { return HudResizeHandle.TopLeft; } val = new Rect(((Rect)(ref rect)).xMax - 14f, ((Rect)(ref rect)).y, 14f, 14f); if (((Rect)(ref val)).Contains(mouse)) { return HudResizeHandle.TopRight; } val = new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 14f, 14f, 14f); if (((Rect)(ref val)).Contains(mouse)) { return HudResizeHandle.BottomLeft; } val = new Rect(((Rect)(ref rect)).xMax - 14f, ((Rect)(ref rect)).yMax - 14f, 14f, 14f); if (((Rect)(ref val)).Contains(mouse)) { return HudResizeHandle.BottomRight; } return HudResizeHandle.None; } private static Rect ResizeRect(Rect start, Vector2 delta, HudResizeHandle handle, float minimumWidth, float minimumHeight) { //IL_0029: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005f: 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_0072: 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_00b9: Unknown result type (might be due to invalid IL or missing references) float num = ((Rect)(ref start)).x; float num2 = ((Rect)(ref start)).y; float num3 = ((Rect)(ref start)).width; float num4 = ((Rect)(ref start)).height; switch (handle) { case HudResizeHandle.TopLeft: case HudResizeHandle.BottomLeft: num += delta.x; num3 -= delta.x; break; case HudResizeHandle.TopRight: case HudResizeHandle.BottomRight: num3 += delta.x; break; } switch (handle) { case HudResizeHandle.TopLeft: case HudResizeHandle.TopRight: num2 += delta.y; num4 -= delta.y; break; case HudResizeHandle.BottomLeft: case HudResizeHandle.BottomRight: num4 += delta.y; break; } if (num3 < minimumWidth) { if (handle == HudResizeHandle.TopLeft || handle == HudResizeHandle.BottomLeft) { num = ((Rect)(ref start)).xMax - minimumWidth; } num3 = minimumWidth; } if (num4 < minimumHeight) { if (handle == HudResizeHandle.TopLeft || handle == HudResizeHandle.TopRight) { num2 = ((Rect)(ref start)).yMax - minimumHeight; } num4 = minimumHeight; } return ClampHudRect(new Rect(num, num2, num3, num4), minimumWidth, minimumHeight); } private static void DrawEditorOutline(Rect rect) { //IL_0000: 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_004f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0166: 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_01cc: Unknown result type (might be due to invalid IL or missing references) Color color = GUI.color; GUI.color = new Color(1f, 0.72f, 0.15f, 0.95f); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x - 1f, ((Rect)(ref rect)).y - 1f, ((Rect)(ref rect)).width + 2f, 2f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x - 1f, ((Rect)(ref rect)).yMax - 1f, ((Rect)(ref rect)).width + 2f, 2f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x - 1f, ((Rect)(ref rect)).y - 1f, 2f, ((Rect)(ref rect)).height + 2f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 1f, ((Rect)(ref rect)).y - 1f, 2f, ((Rect)(ref rect)).height + 2f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x - 2f, ((Rect)(ref rect)).y - 2f, 8f, 8f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 6f, ((Rect)(ref rect)).y - 2f, 8f, 8f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).x - 2f, ((Rect)(ref rect)).yMax - 6f, 8f, 8f), (Texture)(object)Texture2D.whiteTexture); GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 6f, ((Rect)(ref rect)).yMax - 6f, 8f, 8f), (Texture)(object)Texture2D.whiteTexture); GUI.color = color; } 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 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; } } 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 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 sealed class BloodImpactSprite : MonoBehaviour { private Renderer cachedRenderer; private MaterialPropertyBlock propertyBlock; private Vector3 velocity; private float remainingLifetime; private float startLifetime; private Vector3 startingScale; internal void Initialize(Vector3 initialVelocity, float lifetime, Renderer renderer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown velocity = initialVelocity; remainingLifetime = Mathf.Max(0.04f, lifetime); startLifetime = remainingLifetime; cachedRenderer = renderer; startingScale = ((Component)this).transform.localScale; propertyBlock = new MaterialPropertyBlock(); } private void Update() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_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_0047: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: 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_010a: Unknown result type (might be due to invalid IL or missing references) float deltaTime = Time.deltaTime; remainingLifetime -= deltaTime; Transform transform = ((Component)this).transform; transform.position += velocity * deltaTime; velocity += Physics.gravity * 0.08f * deltaTime; Camera main = Camera.main; if ((Object)(object)main != (Object)null) { ((Component)this).transform.rotation = ((Component)main).transform.rotation; } float num = Mathf.Clamp01(remainingLifetime / Mathf.Max(0.001f, startLifetime)); ((Component)this).transform.localScale = startingScale * Mathf.Lerp(1f, 1.28f, 1f - num); if ((Object)(object)cachedRenderer != (Object)null) { cachedRenderer.GetPropertyBlock(propertyBlock); propertyBlock.SetColor("_Color", new Color(0.4f, 0.01f, 0.016f, num * 0.78f)); cachedRenderer.SetPropertyBlock(propertyBlock); } if (remainingLifetime <= 0f) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } 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); } } } [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(); } } }