Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VoidFiendPassiveAndBuffs v0.2.3
plugins/VoidFiendUnstableTouch.dll
Decompiled 14 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.VoidSurvivor; using EntityStates.VoidSurvivor.CorruptMode; using EntityStates.VoidSurvivor.Weapon; using HarmonyLib; using Microsoft.CodeAnalysis; using RoR2; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace VoidFiendUnstableTouch { internal sealed class AbilityBuffs : IDisposable { private static AbilityBuffs active; private readonly Harmony patches = new Harmony("local.voidfiend.unstabletouch.abilities"); private readonly AbilityEffects effects = new AbilityEffects(); private readonly Func<BuffOptions> options; private readonly ManualLogSource logger; private readonly MethodInfo fixedAgeGetter; internal AbilityBuffs(Func<BuffOptions> options, ManualLogSource logger) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown //IL_00df: 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_0101: Expected O, but got Unknown //IL_0101: Expected O, but got Unknown //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown this.options = options; this.logger = logger; try { MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(ChargeMegaBlaster), "OnEnter", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(VoidBlinkBase), "OnExit", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.DeclaredMethod(typeof(CorruptMode), "OnEnter", (Type[])null, (Type[])null); fixedAgeGetter = AccessTools.PropertyGetter(typeof(EntityState), "fixedAge"); if (methodInfo == null || methodInfo2 == null || methodInfo3 == null || fixedAgeGetter == null) { throw new MissingMethodException("Void Fiend ability states changed."); } active = this; patches.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(AbilityBuffs), "BeginCharge", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(AbilityBuffs), "RestoreCharge", (Type[])null), (HarmonyMethod)null); patches.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(AbilityBuffs), "EndTrespass", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); patches.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(AbilityBuffs), "EnterCorruption", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Run.onRunDestroyGlobal += OnRunEnd; } catch { Dispose(); throw; } } internal float? ConsumeFollowupChance(CharacterBody body) { BuffOptions buffOptions = options(); return effects.ConsumeFollowupChance(body, Time.fixedTime, buffOptions); } private static void BeginCharge(ChargeMegaBlaster __instance, out float __state) { __state = __instance.baseDuration; if (active != null) { __state = AbilityEffects.BeforeCharge(__instance, active.options().ChargeSpeedBonusPercent); } } private static Exception RestoreCharge(ChargeMegaBlaster __instance, float __state, Exception __exception) { __instance.baseDuration = __state; return __exception; } private static void EndTrespass(VoidBlinkBase __instance) { AbilityBuffs abilityBuffs = active; if (abilityBuffs != null) { BuffOptions buffOptions = abilityBuffs.options(); if (abilityBuffs.effects.AfterTrespass(__instance, buffOptions, (float)abilityBuffs.fixedAgeGetter.Invoke(__instance, null)) && buffOptions.LogEvents) { abilityBuffs.logger.LogInfo((object)("Trespass primed one " + buffOptions.FollowupChancePercent + "% Collapse roll for " + buffOptions.HitWindowSeconds + " seconds.")); } } } private static void EnterCorruption(CorruptMode __instance) { AbilityBuffs abilityBuffs = active; if (abilityBuffs != null) { BuffOptions buffOptions = abilityBuffs.options(); int num = abilityBuffs.effects.OnCorruption(__instance, buffOptions); if (num > 0 && buffOptions.LogEvents) { abilityBuffs.logger.LogInfo((object)("Transformation pulse applied Collapse to " + num + " enemies.")); } } } private void OnRunEnd(Run run) { effects.Clear(); } public void Dispose() { Run.onRunDestroyGlobal -= OnRunEnd; patches.UnpatchSelf(); effects.Clear(); if (active == this) { active = null; } } } internal sealed class BuffOptions { internal float ChargeSpeedBonusPercent = 10f; internal bool TrespassEnabled = true; internal float FollowupChancePercent = 50f; internal float HitWindowSeconds = 5f; internal bool PulseEnabled = true; internal float PulseRadius = 10f; internal bool LogEvents; } internal sealed class AbilityEffects { private sealed class Window { internal float Expires; } private sealed class Handled { } private ConditionalWeakTable<CharacterBody, Window> windows = new ConditionalWeakTable<CharacterBody, Window>(); private ConditionalWeakTable<object, Handled> blinkExits = new ConditionalWeakTable<object, Handled>(); private ConditionalWeakTable<object, Handled> corruptEntries = new ConditionalWeakTable<object, Handled>(); internal static float BeforeCharge(ChargeMegaBlaster state, float bonusPercent) { float baseDuration = state.baseDuration; CharacterBody val = (Object.op_Implicit((Object)(object)((EntityState)state).outer) ? ((Component)((EntityState)state).outer).GetComponent<CharacterBody>() : null); VoidSurvivorController val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<VoidSurvivorController>() : null); if (Object.op_Implicit((Object)(object)val2) && !val2.isCorrupted && ValidPositive(baseDuration) && ValidPositive(bonusPercent)) { state.baseDuration = baseDuration / (1f + Math.Min(100f, bonusPercent) / 100f); } return baseDuration; } internal bool AfterTrespass(VoidBlinkBase state, BuffOptions options, float fixedAge) { CharacterBody val = (Object.op_Implicit((Object)(object)((EntityState)state).outer) ? ((Component)((EntityState)state).outer).GetComponent<CharacterBody>() : null); if (!NetworkServer.active || !options.TrespassEnabled || !ValidPositive(options.HitWindowSeconds) || !ValidPositive(options.FollowupChancePercent) || !Object.op_Implicit((Object)(object)((EntityState)state).outer) || ((EntityState)state).outer.destroying || !(fixedAge >= state.duration) || !LivingFiend(val) || blinkExits.TryGetValue(state, out var _)) { return false; } blinkExits.Add(state, new Handled()); windows.Remove(val); windows.Add(val, new Window { Expires = Time.fixedTime + Math.Min(30f, options.HitWindowSeconds) }); return true; } internal bool TryConsume(CharacterBody body, float now, bool enabled) { if (!Object.op_Implicit((Object)(object)body) || !windows.TryGetValue(body, out var value)) { return false; } windows.Remove(body); if (enabled && LivingFiend(body) && !float.IsNaN(now) && !float.IsInfinity(now)) { return now < value.Expires; } return false; } internal float? ConsumeFollowupChance(CharacterBody body, float now, BuffOptions options) { bool enabled = options.TrespassEnabled && ValidPositive(options.HitWindowSeconds) && ValidPositive(options.FollowupChancePercent); if (!TryConsume(body, now, enabled)) { return null; } return Math.Min(100f, options.FollowupChancePercent); } internal int OnCorruption(CorruptMode state, BuffOptions options) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_014a: 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_015e: Invalid comparison between Unknown and I4 //IL_0169: 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_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) CharacterBody val = (Object.op_Implicit((Object)(object)((EntityState)state).outer) ? ((Component)((EntityState)state).outer).GetComponent<CharacterBody>() : null); if (!NetworkServer.active || !options.PulseEnabled || !ValidPositive(options.PulseRadius) || !LivingFiend(val) || !((Component)val).GetComponent<VoidSurvivorController>().isCorrupted || !Object.op_Implicit((Object)(object)((EntityState)state).outer) || ((EntityState)state).outer.destroying || corruptEntries.TryGetValue(state, out var _)) { return 0; } corruptEntries.Add(state, new Handled()); if (!Object.op_Implicit((Object)(object)val.teamComponent)) { return 0; } float num = Math.Min(30f, options.PulseRadius); float num2 = num * num; TeamMask enemyTeams = TeamMask.GetEnemyTeams(val.teamComponent.teamIndex); int num3 = 0; foreach (CharacterBody item in new List<CharacterBody>(CharacterBody.readOnlyInstancesList)) { if (Object.op_Implicit((Object)(object)item) && !((Object)(object)item == (Object)(object)val) && Object.op_Implicit((Object)(object)item.healthComponent) && item.healthComponent.alive && Object.op_Implicit((Object)(object)item.teamComponent) && item.teamComponent.teamIndex != val.teamComponent.teamIndex && (int)item.teamComponent.teamIndex != 0 && (int)item.teamComponent.teamIndex != -1 && ((TeamMask)(ref enemyTeams)).HasTeam(item.teamComponent.teamIndex)) { Vector3 val2 = item.corePosition - val.corePosition; if (((Vector3)(ref val2)).sqrMagnitude <= num2 && TouchEffect.Inflict(val, item.healthComponent, null, default(ProcChainMask))) { num3++; } } } return num3; } internal void Clear() { windows = new ConditionalWeakTable<CharacterBody, Window>(); blinkExits = new ConditionalWeakTable<object, Handled>(); corruptEntries = new ConditionalWeakTable<object, Handled>(); } private static bool LivingFiend(CharacterBody body) { if (Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.healthComponent) && body.healthComponent.alive) { return Object.op_Implicit((Object)(object)((Component)body).GetComponent<VoidSurvivorController>()); } return false; } private static bool ValidPositive(float value) { if (value > 0f) { return !float.IsInfinity(value); } return false; } } [BepInPlugin("local.voidfiend.unstabletouch", "Void Fiend Passive and Buffs", "0.2.3")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "local.voidfiend.unstabletouch"; private static Plugin instance; private ConfigEntry<float> normalChance; private ConfigEntry<float> corruptedChance; private ConfigEntry<float> chargeSpeedBonus; private ConfigEntry<float> hitWindow; private ConfigEntry<float> pulseRadius; private ConfigEntry<float> followupChance; private ConfigEntry<bool> logProcs; private ConfigEntry<bool> trespassEnabled; private ConfigEntry<bool> pulseEnabled; private Harmony presentation; private AbilityBuffs abilities; private Func<CharacterBody, float?> consumeFollowupChance; private void Awake() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Expected O, but got Unknown //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Expected O, but got Unknown instance = this; normalChance = ((BaseUnityPlugin)this).Config.Bind<float>("Passive", "NormalChancePercent", 3f, new ConfigDescription("Collapse chance in normal form, multiplied by the attack proc coefficient. Zero disables this form.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); corruptedChance = ((BaseUnityPlugin)this).Config.Bind<float>("Passive", "CorruptedChancePercent", 7f, new ConfigDescription("Collapse chance in corrupted form, multiplied by the attack proc coefficient. Zero disables this form.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); chargeSpeedBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Flood", "ChargeSpeedBonusPercent", 10f, new ConfigDescription("Normal Flood charges this percent faster, on top of attack speed. 10 means charge time divided by 1.1. Zero disables the buff.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); trespassEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Trespass", "GuaranteedCollapseEnabled", true, "Legacy setting name: enables the Trespass follow-up Collapse roll, which is no longer guaranteed. The first eligible hit consumes the roll even if it fails. Does not stack."); followupChance = ((BaseUnityPlugin)this).Config.Bind<float>("Trespass", "FollowupChancePercent", 50f, new ConfigDescription("Base Collapse chance on the first eligible hit after Trespass. Replaces the passive roll on that hit, and is consumed on success or failure. Uses normal attacker luck; not multiplied by proc coefficient. Zero disables the follow-up.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); hitWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Trespass", "HitWindowSeconds", 5f, new ConfigDescription("Seconds after completing Trespass to use the follow-up Collapse roll. Zero disables it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); pulseEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Transformation", "PulseEnabled", true, "Entering corrupted mode applies one Collapse stack to each nearby enemy."); pulseRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Transformation", "PulseRadiusMetres", 10f, new ConfigDescription("Transformation pulse radius in metres, measured between body centres. Zero disables the pulse.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>())); logProcs = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogProcs", false, "Log successful Collapse applications, Trespass primes, and transformation pulses for testing."); try { abilities = new AbilityBuffs(CurrentOptions, ((BaseUnityPlugin)this).Logger); consumeFollowupChance = abilities.ConsumeFollowupChance; } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Ability buffs unavailable; Unstable Touch remains active: " + ex)); } GlobalEventManager.onServerDamageDealt += OnDamage; try { presentation = new Harmony("local.voidfiend.unstabletouch.tooltip"); MethodInfo methodInfo = AccessTools.Method(typeof(Language), "GetLocalizedStringByToken", new Type[1] { typeof(string) }, (Type[])null); if (methodInfo == null) { throw new MissingMethodException("Language.GetLocalizedStringByToken"); } presentation.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "Describe", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex2) { Harmony obj = presentation; if (obj != null) { obj.UnpatchSelf(); } ((BaseUnityPlugin)this).Logger.LogWarning((object)("Skill tooltips unavailable; gameplay remains active: " + ex2)); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Void Fiend Passive and Buffs 0.2.3 loaded: " + normalChance.Value + "% normal / " + corruptedChance.Value + "% corrupted Collapse; Trespass follow-up " + followupChance.Value + "%; ability buffs " + ((abilities != null) ? "active" : "unavailable") + ".")); } private BuffOptions CurrentOptions() { return new BuffOptions { ChargeSpeedBonusPercent = chargeSpeedBonus.Value, TrespassEnabled = trespassEnabled.Value, FollowupChancePercent = followupChance.Value, HitWindowSeconds = hitWindow.Value, PulseEnabled = pulseEnabled.Value, PulseRadius = pulseRadius.Value, LogEvents = logProcs.Value }; } private void OnDamage(DamageReport report) { if (TouchEffect.Apply(report, normalChance.Value, corruptedChance.Value, consumeFollowupChance) && logProcs.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Void Fiend Passive and Buffs applied Collapse to " + ((Object)report.victimBody).name)); } } private static void Describe(string __0, ref string __result) { if (Object.op_Implicit((Object)(object)instance) && TooltipText.IsSupported(__0)) { __result = TooltipText.Describe(__0, __result, instance.normalChance.Value, instance.corruptedChance.Value, (instance.abilities != null) ? instance.CurrentOptions() : null); } } private void OnDestroy() { GlobalEventManager.onServerDamageDealt -= OnDamage; consumeFollowupChance = null; abilities?.Dispose(); Harmony obj = presentation; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)instance == (Object)(object)this) { instance = null; } } } internal static class TooltipText { private static string Number(float value) { return value.ToString("0.##", CultureInfo.InvariantCulture); } internal static bool IsSupported(string token) { switch (token) { default: return token == "VOIDSURVIVOR_UTILITY_UPRADE_TOOLTIP"; case "VOIDSURVIVOR_PASSIVE_DESCRIPTION": case "VOIDSURVIVOR_SECONDARY_DESCRIPTION": case "VOIDSURVIVOR_UTILITY_DESCRIPTION": return true; } } internal static string Describe(string token, string original, float normal, float corrupted, BuffOptions buffs) { string text = original; if (token == "VOIDSURVIVOR_PASSIVE_DESCRIPTION") { text = Append(text, normal, corrupted); if (buffs != null && buffs.PulseEnabled && buffs.PulseRadius > 0f) { text = Add(text, "Transformation Pulse", "Entering corrupted mode inflicts <style=cIsVoid>1 Collapse stack</style> on each enemy within <style=cIsUtility>" + Number(buffs.PulseRadius) + "m</style>. Occurs once per transformation."); } } if (buffs == null) { return text; } if (token == "VOIDSURVIVOR_SECONDARY_DESCRIPTION" && buffs.ChargeSpeedBonusPercent > 0f) { text = Add(text, "Faster Flood", "Normal-form Flood charges <style=cIsUtility>" + Number(buffs.ChargeSpeedBonusPercent) + "% faster</style>, in addition to attack speed."); } if ((token == "VOIDSURVIVOR_UTILITY_DESCRIPTION" || token == "VOIDSURVIVOR_UTILITY_UPRADE_TOOLTIP") && buffs.TrespassEnabled && buffs.HitWindowSeconds > 0f && buffs.FollowupChancePercent > 0f) { text = Add(text, "Void Follow-through", "After completing Trespass in either form, your next successful hit within <style=cIsUtility>" + Number(buffs.HitWindowSeconds) + "s</style> has a <style=cIsDamage>" + Number(buffs.FollowupChancePercent) + "% chance</style> to inflict <style=cIsVoid>1 Collapse stack</style>. Consumed on success or failure. Requires a positive proc coefficient; chance uses normal luck and is not scaled by that coefficient. Damage-over-time cannot consume it. Refreshes instead of stacking; replaces the passive roll on that hit."); } return text; } private static string Add(string original, string title, string description) { string text = "<style=cIsVoid>" + title + "</style>"; if (original != null && original.Contains(text)) { return original; } return original + "\n\n" + text + ": " + description; } internal static string Append(string original, float normal, float corrupted) { if (normal <= 0f && corrupted <= 0f) { return original; } return Add(original, "Unstable Touch", "Hits have a <style=cIsDamage>" + Number(normal) + "%</style> chance to inflict <style=cIsVoid>Collapse</style> in normal form, or <style=cIsDamage>" + Number(corrupted) + "%</style> while corrupted. Chance scales with the attack's proc coefficient. Collapse cannot trigger itself."); } } internal static class TouchEffect { internal static bool Apply(DamageReport report, float normalChance, float corruptedChance, Func<CharacterBody, float?> consumeFollowupChance = null) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_009e: 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_015c: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || report?.damageInfo == null) { return false; } DamageInfo damageInfo = report.damageInfo; if (damageInfo.rejected || damageInfo.delayedDamageSecondHalf || !(report.damageDealt > 0f) || (int)damageInfo.dotIndex != -1 || ((ProcChainMask)(ref damageInfo.procChainMask)).HasProc((ProcType)19) || !Object.op_Implicit((Object)(object)report.attackerBody) || !Object.op_Implicit((Object)(object)report.victim) || !report.victim.alive || !Object.op_Implicit((Object)(object)report.victimBody) || (Object)(object)report.attackerBody == (Object)(object)report.victimBody || report.attackerTeamIndex == report.victimTeamIndex) { return false; } CharacterBody attackerBody = report.attackerBody; VoidSurvivorController component = ((Component)attackerBody).GetComponent<VoidSurvivorController>(); if (!Object.op_Implicit((Object)(object)component)) { return false; } if (Chance(100f, damageInfo.procCoefficient) <= 0f) { return false; } if (DotController.GetDotDef((DotIndex)8) == null) { return false; } float? num = consumeFollowupChance?.Invoke(attackerBody); float num2 = (num.HasValue ? Chance(num.Value, 1f) : Chance(component.isCorrupted ? corruptedChance : normalChance, damageInfo.procCoefficient)); if (num2 <= 0f || !Util.CheckRoll(num2, attackerBody.master)) { return false; } return Inflict(attackerBody, report.victim, damageInfo.inflictedHurtbox, damageInfo.procChainMask); } internal static bool Inflict(CharacterBody attacker, HealthComponent victim, HurtBox hurtbox, ProcChainMask mask) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !Object.op_Implicit((Object)(object)attacker) || !Object.op_Implicit((Object)(object)victim) || !victim.alive) { return false; } DotDef dotDef = DotController.GetDotDef((DotIndex)8); if (dotDef == null) { return false; } ((ProcChainMask)(ref mask)).AddProc((ProcType)19); DotController.InflictDot(((Component)victim).gameObject, ((Component)attacker).gameObject, hurtbox, mask, (DotIndex)8, dotDef.interval, 1f, (uint?)null); return true; } internal static float Chance(float configuredPercent, float coefficient) { if (float.IsNaN(configuredPercent) || float.IsInfinity(configuredPercent) || float.IsNaN(coefficient) || float.IsInfinity(coefficient) || configuredPercent <= 0f || coefficient <= 0f) { return 0f; } return (float)Math.Min(100.0, Math.Min(100.0, configuredPercent) * (double)coefficient); } } }