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 MonsterModifiers v1.3.126
MonsterModifiers.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using MonsterModifiers.Custom_Components; using MonsterModifiers.Modifiers; using MonsterModifiers.Patches; using MonsterModifiers.StatusEffects; using MonsterModifiers.Visuals; using TMPro; using UnityEngine; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("MonsterModifiers")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("KorCaptain")] [assembly: AssemblyProduct("MonsterModifiers")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("E0E2F92E-557C-4A05-9D89-AA92A0BD75C4")] [assembly: AssemblyFileVersion("1.3.126")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.126.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace MonsterModifiers { [BepInPlugin("KorCaptain.MonsterModifiers", "MonsterModifiers", "1.3.126")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class MonsterModifiersPlugin : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } internal const string ModName = "MonsterModifiers"; internal const string ModVersion = "1.3.126"; internal const string Author = "KorCaptain"; private const string ModGUID = "KorCaptain.MonsterModifiers"; private static string ConfigFileName = "KorCaptain.MonsterModifiers.cfg"; private static string ConfigFileFullPath; internal static string ConnectionError; private readonly Harmony _harmony = new Harmony("KorCaptain.MonsterModifiers"); public static readonly ManualLogSource MonsterModifiersLogger; public static ConfigEntry<int> Configurations_Monster_Modifiers; public static ConfigEntry<int> Configurations_Boss_Modifiers; public static ConfigEntry<int> Cfg_PierceImmunity_DamageReduction; public static ConfigEntry<int> Cfg_SlashImmunity_DamageReduction; public static ConfigEntry<int> Cfg_BluntImmunity_DamageReduction; public static ConfigEntry<int> Cfg_ElementalImmunity_DamageReduction; public static ConfigEntry<int> Cfg_Knockback_StaggerForce; public static ConfigEntry<int> Cfg_Knockback_PushForce; public static ConfigEntry<float> Cfg_FastAttackSpeed_AnimatorMultiplier; public static ConfigEntry<float> Cfg_FastAttackSpeed_IntervalReduction; public static ConfigEntry<float> Cfg_SplitSpawn_Scale; public static ConfigEntry<float> Cfg_SplitSpawn_HP; public static ConfigEntry<float> Cfg_SplitSpawn_ChildDropRate; public static ConfigEntry<int> Cfg_SplitSpawn_MaxTotal; public static ConfigEntry<Toggle> Cfg_SplitSpawn_RandomizeWeapon; public static ConfigEntry<float> Cfg_ShieldBreaker_DurabilityThreshold; public static ConfigEntry<float> Cfg_ShieldBreaker_DurabilityReduction; public static ConfigEntry<float> Cfg_IgnoreArmor_ArmorReduction; public static ConfigEntry<float> Cfg_FoodDrain_DurationReduction; public static ConfigEntry<float> Cfg_ElementalInfusion_DamageRatio; public static ConfigEntry<float> Cfg_Forceful_PushMultiplier; public static ConfigEntry<float> Cfg_Vampiric_HealRatio; public static ConfigEntry<int> Cfg_PersonalShield_Duration; public static ConfigEntry<float> Cfg_PersonalShield_Magnitude; public static ConfigEntry<float> Cfg_FastMovement_SpeedMultiplier; public static ConfigEntry<float> Cfg_DistantDetection_RangeMultiplier; public static ConfigEntry<float> Cfg_SoulEater_Radius; public static ConfigEntry<int> Cfg_SoulEater_MaxStacks; public static ConfigEntry<float> Cfg_SoulEater_GrowthMultiplier; public static ConfigEntry<float> Cfg_SoulEater_DmgStack1; public static ConfigEntry<float> Cfg_SoulEater_DmgStack2; public static ConfigEntry<float> Cfg_SoulEater_DmgStack3; public static ConfigEntry<int> Cfg_ResistanceNotification_MaxCount; public static ConfigEntry<int> Cfg_Boss_OffenseMultiplier; public static ConfigEntry<int> Cfg_Boss_HealMultiplier; public static ConfigEntry<int> Cfg_Offense_Probability; public static ConfigEntry<int> Cfg_Defense_Probability; public static ConfigEntry<int> Cfg_Utility_Probability; public static ConfigEntry<int> Cfg_SplitSpawn_Probability; public static ConfigEntry<Toggle> Cfg_EliteMonster_Enabled; public static ConfigEntry<Toggle> Cfg_HealthText_Enabled; public static ConfigEntry<int> Cfg_EliteMonster_Probability; public static ConfigEntry<int> Cfg_Elite_Size; public static ConfigEntry<int> Cfg_Elite_HP; public static ConfigEntry<int> Cfg_Elite_ATK; public static ConfigEntry<int> Cfg_Elite_DFS; public static ConfigEntry<int> Cfg_SkullDeath_HP; private FileSystemWatcher? _configWatcher; public void Awake() { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); if (saveOnConfigSet) { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; ((BaseUnityPlugin)this).Config.Save(); } YamlUtils.ParseDefaultYamls(); TranslationUtils.AddLocalizations(); ModifierAssetUtils.Setup(); ModifierAssetUtils.LoadAllIcons(); int length = Enum.GetValues(typeof(MonsterModifierTypes)).Length; int num = length - ModifierUtils.BossExcludedModifiers.Count; ConfigFile config = ((BaseUnityPlugin)this).Config; AcceptableValueBase val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, num); Configurations_Boss_Modifiers = ConfigFileExtensions.BindConfig<int>(config, "General", "boss_Modifiers", 5, "Minimum modifiers for bosses (0 = disabled). Max is auto-calculated excluding death-spawn modifiers. N = always assign at least N modifiers.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Configurations_Boss_Modifiers, 7); Cfg_EliteMonster_Enabled = ConfigFileExtensions.BindConfig<Toggle>(((BaseUnityPlugin)this).Config, "General", "Elite_Monster", Toggle.On, "Enable Elite Monster spawning. When Off, its 10% probability is automatically redistributed (+5% Offense, +5% Defense).", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Cfg_EliteMonster_Enabled, 6); Cfg_HealthText_Enabled = ConfigFileExtensions.BindConfig<Toggle>(((BaseUnityPlugin)this).Config, "General", "Show_Health_Text", Toggle.On, "Show numeric health (e.g. 70/100) in white inside the enemy health bar.", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Cfg_HealthText_Enabled, 8); ConfigFile config2 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, length); Configurations_Monster_Modifiers = ConfigFileExtensions.BindConfig<int>(config2, "General", "Monster_Modifiers", 5, "Maximum modifiers for regular monsters. 0 = disabled.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Configurations_Monster_Modifiers, 5); ConfigFile config3 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_EliteMonster_Probability = ConfigFileExtensions.BindConfig<int>(config3, "General", "Elite_Monster_Probability", 10, "Relative roll probability for Elite Monster (boss-excluded, biome-spawn only).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Cfg_EliteMonster_Probability, 4); ConfigFile config4 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_SplitSpawn_Probability = ConfigFileExtensions.BindConfig<int>(config4, "General", "SplitSpawn_Probability", 10, "Relative roll probability for SplitSpawn modifier (boss-excluded). Set 0 to disable SplitSpawn from rolling.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Cfg_SplitSpawn_Probability, 3); ConfigFile config5 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_Offense_Probability = ConfigFileExtensions.BindConfig<int>(config5, "General", "Offense_Probability", 35, "Relative roll probability for Offense modifiers (values are treated as ratio).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Cfg_Offense_Probability, 2); ConfigFile config6 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_Defense_Probability = ConfigFileExtensions.BindConfig<int>(config6, "General", "Defense_Probability", 35, "Relative roll probability for Defense modifiers (values are treated as ratio).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Cfg_Defense_Probability, 1); ConfigFile config7 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_Utility_Probability = ConfigFileExtensions.BindConfig<int>(config7, "General", "Utility_Probability", 10, "Relative roll probability for Utility modifiers.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SetConfigOrder((ConfigEntryBase)(object)Cfg_Utility_Probability, 0); ConfigFile config8 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_PierceImmunity_DamageReduction = ConfigFileExtensions.BindConfig<int>(config8, "Modifier_Defense", "PierceImmunity Damage Reduction %", 70, "Percentage of pierce damage reduced when PierceImmunity modifier is active. 100 = full immunity.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config9 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_SlashImmunity_DamageReduction = ConfigFileExtensions.BindConfig<int>(config9, "Modifier_Defense", "SlashImmunity Damage Reduction %", 70, "Percentage of slash damage reduced when SlashImmunity modifier is active. 100 = full immunity.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config10 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_BluntImmunity_DamageReduction = ConfigFileExtensions.BindConfig<int>(config10, "Modifier_Defense", "BluntImmunity Damage Reduction %", 70, "Percentage of blunt damage reduced when BluntImmunity modifier is active. 100 = full immunity.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config11 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_ElementalImmunity_DamageReduction = ConfigFileExtensions.BindConfig<int>(config11, "Modifier_Defense", "ElementalImmunity Damage Reduction %", 70, "Percentage of elemental damage (fire/frost/lightning/poison/spirit) reduced when ElementalImmunity modifier is active. 100 = full immunity.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config12 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2000); Cfg_Knockback_StaggerForce = ConfigFileExtensions.BindConfig<int>(config12, "Modifier_Offense", "Knockback Stagger Force", 500, "Stagger force applied by the Knockback modifier.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config13 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200); Cfg_Knockback_PushForce = ConfigFileExtensions.BindConfig<int>(config13, "Modifier_Offense", "Knockback Push Force", 45, "Push force applied by the Knockback modifier.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config14 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f); Cfg_FastAttackSpeed_AnimatorMultiplier = ConfigFileExtensions.BindConfig<float>(config14, "Modifier_Offense", "FastAttackSpeed Animator Speed Multiplier", 0.3f, "Animator speed bonus for FastAttackSpeed modifier (0.3 = +30% faster animation). Default: 0.3", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config15 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.95f); Cfg_FastAttackSpeed_IntervalReduction = ConfigFileExtensions.BindConfig<float>(config15, "Modifier_Offense", "FastAttackSpeed Attack Interval Reduction", 0.3f, "Attack cooldown reduction fraction for FastAttackSpeed modifier (0.3 = -30% cooldown). Default: 0.3", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config16 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f); Cfg_SplitSpawn_Scale = ConfigFileExtensions.BindConfig<float>(config16, "Modifier_Offense", "SplitSpawn Scale", 0.85f, "Size of SplitSpawn children relative to parent size (0.7 = 70%).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config17 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f); Cfg_SplitSpawn_HP = ConfigFileExtensions.BindConfig<float>(config17, "Modifier_Offense", "SplitSpawn Health", 0.7f, "HP of SplitSpawn children as a fraction of parent max HP (0.7 = 70%).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config18 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f); Cfg_SplitSpawn_ChildDropRate = ConfigFileExtensions.BindConfig<float>(config18, "Modifier_Offense", "SplitSpawn Child Drop Rate", 0.35f, "Fraction of normal drops kept by monsters created from a split (0.35 = 35%). The original monster drops normally.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config19 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100); Cfg_SplitSpawn_MaxTotal = ConfigFileExtensions.BindConfig<int>(config19, "Modifier_Offense", "SplitSpawn Max Total", 10, "Max total number of children one SplitSpawn lineage (original + all descendants) can spawn.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); Cfg_SplitSpawn_RandomizeWeapon = ConfigFileExtensions.BindConfig<Toggle>(((BaseUnityPlugin)this).Config, "Modifier_Offense", "SplitSpawn Randomize Weapon", Toggle.On, "When On, bow-wielding creatures may spawn melee-variant children instead of archer copies.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config20 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f); Cfg_ShieldBreaker_DurabilityThreshold = ConfigFileExtensions.BindConfig<float>(config20, "Modifier_Offense", "ShieldBreaker Durability Threshold", 0.1f, "Shield durability fraction below which reduction is skipped (0.1 = skip if below 10%).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config21 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f); Cfg_ShieldBreaker_DurabilityReduction = ConfigFileExtensions.BindConfig<float>(config21, "Modifier_Offense", "ShieldBreaker Durability Reduction", 0.5f, "Multiplier applied to shield durability on block (0.5 = halved).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config22 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f); Cfg_IgnoreArmor_ArmorReduction = ConfigFileExtensions.BindConfig<float>(config22, "Modifier_Offense", "IgnoreArmor Armor Reduction", 0.5f, "Multiplier applied to player armor value (0.5 = armor halved).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config23 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f); Cfg_FoodDrain_DurationReduction = ConfigFileExtensions.BindConfig<float>(config23, "Modifier_Offense", "FoodDrain Duration Reduction", 0.5f, "Multiplier applied to food duration on hit (0.5 = halved).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config24 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f); Cfg_ElementalInfusion_DamageRatio = ConfigFileExtensions.BindConfig<float>(config24, "Modifier_Offense", "ElementalInfusion Damage Ratio", 0.5f, "Ratio of total hit damage added as elemental bonus (0.5 = +50% as element).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config25 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f); Cfg_Forceful_PushMultiplier = ConfigFileExtensions.BindConfig<float>(config25, "Modifier_Offense", "Forceful Push Multiplier", 5f, "Multiplier applied to hit push force (5.0 = 5x knockback).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config26 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f); Cfg_Vampiric_HealRatio = ConfigFileExtensions.BindConfig<float>(config26, "Modifier_Offense", "Vampiric Heal Ratio", 0.5f, "Ratio of total hit damage healed by the attacker (0.5 = heal 50% of damage).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config27 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 60); Cfg_PersonalShield_Duration = ConfigFileExtensions.BindConfig<int>(config27, "Modifier_Defense", "PersonalShield Duration", 10, "Duration (seconds) of the GoblinShaman shield status effect.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config28 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 10f); Cfg_PersonalShield_Magnitude = ConfigFileExtensions.BindConfig<float>(config28, "Modifier_Defense", "PersonalShield Magnitude", 2f, "Magnitude of the GoblinShaman shield status effect.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config29 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f); Cfg_FastMovement_SpeedMultiplier = ConfigFileExtensions.BindConfig<float>(config29, "Modifier_Utility", "FastMovement Speed Multiplier", 1.5f, "Speed multiplier applied to m_speed/m_runSpeed/m_walkSpeed (1.5 = +50%).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config30 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f); Cfg_DistantDetection_RangeMultiplier = ConfigFileExtensions.BindConfig<float>(config30, "Modifier_Utility", "DistantDetection Range Multiplier", 2f, "Multiplier applied to hear and view range (2.0 = double range).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config31 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 20f); Cfg_SoulEater_Radius = ConfigFileExtensions.BindConfig<float>(config31, "Modifier_Utility", "SoulEater Absorb Radius", 5f, "Radius (units) in which SoulEater detects dying enemies.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config32 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10); Cfg_SoulEater_MaxStacks = ConfigFileExtensions.BindConfig<int>(config32, "Modifier_Utility", "SoulEater Max Stacks", 3, "Maximum number of soul stacks the SoulEater can accumulate.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config33 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2f); Cfg_SoulEater_GrowthMultiplier = ConfigFileExtensions.BindConfig<float>(config33, "Modifier_Utility", "SoulEater Growth Multiplier", 1.1f, "Size and health growth multiplier per stack (1.1 = +10% per soul).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config34 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f); Cfg_SoulEater_DmgStack1 = ConfigFileExtensions.BindConfig<float>(config34, "Modifier_Utility", "SoulEater Damage Stack 1", 1.1f, "Damage multiplier at 1 soul stack.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config35 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f); Cfg_SoulEater_DmgStack2 = ConfigFileExtensions.BindConfig<float>(config35, "Modifier_Utility", "SoulEater Damage Stack 2", 1.2f, "Damage multiplier at 2 soul stacks.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config36 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3f); Cfg_SoulEater_DmgStack3 = ConfigFileExtensions.BindConfig<float>(config36, "Modifier_Utility", "SoulEater Damage Stack 3", 1.3f, "Damage multiplier at 3 soul stacks.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config37 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10); Cfg_ResistanceNotification_MaxCount = ConfigFileExtensions.BindConfig<int>(config37, "Modifier_Utility", "ResistanceNotification Max Count", 2, "Max times to show a resistance notification per damage type per enemy.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config38 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_Boss_OffenseMultiplier = ConfigFileExtensions.BindConfig<int>(config38, "Boss", "Boss_Offense_Multiplier", 20, "Scales offensive modifier effects when the modifier is on a boss (100 = full effect, 10 = 10% of normal).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config39 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100); Cfg_Boss_HealMultiplier = ConfigFileExtensions.BindConfig<int>(config39, "Boss", "Boss_Heal_Multiplier", 10, "Scales healing modifier effects when the modifier is on a boss (100 = full effect, 10 = 10% of normal).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config40 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(100, 300); Cfg_SkullDeath_HP = ConfigFileExtensions.BindConfig<int>(config40, "Modifier_SkullDeath", "SkullDeath_HP", 120, "Health multiplier % for Death skull monsters (FireDeath, PoisonDeath, FrostDeath, HealDeath, StaggerDeath, TarDeath, SplitSpawn). 120 = 1.2x base HP.", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config41 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200); Cfg_Elite_Size = ConfigFileExtensions.BindConfig<int>(config41, "Modifier_Elite", "Elite_Monster_Size", 100, "Size increase % for Elite monsters (100 = +100% scale, i.e. 2x base size).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config42 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(100, 500); Cfg_Elite_HP = ConfigFileExtensions.BindConfig<int>(config42, "Modifier_Elite", "Elite_Monster_HP", 150, "Health multiplier % for Elite monsters (150 = 1.5x base HP).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config43 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 200); Cfg_Elite_ATK = ConfigFileExtensions.BindConfig<int>(config43, "Modifier_Elite", "Elite_Monster_ATK", 30, "Attack power increase % for Elite monsters (30 = +30% damage output).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ConfigFile config44 = ((BaseUnityPlugin)this).Config; val = (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 90); Cfg_Elite_DFS = ConfigFileExtensions.BindConfig<int>(config44, "Modifier_Elite", "Elite_Monster_DFS", 30, "Physical and elemental damage reduction % for Elite monsters (30 = -30% incoming damage).", true, (int?)null, val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); RtDSpawnControl.Init(((BaseUnityPlugin)this).Config); ShaderLogFilter.Install(); CompatibilityUtils.RunCompatibiltyChecks(); StatusEffectUtils.CreateCustomStatusEffects(); PrefabManager.OnVanillaPrefabsAvailable += PrefabUtils.CreateCustomPrefabs; } private static void SetConfigOrder(ConfigEntryBase entry, int order) { ConfigDescription description = entry.Description; if (((description != null) ? description.Tags : null) == null) { return; } object[] tags = entry.Description.Tags; foreach (object obj in tags) { if (obj == null) { continue; } PropertyInfo property = obj.GetType().GetProperty("Order"); if (!(property == null)) { try { property.SetValue(obj, (property.PropertyType == typeof(int?)) ? ((object)order) : ((object)order)); break; } catch { break; } } } } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); _configWatcher?.Dispose(); } private void SetupWatcher() { _configWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); _configWatcher.Changed += ReadConfigValues; _configWatcher.Created += ReadConfigValues; _configWatcher.Renamed += ReadConfigValues; _configWatcher.IncludeSubdirectories = true; _configWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _configWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { if (!File.Exists(ConfigFileFullPath)) { return; } try { MonsterModifiersLogger.LogDebug((object)"ReadConfigValues called"); ((BaseUnityPlugin)this).Config.Reload(); } catch { MonsterModifiersLogger.LogError((object)("There was an issue loading your " + ConfigFileName)); MonsterModifiersLogger.LogError((object)"Please check your config entries for spelling and format!"); } } static MonsterModifiersPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ConnectionError = ""; MonsterModifiersLogger = Logger.CreateLogSource("MonsterModifiers"); Configurations_Monster_Modifiers = null; Configurations_Boss_Modifiers = null; Cfg_PierceImmunity_DamageReduction = null; Cfg_SlashImmunity_DamageReduction = null; Cfg_BluntImmunity_DamageReduction = null; Cfg_ElementalImmunity_DamageReduction = null; Cfg_Knockback_StaggerForce = null; Cfg_Knockback_PushForce = null; Cfg_FastAttackSpeed_AnimatorMultiplier = null; Cfg_FastAttackSpeed_IntervalReduction = null; Cfg_SplitSpawn_Scale = null; Cfg_SplitSpawn_HP = null; Cfg_SplitSpawn_ChildDropRate = null; Cfg_SplitSpawn_MaxTotal = null; Cfg_SplitSpawn_RandomizeWeapon = null; Cfg_ShieldBreaker_DurabilityThreshold = null; Cfg_ShieldBreaker_DurabilityReduction = null; Cfg_IgnoreArmor_ArmorReduction = null; Cfg_FoodDrain_DurationReduction = null; Cfg_ElementalInfusion_DamageRatio = null; Cfg_Forceful_PushMultiplier = null; Cfg_Vampiric_HealRatio = null; Cfg_PersonalShield_Duration = null; Cfg_PersonalShield_Magnitude = null; Cfg_FastMovement_SpeedMultiplier = null; Cfg_DistantDetection_RangeMultiplier = null; Cfg_SoulEater_Radius = null; Cfg_SoulEater_MaxStacks = null; Cfg_SoulEater_GrowthMultiplier = null; Cfg_SoulEater_DmgStack1 = null; Cfg_SoulEater_DmgStack2 = null; Cfg_SoulEater_DmgStack3 = null; Cfg_ResistanceNotification_MaxCount = null; Cfg_Boss_OffenseMultiplier = null; Cfg_Boss_HealMultiplier = null; Cfg_Offense_Probability = null; Cfg_Defense_Probability = null; Cfg_Utility_Probability = null; Cfg_SplitSpawn_Probability = null; Cfg_EliteMonster_Enabled = null; Cfg_HealthText_Enabled = null; Cfg_EliteMonster_Probability = null; Cfg_Elite_Size = null; Cfg_Elite_HP = null; Cfg_Elite_ATK = null; Cfg_Elite_DFS = null; Cfg_SkullDeath_HP = null; } } public class CompatibilityUtils { public static bool isStarLevelsExpandedInstalled; public static void RunCompatibiltyChecks() { if (Chainloader.PluginInfos.ContainsKey("CreatureLevelControl")) { MonsterModifiersPlugin.MonsterModifiersLogger.LogWarning((object)"CreatureLevelandLootControl plugin is installed. Please ensure special effects and infusions are disabled in CLLC configuration."); } if (Chainloader.PluginInfos.ContainsKey("MidnightsFX.StarLevelSystem")) { MonsterModifiersPlugin.MonsterModifiersLogger.LogWarning((object)"StarLevelSystem plugin is installed. Please ensure max modifiers config is set."); isStarLevelsExpandedInstalled = true; } } } public class DamageUtils { public static float TryCurrentWeapon(Humanoid humanoid) { //IL_001d: 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_0063: 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) ItemData currentWeapon = humanoid.GetCurrentWeapon(); if (currentWeapon == null) { return 10f; } DamageTypes damage = currentWeapon.GetDamage(); if (!((DamageTypes)(ref damage)).HaveDamage()) { return 10f; } float totalDamage = ((DamageTypes)(ref damage)).GetTotalDamage(); if (totalDamage == 0f) { return 10f; } DamageTypes damage2 = humanoid.GetCurrentWeapon().GetDamage(); return ((DamageTypes)(ref damage2)).GetTotalDamage(); } public static float TryWeaponList(GameObject[] weaponArray) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) float num = 10f; foreach (GameObject val in weaponArray) { ItemData itemData = val.GetComponent<ItemDrop>().m_itemData; if (itemData != null) { DamageTypes damage = itemData.GetDamage(); float totalDamage = ((DamageTypes)(ref damage)).GetTotalDamage(); if (totalDamage > num) { num = totalDamage; } } } return num; } public static float CalculateDamage(Character character, float percentTotal) { Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null); if ((Object)(object)val == (Object)null) { return 10f; } if (character.IsPlayer()) { return 10f; } float num = 10f; float num2 = TryCurrentWeapon(val); if (num2 > 0f && num2 > num) { num = num2; } float num3 = TryWeaponList(val.m_defaultItems); if (num3 > 0f && num3 > num) { num = num3; } float num4 = TryWeaponList(val.m_randomWeapon); if (num4 > 0f && num4 > num) { num = num4; } return num * percentTotal; } } public class ModifierAssetUtils { public static AssetBundle statusEffectBundle; public static AssetBundle modiferIconsBundle; public static Sprite swordIcon; public static Sprite shieldIcon; public static Sprite plusSquareIcon; public static Sprite circleIcon; public static Sprite soulIcon; public static Sprite skullIcon; public static Sprite appleIcon; public static Sprite shieldBrokenIcon; public static Sprite shieldSpearIcon; public static Sprite shieldMaceIcon; public static Sprite shieldSwordIcon; public static Sprite potionIcon; public static Sprite bloodIcon; public static Sprite bloodIconRed; public static Sprite heartIcon; public static Sprite earIcon; public static void Setup() { statusEffectBundle = AssetUtils.LoadAssetBundleFromResources("statusicon", Assembly.GetExecutingAssembly()); modiferIconsBundle = AssetUtils.LoadAssetBundleFromResources("modifiericons", Assembly.GetExecutingAssembly()); } public static void LoadAllIcons() { swordIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/Sword.png"); shieldIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/Shield.png"); plusSquareIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/PlusBox.png"); circleIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/Circle.png"); soulIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/SoulEater.png"); skullIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/Skull.png"); appleIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/Apple.png"); shieldBrokenIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/ShieldBroken.png"); shieldSpearIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/ShieldSpear.png"); shieldMaceIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/ShieldMace.png"); shieldSwordIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/ShieldSword.png"); potionIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/Potion.png"); heartIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/heartIcon.png"); bloodIcon = statusEffectBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/bloodIcon.png"); bloodIconRed = statusEffectBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/bloodIconRed.png"); earIcon = modiferIconsBundle.LoadAsset<Sprite>("Assets/WarpProjects/Modifiers/NewModifierIcons/Ear.png"); } } public enum MonsterModifierTypes { StaminaSiphon, EitrSiphon, ShieldBreaker, FoodDrain, IgnoreArmor, PoisonDeath, FrostDeath, FireDeath, HealDeath, StaggerDeath, TarDeath, PersonalShield, SoulEater, StaggerImmune, FireInfused, PoisonInfused, FrostInfused, LightningInfused, ElementalImmunity, PierceImmunity, BluntImmunity, SlashImmunity, FastMovement, FastAttackSpeed, DistantDetection, BloodLoss, Absorption, Vampiric, Forceful, Wet, Quiet, Knockback, ArmorCharge, FireTrail, ResistanceNotification, SplitSpawn, EliteMonster } public enum ModifierCategory { Offense, Defense, Utility, SplitSpawn, Elite } public class ModifierData { public int weight { get; set; } public List<float> color { get; set; } = null; } public class ModifierUtils { public static Dictionary<MonsterModifierTypes, ModifierData> modifiers = null; public static readonly Dictionary<MonsterModifierTypes, ModifierCategory> ModifierCategories = new Dictionary<MonsterModifierTypes, ModifierCategory> { { MonsterModifierTypes.StaminaSiphon, ModifierCategory.Offense }, { MonsterModifierTypes.EitrSiphon, ModifierCategory.Offense }, { MonsterModifierTypes.ShieldBreaker, ModifierCategory.Offense }, { MonsterModifierTypes.FoodDrain, ModifierCategory.Offense }, { MonsterModifierTypes.IgnoreArmor, ModifierCategory.Offense }, { MonsterModifierTypes.PoisonDeath, ModifierCategory.Offense }, { MonsterModifierTypes.FrostDeath, ModifierCategory.Offense }, { MonsterModifierTypes.FireDeath, ModifierCategory.Offense }, { MonsterModifierTypes.StaggerDeath, ModifierCategory.Offense }, { MonsterModifierTypes.TarDeath, ModifierCategory.Offense }, { MonsterModifierTypes.FireInfused, ModifierCategory.Offense }, { MonsterModifierTypes.PoisonInfused, ModifierCategory.Offense }, { MonsterModifierTypes.FrostInfused, ModifierCategory.Offense }, { MonsterModifierTypes.LightningInfused, ModifierCategory.Offense }, { MonsterModifierTypes.FastAttackSpeed, ModifierCategory.Offense }, { MonsterModifierTypes.BloodLoss, ModifierCategory.Offense }, { MonsterModifierTypes.Vampiric, ModifierCategory.Offense }, { MonsterModifierTypes.Forceful, ModifierCategory.Offense }, { MonsterModifierTypes.Wet, ModifierCategory.Offense }, { MonsterModifierTypes.Knockback, ModifierCategory.Offense }, { MonsterModifierTypes.PersonalShield, ModifierCategory.Defense }, { MonsterModifierTypes.ElementalImmunity, ModifierCategory.Defense }, { MonsterModifierTypes.PierceImmunity, ModifierCategory.Defense }, { MonsterModifierTypes.BluntImmunity, ModifierCategory.Defense }, { MonsterModifierTypes.SlashImmunity, ModifierCategory.Defense }, { MonsterModifierTypes.StaggerImmune, ModifierCategory.Defense }, { MonsterModifierTypes.Absorption, ModifierCategory.Defense }, { MonsterModifierTypes.FastMovement, ModifierCategory.Utility }, { MonsterModifierTypes.DistantDetection, ModifierCategory.Utility }, { MonsterModifierTypes.SoulEater, ModifierCategory.Utility }, { MonsterModifierTypes.HealDeath, ModifierCategory.Utility }, { MonsterModifierTypes.Quiet, ModifierCategory.Utility }, { MonsterModifierTypes.ResistanceNotification, ModifierCategory.Utility }, { MonsterModifierTypes.ArmorCharge, ModifierCategory.Utility }, { MonsterModifierTypes.FireTrail, ModifierCategory.Utility }, { MonsterModifierTypes.SplitSpawn, ModifierCategory.SplitSpawn }, { MonsterModifierTypes.EliteMonster, ModifierCategory.Elite } }; public static readonly HashSet<MonsterModifierTypes> BossExcludedModifiers = new HashSet<MonsterModifierTypes> { MonsterModifierTypes.PoisonDeath, MonsterModifierTypes.FireDeath, MonsterModifierTypes.FrostDeath, MonsterModifierTypes.StaggerDeath, MonsterModifierTypes.HealDeath, MonsterModifierTypes.TarDeath, MonsterModifierTypes.SplitSpawn, MonsterModifierTypes.EliteMonster, MonsterModifierTypes.Vampiric, MonsterModifierTypes.Absorption, MonsterModifierTypes.SoulEater }; public static readonly HashSet<MonsterModifierTypes> TamedExcludedModifiers = new HashSet<MonsterModifierTypes> { MonsterModifierTypes.SplitSpawn }; public static readonly MonsterModifierTypes[] ImmunityModifierGroup = new MonsterModifierTypes[4] { MonsterModifierTypes.PierceImmunity, MonsterModifierTypes.SlashImmunity, MonsterModifierTypes.BluntImmunity, MonsterModifierTypes.ElementalImmunity }; public static Color GetModifierColor(MonsterModifierTypes modifier) { //IL_0035: 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_0039: Unknown result type (might be due to invalid IL or missing references) List<float> color = modifiers[modifier].color; Color result = default(Color); ((Color)(ref result))..ctor(color[0], color[1], color[2], color[3]); return result; } public static Sprite GetModifierIcon(MonsterModifierTypes modifier) { if (modifier == MonsterModifierTypes.FireInfused || modifier == MonsterModifierTypes.FrostInfused || modifier == MonsterModifierTypes.PoisonInfused || modifier == MonsterModifierTypes.LightningInfused) { return ModifierAssetUtils.swordIcon; } if (modifier == MonsterModifierTypes.ShieldBreaker || modifier == MonsterModifierTypes.IgnoreArmor) { return ModifierAssetUtils.shieldBrokenIcon; } if (modifier == MonsterModifierTypes.StaminaSiphon || modifier == MonsterModifierTypes.EitrSiphon) { return ModifierAssetUtils.potionIcon; } switch (modifier) { case MonsterModifierTypes.FoodDrain: return ModifierAssetUtils.appleIcon; default: if (modifier != MonsterModifierTypes.TarDeath) { if (modifier == MonsterModifierTypes.ElementalImmunity || modifier == MonsterModifierTypes.StaggerImmune) { return ModifierAssetUtils.shieldIcon; } switch (modifier) { case MonsterModifierTypes.PersonalShield: return ModifierAssetUtils.circleIcon; case MonsterModifierTypes.SoulEater: return ModifierAssetUtils.soulIcon; case MonsterModifierTypes.PierceImmunity: return ModifierAssetUtils.shieldSpearIcon; case MonsterModifierTypes.SlashImmunity: return ModifierAssetUtils.shieldSwordIcon; case MonsterModifierTypes.BluntImmunity: return ModifierAssetUtils.shieldMaceIcon; default: if (modifier != MonsterModifierTypes.Forceful) { if (modifier == MonsterModifierTypes.BloodLoss || modifier == MonsterModifierTypes.Wet) { return ModifierAssetUtils.bloodIcon; } if (modifier == MonsterModifierTypes.Absorption || modifier == MonsterModifierTypes.Vampiric) { return ModifierAssetUtils.heartIcon; } switch (modifier) { case MonsterModifierTypes.Quiet: return ModifierAssetUtils.earIcon; default: if (modifier != MonsterModifierTypes.FireTrail) { switch (modifier) { case MonsterModifierTypes.ResistanceNotification: return ModifierAssetUtils.potionIcon; case MonsterModifierTypes.SplitSpawn: return ModifierAssetUtils.skullIcon; case MonsterModifierTypes.EliteMonster: return ModifierAssetUtils.skullIcon; default: Debug.Log((object)"Could not find icon for modifier"); return ModifierAssetUtils.plusSquareIcon; } } goto case MonsterModifierTypes.Knockback; case MonsterModifierTypes.Knockback: case MonsterModifierTypes.ArmorCharge: return ModifierAssetUtils.plusSquareIcon; } } goto case MonsterModifierTypes.FastMovement; case MonsterModifierTypes.FastMovement: case MonsterModifierTypes.FastAttackSpeed: case MonsterModifierTypes.DistantDetection: return ModifierAssetUtils.plusSquareIcon; } } goto case MonsterModifierTypes.PoisonDeath; case MonsterModifierTypes.PoisonDeath: case MonsterModifierTypes.FrostDeath: case MonsterModifierTypes.FireDeath: case MonsterModifierTypes.HealDeath: case MonsterModifierTypes.StaggerDeath: return ModifierAssetUtils.skullIcon; } } public static float BossOffenseMult(Character attacker) { return ((Object)(object)attacker != (Object)null && attacker.IsBoss()) ? ((float)MonsterModifiersPlugin.Cfg_Boss_OffenseMultiplier.Value / 100f) : 1f; } public static float BossHealMult(Character monster) { return ((Object)(object)monster != (Object)null && monster.IsBoss()) ? ((float)MonsterModifiersPlugin.Cfg_Boss_HealMultiplier.Value / 100f) : 1f; } public static float ScaleReductionEffect(float configMult, float bossOffenseMult) { return 1f - (1f - configMult) * bossOffenseMult; } public static int GetModifierWeight(MonsterModifierTypes modifier) { return modifiers[modifier].weight; } public static int GetAvailableModifierCount(HashSet<MonsterModifierTypes>? excluded = null) { int num = 0; foreach (KeyValuePair<MonsterModifierTypes, ModifierData> modifier in modifiers) { if (modifier.Value.weight > 0 && (excluded == null || !excluded.Contains(modifier.Key))) { num++; } } return num; } public static List<MonsterModifierTypes> RollRandomModifiers(int numModifiers, HashSet<MonsterModifierTypes>? excluded = null, int splitGeneration = 0) { List<MonsterModifierTypes> list = new List<MonsterModifierTypes>(); Dictionary<MonsterModifierTypes, ModifierData> dictionary = new Dictionary<MonsterModifierTypes, ModifierData>(modifiers); if (excluded != null) { foreach (MonsterModifierTypes item in excluded) { dictionary.Remove(item); } } Dictionary<ModifierCategory, List<MonsterModifierTypes>> buckets = new Dictionary<ModifierCategory, List<MonsterModifierTypes>>(); foreach (KeyValuePair<MonsterModifierTypes, ModifierData> item2 in dictionary) { if (item2.Value.weight > 0) { ModifierCategory value; ModifierCategory key = (ModifierCategories.TryGetValue(item2.Key, out value) ? value : ModifierCategory.Utility); if (!buckets.ContainsKey(key)) { buckets[key] = new List<MonsterModifierTypes>(); } buckets[key].Add(item2.Key); } } for (int i = 0; i < numModifiers; i++) { if (dictionary.Count == 0) { break; } int num = (buckets.ContainsKey(ModifierCategory.Offense) ? MonsterModifiersPlugin.Cfg_Offense_Probability.Value : 0); int num2 = (buckets.ContainsKey(ModifierCategory.Defense) ? MonsterModifiersPlugin.Cfg_Defense_Probability.Value : 0); int num3 = (buckets.ContainsKey(ModifierCategory.Utility) ? MonsterModifiersPlugin.Cfg_Utility_Probability.Value : 0); float num4 = (float)Math.Pow(0.5, splitGeneration); int num5 = (buckets.ContainsKey(ModifierCategory.SplitSpawn) ? Mathf.RoundToInt((float)MonsterModifiersPlugin.Cfg_SplitSpawn_Probability.Value * num4) : 0); int num6 = 0; if (MonsterModifiersPlugin.Cfg_EliteMonster_Enabled.Value == MonsterModifiersPlugin.Toggle.On && buckets.ContainsKey(ModifierCategory.Elite)) { num6 = MonsterModifiersPlugin.Cfg_EliteMonster_Probability.Value; } else if (MonsterModifiersPlugin.Cfg_EliteMonster_Enabled.Value == MonsterModifiersPlugin.Toggle.Off) { if (buckets.ContainsKey(ModifierCategory.Offense)) { num += 5; } if (buckets.ContainsKey(ModifierCategory.Defense)) { num2 += 5; } } int num7 = num + num2 + num3 + num5 + num6; MonsterModifierTypes monsterModifierTypes; if (num7 <= 0) { int num8 = 0; foreach (ModifierData value4 in dictionary.Values) { num8 += value4.weight; } if (num8 <= 0) { break; } int num9 = Random.Range(0, num8); int num10 = 0; monsterModifierTypes = MonsterModifierTypes.StaminaSiphon; foreach (KeyValuePair<MonsterModifierTypes, ModifierData> item3 in dictionary) { num10 += item3.Value.weight; if (num9 < num10) { monsterModifierTypes = item3.Key; break; } } } else { int num11 = Random.Range(0, num7); ModifierCategory key2 = ((num11 >= num) ? ((num11 < num + num2) ? ModifierCategory.Defense : ((num11 < num + num2 + num3) ? ModifierCategory.Utility : ((num11 >= num + num2 + num3 + num5) ? ModifierCategory.Elite : ModifierCategory.SplitSpawn))) : ModifierCategory.Offense); List<MonsterModifierTypes> list2 = buckets[key2]; monsterModifierTypes = list2[Random.Range(0, list2.Count)]; } list.Add(monsterModifierTypes); dictionary.Remove(monsterModifierTypes); RemoveFromBuckets(monsterModifierTypes); if (monsterModifierTypes == MonsterModifierTypes.EliteMonster) { dictionary.Remove(MonsterModifierTypes.SplitSpawn); dictionary.Remove(MonsterModifierTypes.HealDeath); dictionary.Remove(MonsterModifierTypes.Vampiric); dictionary.Remove(MonsterModifierTypes.Absorption); RemoveFromBuckets(MonsterModifierTypes.SplitSpawn); RemoveFromBuckets(MonsterModifierTypes.HealDeath); RemoveFromBuckets(MonsterModifierTypes.Vampiric); RemoveFromBuckets(MonsterModifierTypes.Absorption); } if (Array.IndexOf(ImmunityModifierGroup, monsterModifierTypes) < 0) { continue; } MonsterModifierTypes[] immunityModifierGroup = ImmunityModifierGroup; foreach (MonsterModifierTypes monsterModifierTypes2 in immunityModifierGroup) { if (monsterModifierTypes2 != monsterModifierTypes) { dictionary.Remove(monsterModifierTypes2); RemoveFromBuckets(monsterModifierTypes2); } } } return list; void RemoveFromBuckets(MonsterModifierTypes type) { ModifierCategory value2; ModifierCategory key3 = (ModifierCategories.TryGetValue(type, out value2) ? value2 : ModifierCategory.Utility); if (buckets.TryGetValue(key3, out List<MonsterModifierTypes> value3)) { value3.Remove(type); if (value3.Count == 0) { buckets.Remove(key3); } } } } public static bool RunRPCDamageChecks(Character character, HitData hit) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 if (hit == null || (Object)(object)character == (Object)null) { return false; } if (((DamageTypes)(ref hit.m_damage)).GetTotalDamage() == 0f) { return false; } if ((int)hit.m_hitType != 1) { return false; } return true; } public static bool RunHitChecks(HitData hit) { Character attacker = hit.GetAttacker(); if ((Object)(object)attacker == (Object)null) { return false; } if (attacker.IsPlayer()) { return false; } return true; } public static bool TryGetModifier(Character character, out MonsterModifier modifier) { modifier = ((Component)character).GetComponent<MonsterModifier>(); return (Object)(object)modifier != (Object)null; } } public class PrefabUtils { public static GameObject leechDeathVFX; public static GameObject leechDeathSFX; public static void CreateCustomPrefabs() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0139: 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) //IL_015d: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = PrefabManager.Instance.GetPrefab("shaman_heal_aoe"); GameObject val = PrefabManager.Instance.CreateClonedPrefab("healCustomPrefab", prefab); CustomPrefab val2 = new CustomPrefab(val, false); Aoe component = val2.Prefab.GetComponent<Aoe>(); component.m_statusEffect = ""; GameObject prefab2 = PrefabManager.Instance.GetPrefab("Mistile"); GameObject val3 = PrefabManager.Instance.CreateClonedPrefab("mistleCustomPrefab", prefab2); CustomPrefab val4 = new CustomPrefab(val3, false); Character component2 = (Character)(object)val4.Prefab.GetComponent<Humanoid>(); component2.m_speed = 0f; component2.m_flyFastSpeed = 0f; component2.m_flySlowSpeed = 0f; component2.m_name = "$modifier_mistile"; val4.Prefab.GetComponent<CharacterTimedDestruction>().m_timeoutMin = 2f; val4.Prefab.GetComponent<CharacterTimedDestruction>().m_timeoutMax = 4f; GameObject prefab3 = PrefabManager.Instance.GetPrefab("fx_DvergerMage_Mistile_attack"); GameObject val5 = PrefabManager.Instance.CreateClonedPrefab("staggerDeathNovaCustomPrefab", prefab3); CustomPrefab val6 = new CustomPrefab(val5, false); GameObject gameObject = ((Component)ExposedGameObjectExtension.FindDeepChild(val6.Prefab, "shockwave (1)", (IterativeSearchType)1)).gameObject; ParticleSystem component3 = gameObject.GetComponent<ParticleSystem>(); MainModule main = component3.main; ((MainModule)(ref main)).startRotationX = new MinMaxCurve((float)Math.PI / 2f); ((MainModule)(ref main)).startRotationY = new MinMaxCurve(0f); ((MainModule)(ref main)).startRotationZ = new MinMaxCurve(0f); GameObject prefab4 = PrefabManager.Instance.GetPrefab("skeleton_bow"); CustomItem val7 = CreateElementalBow(prefab4, "skeletonBow", "Fire", "bow_projectile_fire"); CustomItem val8 = CreateElementalBow(prefab4, "skeletonBow", "Frost", "bow_projectile_frost"); CustomItem val9 = CreateElementalBow(prefab4, "skeletonBow", "Poison", "bow_projectile_poison"); GameObject prefab5 = PrefabManager.Instance.GetPrefab("draugr_bow"); CustomItem val10 = CreateElementalBow(prefab5, "draugrBow", "Fire", "bow_projectile_fire"); CustomItem val11 = CreateElementalBow(prefab5, "draugrBow", "Frost", "bow_projectile_frost"); CustomItem val12 = CreateElementalBow(prefab5, "draugrBow", "Poison", "bow_projectile_poison"); PrefabManager.Instance.AddPrefab(val2); PrefabManager.Instance.AddPrefab(val4); PrefabManager.Instance.AddPrefab(val6); ItemManager.Instance.AddItem(val7); ItemManager.Instance.AddItem(val8); ItemManager.Instance.AddItem(val9); ItemManager.Instance.AddItem(val10); ItemManager.Instance.AddItem(val11); ItemManager.Instance.AddItem(val12); leechDeathVFX = PrefabManager.Instance.GetPrefab("vfx_leech_death"); leechDeathSFX = PrefabManager.Instance.GetPrefab("sfx_leech_death"); PrefabManager.OnVanillaPrefabsAvailable -= CreateCustomPrefabs; } private static CustomItem CreateElementalBow(GameObject baseBow, string baseName, string element, string projectilePrefabName) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown GameObject val = PrefabManager.Instance.CreateClonedPrefab(baseName + "CustomPrefab_" + element, baseBow); CustomItem val2 = new CustomItem(val, false); ItemData itemData = val2.ItemPrefab.GetComponent<ItemDrop>().m_itemData; itemData.m_shared.m_attack.m_attackProjectile = PrefabManager.Instance.GetPrefab(projectilePrefabName); return val2; } } public static class SpawnCommands { [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static class Patch_Terminal_InitTerminal { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__1_0; internal void <Postfix>b__1_0(ConsoleEventArgs args) { if (args.Length > 2) { string creatureName = args[1]; string modifierName = args[2]; int result; int level = ((args.Length > 3 && int.TryParse(args[3], out result)) ? Mathf.Clamp(result, 1, 5) : 2); SpawnModifier(creatureName, modifierName, level); } else { args.Context.AddString("Usage: modifier [creature] [modifier] [level=2]"); } } } [HarmonyPriority(800)] private static void Prefix(out bool __state) { __state = Terminal.m_terminalInitialized; } private static void Postfix(bool __state) { //IL_004c: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown if (__state) { return; } MonsterModifiersPlugin.MonsterModifiersLogger.LogInfo((object)"Adding Terminal Commands for monster modifier spawning."); object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (args.Length > 2) { string creatureName = args[1]; string modifierName = args[2]; int result; int level = ((args.Length > 3 && int.TryParse(args[3], out result)) ? Mathf.Clamp(result, 1, 5) : 2); SpawnModifier(creatureName, modifierName, level); } else { args.Context.AddString("Usage: modifier [creature] [modifier] [level=2]"); } }; <>c.<>9__1_0 = val; obj = (object)val; } new ConsoleCommand("modifier", "[creature] [modifier] [level=2]", (ConsoleEvent)obj, true, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } public static void SpawnModifier(string creatureName, string modifierName, int level = 2) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } GameObject prefab = ZNetScene.instance.GetPrefab(creatureName); MonsterModifierTypes result; if ((Object)(object)prefab == (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)1, "Missing object " + creatureName, 0, (Sprite)null, false); } else if (Enum.TryParse<MonsterModifierTypes>(modifierName, ignoreCase: true, out result)) { Vector3 insideUnitSphere = Random.insideUnitSphere; GameObject val = Object.Instantiate<GameObject>(prefab, ((Component)Player.m_localPlayer).transform.position + ((Component)Player.m_localPlayer).transform.forward * 2f + Vector3.up + insideUnitSphere, Quaternion.identity); Character component = val.GetComponent<Character>(); if (component.m_nview.GetZDO().IsOwner()) { component.SetLevel(level); component.m_nview.GetZDO().Set("modifiers", modifierName); } } else { ((Character)Player.m_localPlayer).Message((MessageType)1, "Invalid modifier name: " + modifierName, 0, (Sprite)null, false); } } } public class StatusEffectUtils { public static void CreateCustomStatusEffects() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown BloodLoss_SE bloodLoss_SE = ScriptableObject.CreateInstance<BloodLoss_SE>(); ((Object)bloodLoss_SE).name = "BloodLossStatusEffect"; ((StatusEffect)bloodLoss_SE).m_name = "$se_bloodLoss"; ((StatusEffect)bloodLoss_SE).m_icon = ModifierAssetUtils.bloodIconRed; CustomStatusEffect val = new CustomStatusEffect((StatusEffect)(object)bloodLoss_SE, false); HealDeath_SE healDeath_SE = ScriptableObject.CreateInstance<HealDeath_SE>(); ((Object)healDeath_SE).name = "HealDeathStatusEffect"; ((StatusEffect)healDeath_SE).m_name = "$se_healDeath"; ((StatusEffect)healDeath_SE).m_ttl = 5f; ((SE_Stats)healDeath_SE).m_tickInterval = 1f; ((SE_Stats)healDeath_SE).m_healthOverTimeDuration = 5f; ((SE_Stats)healDeath_SE).m_healthOverTimeInterval = 0.5f; ((SE_Stats)healDeath_SE).m_healthOverTimeTicks = 10f; ((SE_Stats)healDeath_SE).m_healthOverTime = 0f; CustomStatusEffect val2 = new CustomStatusEffect((StatusEffect)(object)healDeath_SE, false); ItemManager.Instance.AddStatusEffect(val); ItemManager.Instance.AddStatusEffect(val2); } } public class TranslationUtils { public static CustomLocalization Localization; public static void AddLocalizations() { Localization = LocalizationManager.Instance.GetLocalization(); CustomLocalization localization = Localization; string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "$se_bloodLoss", "Blood Loss" }, { "$modifier_mistile", "Stagger Bomb" } }); } } public class ShaderLogFilter : ILogListener, IDisposable { private readonly ILogListener _inner; private ShaderLogFilter(ILogListener inner) { _inner = inner; } public static void Install() { ICollection<ILogListener> listeners = Logger.Listeners; foreach (ILogListener item in listeners) { if (item is ShaderLogFilter) { return; } } List<ILogListener> list = new List<ILogListener>(listeners); listeners.Clear(); foreach (ILogListener item2 in list) { listeners.Add((ILogListener)(object)new ShaderLogFilter(item2)); } } public void LogEvent(object sender, LogEventArgs eventArgs) { if (eventArgs == null || eventArgs.Data?.ToString()?.Contains("Failed to find expected binary shader data") != true) { ILogListener inner = _inner; if (inner != null) { inner.LogEvent(sender, eventArgs); } } } public void Dispose() { ((IDisposable)_inner)?.Dispose(); } } public class WorldUtils { private static readonly Collider[] s_buffer = (Collider[])(object)new Collider[512]; public static List<Character> GetAllCharacter(Vector3 position, float range) { //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_0008: 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) int num = Physics.OverlapBoxNonAlloc(position, Vector3.one * range, s_buffer, Quaternion.identity); List<Character> list = new List<Character>(); for (int i = 0; i < num; i++) { Character component = ((Component)((Component)s_buffer[i]).transform.root).GetComponent<Character>(); if ((Object)(object)component != (Object)null && !list.Contains(component)) { list.Add(component); } } return list; } } public class YamlUtils { public static string defaultModifierValues; public static void ParseDefaultYamls() { defaultModifierValues = AssetUtils.LoadTextFromResources("modifierValues.yml"); IDeserializer deserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build(); ModifierUtils.modifiers = deserializer.Deserialize<Dictionary<MonsterModifierTypes, ModifierData>>(new StringReader(defaultModifierValues)); MonsterModifiersPlugin.MonsterModifiersLogger.LogInfo((object)($"[YamlUtils] Loaded {ModifierUtils.modifiers.Count} modifier entries. " + $"EliteMonster present: {ModifierUtils.modifiers.ContainsKey(MonsterModifierTypes.EliteMonster)}")); } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] public static class RegisterAndCheckVersion { private static void Prefix(ZNetPeer peer, ref ZNet __instance) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown MonsterModifiersPlugin.MonsterModifiersLogger.LogDebug((object)"Registering version RPC handler"); peer.m_rpc.Register<ZPackage>("MonsterModifiers_VersionCheck", (Action<ZRpc, ZPackage>)RpcHandlers.RPC_MonsterModifiers_Version); MonsterModifiersPlugin.MonsterModifiersLogger.LogDebug((object)"Invoking version check"); ZPackage val = new ZPackage(); val.Write("1.3.126"); peer.m_rpc.Invoke("MonsterModifiers_VersionCheck", new object[1] { val }); } } [HarmonyPatch(typeof(ZNet), "RPC_PeerInfo")] public static class VerifyClient { private static bool Prefix(ZRpc rpc, ZPackage pkg, ref ZNet __instance) { if (!__instance.IsServer() || RpcHandlers.ValidatedPeers.Contains(rpc)) { return true; } MonsterModifiersPlugin.MonsterModifiersLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") never sent version or couldn't due to previous disconnect, disconnecting")); rpc.Invoke("Error", new object[1] { 3 }); return false; } private static void Postfix(ZNet __instance) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), "MonsterModifiersRequestAdminSync", new object[1] { (object)new ZPackage() }); } } [HarmonyPatch(typeof(FejdStartup), "ShowConnectError")] public class ShowConnectionError { private static void Postfix(FejdStartup __instance) { if (__instance.m_connectionFailedPanel.activeSelf) { __instance.m_connectionFailedError.fontSizeMax = 25f; __instance.m_connectionFailedError.fontSizeMin = 15f; TMP_Text connectionFailedError = __instance.m_connectionFailedError; connectionFailedError.text = connectionFailedError.text + "\n" + MonsterModifiersPlugin.ConnectionError; } } } [HarmonyPatch(typeof(ZNet), "Disconnect")] public static class RemoveDisconnectedPeerFromVerified { private static void Prefix(ZNetPeer peer, ref ZNet __instance) { if (__instance.IsServer()) { MonsterModifiersPlugin.MonsterModifiersLogger.LogInfo((object)("Peer (" + peer.m_rpc.m_socket.GetHostName() + ") disconnected, removing from validated list")); RpcHandlers.ValidatedPeers.Remove(peer.m_rpc); } } } public static class RpcHandlers { public static readonly List<ZRpc> ValidatedPeers = new List<ZRpc>(); public static void RPC_MonsterModifiers_Version(ZRpc rpc, ZPackage pkg) { string text = pkg.ReadString(); MonsterModifiersPlugin.MonsterModifiersLogger.LogInfo((object)("Version check, local: 1.3.126, remote: " + text)); if (text != "1.3.126") { MonsterModifiersPlugin.ConnectionError = "MonsterModifiers Installed: 1.3.126\n Needed: " + text; if (ZNet.instance.IsServer()) { MonsterModifiersPlugin.MonsterModifiersLogger.LogWarning((object)("Peer (" + rpc.m_socket.GetHostName() + ") has incompatible version, disconnecting...")); rpc.Invoke("Error", new object[1] { 3 }); } } else if (!ZNet.instance.IsServer()) { MonsterModifiersPlugin.MonsterModifiersLogger.LogInfo((object)"Received same version from server!"); } else { MonsterModifiersPlugin.MonsterModifiersLogger.LogInfo((object)("Adding peer (" + rpc.m_socket.GetHostName() + ") to validated list")); ValidatedPeers.Add(rpc); } } } } namespace MonsterModifiers.Visuals { public class BowVisuals { public static GameObject? GetModifierVisual(string itemName, List<MonsterModifierTypes> modifiers) { if (!(itemName == "skeleton_bow")) { if (itemName == "draugr_bow") { return GetBowVisual("draugrBow", modifiers); } return null; } return GetBowVisual("skeletonBow", modifiers); } private static GameObject? GetBowVisual(string prefabPrefix, List<MonsterModifierTypes> modifiers) { if (modifiers.Contains(MonsterModifierTypes.FireInfused)) { return PrefabManager.Instance.GetPrefab(prefabPrefix + "CustomPrefab_Fire"); } if (modifiers.Contains(MonsterModifierTypes.FrostInfused)) { return PrefabManager.Instance.GetPrefab(prefabPrefix + "CustomPrefab_Frost"); } if (modifiers.Contains(MonsterModifierTypes.PoisonInfused)) { return PrefabManager.Instance.GetPrefab(prefabPrefix + "CustomPrefab_Poison"); } return null; } } } namespace MonsterModifiers.StatusEffects { public class BloodLoss_SE : StatusEffect { public int bloodLossAmount = 0; public int bloodLossCap; private float reductionTimer = 0f; private bool shouldRemove = false; public override void Setup(Character character) { ((StatusEffect)this).Setup(character); bloodLossCap = Mathf.FloorToInt(character.GetMaxHealth()); } public override void UpdateStatusEffect(float dt) { //IL_007f: 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_00a1: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)base.m_character == (Object)null) { shouldRemove = true; return; } reductionTimer += dt; if (reductionTimer >= 60f) { bloodLossAmount = Mathf.Max(0, bloodLossAmount - 10); reductionTimer = 0f; } if (bloodLossAmount > bloodLossCap) { bloodLossAmount = 0; HitData val = new HitData { m_damage = { m_slash = base.m_character.GetMaxHealth() * 0.3f } }; base.m_character.Damage(val); Object.Instantiate<GameObject>(PrefabUtils.leechDeathSFX, ((Component)base.m_character).transform.position, ((Component)base.m_character).transform.rotation); Object.Instantiate<GameObject>(PrefabUtils.leechDeathVFX, ((Component)base.m_character).transform.position, ((Component)base.m_character).transform.rotation); shouldRemove = true; } } public override string GetIconText() { return bloodLossAmount.ToString(); } public override void OnDamaged(HitData hit, Character attacker) { if (ModifierUtils.RunRPCDamageChecks(attacker, hit) && ModifierUtils.RunHitChecks(hit) && ModifierUtils.TryGetModifier(attacker, out MonsterModifier modifier) && modifier.Modifiers.Contains(MonsterModifierTypes.BloodLoss)) { bloodLossAmount += Mathf.FloorToInt(hit.GetTotalDamage()); } } public override bool IsDone() { return shouldRemove || ((StatusEffect)this).IsDone(); } } public class HealDeath_SE : SE_Stats { public override void SetLevel(int itemLevel, float skillLevel) { base.m_healthPerTick = skillLevel / 10f; } } } namespace MonsterModifiers.Patches { [HarmonyPatch(typeof(EnemyHud), "ShowHud")] public static class EnemyHud_ShowHud_Patch { private static void Postfix(EnemyHud __instance, Character c, bool isMount) { if (!(c.IsPlayer() || isMount) && ModifierUtils.TryGetModifier(c, out MonsterModifier modifier)) { ChangeEnemyStars(c, modifier.Modifiers, modifier.IsBossCharacter, modifier.OverflowStars); } } public static void ChangeEnemyStars(Character character, List<MonsterModifierTypes> modifiers, bool isBoss = false, int overflowStars = 0) { //IL_016a: Unknown result type (might be due to invalid IL or missing references) if ((character.GetLevel() <= 1 && !isBoss) || !EnemyHud.instance.m_huds.TryGetValue(character, out var value)) { return; } GameObject gui = value.m_gui; int num = 0; int num2 = 7; if (CompatibilityUtils.isStarLevelsExpandedInstalled && character.GetLevel() > num2) { num = 2; } int num3 = (isBoss ? MonsterModifiersPlugin.Configurations_Boss_Modifiers.Value : 0); int num4 = modifiers.Count - num3; for (int i = num; i < gui.transform.childCount; i++) { Transform child = gui.transform.GetChild(i); if (!((Object)child).name.StartsWith("level_" + (modifiers.Count - num3 + overflowStars + 1)) && (!((Object)child).name.StartsWith("level_n") || !((Component)child).gameObject.activeSelf)) { continue; } for (int j = 0; j < ((Component)child).transform.childCount; j++) { Transform child2 = ((Component)child).transform.GetChild(j); if (((Object)child2).name.StartsWith("star") && ((Component)child2).gameObject.activeSelf && j < num4) { int index = num3 + j; ((Component)child2).GetComponent<Image>().sprite = ModifierUtils.GetModifierIcon(modifiers[index]); ((Graphic)((Component)child2).GetComponent<Image>()).color = ModifierUtils.GetModifierColor(modifiers[index]); ((Component)child2.GetChild(0)).gameObject.SetActive(false); } } } } } public static class RtDSpawnControl { private const string PrefabSuffix = "_RtD"; private const string DividerSection = "----RTD Monster Spawn----"; private const string SectionPrefix = "RTD Monster Spawn - "; private static readonly (string Display, string Prefix)[] Biomes = new(string, string)[8] { ("Meadows", "Meadows"), ("Black Forest", "BlackForest"), ("Swamp", "Swamp"), ("Mountain", "Mountain"), ("Plains", "Plains"), ("Mistlands", "Mistlands"), ("Ash Lands", "AshLands"), ("Deep North", "DeepNorth") }; private static readonly HashSet<string> DefaultOffMeadowsHumanoids = new HashSet<string> { "MeadowsHobgoblin_RtD", "MeadowsKobald_RtD" }; private static ConfigFile _config; private static ConfigEntry<bool> _masterToggle; private static readonly Dictionary<string, ConfigEntry<bool>> Entries = new Dictionary<string, ConfigEntry<bool>>(); private static readonly string[] KnownCreatures = new string[144] { "AshLandsDarkS_RtD", "AshLandsFairyS_RtD", "AshLandsFairy_RtD", "AshLandsHorror_RtD", "AshLandsPixie_RtD", "AshLandsWhispA_RtD", "AshLandsWhispF_RtD", "Assassin_RtD", "Befouler_RtD", "Belzor_RtD", "Berserker_RtD", "BlacKForestTreeEnt_RtD", "BlacKForestTroll_RtD", "BlackForestFairy_RtD", "BlackForestGolem_RtD", "BlackForestHorror_RtD", "BlackForestNatureS_RtD", "BlackForestPixie_RtD", "BlackForestShockG_RtD", "BlackForestUndead_RtD", "BlackForestWhispA_RtD", "BlackForestWhispF_RtD", "BoneFish_RtD", "BoneSquid_RtD", "CatFish_RtD", "Cod_RtD", "Crab_RtD", "CursedKnight_RtD", "Davil_RtD", "DeepNorthArcaneS_RtD", "DeepNorthFairyS_RtD", "DeepNorthFairy_RtD", "DeepNorthHorror_RtD", "DeepNorthPixie1_RtD", "DeepNorthPixie2_RtD", "DeepNorthPixie3_RtD", "DeepNorthWhispA_RtD", "DeepNorthWhispF_RtD", "Demon_RtD", "Dolphin_RtD", "DragonBoarTamed_RtD", "DragonBoar_RtD", "DragonPiglet_RtD", "EikthyrSpirit_RtD", "ElfHunterF_RtD", "ElfHunterM_RtD", "ElfPriestM_RtD", "ElfWarriorF_RtD", "ElfWarriorM_RtD", "Executioner_RtD", "FaeWolfIceCub_RtD", "FaeWolfIceTamed_RtD", "FaeWolfIce_RtD", "FaeWolfLighteningCub_RtD", "FaeWolfLighteningTamed_RtD", "FaeWolfLightening_RtD", "Fairy4_RtD", "FallenCrusader_RtD", "GreatWhiteShark_RtD", "HammerheadShark_RtD", "HumpbackWhale_RtD", "LichKing_RtD", "LuminousLooker_RtD", "Manta_RtD", "Marlin_RtD", "MeadowsAirS_RtD", "MeadowsFairy_RtD", "MeadowsHobgoblin_RtD", "MeadowsHorror_RtD", "MeadowsKobald_RtD", "MeadowsNatureS_RtD", "MeadowsPixie_RtD", "MeadowsSpider_RtD", "MeadowsWhispA_RtD", "MeadowsWhispF_RtD", "Miniboss_RtD", "MirLizard_RtD", "MirRake_RtD", "Mirmaid_RtD", "MistlandsFairyS_RtD", "MistlandsFairy_RtD", "MistlandsHarpy_RtD", "MistlandsHorror_RtD", "MistlandsPixie_RtD", "MistlandsSpider1_RtD", "MistlandsUniverseS_RtD", "MistlandsWhispA_RtD", "MistlandsWhispF_RtD", "MistlandsWolf_RtD", "MountainBoss_RtD", "MountainFairy_RtD", "MountainGriffin_RtD", "MountainHolyS_RtD", "MountainHorror_RtD", "MountainIceS_RtD", "MountainPixie_RtD", "MountainUndead_RtD", "MountainWerewolf_RtD", "MountainWhispA_RtD", "MountainWhispF_RtD", "MurkPod_RtD", "NeckSummon_RtD", "Neck_RtD", "Necromancer_RtD", "NorthernTroll_RtD", "OceanHolyS_RtD", "OceanWaterS_RtD", "Orca_RtD", "PlainsBoss_RtD", "PlainsChimera_RtD", "PlainsChomper1_RtD", "PlainsDragonide_RtD", "PlainsFairy_RtD", "PlainsHolyS_RtD", "PlainsHorror_RtD", "PlainsOrc_RtD", "PlainsPixie_RtD", "PlainsVoidS_RtD", "PlainsWhispA_RtD", "PlainsWhispF_RtD", "Reptile_RtD", "SeekerMutant_RtD", "Shark_RtD", "SpermWhale_RtD", "SpiderQueen_RtD", "Squid_RtD", "SwampBoss_RtD", "SwampChaser_RtD", "SwampDarkS_RtD", "SwampFairy_RtD", "SwampGhoul_RtD", "SwampMummy_RtD", "SwampNatureS_RtD", "SwampPixie_RtD", "SwampRat_RtD", "SwampSludger_RtD", "SwampVampire_RtD", "SwampWhispA_RtD", "SwampWhispF_RtD", "Thor_RtD", "TrollKing_RtD", "Tuna_RtD", "Turtle_RtD", "Wizard_RtD" }; public static void Init(ConfigFile config) { _config = config; if (!Chainloader.PluginInfos.Keys.Any((string g) => g.StartsWith("soloredis.rtd", StringComparison.OrdinalIgnoreCase))) { return; } bool saveOnConfigSet = _config.SaveOnConfigSet; _config.SaveOnConfigSet = false; BindMasterToggle(); foreach (string item in OrderedByBiome(KnownCreatures)) { BindEntry(item, null); } _config.SaveOnConfigSet = saveOnConfigSet; if (saveOnConfigSet) { _config.Save(); } } private static void BindMasterToggle() { if (_masterToggle == null) { _masterToggle = ConfigFileExtensions.BindConfig<bool>(_config, "----RTD Monster Spawn----", "Enable RtD Field Spawn Control", true, "Master switch. When On, RtD creatures whose own 'Spawn' entry below is Off no longer spawn outside dungeons. Dungeon spawns are never blocked.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } } private static void BindEntry(string prefabName, string nameToken) { if (!Entries.ContainsKey(prefabName)) { Entries[prefabName] = ConfigFileExtensions.BindConfig<bool>(_config, BiomeSection(prefabName), DisplayName(prefabName) + " Spawn", IsDefaultOn(prefabName), Describe(prefabName, nameToken), true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); } } private static IEnumerable<string> OrderedByBiome(IEnumerable<string> names) { return names.OrderBy(delegate(string n) { int num = Array.FindIndex(Biomes, ((string Display, string Prefix) b) => n.StartsWith(b.Prefix, StringComparison.Ordinal)); return (num < 0) ? int.MaxValue : num; }).ThenBy<string, string>((string n) => n, StringComparer.Ordinal); } private static void UpdateDescription(ConfigEntry<bool> entry, string description) { try { typeof(ConfigDescription).GetField("<Description>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(((ConfigEntryBase)entry).Description, description); } catch (Exception ex) { MonsterModifiersPlugin.MonsterModifiersLogger.LogDebug((object)("RtD spawn control: could not update tooltip: " + ex.Message)); } } internal static bool IsBlocked(GameObject prefab, Vector3 position) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null || _masterToggle == null || !_masterToggle.Value) { return false; } if (Character.InInterior(position)) { return false; } ConfigEntry<bool> value; return Entries.TryGetValue(((Object)prefab).name, out value) && !value.Value; } private static bool IsDefaultOn(string prefabName) { if (prefabName.IndexOf("Fairy", StringComparison.OrdinalIgnoreCase) >= 0 || prefabName.IndexOf("Pixie", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } return !DefaultOffMeadowsHumanoids.Contains(prefabName); } private static string BiomeSection(string prefabName) { (string, string)[] biomes = Biomes; for (int i = 0; i < biomes.Length; i++) { var (text, value) = biomes[i]; if (prefabName.StartsWith(value, StringComparison.Ordinal)) { return "RTD Monster Spawn - " + text; } } return "RTD Monster Spawn - Other"; } private static string DisplayName(string prefabName) { string text = prefabName.Substring(0, prefabName.Length - "_RtD".Length); (string, string)[] biomes = Biomes; for (int i = 0; i < biomes.Length; i++) { string item = biomes[i].Item2; if (text.StartsWith(item, StringComparison.Ordinal) && text.Length > item.Length) { return text.Substring(item.Length); } } return text; } private static string Describe(string prefabName, string nameToken) { Localization instance = Localization.instance; if (nameToken == null || instance == null || instance.GetSelectedLanguage() != "Korean") { return prefabName + ": allow it to spawn outside dungeons (world spawns and rune-stone spawners). Off = blocked outside dungeons. Dungeon spawns are not affected."; } string text = instance.Localize(nameToken); if (string.IsNullOrEmpty(text) || text.StartsWith("[", StringComparison.Ordinal)) { text = instance.Localize("$" + prefabName); } if (string.IsNullOrEmpty(text) || text.StartsWith("[", StringComparison.Ordinal)) { text = DisplayName(prefabName); } return text + " (" + prefabName + "): 던전 밖 스폰 허용 여부. Off = 던전 밖 스폰 차단 (월드 스폰·룬스톤 스포너). 던전 안 스폰은 영향 없음."; } internal static void RegisterCreatures(ZNetScene scene) { if (_config == null) { return; } Dictionary<string, string> dictionary = (from p in scene.m_prefabs where (Object)(object)p != (Object)null && ((Object)p).name.EndsWith("_RtD", StringComparison.Ordinal) && (Object)(object)p.GetComponent<Character>() != (Object)null group p by ((Object)p).name).ToDictionary((IGrouping<string, GameObject> g) => g.Key, (IGrouping<string, GameObject> g) => g.First().GetComponent<Character>().m_name); if (dictionary.Count == 0) { MonsterModifiersPlugin.MonsterModifiersLogger.LogInfo((object)"RtD spawn control: no RtD creatures found, config sections skipped."); return; } bool saveOnConfigSet = _config.SaveOnConfigSet; _config.SaveOnConfigSet = false; BindMasterToggle(); foreach (string item in OrderedByBiome(dictionary.Keys)) { BindEntry(item, dictionary[item]); } foreach (KeyValuePair<string, ConfigEntry<bool>> entry in Entries) { if (dictionary.TryGetValue(entry.Key, out var value)) { UpdateDescription(entry.Value, Describe(entry.Key, value)); } } _config.SaveOnConfigSet = saveOnConfigSet; if (saveOnConfigSet) { _config.Save(); } MonsterModifiersPlugin.MonsterModifiersLogger.LogInfo((object)$"RtD spawn control: {Entries.Count} RtD creatures registered."); } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class RtDSpawnControl_ZNetScene_Awake_Patch { private static void Postfix(ZNetScene __instance) { RtDSpawnControl.RegisterCreatures(__instance); } } [HarmonyPatch(typeof(SpawnSystem), "Spawn", new Type[] { typeof(SpawnData), typeof(Vector3), typeof(bool) })] public static class RtDSpawnControl_SpawnSystem_Spawn_Patch { private static bool Prefix(SpawnData critter, Vector3 spawnPoint, bool eventSpawner) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) return eventSpawner || !RtDSpawnControl.IsBlocked(critter?.m_prefab, spawnPoint); } } [HarmonyPatch(typeof(CreatureSpawner), "Spawn")] public static class RtDSpawnControl_CreatureSpawner_Spawn_Patch { private static bool Prefix(CreatureSpawner __instance, ref ZNetView __result) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (!RtDSpawnControl.IsBlocked(__instance.m_creaturePrefab, ((Component)__instance).transform.position)) { return true; } __result = null; return false; } } [HarmonyPatch(typeof(EnemyHud), "UpdateHuds")] [HarmonyPriority(0)] public static class EnemyHud_UpdateHuds_HealthText_Patch { private sealed class FloatBox { public readonly float Value; public FloatBox(float value) { Value = value; } } private sealed class LabelState { public readonly float NameX; public readonly Vector2 LabelPos; public LabelState(float nameX, Vector2 labelPos) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) NameX = nameX; LabelPos = labelPos; } } private static readonly ConditionalWeakTable<RectTransform, LabelState> LabelStates = new ConditionalWeakTable<RectTransform, LabelState>(); private static readonly ConditionalWeakTable<RectTransform, FloatBox> IconRowY = new ConditionalWeakTable<RectTransform, FloatBox>(); private const string TextObjectName = "MM_HealthText"; private const float BarThicknessMultiplier = 4f; private const float BossBarThicknessMultiplier = 2.3f; private const float BossTextHeightMultiplier = 1.25f; private const float FontSizeMax = 20f; private const float BossFontSizeMax = 24.12f; private const float BossCharacterSpacing = 25f; private const float LevelLabelGap = 4f; private const float BossIconGap = 4f; private static readonly ConditionalWeakTable<Transform, FloatBox> BossIconRowY = new ConditionalWeakTable<Transform, FloatBox>(); private static void Postfix(EnemyHud __instance) { bool flag = MonsterModifiersPlugin.Cfg_HealthText_Enabled.Value == MonsterModifiersPlugin.Toggle.On; foreach (HudData value in __instance.m_huds.Values) { if (!Object.op_Implicit((Object)(object)value.m_gui) || !Object.op_Implicit((Object)(object)value.m_character) || value.m_character.IsPlayer() || value.m_isMount) { continue; } Transform val = value.m_gui.transform.Find("Health"); if (!Object.op_Implicit((Object)(object)val)) { continue; } Transform val2 = val.Find("MM_HealthText"); if (!flag) { if (Object.op_Implicit((Object)(object)val2) && ((Component)val2).gameObject.activeSelf) { ((Component)val2).gameObject.SetActive(false); ScaleBarThickness(val, 1f / GetThickness(value)); RestoreLevelLabel(value); ApplyThickBarLayout(value, val, thick: false); } continue; } TextMeshProUGUI val3 = (TextMeshProUGUI)(Object.op_Implicit((Object)(object)val2) ? ((object)((Component)val2).GetComponent<TextMeshProUGUI>()) : ((object)CreateText(value, val))); if (Object.op_Implicit((Object)(object)val3)) { if (Object.op_Implicit((Object)(object)val2) && !((Component)val2).gameObject.activeSelf) { ((Component)val2).gameObject.SetActive(true); ScaleBarThickness(val, GetThickness(value)); } string text = $"{Mathf.CeilToInt(value.m_character.GetHealth())}/{Mathf.CeilToInt(value.m_character.GetMaxHealth())}"; if (((TMP_Text)val3).text != text) { ((TMP_Text)val3).text = text; } MoveLevelLabelBeforeName(value); ApplyThickBarLayout(value, val, thick: true); } } } private static float GetThickness(HudData hud) { return hud.m_character.IsBoss() ? 2.3f : 4f; } private static void ApplyThickBarLayout(HudData hud, Transform health, bool thick) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_0139: 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) Transform val = health.Find("darken"); if (Object.op_Implicit((Object)(object)val) && ((Component)val).gameObject.activeSelf == thick) { ((Component)val).gameObject.SetActive(!thick); } RectTransform val2 = (RectTransform)(object)((health is RectTransform) ? health : null); if (val2 == null) { return; } Rect rect = val2.rect; float num = ((Rect)(ref rect)).height * (GetThickness(hud) - 1f); bool flag = hud.m_character.IsBoss(); foreach (Transform item in hud.m_gui.transform) { Transform val3 = item; if (!((Object)val3).name.StartsWith("level_")) { continue; } if (flag && !(val3 is RectTransform)) { PlaceBossIcons(val2, val3, thick); continue; } RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null); if (val4 != null) { float value = IconRowY.GetValue(val4, (RectTransform r) => new FloatBox(r.anchoredPosition.y)).Value; SetPosition(val4, new Vector2(val4.anchoredPosition.x, thick ? (value - num) : value)); } } } private static void PlaceBossIcons(RectTransform healthRect, Transform levelRow, bool thick) { //IL_003d: 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_0069: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_0159: 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) float value = BossIconRowY.GetValue(levelRow, (Transform t) => new FloatBox(t.localPosition.y)).Value; if (!thick) { if (Mathf.Abs(levelRow.localPosition.y - value) > 0.01f) { levelRow.localPosition = new Vector3(levelRow.localPosition.x, value, levelRow.localPosition.z); } return; } Vector3[] array = (Vector3[])(object)new Vector3[4]; float num = float.MinValue; foreach (Transform item in levelRow) { Transform val = item; if (((Object)val).name.StartsWith("star")) { RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null); if (val2 != null) { val2.GetWorldCorners(array); num = Mathf.Max(num, array[1].y); } } } if (num != float.MinValue) { healthRect.GetWorldCorners(array); float num2 = num - array[0].y + 4f; if (Mathf.Abs(num2) > 0.01f) { levelRow.position -= new Vector3(0f, num2, 0f); } } } private static void MoveLevelLabelBeforeName(HudData hud) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_011e: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)hud.m_name)) { return; } Transform val = ((TMP_Text)hud.m_name).transform.Find("Name(Clone)"); if (!Object.op_Implicit((Object)(object)val)) { return; } TextMeshProUGUI component = ((Component)val).GetComponent<TextMeshProUGUI>(); if (Object.op_Implicit((Object)(object)component)) { RectTransform nameRect = (RectTransform)((TMP_Text)hud.m_name).transform; RectTransform labelRect = (RectTransform)val; LabelState value = LabelStates.GetValue(nameRect, (RectTransform _) => new LabelState(nameRect.anchoredPosition.x, labelRect.anchoredPosition)); float preferredWidth = ((TMP_Text)hud.m_name).preferredWidth; float preferredWidth2 = ((TMP_Text)component).preferredWidth; SetPosition(labelRect, new Vector2(0f - (preferredWidth / 2f + preferredWidth2 / 2f + 4f), 0f)); SetPosition(nameRect, new Vector2(value.NameX + (preferredWidth2 + 4f) / 2f, nameRect.anchoredPosition.y)); ((Graphic)component).color = Color.white; } } private static void RestoreLevelLabel(HudData hud) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //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_0066: Expected O, but got Unknown //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)hud.m_name)) { RectTransform val = (RectTransform)((TMP_Text)hud.m_name).transform; Transform val2 = ((Transform)val).Find("Name(Clone)"); if (Object.op_Implicit((Object)(object)val2) && LabelStates.TryGetValue(val, out LabelState value)) { SetPosition((RectTransform)val2, value.LabelPos); SetPosition(val, new Vector2(value.NameX, val.anchoredPosition.y)); } } } private static void SetPosition(RectTransform rect, Vector2 target) { //IL_0002: 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_000d: 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) Vector2 val = rect.anchoredPosition - target; if (((Vector2)(ref val)).sqrMagnitude > 0.01f) { rect.anchoredPosition = target; } } private static TextMeshProUGUI? CreateText(HudData hud, Transform health) { //IL_001e: 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_0028: 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_0050: Expected O, but got Unknown //IL_0070: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00db: 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_0134: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)hud.m_name)) { return null; } Rect rect = ((RectTransform)health).rect; float height = ((Rect)(ref rect)).height; GameObject val = new GameObject("MM_HealthText", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(health, false); RectTransform component = val.GetComponent<RectTransform>(); component.anchorMin = new Vector2(0f, 0.5f); component.anchorMax = new Vector2(1f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = Vector2.zero; component.sizeDelta = new Vector2(0f, height * GetThickness(hud) * (hud.m_character.IsBoss() ? 1.25f : 1f)); ((Transform)component).localScale = new Vector3(1f, 1f / GetThickness(hud), 1f); TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)val2).font = ((TMP_Text)hud.m_name).font; ((TMP_Text)val2).fontSharedMaterial = ((TMP_Text)hud.m_name).fontSharedMaterial; ((Graphic)val2).color = Color.white; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((TMP_Text)val2).enableAutoSizing = true; ((TMP_Text)val2).fontSizeMin = 8f; ((TMP_Text)val2).fontSizeMax = (hud.m_character.IsBoss() ? 24.12f : 20f); if (hud.m_character.IsBoss()) { ((TMP_Text)val2).characterSpacing = 25f; ((TMP_Text)val2).fontStyle = (FontStyles)1; } ((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0; ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).text = string.Empty; val.transform.SetAsLastSibling(); ScaleBarThickness(health, GetThickness(hud)); return val2; } private static void ScaleBarThickness(Transform health, float factor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected