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 EnemyAbilities v1.19.3
plugins/EnemyAbilities.dll
Decompiled 2 weeks 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.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using ArchaicWisp; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EnemyAbilities.Modules; using EntityStates; using EntityStates.AI.Walker; using EntityStates.BeetleMonster; using EntityStates.Bell.BellWeapon; using EntityStates.Gup; using EntityStates.MajorConstruct.Weapon; using EntityStates.NullifierMonster; using EntityStates.ParentMonster; using EntityStates.SolusAmalgamator; using EntityStates.SolusMine; using EntityStates.Tanker; using EntityStates.Vulture; using Grumpy; using HarmonyLib; using IL.EntityStates.ChildMonster; using IL.EntityStates.Tanker; using IL.RoR2; using JetBrains.Annotations; using KinematicCharacterController; using Microsoft.CodeAnalysis; using MiscFixes.Modules; using Mono.Cecil.Cil; using MonoMod.Cil; using On.EntityStates.Gup; using On.EntityStates.ParentMonster; using On.EntityStates.SolusAmalgamator; using On.RoR2; using On.RoR2.Projectile; using R2API; using Rewired.ComponentControls.Effects; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.Audio; using RoR2.CharacterAI; using RoR2.Navigation; using RoR2.Orbs; using RoR2.Projectile; using RoR2.Scripts.GameBehaviors; using RoR2.Skills; using RoR2BepInExPack.GameAssetPaths.Version_1_39_0; using RoR2BepInExPack.GameAssetPathsBetter; using ThreeEyedGames; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EnemyAbilities")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+98f367e54d59922a20405131660810e3b5fac34d")] [assembly: AssemblyProduct("EnemyAbilities")] [assembly: AssemblyTitle("EnemyAbilities")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { return !_moveNextCalled && (_moveNextCalled = true); } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { return (!EqualityComparer<T>.Default.Equals(_item, (T)value)) ? (-1) : 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return (!EqualityComparer<T>.Default.Equals(_item, item)) ? (-1) : 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } } namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace EnemyAbilities { public static class EnemiesPlusUtils { public class ProjectileDetonateOnImpact : ProjectileExplosion, IProjectileImpactBehavior { public enum TransformSpace { World, Local, Normal } private Vector3 impactNormal = Vector3.up; public GameObject impactEffect; public NetworkSoundEventDef lifetimeExpiredSound; public float offsetForLifetimeExpiredSound; public bool destroyOnEnemy = true; public bool detonateOnEnemy; public bool detonateOnWorld; public bool destroyOnWorld; public bool destroyOnDistance; public float maxDistance; private float maxDistanceSqr; public bool impactOnWorld = true; public bool timerAfterImpact; public float lifetime; public float lifetimeAfterImpact; public float lifetimeRandomOffset; private float stopwatch; public uint minimumPhysicsStepsToKeepAliveAfterImpact; private float stopwatchAfterImpact; private bool hasImpact; private bool hasPlayedLifetimeExpiredSound; public TransformSpace transformSpace; private Vector3 startPos; public bool explodeOnLifeTimeExpiration; public bool nullifyExplosions = false; public override void Awake() { ((ProjectileExplosion)this).Awake(); lifetime += Random.Range(0f, lifetimeRandomOffset); } protected void Start() { //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) startPos = ((Component)this).transform.position; maxDistanceSqr = maxDistance * maxDistance; } protected void FixedUpdate() { //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Unknown result type (might be due to invalid IL or missing references) stopwatch += Time.fixedDeltaTime; if (!NetworkServer.active && !base.projectileController.isPrediction) { return; } if (explodeOnLifeTimeExpiration && base.alive && stopwatch >= lifetime) { base.explosionEffect = impactEffect ?? base.explosionEffect; if (!nullifyExplosions) { ((ProjectileExplosion)this).Detonate(); } } if (timerAfterImpact && hasImpact) { stopwatchAfterImpact += Time.fixedDeltaTime; } bool flag = stopwatch >= lifetime; bool flag2 = timerAfterImpact && stopwatchAfterImpact > lifetimeAfterImpact; bool flag3 = Object.op_Implicit((Object)(object)base.projectileHealthComponent) && !base.projectileHealthComponent.alive; bool flag4 = false; if (destroyOnDistance) { Vector3 val = ((Component)this).transform.position - startPos; if (((Vector3)(ref val)).sqrMagnitude >= maxDistanceSqr) { flag4 = true; } } if (flag || flag2 || flag3 || flag4) { base.alive = false; } if (timerAfterImpact && hasImpact && minimumPhysicsStepsToKeepAliveAfterImpact != 0) { minimumPhysicsStepsToKeepAliveAfterImpact--; base.alive = true; } if (base.alive && !hasPlayedLifetimeExpiredSound) { bool flag5 = stopwatch > lifetime - offsetForLifetimeExpiredSound; if (timerAfterImpact) { flag5 |= stopwatchAfterImpact > lifetimeAfterImpact - offsetForLifetimeExpiredSound; } if (flag5) { hasPlayedLifetimeExpiredSound = true; if (NetworkServer.active && Object.op_Implicit((Object)(object)lifetimeExpiredSound)) { PointSoundManager.EmitSoundServer(lifetimeExpiredSound.index, ((Component)this).transform.position); } } } if (!base.alive) { base.explosionEffect = impactEffect ?? base.explosionEffect; if (!nullifyExplosions) { ((ProjectileExplosion)this).Detonate(); } } } public override Quaternion GetRandomDirectionForChild() { //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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) Quaternion randomChildRollPitch = ((ProjectileExplosion)this).GetRandomChildRollPitch(); TransformSpace transformSpace = this.transformSpace; if (1 == 0) { } Quaternion result = (Quaternion)(transformSpace switch { TransformSpace.Local => ((Component)this).transform.rotation * randomChildRollPitch, TransformSpace.Normal => Quaternion.FromToRotation(Vector3.forward, impactNormal) * randomChildRollPitch, _ => randomChildRollPitch, }); if (1 == 0) { } return result; } public void OnProjectileImpact(ProjectileImpactInfo impactInfo) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_00c9: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if (nullifyExplosions || !base.alive) { return; } Collider collider = impactInfo.collider; impactNormal = impactInfo.estimatedImpactNormal; if (!Object.op_Implicit((Object)(object)collider)) { return; } DamageInfo val = new DamageInfo(); if (Object.op_Implicit((Object)(object)base.projectileDamage)) { val.damage = base.projectileDamage.damage; val.crit = base.projectileDamage.crit; val.attacker = (Object.op_Implicit((Object)(object)base.projectileController.owner) ? base.projectileController.owner.gameObject : null); val.inflictor = ((Component)this).gameObject; val.damageType = base.projectileDamage.damageType; val.inflictor = ((Component)this).gameObject; val.position = impactInfo.estimatedPointOfImpact; val.force = base.projectileDamage.force * ((Component)this).transform.forward; val.procChainMask = base.projectileController.procChainMask; val.procCoefficient = base.projectileController.procCoefficient; val.damageType = base.projectileDamage.damageType; } HurtBox component = ((Component)collider).GetComponent<HurtBox>(); if (Object.op_Implicit((Object)(object)component)) { if (destroyOnEnemy) { HealthComponent healthComponent = component.healthComponent; if (Object.op_Implicit((Object)(object)healthComponent)) { if ((Object)(object)((Component)healthComponent).gameObject == (Object)(object)base.projectileController.owner || (Object.op_Implicit((Object)(object)base.projectileHealthComponent) && (Object)(object)healthComponent == (Object)(object)base.projectileHealthComponent)) { return; } base.alive = false; } } else if (detonateOnEnemy) { HealthComponent healthComponent2 = component.healthComponent; if (Object.op_Implicit((Object)(object)healthComponent2) && (Object)(object)((Component)healthComponent2).gameObject != (Object)(object)base.projectileController.owner && (Object)(object)healthComponent2 != (Object)(object)base.projectileHealthComponent) { ((ProjectileExplosion)this).DetonateNoDestroy(); } } } else if (detonateOnWorld) { ((ProjectileExplosion)this).DetonateNoDestroy(); } else if (destroyOnWorld) { base.alive = false; } hasImpact = Object.op_Implicit((Object)(object)component) || impactOnWorld; if (NetworkServer.active && hasImpact) { GlobalEventManager.instance.OnHitAll(val, ((Component)collider).gameObject); } } } public static void ReorderSkillDrivers(this GameObject master, AISkillDriver targetSkill, int targetIdx) { AISkillDriver[] components = master.GetComponents<AISkillDriver>(); master.ReorderSkillDrivers(components, Array.IndexOf(components, targetSkill), targetIdx); } public static void ReorderSkillDrivers(this GameObject master, AISkillDriver[] skills, int currentIdx, int targetIdx) { if (currentIdx < 0 || currentIdx >= skills.Length) { Log.Error($"{currentIdx} index not found or out of range. Must be less than {skills.Length}"); return; } string targetName = skills[currentIdx].customName; if (targetIdx < 0 || targetIdx >= skills.Length) { Log.Error($"Unable to reorder skilldriver {targetName} into position {targetIdx}. target must be less than {skills.Length}"); } else { if (targetIdx == currentIdx) { return; } Dictionary<string, string> dictionary = skills.Where((AISkillDriver s) => (Object)(object)s.nextHighPriorityOverride != (Object)null).ToDictionary((AISkillDriver s) => s.customName, (AISkillDriver s) => s.nextHighPriorityOverride.customName); if (targetIdx > currentIdx) { master.AddComponentCopy<AISkillDriver>(skills[currentIdx]); Object.DestroyImmediate((Object)(object)skills[currentIdx]); } for (int num = targetIdx; num < skills.Length; num++) { if (num != currentIdx) { master.AddComponentCopy<AISkillDriver>(skills[num]); Object.DestroyImmediate((Object)(object)skills[num]); } } skills = master.GetComponents<AISkillDriver>(); AISkillDriver val = ((IEnumerable<AISkillDriver>)skills).FirstOrDefault((Func<AISkillDriver, bool>)((AISkillDriver s) => s.customName == targetName)); if (!dictionary.Any()) { return; } foreach (AISkillDriver val2 in skills) { if (Object.op_Implicit((Object)(object)val2) && dictionary.TryGetValue(val2.customName, out var target)) { AISkillDriver val3 = ((IEnumerable<AISkillDriver>)skills).FirstOrDefault((Func<AISkillDriver, bool>)((AISkillDriver s) => s.customName == target)); if (!((Object)(object)val3 == (Object)null)) { val2.nextHighPriorityOverride = val3; } } } } } public static T GetCopyOf<T>(this Component comp, T other) where T : Component { Type type = ((object)comp).GetType(); if (type != ((object)other).GetType()) { return default(T); } BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; PropertyInfo[] properties = type.GetProperties(bindingAttr); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { if (propertyInfo.CanWrite) { try { propertyInfo.SetValue(comp, propertyInfo.GetValue(other, null), null); } catch { } } } FieldInfo[] fields = type.GetFields(bindingAttr); FieldInfo[] array2 = fields; foreach (FieldInfo fieldInfo in array2) { fieldInfo.SetValue(comp, fieldInfo.GetValue(other)); } return (T)(object)((comp is T) ? comp : null); } public static T AddComponentCopy<T>(this GameObject go, T toAdd) where T : Component { return ((Component)(object)go.AddComponent<T>()).GetCopyOf(toAdd); } } public static class Utils { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Func<float, CharacterBody, float> <>9__2_1; public static Manipulator <>9__2_0; internal void <Init>b__2_0(ILContext il) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) <>c__DisplayClass2_0 CS$<>8__locals2 = new <>c__DisplayClass2_0(); ILCursor val = new ILCursor(il); CS$<>8__locals2.methodInfo = AccessTools.PropertySetter(typeof(CharacterBody), "maxHealth"); if (val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)CS$<>8__locals2.methodInfo) })) { val.Emit(OpCodes.Ldarg_0); val.EmitDelegate<Func<float, CharacterBody, float>>((Func<float, CharacterBody, float>)delegate(float originalMaxHealth, CharacterBody characterBody) { foreach (Func<float, CharacterBody, float> projectileHealthOverride in projectileHealthOverrides) { float num = projectileHealthOverride(originalMaxHealth, characterBody); if (num != originalMaxHealth) { return num; } } return originalMaxHealth; }); } else { Log.Error("IL.RoR2.CharacterBody.RecalculateStats health override hook failed!"); } } internal float <Init>b__2_1(float originalMaxHealth, CharacterBody characterBody) { foreach (Func<float, CharacterBody, float> projectileHealthOverride in projectileHealthOverrides) { float num = projectileHealthOverride(originalMaxHealth, characterBody); if (num != originalMaxHealth) { return num; } } return originalMaxHealth; } } [CompilerGenerated] private sealed class <>c__DisplayClass2_0 { public MethodInfo methodInfo; internal bool <Init>b__2(Instruction x) { return ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)methodInfo); } } private static readonly List<Func<float, CharacterBody, float>> projectileHealthOverrides = new List<Func<float, CharacterBody, float>>(); public static void AddHealthOverride(Func<float, CharacterBody, float> func) { projectileHealthOverrides.Add(func); } public static void Init() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown object obj = <>c.<>9__2_0; if (obj == null) { Manipulator val = delegate(ILContext il) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) ILCursor val2 = new ILCursor(il); MethodInfo methodInfo = AccessTools.PropertySetter(typeof(CharacterBody), "maxHealth"); if (val2.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, (MethodBase)methodInfo) })) { val2.Emit(OpCodes.Ldarg_0); val2.EmitDelegate<Func<float, CharacterBody, float>>((Func<float, CharacterBody, float>)delegate(float originalMaxHealth, CharacterBody characterBody) { foreach (Func<float, CharacterBody, float> projectileHealthOverride in projectileHealthOverrides) { float num = projectileHealthOverride(originalMaxHealth, characterBody); if (num != originalMaxHealth) { return num; } } return originalMaxHealth; }); } else { Log.Error("IL.RoR2.CharacterBody.RecalculateStats health override hook failed!"); } }; <>c.<>9__2_0 = val; obj = (object)val; } CharacterBody.RecalculateStats += (Manipulator)obj; } public static Sprite CreateSprite(Texture2D texture) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)texture == (Object)null) { Log.Error("CreateSprite failed! Texture2D is null!"); return null; } return Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), Vector2.op_Implicit(new Vector3(0.5f, 0.5f)), 100f); } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("Skeletogne.EnemyAbilities", "EnemyAbilities", "1.19.3")] public class EnemyAbilities : BaseUnityPlugin { public class EnemyInfoAttribute : Attribute { public string EnemyName { get; } public string Description { get; } public EnemyInfoAttribute(string enemyName, string description) { EnemyName = enemyName; Description = description; } } public class SkillInfoAttribute : Attribute { public string SkillName { get; } public string Description { get; } public SkillInfoAttribute(string skillName, string description) { SkillName = skillName; Description = description; } } public const string PluginGUID = "Skeletogne.EnemyAbilities"; public const string PluginAuthor = "Skeletogne"; public const string PluginName = "EnemyAbilities"; public const string PluginVersion = "1.19.3"; internal static bool AVRInstalled = Chainloader.PluginInfos.ContainsKey("com.Nuxlar.AugmentedVoidReaver"); internal static bool ArchWispInstalled = Chainloader.PluginInfos.ContainsKey("com.Moffein.ArchaicWisp"); public AssetBundle assetBundle; internal static bool RooInstalled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"); public static EnemyAbilities Instance { get; private set; } internal string DirectoryName => Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); public void Awake() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) assetBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location), "anglereye")); Shader shader = Addressables.LoadAssetAsync<Shader>((object)RoR2_Base_Shaders.HGStandard_shader).WaitForCompletion(); Material[] array = assetBundle.LoadAllAssets<Material>(); foreach (Material val in array) { val.shader = shader; } Instance = this; Log.Init(((BaseUnityPlugin)this).Logger); Utils.Init(); SkillGate.Init(); PluginConfig.Init(); ModuleOrganiser.Init(((Component)this).gameObject); } } internal static class Log { private static ManualLogSource _logSource; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void Debug(object data) { _logSource.LogDebug(data); } internal static void Error(object data) { _logSource.LogError(data); } internal static void Fatal(object data) { _logSource.LogFatal(data); } internal static void Info(object data) { _logSource.LogInfo(data); } internal static void Message(object data) { _logSource.LogMessage(data); } internal static void Warning(object data) { _logSource.LogWarning(data); } } public static class PluginConfig { public enum FormatType { None, Percentage, Time, Distance, Speed, Multiplier } public static void Init() { if (EnemyAbilities.RooInstalled) { InitRoO(); } } public static void InitRoO() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) try { ModSettingsManager.SetModDescription("Give enemies new abilities!", "Skeletogne.EnemyAbilities", "EnemyAbilities"); byte[] array = File.ReadAllBytes(Path.Combine(EnemyAbilities.Instance.DirectoryName, "icon.png")); Texture2D val = new Texture2D(256, 256); ImageConversion.LoadImage(val, array); Sprite modIcon = Sprite.Create(val, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f)); ModSettingsManager.SetModIcon(modIcon); } catch (Exception data) { Log.Debug(data); } } public static ConfigEntry<bool> BindBool(this ConfigFile cfg, string section, string name, bool defaultValue, string description, bool restartRequired = false) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown ConfigEntry<bool> val = cfg.Bind<bool>(section, name, defaultValue, new ConfigDescription(BuildDescription(name, description, defaultValue, restartRequired), (AcceptableValueBase)null, Array.Empty<object>())); if (EnemyAbilities.RooInstalled) { ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(val, restartRequired)); } return val; } public static ConfigEntry<T> BindEnum<T>(this ConfigFile cfg, string section, string name, T defaultValue, string description, bool restartRequired = false) where T : Enum { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown ConfigEntry<T> val = cfg.Bind<T>(section, name, defaultValue, new ConfigDescription(BuildDescription(name, description, defaultValue, restartRequired), (AcceptableValueBase)null, Array.Empty<object>())); if (EnemyAbilities.RooInstalled) { ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)val, restartRequired)); } return val; } public static ConfigEntry<int> BindInt(this ConfigFile cfg, string section, string name, int defaultValue, string description, int min, int max, bool restartRequired = false, FormatType formatType = FormatType.None) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown ConfigEntry<int> val = cfg.Bind<int>(section, name, defaultValue, new ConfigDescription(BuildDescription(name, description, defaultValue, restartRequired), (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>())); if (EnemyAbilities.RooInstalled) { ModSettingsManager.AddOption((BaseOption)new IntSliderOption(val, new IntSliderConfig { min = min, max = max, formatString = "{0:0}" + AppendSuffix(formatType), restartRequired = restartRequired })); } return val; } public static ConfigEntry<float> BindFloat(this ConfigFile cfg, string section, string name, float defaultValue, string description, float min, float max, float increment = 0.1f, bool restartRequired = false, FormatType formatType = FormatType.None) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown ConfigEntry<float> val = cfg.Bind<float>(section, name, defaultValue, new ConfigDescription(BuildDescription(name, description, defaultValue, restartRequired), (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>())); if (EnemyAbilities.RooInstalled) { ModSettingsManager.AddOption((BaseOption)new StepSliderOption(val, new StepSliderConfig { increment = increment, min = min, max = max, FormatString = GetStepSizePrecision((decimal)increment, formatType), restartRequired = restartRequired })); } return val; } private static string BuildDescription(string name, string description, object defaultValue, bool restartRequired) { if (string.IsNullOrEmpty(description)) { description = name; } if ((defaultValue is int || defaultValue is float) ? true : false) { description = description + " (Default: " + defaultValue?.ToString() + ")"; } if (restartRequired) { description += " (restart required)"; } return description; } private static string GetStepSizePrecision(decimal n, FormatType formatType) { n = Math.Abs(n); n -= (decimal)(int)n; int num = 0; string text = "{0:"; while (n > 0m) { num++; n *= 10m; n -= (decimal)(int)n; } if (num == 0) { return text + "0}" + AppendSuffix(formatType); } text += "0."; for (int i = 0; i < num; i++) { text += "0"; } text += "}"; return text + AppendSuffix(formatType); } private static string AppendSuffix(FormatType formatType) { return formatType switch { FormatType.Percentage => "%", FormatType.Time => "s", FormatType.Distance => "m", FormatType.Speed => "m/s", FormatType.Multiplier => "x", _ => "", }; } } } namespace EnemyAbilities.Modules { public abstract class BaseModule : MonoBehaviour { protected class AISkillDriverData { public GameObject masterPrefab; public string customName; public SkillSlot skillSlot; public float minDistance = 0f; public float maxDistance = float.PositiveInfinity; public int desiredIndex = 0; public float moveInputScale = 1f; public MovementType movementType; public AimType aimType; public TargetType targetType; public bool ignoreNodeGraph = false; public float maxHealthFraction = float.PositiveInfinity; public float minHealthFraction = float.NegativeInfinity; public float maxTargetHealthFraction = float.PositiveInfinity; public float minTargetHealthFraction = float.NegativeInfinity; public bool requireReady = false; public SkillDef requiredSkillDef = null; public bool activationRequiresAimTargetLoS = false; public bool activationRequiresAimConfirmation = false; public bool activationRequiresTargetLoS = false; public bool selectionRequiresAimTarget = false; public bool selectionRequiresOnGround = false; public bool selectionRequiresTargetLoS = false; public bool selectionRequiresTargetNonFlier = false; public int maxTimesSelected = -1; public float driverUpdateTimerOverride = -1f; public bool noRepeat = false; public AISkillDriver nextHighPriorityOverride = null; public bool shouldSprint = false; public float aimVectorMaxSpeedOverride = -1f; public ButtonPressType buttonPressType = (ButtonPressType)0; } protected ConfigFile config => ((BaseUnityPlugin)EnemyAbilities.Instance).Config; public abstract string Section { get; } public virtual void RegisterConfig() { } public virtual void Initialise() { } protected static T Load<T>(string assetPath) where T : Object { //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) T val = Addressables.LoadAssetAsync<T>((object)assetPath).WaitForCompletion(); if ((Object)(object)val == (Object)null) { Log.Error("Failed to load asset under path: " + assetPath); } return val; } protected virtual AISkillDriver CreateAISkillDriver(AISkillDriverData data) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) if (data == null || (Object)(object)data.masterPrefab == (Object)null) { Log.Error(((object)this).GetType().Name + ": Could not create AISkillDriver " + data?.customName + " as no master prefab exists."); return null; } AISkillDriver val = data.masterPrefab.AddComponent<AISkillDriver>(); val.customName = data.customName; val.skillSlot = data.skillSlot; val.minDistance = data.minDistance; val.maxDistance = data.maxDistance; val.moveInputScale = data.moveInputScale; val.movementType = data.movementType; val.aimType = data.aimType; val.moveTargetType = data.targetType; val.ignoreNodeGraph = data.ignoreNodeGraph; val.maxUserHealthFraction = data.maxHealthFraction; val.minUserHealthFraction = data.minHealthFraction; val.maxTargetHealthFraction = data.maxTargetHealthFraction; val.minTargetHealthFraction = data.minTargetHealthFraction; val.requireSkillReady = data.requireReady; val.requiredSkill = data.requiredSkillDef; val.activationRequiresAimConfirmation = data.activationRequiresAimConfirmation; val.activationRequiresAimTargetLoS = data.activationRequiresAimTargetLoS; val.activationRequiresTargetLoS = data.activationRequiresTargetLoS; val.selectionRequiresAimTarget = data.selectionRequiresAimTarget; val.selectionRequiresOnGround = data.selectionRequiresOnGround; val.selectionRequiresTargetLoS = data.selectionRequiresTargetLoS; val.selectionRequiresTargetNonFlier = data.selectionRequiresTargetNonFlier; val.maxTimesSelected = data.maxTimesSelected; val.driverUpdateTimerOverride = data.driverUpdateTimerOverride; val.noRepeat = data.noRepeat; val.nextHighPriorityOverride = data.nextHighPriorityOverride; val.shouldSprint = data.shouldSprint; val.aimVectorMaxSpeedOverride = data.aimVectorMaxSpeedOverride; val.buttonPressType = data.buttonPressType; data.masterPrefab.ReorderSkillDrivers(val, data.desiredIndex); return val; } protected ConfigEntry<float> BindFloat(string name, float defaultValue, string desc, float min, float max, float step = 0.1f, PluginConfig.FormatType format = PluginConfig.FormatType.None, bool restartRequired = true) { return config.BindFloat(Section, name, defaultValue, desc, min, max, step, restartRequired, format); } protected ConfigEntry<int> BindInt(string name, int defaultValue, string desc, int min, int max, PluginConfig.FormatType format = PluginConfig.FormatType.None, bool restartRequired = true) { return config.BindInt(Section, name, defaultValue, desc, min, max, restartRequired, format); } protected ConfigEntry<bool> BindBool(string name, bool defaultValue, string desc, bool restartRequired = true) { return config.BindBool(Section, name, defaultValue, desc, restartRequired); } protected ConfigEntry<T> BindEnum<T>(string name, T defaultValue, string desc, bool restartRequired = true) where T : Enum { return config.BindEnum(Section, name, defaultValue, desc, restartRequired); } } public abstract class BaseSkillModule : BaseModule { protected class SkillDefData { public string objectName; public string skillName; public string esmName; public SerializableEntityStateType activationState; public float cooldown; public int baseMaxStock = 1; public int rechargeStock = 1; public int requiredStock = 1; public int stockToConsume = 1; public InterruptPriority intPrio = (InterruptPriority)0; public bool resetCdOnUse = false; public bool cdOnEnd = false; public bool cdBlocked = false; public bool combatSkill = true; } private EnemyAbilities.SkillInfoAttribute _info; internal readonly List<Attachment> attachments = new List<Attachment>(); internal readonly HashSet<SkillDef> skillDefs = new HashSet<SkillDef>(); protected Attachment current; public EnemyAbilities.SkillInfoAttribute Info => _info ?? (_info = ((object)this).GetType().GetCustomAttribute<EnemyAbilities.SkillInfoAttribute>()); public string SkillName => Info?.SkillName ?? ((object)this).GetType().Name; public override string Section => (attachments.Count > 0) ? attachments[0].host.Section : SkillName; public bool HasEnabledAttachment { get { foreach (Attachment attachment in attachments) { if (attachment.Enabled) { return true; } } return false; } } public abstract void DeclareHosts(); public abstract void Attach(Attachment attachment); protected void Host<T>() where T : BaseTweakModule { T val = BaseTweakModule.Get<T>(); if ((Object)(object)val == (Object)null) { Log.Debug(SkillName + ": host " + typeof(T).Name + " is unavailable, skipping."); } else { attachments.Add(new Attachment(this, val)); } } internal void RunAttach(Attachment attachment) { current = attachment; try { Attach(attachment); } finally { current = null; } } public Attachment GetAttachment(CharacterBody body) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)body == (Object)null) { return null; } foreach (Attachment attachment in attachments) { if (attachment.Enabled && (Object)(object)attachment.host.bodyPrefab != (Object)null && attachment.host.BodyIndex == body.bodyIndex) { return attachment; } } return null; } protected T CreateSkillDef<T>(SkillDefData data) where T : SkillDef { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) T val = ScriptableObject.CreateInstance<T>(); ((Object)(object)val).name = data.objectName; ((SkillDef)val).skillName = data.skillName; ((SkillDef)val).activationStateMachineName = data.esmName; ((SkillDef)val).activationState = data.activationState; ((SkillDef)val).baseRechargeInterval = data.cooldown; ((SkillDef)val).baseMaxStock = data.baseMaxStock; ((SkillDef)val).rechargeStock = data.rechargeStock; ((SkillDef)val).requiredStock = data.requiredStock; ((SkillDef)val).stockToConsume = data.stockToConsume; ((SkillDef)val).interruptPriority = data.intPrio; ((SkillDef)val).resetCooldownTimerOnUse = data.resetCdOnUse; ((SkillDef)val).beginSkillCooldownOnSkillEnd = data.cdOnEnd; ((SkillDef)val).isCooldownBlockedUntilManuallyReset = data.cdBlocked; ((SkillDef)val).isCombatSkill = data.combatSkill; ContentAddition.AddSkillDef((SkillDef)(object)val); skillDefs.Add((SkillDef)(object)val); SkillGate.RegisterSkillDef((SkillDef)(object)val, this); return val; } protected GenericSkill CreateGenericSkill(GameObject bodyPrefab, SkillDef skillDef, string familyName, SkillSlot slot) { //IL_001a: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected I4, but got Unknown SkillFamily val = ScriptableObject.CreateInstance<SkillFamily>(); ((Object)val).name = familyName; val.variants = (Variant[])(object)new Variant[1] { new Variant { skillDef = skillDef } }; GenericSkill val2 = bodyPrefab.AddComponent<GenericSkill>(); val2.skillName = skillDef.skillName; val2._skillFamily = val; SkillLocator component = bodyPrefab.GetComponent<SkillLocator>(); switch (slot - -1) { case 0: Log.Error("SkillSlot.None detected in CreateGenericSkill!"); break; case 1: component.primary = val2; break; case 2: component.secondary = val2; break; case 3: component.utility = val2; break; case 4: component.special = val2; break; } ContentAddition.AddSkillFamily(val); return val2; } protected EntityStateMachine CreateEntityStateMachine(GameObject bodyPrefab, string name, Type initialState = null, Type mainState = null) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) EntityStateMachine val = EntityStateMachine.FindByCustomName(bodyPrefab, name); if ((Object)(object)val != (Object)null) { Log.Info($"Tried to create new entity state machine with name {name} on {bodyPrefab} but one with this name already exists!"); return val; } EntityStateMachine val2 = bodyPrefab.AddComponent<EntityStateMachine>(); val2.customName = name; val2.initialStateType = new SerializableEntityStateType(initialState ?? typeof(Idle)); val2.mainStateType = new SerializableEntityStateType(mainState ?? typeof(Idle)); NetworkStateMachine component = bodyPrefab.GetComponent<NetworkStateMachine>(); if ((Object)(object)component != (Object)null) { component.stateMachines = component.stateMachines.Append(val2).ToArray(); } else { Log.Error($"{bodyPrefab} lacks a NetworkStateMachine!"); } return val2; } protected override AISkillDriver CreateAISkillDriver(AISkillDriverData data) { if (data != null && (Object)(object)data.masterPrefab == (Object)null && current != null) { data.masterPrefab = current.host.masterPrefab; } AISkillDriver val = base.CreateAISkillDriver(data); if ((Object)(object)val != (Object)null && current != null && (Object)(object)data.masterPrefab == (Object)(object)current.host.masterPrefab) { if (string.IsNullOrEmpty(data.customName)) { Log.Error(SkillName + ": AISkillDriver on " + ((Object)data.masterPrefab).name + " has no customName and can't be gated!"); } current.gatedDriverNames.Add(data.customName); } return val; } protected T AddGatedComponent<T>(GameObject bodyPrefab = null) where T : Behaviour { if (bodyPrefab == null) { bodyPrefab = current?.host.bodyPrefab; } if ((Object)(object)bodyPrefab == (Object)null) { Log.Error(SkillName + ": AddGatedComponent<" + typeof(T).Name + "> has no body prefab to add to!"); return default(T); } T result = bodyPrefab.AddComponent<T>(); if (current != null && (Object)(object)bodyPrefab == (Object)(object)current.host.bodyPrefab) { current.gatedComponentTypes.Add(typeof(T)); } return result; } protected void OnBodySpawn(Action<CharacterBody, bool> callback) { if (current == null) { Log.Error(SkillName + ": OnBodySpawn can only be used inside Attach!"); } else { current.onBodySpawn.Add(callback); } } protected void OnMasterSpawn(Action<CharacterMaster, bool> callback) { if (current == null) { Log.Error(SkillName + ": OnMasterSpawn can only be used inside Attach!"); } else { current.onMasterSpawn.Add(callback); } } } public class Attachment { public readonly BaseSkillModule skill; public readonly BaseTweakModule host; internal ConfigEntry<bool> enabledCfg; internal ConfigEntry<int> minimumStageCompletions; internal ConfigEntry<SkillGate.DifficultyTier> minimumDifficulty; internal ConfigEntry<int> minimumEclipseLevel; internal ConfigEntry<bool> elitesOnly; internal readonly HashSet<string> gatedDriverNames = new HashSet<string>(); internal readonly List<Type> gatedComponentTypes = new List<Type>(); internal readonly List<Action<CharacterBody, bool>> onBodySpawn = new List<Action<CharacterBody, bool>>(); internal readonly List<Action<CharacterMaster, bool>> onMasterSpawn = new List<Action<CharacterMaster, bool>>(); public GameObject bodyPrefab => host.bodyPrefab; public GameObject masterPrefab => host.masterPrefab; public bool Enabled => host.IsAvailable && (enabledCfg == null || enabledCfg.Value); public bool Unlocked => SkillGate.ConditionsMet(minimumStageCompletions?.Value ?? 0, minimumDifficulty?.Value ?? SkillGate.DifficultyTier.Drizzle, minimumEclipseLevel?.Value ?? 1); public bool IsUnlockedFor(CharacterBody body) { if (!Unlocked) { return false; } if (elitesOnly != null && elitesOnly.Value && !SkillGate.IsElite(body)) { return false; } return true; } public Attachment(BaseSkillModule skill, BaseTweakModule host) { this.skill = skill; this.host = host; } internal void RegisterConfig(ConfigFile config) { string section = host.Section; string skillName = skill.SkillName; enabledCfg = config.BindBool(section, skillName, defaultValue: true, skill.Info?.Description ?? ("Gives this enemy " + skillName + "."), restartRequired: true); minimumStageCompletions = config.BindInt(section, skillName + " Minimum Stage Completions", 0, "The number of stages that must be completed before this enemy can use " + skillName + ". Enemies that spawn before then behave as they would without it.", 0, 20); minimumDifficulty = config.BindEnum(section, skillName + " Minimum Difficulty", SkillGate.DifficultyTier.Drizzle, "The easiest difficulty on which this enemy can use " + skillName + ". Doesn't apply to Eclipse - see Minimum Eclipse Level.\nFrom easiest to hardest: Drizzle, Rainstorm, Monsoon, Typhoon, Downpour, Inferno, Brimstone.\nAny other modded difficulty counts as Typhoon."); minimumEclipseLevel = config.BindInt(section, skillName + " Minimum Eclipse Level", 1, "The lowest Eclipse level on which this enemy can use " + skillName + ". 0 disables it on all Eclipse levels.", 0, 8); elitesOnly = config.BindBool(section, skillName + " Elites Only", defaultValue: false, "If enabled, only elite enemies of this type can use " + skillName + ". Regular enemies behave as they would without it."); } } public abstract class BaseTweakModule : BaseModule { public class StatOverrides { public float? baseMaxHealth; public float? baseDamage; public float? baseMoveSpeed; public float? baseAcceleration; public float? baseArmor; public int? directorCost; } private static readonly Dictionary<Type, BaseTweakModule> tweakDictionary = new Dictionary<Type, BaseTweakModule>(); private EnemyAbilities.EnemyInfoAttribute _info; public GameObject bodyPrefab; public GameObject masterPrefab; public List<CharacterSpawnCard> spawnCards = new List<CharacterSpawnCard>(); private BodyIndex cachedBodyIndex = (BodyIndex)(-1); private MasterIndex cachedMasterIndex = MasterIndex.none; internal ConfigEntry<bool> enabledCfg; internal ConfigEntry<float> baseMaxHealthCfg; internal ConfigEntry<float> baseDamageCfg; internal ConfigEntry<float> baseMoveSpeedCfg; internal ConfigEntry<float> baseAccelerationCfg; internal ConfigEntry<float> baseArmorCfg; internal ConfigEntry<int> costCfg; public EnemyAbilities.EnemyInfoAttribute Info => _info ?? (_info = ((object)this).GetType().GetCustomAttribute<EnemyAbilities.EnemyInfoAttribute>()); public override string Section => Info?.EnemyName ?? ((object)this).GetType().Name; public CharacterBody CharacterBody => ((Object)(object)bodyPrefab != (Object)null) ? bodyPrefab.GetComponent<CharacterBody>() : null; public BodyIndex BodyIndex { get { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0031: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if ((int)cachedBodyIndex == -1 && (Object)(object)bodyPrefab != (Object)null) { cachedBodyIndex = BodyCatalog.FindBodyIndex(bodyPrefab); } return cachedBodyIndex; } } public MasterIndex MasterIndex { get { //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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (cachedMasterIndex == MasterIndex.none && (Object)(object)masterPrefab != (Object)null) { cachedMasterIndex = MasterCatalog.FindMasterIndex(masterPrefab); } return cachedMasterIndex; } } public virtual bool IsAvailable => true; protected virtual bool HasStats => true; protected virtual StatOverrides Overrides => null; public bool Enabled => enabledCfg == null || enabledCfg.Value; public static T Get<T>() where T : BaseTweakModule { BaseTweakModule value; return tweakDictionary.TryGetValue(typeof(T), out value) ? ((T)value) : null; } internal static void Register(BaseTweakModule tweaks) { tweakDictionary[((object)tweaks).GetType()] = tweaks; } public abstract void LoadPrefabs(); public override void RegisterConfig() { enabledCfg = BindBool("Enable Tweaks", defaultValue: true, Info?.Description ?? "Enables the stat changes and tweaks for this enemy."); if (HasStats) { BindStats(); } } public override void Initialise() { ApplyStats(); } protected void BindStats() { CharacterBody characterBody = CharacterBody; if ((Object)(object)characterBody == (Object)null) { Log.Error(((object)this).GetType().Name + ": bodyPrefab has no CharacterBody!"); return; } StatOverrides statOverrides = Overrides ?? new StatOverrides(); baseMaxHealthCfg = BindFloat("Base Max Health", statOverrides.baseMaxHealth ?? characterBody.baseMaxHealth, $"Base Max Health of this enemy.\nValue without this mod is {characterBody.baseMaxHealth}.{RebalanceNote(statOverrides.baseMaxHealth)}", characterBody.baseMaxHealth / 5f, characterBody.baseMaxHealth * 5f, 1f); baseDamageCfg = BindFloat("Base Damage", statOverrides.baseDamage ?? characterBody.baseDamage, $"Base Damage of this enemy.\nValue without this mod is {characterBody.baseDamage}.{RebalanceNote(statOverrides.baseDamage)}", characterBody.baseDamage / 5f, characterBody.baseDamage * 5f); if (characterBody.baseMoveSpeed > 0f) { baseMoveSpeedCfg = BindFloat("Base Move Speed", statOverrides.baseMoveSpeed ?? characterBody.baseMoveSpeed, $"Base Move Speed of this enemy.\nValue without this mod is {characterBody.baseMoveSpeed}.{RebalanceNote(statOverrides.baseMoveSpeed)}", characterBody.baseMoveSpeed / 5f, characterBody.baseMoveSpeed * 5f); } if (characterBody.baseAcceleration > 0f) { baseAccelerationCfg = BindFloat("Base Acceleration", statOverrides.baseAcceleration ?? characterBody.baseAcceleration, $"Base Acceleration of this enemy.\nValue without this mod is {characterBody.baseAcceleration}.{RebalanceNote(statOverrides.baseAcceleration)}", characterBody.baseAcceleration / 5f, characterBody.baseAcceleration * 5f); } baseArmorCfg = BindFloat("Base Armor", statOverrides.baseArmor ?? characterBody.baseArmor, $"Base Armor of this enemy.\nValue without this mod is {characterBody.baseArmor}.{RebalanceNote(statOverrides.baseArmor)}", 0f, Mathf.Max(100f, characterBody.baseArmor), 1f); if (spawnCards.Count > 0) { int directorCreditCost = ((SpawnCard)spawnCards[0]).directorCreditCost; costCfg = BindInt("Director Cost", statOverrides.directorCost ?? directorCreditCost, $"The amount of credits required for the director to spawn this enemy.\nValue without this mod is {directorCreditCost}.{RebalanceNote(statOverrides.directorCost)}", Mathf.Max(1, directorCreditCost / 5), directorCreditCost * 5); } } private static string RebalanceNote<T>(T? overrideValue) where T : struct { return overrideValue.HasValue ? $"\n<style=cShrine>This mod rebalances this stat to {overrideValue} by default.</style>" : ""; } protected void ApplyStats() { CharacterBody characterBody = CharacterBody; if ((Object)(object)characterBody == (Object)null || baseMaxHealthCfg == null) { return; } characterBody.baseMaxHealth = baseMaxHealthCfg.Value; characterBody.levelMaxHealth = baseMaxHealthCfg.Value * 0.3f; characterBody.baseDamage = baseDamageCfg.Value; characterBody.levelDamage = baseDamageCfg.Value * 0.2f; if (baseMoveSpeedCfg != null) { characterBody.baseMoveSpeed = baseMoveSpeedCfg.Value; } if (baseAccelerationCfg != null) { characterBody.baseAcceleration = baseAccelerationCfg.Value; } if (baseArmorCfg != null) { characterBody.baseArmor = baseArmorCfg.Value; } if (costCfg == null) { return; } foreach (CharacterSpawnCard spawnCard in spawnCards) { ((SpawnCard)spawnCard).directorCreditCost = costCfg.Value; } } } public static class ModuleOrganiser { public static readonly List<BaseTweakModule> tweaks = new List<BaseTweakModule>(); public static readonly List<BaseSkillModule> skills = new List<BaseSkillModule>(); public static void Init(GameObject owner) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); Type[] source = (from type in executingAssembly.GetTypes() where type.IsClass && !type.IsAbstract select type).ToArray(); foreach (Type item in source.Where((Type type) => type.IsSubclassOf(typeof(BaseTweakModule)))) { if (item.GetCustomAttribute<EnemyAbilities.EnemyInfoAttribute>() == null) { Log.Warning("EnemyInfo for " + item.FullName + " does not exist! Module skipped."); continue; } BaseTweakModule baseTweakModule = (BaseTweakModule)(object)owner.AddComponent(item); if (!baseTweakModule.IsAvailable) { Log.Debug(item.Name + " is unavailable, skipping."); Object.Destroy((Object)(object)baseTweakModule); continue; } try { baseTweakModule.LoadPrefabs(); baseTweakModule.RegisterConfig(); } catch (Exception arg) { Log.Error($"{item.Name} failed to load: {arg}"); Object.Destroy((Object)(object)baseTweakModule); continue; } BaseTweakModule.Register(baseTweakModule); tweaks.Add(baseTweakModule); } foreach (Type item2 in source.Where((Type type) => type.IsSubclassOf(typeof(BaseSkillModule)))) { if (item2.GetCustomAttribute<EnemyAbilities.SkillInfoAttribute>() == null) { Log.Warning("SkillInfo for " + item2.FullName + " does not exist! Module skipped."); continue; } BaseSkillModule baseSkillModule = (BaseSkillModule)(object)owner.AddComponent(item2); try { baseSkillModule.DeclareHosts(); foreach (Attachment attachment in baseSkillModule.attachments) { attachment.RegisterConfig(((BaseUnityPlugin)EnemyAbilities.Instance).Config); } baseSkillModule.RegisterConfig(); } catch (Exception arg2) { Log.Error($"{item2.Name} failed to register config: {arg2}"); Object.Destroy((Object)(object)baseSkillModule); continue; } skills.Add(baseSkillModule); } foreach (BaseTweakModule tweak in tweaks) { if (tweak.Enabled) { try { tweak.Initialise(); } catch (Exception arg3) { Log.Error($"{((object)tweak).GetType().Name} failed to initialise: {arg3}"); } } } foreach (BaseSkillModule skill in skills) { if (!skill.HasEnabledAttachment) { continue; } try { skill.Initialise(); } catch (Exception arg4) { Log.Error($"{((object)skill).GetType().Name} failed to initialise: {arg4}"); continue; } foreach (Attachment attachment2 in skill.attachments) { if (attachment2.Enabled) { try { skill.RunAttach(attachment2); SkillGate.RegisterAttachment(attachment2); } catch (Exception arg5) { Log.Error($"{((object)skill).GetType().Name} failed to attach to {((object)attachment2.host).GetType().Name}: {arg5}"); } } } } } } public static class SkillGate { public enum DifficultyTier { Drizzle, Rainstorm, Monsoon, Typhoon, Downpour, Inferno, Brimstone } [CompilerGenerated] private static class <>O { public static hook_IsReady <0>__IsReady; public static hook_CanExecute <1>__CanExecute; public static Action<CharacterBody> <2>__OnBodyStart; } private static readonly Dictionary<SkillDef, BaseSkillModule> skillDefOwners = new Dictionary<SkillDef, BaseSkillModule>(); private static readonly List<Attachment> attachments = new List<Attachment>(); private static bool initialised; private static readonly Dictionary<string, DifficultyTier> knownDifficulties = new Dictionary<string, DifficultyTier> { { "DIFFICULTY_EASY_NAME", DifficultyTier.Drizzle }, { "DIFFICULTY_NORMAL_NAME", DifficultyTier.Rainstorm }, { "DIFFICULTY_HARD_NAME", DifficultyTier.Monsoon }, { "SS2_DIFFICULTY_TYPHOON_NAME", DifficultyTier.Typhoon }, { "DOWNPOUR_NAME", DifficultyTier.Downpour }, { "INFERNO_NAME", DifficultyTier.Inferno }, { "BRIMSTONE_NAME", DifficultyTier.Brimstone } }; private const DifficultyTier unrecognisedTier = DifficultyTier.Typhoon; internal static void Init() { //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_002e: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown if (!initialised) { initialised = true; object obj = <>O.<0>__IsReady; if (obj == null) { hook_IsReady val = IsReady; <>O.<0>__IsReady = val; obj = (object)val; } GenericSkill.IsReady += (hook_IsReady)obj; object obj2 = <>O.<1>__CanExecute; if (obj2 == null) { hook_CanExecute val2 = CanExecute; <>O.<1>__CanExecute = val2; obj2 = (object)val2; } GenericSkill.CanExecute += (hook_CanExecute)obj2; CharacterBody.onBodyStartGlobal += OnBodyStart; } } internal static void RegisterSkillDef(SkillDef skillDef, BaseSkillModule owner) { if ((Object)(object)skillDef != (Object)null && (Object)(object)owner != (Object)null) { skillDefOwners[skillDef] = owner; } } internal static void RegisterAttachment(Attachment attachment) { if (attachment != null && !attachments.Contains(attachment)) { attachments.Add(attachment); } } public static bool IsModded(DifficultyIndex index) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 return (int)index < 0 || (int)index > 10; } public static DifficultyTier GetTier(DifficultyIndex index) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(index); if (difficultyDef != null && difficultyDef.nameToken != null && knownDifficulties.TryGetValue(difficultyDef.nameToken, out var value)) { return value; } return DifficultyTier.Typhoon; } public static bool ConditionsMet(int minimumStageCompletions, DifficultyTier minimumTier, int minimumEclipseLevel) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) Run instance = Run.instance; if ((Object)(object)instance == (Object)null) { return false; } if (instance.stageClearCount < minimumStageCompletions) { return false; } int eclipseLevel = GetEclipseLevel(instance.selectedDifficulty); if (eclipseLevel > 0) { return minimumEclipseLevel > 0 && eclipseLevel >= minimumEclipseLevel; } return GetTier(instance.selectedDifficulty) >= minimumTier; } public static int GetEclipseLevel(DifficultyIndex index) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected I4, but got Unknown if ((int)index >= 3 && (int)index <= 10) { return index - 3 + 1; } return 0; } private static bool IsLocked(GenericSkill genericSkill) { if ((Object)(object)genericSkill == (Object)null || (Object)(object)genericSkill.skillDef == (Object)null) { return false; } if (!skillDefOwners.TryGetValue(genericSkill.skillDef, out var value)) { return false; } Attachment attachment = value.GetAttachment(genericSkill.characterBody); return attachment != null && !attachment.IsUnlockedFor(genericSkill.characterBody); } private static bool IsReady(orig_IsReady orig, GenericSkill self) { if (IsLocked(self)) { return false; } return orig.Invoke(self); } private static bool CanExecute(orig_CanExecute orig, GenericSkill self) { if (IsLocked(self)) { return false; } return orig.Invoke(self); } private static void OnBodyStart(CharacterBody body) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)body == (Object)null) { return; } CharacterMaster master = body.master; for (int i = 0; i < attachments.Count; i++) { Attachment attachment = attachments[i]; if (!attachment.Enabled || attachment.host.BodyIndex != body.bodyIndex) { continue; } bool flag = attachment.IsUnlockedFor(body); foreach (Type gatedComponentType in attachment.gatedComponentTypes) { Component[] components = ((Component)body).GetComponents(gatedComponentType); foreach (Component val in components) { Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null); if (val2 != null) { val2.enabled = flag; } } } foreach (Action<CharacterBody, bool> item in attachment.onBodySpawn) { try { item(body, flag); } catch (Exception arg) { Log.Error($"Error during body callback: {arg}"); } } if ((Object)(object)master == (Object)null) { continue; } if (!flag && attachment.gatedDriverNames.Count > 0) { RemoveGatedDrivers(master, attachment.gatedDriverNames); } foreach (Action<CharacterMaster, bool> item2 in attachment.onMasterSpawn) { try { item2(master, flag); } catch (Exception arg2) { Log.Error($"Error during master callback: {arg2}"); } } } } public static bool IsElite(CharacterBody body) { if ((Object)(object)body != (Object)null && body.isElite) { return true; } return false; } private static void RemoveGatedDrivers(CharacterMaster master, HashSet<string> gatedDriverNames) { AISkillDriver[] components = ((Component)master).GetComponents<AISkillDriver>(); List<AISkillDriver> list = new List<AISkillDriver>(components.Length); AISkillDriver[] array = components; foreach (AISkillDriver val in array) { if ((Object)(object)val != (Object)null && val.customName != null && gatedDriverNames.Contains(val.customName)) { ((Behaviour)val).enabled = false; Object.Destroy((Object)(object)val); } else { list.Add(val); } } BaseAI component = ((Component)master).GetComponent<BaseAI>(); if ((Object)(object)component != (Object)null) { component.skillDrivers = list.ToArray(); } } } } namespace EnemyAbilities.Modules.SolusProspector { [EnemyAbilities.SkillInfo("Drill Burrow", "Gives Solus Prospectors a new Secondary ability: \n- Drill Burrow: Allows the Prospector to disappear underground to remain hidden for 1 second, before burrowing up beneath a nearby target.")] public class DrillBurrowSkill : BaseSkillModule { internal static ConfigEntry<float> entryDuration; internal static ConfigEntry<float> waitDuration; internal static ConfigEntry<float> telegraphDuration; internal static ConfigEntry<float> damageCoeff; internal static ConfigEntry<float> radius; internal static ConfigEntry<float> baseVelocity; internal static ConfigEntry<float> cooldown; internal static ConfigEntry<float> spawnCooldown; private static SkillDef drillBurrow; public override void RegisterConfig() { base.RegisterConfig(); entryDuration = BindFloat("Burrow Entry Duration", 1f, "How long it takes for the Solus Prospector to burrow underground.", 0.2f, 2f, 0.1f, PluginConfig.FormatType.Time); waitDuration = BindFloat("Burrow Wait Duration", 1f, "How long the Solus Prospector remains burrowed without attacking", 0.2f, 2f, 0.1f, PluginConfig.FormatType.Time); telegraphDuration = BindFloat("Burrow Telegraph Duration", 1f, "How long the Solus Prospector telegraphs before bursting up from the ground", 0.2f, 2f, 0.1f, PluginConfig.FormatType.Time); radius = BindFloat("Burrow Radius", 6f, "The radius of the burrow attack explosion", 6f, 16f, 1f, PluginConfig.FormatType.Distance); damageCoeff = BindFloat("Burrow Damage Coefficient", 300f, "The damage coefficient of the burrow attack", 100f, 500f, 5f, PluginConfig.FormatType.Percentage); baseVelocity = BindFloat("Burrow Upwards Velocity Modifier", 250f, "The speed multiplier at which the Prospector is ejected from the ground", 100f, 500f, 10f, PluginConfig.FormatType.Percentage); cooldown = BindFloat("Burrow Cooldown", 15f, "The cooldown of the burrow", 8f, 30f, 0.1f, PluginConfig.FormatType.Time); spawnCooldown = BindFloat("Spawn Cooldown", 6f, "The initial cooldown of the burrow when a Solus Prospector spawns in before it can be used.", 0f, 15f, 0.1f, PluginConfig.FormatType.Time); } public override void DeclareHosts() { Host<WorkerUnitTweaks>(); } public override void Initialise() { //IL_0031: 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) base.Initialise(); bool flag = default(bool); SkillDefData data = new SkillDefData { objectName = "WorkerUnitBodyDrillBurrow", skillName = "WorkerUnitDrillBurrow", esmName = "Weapon", activationState = ContentAddition.AddEntityState<DrillBurrow>(ref flag), cooldown = cooldown.Value, combatSkill = true }; drillBurrow = CreateSkillDef<SkillDef>(data); } public override void Attach(Attachment attachment) { //IL_0033: 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_006c: Unknown result type (might be due to invalid IL or missing references) CreateGenericSkill(attachment.bodyPrefab, drillBurrow, "WorkerUnitSecondaryFamily", (SkillSlot)1); AddGatedComponent<DepleteSecondaryStock>((GameObject)null); AISkillDriverData data = new AISkillDriverData { customName = "useSecondary", skillSlot = (SkillSlot)1, requireReady = true, minDistance = 20f, maxDistance = 50f, selectionRequiresOnGround = true, selectionRequiresTargetNonFlier = true, movementType = (MovementType)0, aimType = (AimType)0, ignoreNodeGraph = true, desiredIndex = 0 }; CreateAISkillDriver(data); } } public class DrillBurrow : BaseSkillState { private enum DrillBurrowState { None, Windup, Burrowed, Telegraphing, Attacking } public static float baseWindupDuration = DrillBurrowSkill.entryDuration.Value; public static float baseBurrowDuration = DrillBurrowSkill.waitDuration.Value; public static float baseTelegraphDuration = DrillBurrowSkill.telegraphDuration.Value; public static float baseAttackDuration = 1f; public static float blastRadius = DrillBurrowSkill.radius.Value; public static float force = 1500f; public static Vector3 bonusForce = new Vector3(0f, 2500f, 0f); public static float damageCoefficient = DrillBurrowSkill.damageCoeff.Value / 100f; public static float exitSpeedMultiplier = DrillBurrowSkill.baseVelocity.Value / 100f; private static GameObject indicatorPrefab = Addressables.LoadAssetAsync<GameObject>((object)RoR2_Base_Common.TeamAreaIndicator__GroundOnly_prefab).WaitForCompletion(); private static GameObject explosionPrefab = Addressables.LoadAssetAsync<GameObject>((object)RoR2_Base_BeetleGuard.BeetleGuardGroundSlam_prefab).WaitForCompletion(); private static GameObject burrowPrefab = Addressables.LoadAssetAsync<GameObject>((object)RoR2_Base_MiniMushroom.MiniMushroomPlantEffect_prefab).WaitForCompletion(); private float windupDuration; private float burrowDuration; private float telegraphDuration; private float attackDuration; private float totalDuration; private float stopwatch = 0f; private int originalLayerIndex; private Vector3 targetPos; private GameObject indicatorInstance; private ChildLocator childLocator; private Animator animator; private bool reachedApex; private float burrowEffectTimer = 0f; private float burrowEffectInterval = 0.2f; private Vector3 startPos; private CharacterBody targetBody; private uint soundID; private float attackTimer; private float lastHeight; private DrillBurrowState currentState = DrillBurrowState.None; public override void OnEnter() { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) ((BaseState)this).OnEnter(); animator = ((EntityState)this).GetModelAnimator(); childLocator = ((Component)animator).GetComponent<ChildLocator>(); originalLayerIndex = ((EntityState)this).gameObject.layer; windupDuration = baseWindupDuration / ((BaseState)this).attackSpeedStat; burrowDuration = baseBurrowDuration / ((BaseState)this).attackSpeedStat; telegraphDuration = baseTelegraphDuration; attackDuration = baseAttackDuration / ((BaseState)this).attackSpeedStat; totalDuration = windupDuration + burrowDuration + telegraphDuration + attackDuration; currentState = DrillBurrowState.Windup; soundID = Util.PlaySound("Play_workerUnit_dig", ((EntityState)this).gameObject); startPos = ((EntityState)this).characterBody.transform.position; BullseyeSearch val = new BullseyeSearch(); val.viewer = ((EntityState)this).characterBody; val.teamMaskFilter = TeamMask.allButNeutral; ((TeamMask)(ref val.teamMaskFilter)).RemoveTeam(((EntityState)this).characterBody.teamComponent.teamIndex); val.sortMode = (SortMode)3; val.minDistanceFilter = 0f; val.maxDistanceFilter = 60f; val.searchOrigin = ((EntityState)this).inputBank.aimOrigin; val.searchDirection = ((EntityState)this).inputBank.aimDirection; val.maxAngleFilter = 360f; val.filterByLoS = false; val.RefreshCandidates(); HurtBox val2 = val.GetResults().FirstOrDefault(); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.healthComponent != (Object)null) { targetBody = val2.healthComponent.body; } } public override void OnSerialize(NetworkWriter writer) { ((BaseSkillState)this).OnSerialize(writer); CharacterBody obj = targetBody; writer.Write((obj != null) ? ((Component)obj).gameObject : null); } public override void OnDeserialize(NetworkReader reader) { ((BaseSkillState)this).OnDeserialize(reader); GameObject val = reader.ReadGameObject(); targetBody = ((val != null) ? val.GetComponent<CharacterBody>() : null); } public override void OnExit() { ((EntityState)this).OnExit(); SetSprintEffectState(active: false); if (currentState != DrillBurrowState.Attacking) { Emerge(); } AkSoundEngine.StopPlayingID(soundID); } public void SpawnDirtEffect() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0007: 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) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0081: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) EffectData val = new EffectData(); Vector3 val2 = Random.insideUnitSphere * 1f; if (currentState == DrillBurrowState.Windup) { val._origin = ((EntityState)this).characterBody.footPosition + val2; } else if (currentState == DrillBurrowState.Telegraphing) { val._origin = targetPos + val2; } else if (currentState == DrillBurrowState.Burrowed) { Vector3 val3 = ((EntityState)this).characterBody.footPosition; if ((Object)(object)targetBody != (Object)null) { val3 = targetBody.transform.position; } Vector3 val4 = startPos; if (val3.y > startPos.y) { val4.y = val3.y; } else { val3.y = val4.y; } Vector3 val5 = Vector3.Lerp(val4, val3, Mathf.Clamp01((stopwatch - windupDuration) / burrowDuration)); RaycastHit val6 = default(RaycastHit); if (Physics.Raycast(val5, Vector3.down, ref val6, 1000f, LayerMask.op_Implicit(((LayerIndex)(ref LayerIndex.world)).mask))) { val._origin = ((RaycastHit)(ref val6)).point + val2; if (((EntityState)this).isAuthority) { TeleportHelper.TeleportBody(((EntityState)this).characterBody, ((RaycastHit)(ref val6)).point, false); } } } val.scale = ((currentState == DrillBurrowState.Burrowed) ? 1f : 2f); EffectManager.SpawnEffect(burrowPrefab, val, true); } public override void FixedUpdate() { //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) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) ((EntityState)this).FixedUpdate(); stopwatch += Time.fixedDeltaTime; if (currentState == DrillBurrowState.Windup) { ((EntityState)this).characterMotor.velocity = Vector3.zero; } if (stopwatch > windupDuration && currentState == DrillBurrowState.Windup) { Burrow(); currentState = DrillBurrowState.Burrowed; burrowEffectTimer = 0f; burrowEffectInterval = 0.05f; } if (stopwatch > windupDuration + burrowDuration && currentState == DrillBurrowState.Burrowed) { Telegraph(); burrowEffectTimer = 0f; burrowEffectInterval = 0.2f; currentState = DrillBurrowState.Telegraphing; } if (stopwatch > windupDuration + burrowDuration + telegraphDuration && currentState == DrillBurrowState.Telegraphing) { FireAttack(); currentState = DrillBurrowState.Attacking; } if (currentState == DrillBurrowState.Attacking && !reachedApex) { attackTimer += Time.fixedDeltaTime; float y = ((EntityState)this).characterBody.transform.position.y; if (attackTimer > 0.2f && y <= lastHeight) { reachedApex = true; OnReachedApex(); } else if (((EntityState)this).isAuthority) { ((EntityState)this).inputBank.aimDirection = Vector3.up; } lastHeight = y; } if ((((EntityState)this).isAuthority && stopwatch > totalDuration && ((EntityState)this).characterMotor.isGrounded) || stopwatch > totalDuration + 3f) { ((EntityState)this).outer.SetNextStateToMain(); } if (currentState == DrillBurrowState.Windup || currentState == DrillBurrowState.Telegraphing || currentState == DrillBurrowState.Burrowed) { burrowEffectTimer -= Time.fixedDeltaTime; if (burrowEffectTimer < 0f) { burrowEffectTimer += burrowEffectInterval; SpawnDirtEffect(); } } } public void OnReachedApex() { SetSprintEffectState(active: false); } public void Burrow() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)((EntityState)this).characterBody == (Object)null) && !((Object)(object)((EntityState)this).characterMotor == (Object)null)) { ((EntityState)this).characterMotor.walkSpeedPenaltyCoefficient = 0f; if (((EntityState)this).characterBody.GetBuffCount(Buffs.HiddenInvincibility.buffIndex) < 1) { ((EntityState)this).characterBody.AddBuff(Buffs.HiddenInvincibility.buffIndex); } ((EntityState)this).gameObject.layer = LayerIndex.GetAppropriateFakeLayerForTeam(((EntityState)this).teamComponent.teamIndex).intVal; ((BaseCharacterController)((EntityState)this).characterMotor).Motor.RebuildCollidableLayers(); if ((Object)(object)((EntityState)this).modelLocator != (Object)null && (Object)(object)((EntityState)this).modelLocator.modelTransform != (Object)null) { ((Component)((EntityState)this).modelLocator.modelTransform).gameObject.SetActive(false); } } } public void Telegraph() { //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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) targetPos = ((EntityState)this).transform.position; if ((Object)(object)targetBody != (Object)null) { targetPos = targetBody.footPosition; Util.PlaySound("Play_GildedElite_Pillar_Spawn", ((Component)targetBody).gameObject); } RaycastHit val = default(RaycastHit); if (Physics.Raycast(targetPos, Vector3.down, ref val, 1000f, LayerMask.op_Implicit(((LayerIndex)(ref LayerIndex.world)).mask))) { targetPos = ((RaycastHit)(ref val)).point; } indicatorInstance = Object.Instantiate<GameObject>(indicatorPrefab, targetPos, Util.QuaternionSafeLookRotation(Vector3.up)); indicatorInstance.transform.localScale = Vector3.one * blastRadius; TeamAreaIndicator component = indicatorInstance.GetComponent<TeamAreaIndicator>(); if ((Object)(object)component != (Object)null) { component.teamComponent = ((EntityState)this).teamComponent; } } private void SetSprintEffectState(bool active) { if (Object.op_Implicit((Object)(object)childLocator)) { Transform obj = childLocator.FindChild("SprintEffect"); if (obj != null) { ((Component)obj).gameObject.SetActive(active); } } } public void FireAttack() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_0113: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) TeleportHelper.TeleportBody(((EntityState)this).characterBody, targetPos, false); Util.PlaySound("Play_MULT_m2_secondary_explode", ((EntityState)this).gameObject); AkSoundEngine.StopPlayingID(soundID); Emerge(); SetSprintEffectState(active: true); ((EntityState)this).PlayAnimation("Gesture, Additive", "FrenziedMeleeAttack", "attack.playbackRate", 1f, 0f); if (((EntityState)this).isAuthority) { DamageTypeCombo damageType = new DamageTypeCombo { damageSource = (DamageSource)2, damageType = (DamageType)0 }; BlastAttack val = new BlastAttack(); val.attacker = ((EntityState)this).gameObject; val.attackerFiltering = (AttackerFiltering)2; val.baseDamage = damageCoefficient * ((BaseState)this).damageStat; val.baseForce = force; val.bonusForce = bonusForce; val.crit = ((BaseState)this).RollCrit(); val.damageColorIndex = (DamageColorIndex)0; val.damageType = damageType; val.falloffModel = (FalloffModel)2; val.inflictor = ((EntityState)this).gameObject; val.position = targetPos; val.procCoefficient = 1f; val.procChainMask = default(ProcChainMask); val.radius = blastRadius; val.teamIndex = ((EntityState)this).teamComponent.teamIndex; val.Fire(); EffectManager.SpawnEffect(explosionPrefab, new EffectData { origin = ((EntityState)this).characterBody.transform.position, scale = blastRadius }, true); } if ((Object)(object)((EntityState)this).characterMotor != (Object)null) { ((BaseCharacterController)((EntityState)this).characterMotor).Motor.ForceUnground(0.1f); ((EntityState)this).characterMotor.velocity = new Vector3(0f, ((BaseState)this).moveSpeedStat * 2.5f, 0f); } } public void Emerge() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)((EntityState)this).characterBody == (Object)null) && !((Object)(object)((EntityState)this).characterMotor == (Object)null)) { if ((Object)(object)indicatorInstance != (Object)null) { Object.Destroy((Object)(object)indicatorInstance); } ((EntityState)this).characterMotor.walkSpeedPenaltyCoefficient = 1f; ((EntityState)this).characterBody.RemoveBuff(Buffs.HiddenInvincibility.buffIndex); ((EntityState)this).gameObject.layer = originalLayerIndex; ((BaseCharacterController)((EntityState)this).characterMotor).Motor.RebuildCollidableLayers(); if ((Object)(object)((EntityState)this).modelLocator != (Object)null && (Object)(object)((EntityState)this).modelLocator.modelTransform != (Object)null) { ((Component)((EntityState)this).modelLocator.modelTransform).gameObject.SetActive(true); } } } public override InterruptPriority GetMinimumInterruptPriority() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (currentState == DrillBurrowState.Windup || currentState == DrillBurrowState.Attacking) { return (InterruptPriority)2; } return (InterruptPriority)9; } } public class DepleteSecondaryStock : MonoBehaviour { public void Start() { SkillLocator component = ((Component)this).GetComponent<SkillLocator>(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component.secondary == (Object)null)) { component.secondary.RemoveAllStocks(); component.secondary.rechargeStopwatch = Mathf.Max(0f, DrillBurrowSkill.cooldown.Value - DrillBurrowSkill.spawnCooldown.Value); } } } [EnemyAbilities.EnemyInfo("Solus Prospector", "Stat changes for Solus Prospectors.")] public class WorkerUnitTweaks : BaseTweakModule { protected override StatOverrides Overrides => new StatOverrides { directorCost = 16 }; public override void LoadPrefabs() { bodyPrefab = BaseModule.Load<GameObject>(RoR2_DLC3_WorkerUnit.WorkerUnitBody_prefab); masterPrefab = BaseModule.Load<GameObject>(RoR2_DLC3_WorkerUnit.WorkerUnitMaster_prefab); spawnCards = new List<CharacterSpawnCard>(1) { BaseModule.Load<CharacterSpawnCard>(RoR2_DLC3_WorkerUnit.cscWorkerUnit_asset) }; } } } namespace EnemyAbilities.Modules.Vulture { [EnemyAbilities.SkillInfo("Swoop", "Gives Alloy Vultures a new secondary:\n- Swoop: Allows Alloy Vultures to swoop towards the player in an arc, dealing contact damage.")] public class SwoopSkill : BaseSkillModule { internal static ConfigEntry<float> damageCoeff; internal static ConfigEntry<float> hitboxScale; internal static ConfigEntry<bool> inflictsBleed; internal static ConfigEntry<float> predictionTime; internal static ConfigEntry<float> selfStunDuration; internal static ConfigEntry<float> cooldown; private static SwoopSkillDef swoop; public override void RegisterConfig() { base.RegisterConfig(); predictionTime = BindFloat("Swoop Prediction Duration", 1.5f, "Affects how far into the future the Alloy Vulture will predict when swooping towards the player. Increasing the value increases the duration of the attack, and slows the speed at which the Vulture travels.", 1f, 3f, 0.1f, PluginConfig.FormatType.Time); hitboxScale = BindFloat("Swoop Hitbox Scale", 100f, "Affects how large the hitbox for swoop is.", 50f, 200f, 1f, PluginConfig.FormatType.Percentage); damageCoeff = BindFloat("Swoop Damage Coefficient", 125f, "The damage coefficient of the swoop attack", 100f, 300f, 5f, PluginConfig.FormatType.Percentage); selfStunDuration = BindFloat("Swoop Stun Duration on Impact", 2f, "How long the Alloy Vulture stuns itself for upon hitting terrain at high speed.", 0f, 4f, 0.1f, PluginConfig.FormatType.Time); inflictsBleed = BindBool("Swoop Inflicts Bleed", defaultValue: true, "Allows Alloy Vultures to inflict 1 stack of bleed for 3 seconds when swoop hits."); cooldown = BindFloat("Swoop Cooldown", 12f, "The cooldown of the swoop ability", 8f, 30f, 0.1f, PluginConfig.FormatType.Time); } public override void DeclareHosts() { Host<VultureTweaks>(); } public override void Initialise() { //IL_0031: 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_0061: Unknown result type (might be due to invalid IL or missing references) base.Initialise(); bool flag = default(bool); SkillDefData data = new SkillDefData { objectName = "VultureBodySwoop", skillName = "VultureSwoop", esmName = "Body", activationState = ContentAddition.AddEntityState<SwoopWindup>(ref flag), cooldown = cooldown.Value, combatSkill = true }; swoop = CreateSkillDef<SwoopSkillDef>(data); ContentAddition.AddEntityState<Swoop>(ref flag); } public override void Attach(Attachment attachment) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) TargetingAndPredictionController val = AddGatedComponent<TargetingAndPredictionController>((GameObject)null); val.manualTrackingMaxDistance = 100f; val.manualTrackingMaxAngle = 360f; CreateGenericSkill(attachment.bodyPrefab, (SkillDef)(object)swoop, "VultureSecondaryFamily", (SkillSlot)1); AddMeleeHitBox(attachment.bodyPrefab); AISkillDriverData data = new AISkillDriverData { customName = "strafeAndUseSecondary", skillSlot = (SkillSlot)1, requiredSkillDef = (SkillDef)(object)swoop, requireReady = true, minDistance = 25f, maxDistance = 50f, targetType = (TargetType)0, movementType = (MovementType)2, desiredIndex = 2 }; CreateAISkillDriver(data); } private void AddMeleeHitBox(GameObject bodyPrefab) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) ModelLocator component = bodyPrefab.GetComponent<ModelLocator>(); if ((Object)(object)component != (Object)null && (Object)(object)component.modelTransform != (Object)null) { CreateHitBoxAndGroup(component.modelTransform, "VultureMelee", new Vector3(0f, -2f, 0f), new Vector3(30f, 30f, 30f) * (hitboxScale.Value / 100f)); } } private void CreateHitBoxAndGroup(Transform modelTransform, string hitBoxGroupName, Vector3 localPosition, Vector3 localScale, string hitBoxGroupObjName = "", string hitBoxObjName = "") { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0046: Unknown result type (migh