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 BouncingHuntress v1.1.0
BouncingHuntress.dll
Decompiled 12 hours 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.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BouncingHuntress.ChainBallista; using BouncingHuntress.Glaive; using BouncingHuntress.PhaseBurst; using BouncingHuntress.Shared; using BouncingHuntress.Strafe; using EntityStates; using EntityStates.Huntress; using EntityStates.Huntress.HuntressWeapon; using EntityStates.Huntress.Weapon; using HG.GeneralSerializer; using HarmonyLib; using RoR2; using RoR2.ContentManagement; using RoR2.Orbs; using RoR2.Skills; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BouncingHuntress")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("BouncingHuntress")] [assembly: AssemblyTitle("BouncingHuntress")] [assembly: AssemblyVersion("1.1.0.0")] namespace BouncingHuntress { [BepInPlugin("com.calvin.BouncingHuntress", "BouncingHuntress", "1.1.0")] public class BouncingHuntressPlugin : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static CollectContentPackProvidersDelegate <>9__3_0; internal void <Awake>b__3_0(AddContentPackProviderDelegate add) { add.Invoke((IContentPackProvider)(object)new BHContent()); } } public const string GUID = "com.calvin.BouncingHuntress"; public const string Name = "BouncingHuntress"; public const string Version = "1.1.0"; private void Awake() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown GreenFx.Prefix = "BouncingHuntress"; GlaiveModule.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); StrafeModule.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); PhaseBurstModule.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); ChainBallistaModule.Init(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); object obj = <>c.<>9__3_0; if (obj == null) { CollectContentPackProvidersDelegate val = delegate(AddContentPackProviderDelegate add) { add.Invoke((IContentPackProvider)(object)new BHContent()); }; <>c.<>9__3_0 = val; obj = (object)val; } ContentManager.collectContentPackProviders += (CollectContentPackProvidersDelegate)obj; Harmony val2 = new Harmony("com.calvin.BouncingHuntress"); val2.PatchAll(typeof(GlaivePatches)); val2.PatchAll(typeof(BouncingHuntress.Strafe.LanguagePatches)); val2.PatchAll(typeof(BouncingHuntress.PhaseBurst.LanguagePatches)); val2.PatchAll(typeof(BouncingHuntress.ChainBallista.LanguagePatches)); val2.PatchAll(typeof(SharedPatches)); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Bouncing Huntress loaded: " + BHContent.SkillDefs.Count + " skills, " + GreenFx.EffectsToRegister.Count + " green effects.")); } } internal class BHContent : IContentPackProvider { internal static readonly List<SkillDef> SkillDefs = new List<SkillDef>(); internal static readonly List<Type> StateTypes = new List<Type>(); private readonly ContentPack contentPack = new ContentPack(); public string identifier => "com.calvin.BouncingHuntress"; public IEnumerator LoadStaticContentAsync(LoadStaticContentAsyncArgs args) { contentPack.skillDefs.Add(SkillDefs.ToArray()); contentPack.entityStateTypes.Add(StateTypes.ToArray()); List<EffectDef> list = new List<EffectDef>(); foreach (GameObject item in GreenFx.EffectsToRegister) { if (Object.op_Implicit((Object)(object)item)) { list.Add(new EffectDef(item)); } } contentPack.effectDefs.Add(list.ToArray()); args.ReportProgress(1f); yield break; } public IEnumerator GenerateContentPackAsync(GetContentPackAsyncArgs args) { ContentPack.Copy(contentPack, args.output); args.ReportProgress(1f); yield break; } public IEnumerator FinalizeAsync(FinalizeAsyncArgs args) { args.ReportProgress(1f); yield break; } } internal static class SharedPatches { [HarmonyPatch(typeof(TemporaryOverlayInstance), "AddToCharacterModel")] [HarmonyPrefix] private static void AddOverlay_Prefix(TemporaryOverlayInstance __instance) { GreenFx.OverlayPrefix(__instance); } } } namespace BouncingHuntress.Strafe { public class FireEndlessArrow : FireSeekingArrow { private const float DefaultHuntressRange = 60f; private static readonly FieldInfo[] tunedFields = typeof(FireSeekingArrow).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); public FireEndlessArrow() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown FireSeekingArrow obj = new FireSeekingArrow(); FieldInfo[] array = tunedFields; foreach (FieldInfo fieldInfo in array) { fieldInfo.SetValue(this, fieldInfo.GetValue(obj)); } if (Object.op_Implicit((Object)(object)StrafeModule.GreenMuzzleFlash)) { base.muzzleflashEffectPrefab = StrafeModule.GreenMuzzleFlash; } } protected override GenericDamageOrb CreateArrowOrb() { HuntressTracker val = (Object.op_Implicit((Object)(object)((EntityState)this).gameObject) ? ((EntityState)this).gameObject.GetComponent<HuntressTracker>() : null); return (GenericDamageOrb)(object)new EndlessArrowOrb { bounceRange = (Object.op_Implicit((Object)(object)val) ? val.maxTrackingDistance : 60f), hitThisRound = new HashSet<HealthComponent>() }; } } public class EndlessArrowOrb : HuntressArrowOrb { private const float MinBounceTime = 0.1f; public float bounceRange = 60f; public HashSet<HealthComponent> hitThisRound; public int bounceCount; public float originalDamage; public float originalProcCoefficient; private static readonly BullseyeSearch search = new BullseyeSearch(); protected override GameObject GetOrbEffect() { if (!Object.op_Implicit((Object)(object)StrafeModule.GreenArrowOrb)) { return ((HuntressArrowOrb)this).GetOrbEffect(); } return StrafeModule.GreenArrowOrb; } public override void Begin() { ((HuntressArrowOrb)this).Begin(); if (bounceCount > 0 && ((Orb)this).duration < 0.1f) { ((Orb)this).duration = 0.1f; } } public override void OnArrival() { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: 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) ((GenericDamageOrb)this).OnArrival(); if (!Object.op_Implicit((Object)(object)((Orb)this).target)) { return; } int value = StrafeModule.BouncesPerShot.Value; if (value > 0 && bounceCount >= value) { return; } if (bounceCount == 0) { originalDamage = ((GenericDamageOrb)this).damageValue; originalProcCoefficient = ((GenericDamageOrb)this).procCoefficient; } float num = 1f - Mathf.Max(0f, StrafeModule.FalloffPerBounce.Value) * (float)(bounceCount + 1); if (num <= 0.001f) { return; } HealthComponent healthComponent = ((Orb)this).target.healthComponent; Vector3 position = ((Component)((Orb)this).target).transform.position; if (hitThisRound == null) { hitThisRound = new HashSet<HealthComponent>(); } if (Object.op_Implicit((Object)(object)healthComponent)) { hitThisRound.Add(healthComponent); } HurtBox val = FindNextTarget(position, healthComponent); if (!Object.op_Implicit((Object)(object)val)) { hitThisRound.Clear(); if (Object.op_Implicit((Object)(object)healthComponent)) { hitThisRound.Add(healthComponent); } val = FindNextTarget(position, healthComponent); } if (Object.op_Implicit((Object)(object)val)) { EndlessArrowOrb endlessArrowOrb = new EndlessArrowOrb { damageValue = originalDamage * num, isCrit = ((GenericDamageOrb)this).isCrit, attacker = ((GenericDamageOrb)this).attacker, teamIndex = ((GenericDamageOrb)this).teamIndex, procCoefficient = originalProcCoefficient * Mathf.Max(0f, StrafeModule.BounceProcMultiplier.Value), originalDamage = originalDamage, originalProcCoefficient = originalProcCoefficient, procChainMask = ((GenericDamageOrb)this).procChainMask, damageColorIndex = ((GenericDamageOrb)this).damageColorIndex, damageType = ((GenericDamageOrb)this).damageType, scale = ((GenericDamageOrb)this).scale, bounceRange = bounceRange, hitThisRound = hitThisRound, bounceCount = bounceCount + 1, origin = position, target = val }; OrbManager.instance.AddOrb((Orb)(object)endlessArrowOrb); } } private HurtBox FindNextTarget(Vector3 from, HealthComponent current) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_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_0032: 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_0054: Unknown result type (might be due to invalid IL or missing references) TeamMask allButNeutral = TeamMask.allButNeutral; ((TeamMask)(ref allButNeutral)).RemoveTeam(((GenericDamageOrb)this).teamIndex); search.searchOrigin = from; search.searchDirection = Vector3.zero; search.teamMaskFilter = allButNeutral; search.filterByLoS = false; search.filterByDistinctEntity = true; search.sortMode = (SortMode)1; search.maxDistanceFilter = bounceRange; search.RefreshCandidates(); foreach (HurtBox result in search.GetResults()) { HealthComponent val = (Object.op_Implicit((Object)(object)result) ? result.healthComponent : null); if (Object.op_Implicit((Object)(object)val) && val.alive && !((Object)(object)val == (Object)(object)current) && !hitThisRound.Contains(val)) { return result; } } return null; } } internal static class StrafeModule { private const string Section = "Bouncing Strafe"; public const string NameToken = "HUNTRESS_PRIMARY_ENDLESSSTRAFE_NAME"; public const string DescriptionToken = "HUNTRESS_PRIMARY_ENDLESSSTRAFE_DESCRIPTION"; private const string VanillaStrafeKey = "RoR2/Base/Huntress/HuntressBodyFireSeekingArrow.asset"; private const string PrimaryFamilyKey = "RoR2/Base/Huntress/HuntressBodyPrimaryFamily.asset"; internal static ManualLogSource Log; internal static ConfigEntry<int> BouncesPerShot; internal static ConfigEntry<float> FalloffPerBounce; internal static ConfigEntry<float> BounceProcMultiplier; internal static SkillDef EndlessStrafeSkillDef; internal static GameObject GreenArrowOrb; internal static GameObject GreenMuzzleFlash; private const string FireSeekingArrowConfigKey = "RoR2/Base/Huntress/EntityStates.Huntress.HuntressWeapon.FireSeekingArrow.asset"; internal static void Init(ConfigFile Config, ManualLogSource logger) { Log = logger; FalloffPerBounce = Config.Bind<float>("Bouncing Strafe", "FalloffPerBounce", 0.25f, "Each bounce loses this fraction of the arrow's original damage. 0.25 = 100% / 75% / 50% / 25%. 0 = no falloff. An arrow stops bouncing once its damage would reach 0."); BounceProcMultiplier = Config.Bind<float>("Bouncing Strafe", "BounceProcMultiplier", 0.5f, "Proc coefficient of bounces, relative to the first hit (0.5 = half as likely to trigger on-hit items). 1 = same as the first hit."); BouncesPerShot = Config.Bind<int>("Bouncing Strafe", "BouncesPerShot", 3, "How many times each arrow bounces after its first hit. 0 = unlimited.\nOnly the host's setting matters in multiplayer."); CreateSkill(); if (Object.op_Implicit((Object)(object)EndlessStrafeSkillDef)) { BHContent.SkillDefs.Add(EndlessStrafeSkillDef); } BHContent.StateTypes.Add(typeof(FireEndlessArrow)); GreenArrowOrb = GreenFx.CloneEffect(GreenFx.LoadLegacy("Prefabs/Effects/OrbEffects/ArrowOrbEffect")); GreenMuzzleFlash = GreenFx.CloneEffect(GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.HuntressWeapon.FireSeekingArrow.asset", "muzzleflashEffectPrefab")); Log.LogInfo((object)("Green visuals: arrow " + (Object.op_Implicit((Object)(object)GreenArrowOrb) ? "ok" : "missing") + ", flash " + (Object.op_Implicit((Object)(object)GreenMuzzleFlash) ? "ok" : "missing") + ".")); LanguagePatches.ApplyToLoaded(); Log.LogInfo((object)("Bouncing Strafe loaded (" + BouncesPerShot.Value + " bounces per shot).")); } private static void CreateSkill() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Huntress/HuntressBodyFireSeekingArrow.asset").WaitForCompletion(); SkillFamily val2 = Addressables.LoadAssetAsync<SkillFamily>((object)"RoR2/Base/Huntress/HuntressBodyPrimaryFamily.asset").WaitForCompletion(); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2)) { Log.LogError((object)"Could not load the vanilla Strafe skill or Huntress primary family. The game's asset paths may have changed."); return; } SkillDef val3 = Object.Instantiate<SkillDef>(val); ((Object)val3).name = "HuntressBodyEndlessStrafe"; val3.skillName = "EndlessStrafe"; val3.skillNameToken = "HUNTRESS_PRIMARY_ENDLESSSTRAFE_NAME"; val3.skillDescriptionToken = "HUNTRESS_PRIMARY_ENDLESSSTRAFE_DESCRIPTION"; val3.activationState = new SerializableEntityStateType(typeof(FireEndlessArrow)); val3.icon = GreenFx.GreenIcon(val.icon); EndlessStrafeSkillDef = val3; int num = val2.variants.Length; Array.Resize(ref val2.variants, num + 1); Variant[] variants = val2.variants; Variant val4 = new Variant { skillDef = val3, unlockableName = "", unlockableDef = null }; ((Variant)(ref val4)).viewableNode = new Node(val3.skillNameToken, false, (Node)null); variants[num] = val4; } } internal static class LanguagePatches { private static string Description() { int value = StrafeModule.BouncesPerShot.Value; string text = ((value > 0) ? ("bounces up to <style=cIsUtility>" + value + "</style> " + ((value == 1) ? "time" : "times") + ((StrafeModule.FalloffPerBounce.Value > 0f) ? " with <style=cIsDamage>diminishing damage</style>" : "")) : "bounces <style=cIsUtility>endlessly</style> between enemies"); return "<style=cIsUtility>Agile</style>. Quickly fire a seeking arrow for <style=cIsDamage>150% damage</style> that " + text + "."; } private static void Apply(Language language) { if (language != null) { language.SetStringByToken("HUNTRESS_PRIMARY_ENDLESSSTRAFE_NAME", "Bouncing Strafe"); language.SetStringByToken("HUNTRESS_PRIMARY_ENDLESSSTRAFE_DESCRIPTION", Description()); } } internal static void ApplyToLoaded() { try { Apply(Language.currentLanguage); } catch { } } [HarmonyPatch(typeof(Language), "LoadStrings")] [HarmonyPostfix] private static void LoadStrings_Postfix(Language __instance) { Apply(__instance); } } } namespace BouncingHuntress.Shared { internal static class GreenFx { internal const float GreenHue = 0.36f; internal static string Prefix = "Mod"; internal static readonly List<GameObject> EffectsToRegister = new List<GameObject>(); private static GameObject holder; private static readonly Dictionary<GameObject, GameObject> effectCache = new Dictionary<GameObject, GameObject>(); private static readonly HashSet<Material> greenMaterials = new HashSet<Material>(); private const int MaxLinkedDepth = 3; private static readonly Dictionary<Material, Material> materialCache = new Dictionary<Material, Material>(); private static readonly Dictionary<Texture, Texture> textureCache = new Dictionary<Texture, Texture>(); internal static bool GreenOverlays; internal static T FromStateConfig<T>(string configKey, string fieldName) where T : Object { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_004e: 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_005f: Unknown result type (might be due to invalid IL or missing references) try { EntityStateConfiguration val = Addressables.LoadAssetAsync<EntityStateConfiguration>((object)configKey).WaitForCompletion(); if (!Object.op_Implicit((Object)(object)val) || val.serializedFieldsCollection.serializedFields == null) { return default(T); } SerializedField[] serializedFields = val.serializedFieldsCollection.serializedFields; foreach (SerializedField val2 in serializedFields) { if (val2.fieldName == fieldName) { Object objectValue = val2.fieldValue.objectValue; return (T)(object)((objectValue is T) ? objectValue : null); } } } catch (Exception ex) { Debug.LogWarning((object)("[" + Prefix + "] Couldn't read " + fieldName + " from " + configKey + ": " + ex.Message)); } return default(T); } internal static GameObject LoadLegacy(string path) { try { return LegacyResourcesAPI.Load<GameObject>(path); } catch { return null; } } internal static GameObject CloneEffect(GameObject vanilla) { return CloneEffect(vanilla, 0); } private static GameObject CloneEffect(GameObject vanilla, int depth) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)vanilla)) { return null; } if (effectCache.TryGetValue(vanilla, out var value)) { return value; } if (!Object.op_Implicit((Object)(object)holder)) { holder = new GameObject(Prefix + "_GreenPrefabs"); Object.DontDestroyOnLoad((Object)(object)holder); holder.SetActive(false); } GameObject val = Object.Instantiate<GameObject>(vanilla, holder.transform); ((Object)val).name = Prefix + "_Green_" + ((Object)vanilla).name; effectCache[vanilla] = val; try { Recolor(val); if (depth < 3) { GreenLinkedEffects(val, depth); } } catch (Exception ex) { Debug.LogWarning((object)("[" + Prefix + "] Couldn't fully recolor " + ((Object)vanilla).name + ": " + ex.Message)); } if (Object.op_Implicit((Object)(object)val.GetComponent<EffectComponent>())) { EffectsToRegister.Add(val); } return val; } private static void GreenLinkedEffects(GameObject root, int depth) { MonoBehaviour[] componentsInChildren = root.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { if (!Object.op_Implicit((Object)(object)val)) { continue; } Type type = ((object)val).GetType(); while (type != null && type != typeof(MonoBehaviour)) { FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (!fieldInfo.IsPublic && ((MemberInfo)fieldInfo).GetCustomAttribute<SerializeField>() == null) { continue; } if (fieldInfo.FieldType == typeof(GameObject)) { object? value = fieldInfo.GetValue(val); GameObject val2 = GreenLinked((GameObject)((value is GameObject) ? value : null), depth); if (Object.op_Implicit((Object)(object)val2)) { fieldInfo.SetValue(val, val2); } } else { if (!(fieldInfo.FieldType == typeof(GameObject[])) || !(fieldInfo.GetValue(val) is GameObject[] array)) { continue; } for (int k = 0; k < array.Length; k++) { GameObject val3 = GreenLinked(array[k], depth); if (Object.op_Implicit((Object)(object)val3)) { array[k] = val3; } } } } type = type.BaseType; } } } private static GameObject GreenLinked(GameObject linked, int depth) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)linked)) { Scene scene = linked.scene; if (!((Scene)(ref scene)).IsValid() && Object.op_Implicit((Object)(object)linked.GetComponent<EffectComponent>())) { return CloneEffect(linked, depth + 1); } } return null; } internal static void Recolor(GameObject root) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem obj in componentsInChildren) { MainModule main = obj.main; ((MainModule)(ref main)).startColor = Shift(((MainModule)(ref main)).startColor); ColorOverLifetimeModule colorOverLifetime = obj.colorOverLifetime; if (((ColorOverLifetimeModule)(ref colorOverLifetime)).enabled) { ((ColorOverLifetimeModule)(ref colorOverLifetime)).color = Shift(((ColorOverLifetimeModule)(ref colorOverLifetime)).color); } ColorBySpeedModule colorBySpeed = obj.colorBySpeed; if (((ColorBySpeedModule)(ref colorBySpeed)).enabled) { ((ColorBySpeedModule)(ref colorBySpeed)).color = Shift(((ColorBySpeedModule)(ref colorBySpeed)).color); } TrailModule trails = obj.trails; if (((TrailModule)(ref trails)).enabled) { ((TrailModule)(ref trails)).colorOverLifetime = Shift(((TrailModule)(ref trails)).colorOverLifetime); ((TrailModule)(ref trails)).colorOverTrail = Shift(((TrailModule)(ref trails)).colorOverTrail); } } Renderer[] componentsInChildren2 = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren2) { Material[] sharedMaterials = val.sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { sharedMaterials[j] = GreenMaterial(sharedMaterials[j]); } val.sharedMaterials = sharedMaterials; ParticleSystemRenderer val2 = (ParticleSystemRenderer)(object)((val is ParticleSystemRenderer) ? val : null); if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.trailMaterial)) { val2.trailMaterial = GreenMaterial(val2.trailMaterial); } LineRenderer val3 = (LineRenderer)(object)((val is LineRenderer) ? val : null); if (Object.op_Implicit((Object)(object)val3)) { val3.colorGradient = Shift(val3.colorGradient); } TrailRenderer val4 = (TrailRenderer)(object)((val is TrailRenderer) ? val : null); if (Object.op_Implicit((Object)(object)val4)) { val4.colorGradient = Shift(val4.colorGradient); } } Light[] componentsInChildren3 = root.GetComponentsInChildren<Light>(true); foreach (Light obj2 in componentsInChildren3) { obj2.color = Shift(obj2.color); } } internal static Material GreenMaterial(Material original) { //IL_0029: 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_0045: Expected O, but got Unknown //IL_0073: 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_007a: 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_0098: Invalid comparison between Unknown and I4 //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)original) || greenMaterials.Contains(original)) { return original; } if (materialCache.TryGetValue(original, out var value)) { return value; } Material val = new Material(original) { name = ((Object)original).name + "_Green" }; Shader shader = original.shader; int num = (Object.op_Implicit((Object)(object)shader) ? shader.GetPropertyCount() : 0); for (int i = 0; i < num; i++) { string propertyName = shader.GetPropertyName(i); ShaderPropertyType propertyType = shader.GetPropertyType(i); if ((int)propertyType == 0) { val.SetColor(propertyName, Shift(original.GetColor(propertyName))); } else { if ((int)propertyType != 4) { continue; } string text = propertyName.ToLowerInvariant(); if (!text.Contains("normal") && !text.Contains("bump") && !text.Contains("distort")) { Texture texture = original.GetTexture(propertyName); if (texture is Texture2D) { val.SetTexture(propertyName, GreenTexture(texture)); } } } } materialCache[original] = val; greenMaterials.Add(val); return val; } internal static Texture GreenTexture(Texture original) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if (!(original is Texture2D)) { return original; } if (textureCache.TryGetValue(original, out var value)) { return value; } Texture2D val = ReadableCopy(original, new Rect(0f, 0f, (float)original.width, (float)original.height)); if (!Object.op_Implicit((Object)(object)val)) { textureCache[original] = original; return original; } Color32[] pixels = val.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { pixels[i] = Color32.op_Implicit(Shift(Color32.op_Implicit(pixels[i]))); } val.SetPixels32(pixels); val.Apply(true, false); ((Object)val).name = ((Object)original).name + "_Green"; ((Texture)val).wrapMode = original.wrapMode; ((Texture)val).filterMode = original.filterMode; ((Texture)val).anisoLevel = original.anisoLevel; textureCache[original] = (Texture)(object)val; return (Texture)(object)val; } internal static Sprite GreenIcon(Sprite original) { //IL_000c: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)original)) { return original; } try { Rect textureRect = original.textureRect; Texture2D val = ReadableCopy((Texture)(object)original.texture, textureRect); if (!Object.op_Implicit((Object)(object)val)) { return original; } Color32[] pixels = val.GetPixels32(); for (int i = 0; i < pixels.Length; i++) { pixels[i] = Color32.op_Implicit(Tint(Color32.op_Implicit(pixels[i]))); } val.SetPixels32(pixels); val.Apply(true, false); ((Object)val).name = ((Object)original).name + "_Green"; ((Texture)val).wrapMode = (TextureWrapMode)1; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(original.pivot.x / ((Rect)(ref textureRect)).width, original.pivot.y / ((Rect)(ref textureRect)).height); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), val2, original.pixelsPerUnit); ((Object)obj).name = ((Object)original).name + "_Green"; return obj; } catch (Exception ex) { Debug.LogWarning((object)("[" + Prefix + "] Couldn't tint icon " + ((Object)original).name + ": " + ex.Message)); return original; } } private static Texture2D ReadableCopy(Texture source, Rect region) { //IL_005d: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)source)) { return null; } RenderTexture active = RenderTexture.active; RenderTexture temporary = RenderTexture.GetTemporary(source.width, source.height, 0, (RenderTextureFormat)0, (RenderTextureReadWrite)2); try { Graphics.Blit(source, temporary); RenderTexture.active = temporary; int num = Mathf.Max(1, Mathf.RoundToInt(((Rect)(ref region)).width)); int num2 = Mathf.Max(1, Mathf.RoundToInt(((Rect)(ref region)).height)); Texture2D val = new Texture2D(num, num2, (TextureFormat)4, true, false); val.ReadPixels(new Rect(((Rect)(ref region)).x, ((Rect)(ref region)).y, (float)num, (float)num2), 0, 0, false); val.Apply(false, false); return val; } catch (Exception ex) { Debug.LogWarning((object)("[" + Prefix + "] Couldn't copy texture " + ((Object)source).name + ": " + ex.Message)); return null; } finally { RenderTexture.active = active; RenderTexture.ReleaseTemporary(temporary); } } internal static Color Shift(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(c, ref num, ref num2, ref num3); if (num2 < 0.08f) { return c; } Color result = Color.HSVToRGB(0.36f, num2, num3, true); result.a = c.a; return result; } private static Color Tint(Color c) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0030: Unknown result type (might be due to invalid IL or missing references) float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(c, ref num, ref num2, ref num3); Color result = Color.HSVToRGB(0.36f, Mathf.Max(num2, 0.55f), num3); result.a = c.a; return result; } internal static Gradient Shift(Gradient g) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown if (g == null) { return null; } GradientColorKey[] colorKeys = g.colorKeys; for (int i = 0; i < colorKeys.Length; i++) { colorKeys[i].color = Shift(colorKeys[i].color); } Gradient val = new Gradient { mode = g.mode }; val.SetKeys(colorKeys, g.alphaKeys); return val; } internal static MinMaxGradient Shift(MinMaxGradient m) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) ParticleSystemGradientMode mode = ((MinMaxGradient)(ref m)).mode; switch ((int)mode) { case 0: return new MinMaxGradient(Shift(((MinMaxGradient)(ref m)).color)); case 2: return new MinMaxGradient(Shift(((MinMaxGradient)(ref m)).colorMin), Shift(((MinMaxGradient)(ref m)).colorMax)); case 1: return new MinMaxGradient(Shift(((MinMaxGradient)(ref m)).gradient)); case 3: return new MinMaxGradient(Shift(((MinMaxGradient)(ref m)).gradientMin), Shift(((MinMaxGradient)(ref m)).gradientMax)); case 4: { MinMaxGradient result = default(MinMaxGradient); ((MinMaxGradient)(ref result))..ctor(Shift(((MinMaxGradient)(ref m)).gradient)); ((MinMaxGradient)(ref result)).mode = (ParticleSystemGradientMode)4; return result; } default: return m; } } internal static void OverlayPrefix(TemporaryOverlayInstance instance) { if (GreenOverlays && instance != null && Object.op_Implicit((Object)(object)instance.originalMaterial)) { instance.originalMaterial = GreenMaterial(instance.originalMaterial); } } } } namespace BouncingHuntress.PhaseBurst { internal static class PhaseBurstModule { private const string Section = "Phase Burst"; public const string NameToken = "HUNTRESS_UTILITY_PHASEBURST_NAME"; public const string DescriptionToken = "HUNTRESS_UTILITY_PHASEBURST_DESCRIPTION"; private const string UtilityFamilyKey = "RoR2/Base/Huntress/HuntressBodyUtilityFamily.asset"; internal static ManualLogSource Log; internal static ConfigEntry<float> Radius; internal static ConfigEntry<float> DamageCoefficient; internal static ConfigEntry<string> VisualEffectKey; internal static ConfigEntry<float> VisualScale; internal static SkillDef PhaseBurstSkillDef; internal static GameObject BurstEffectPrefab; internal static GameObject GreenBlinkEffect; internal static void Init(ConfigFile Config, ManualLogSource logger) { Log = logger; DamageCoefficient = Config.Bind<float>("Phase Burst", "Damage", 3f, "Burst damage as a multiple of Huntress's base damage (3 = 300%, about Laser Glaive's 2nd bounce)."); Radius = Config.Bind<float>("Phase Burst", "Radius", 6f, "Radius (meters) of the damage burst at the end of each blink (the green visual follows it)."); VisualEffectKey = Config.Bind<string>("Phase Burst", "EffectAsset", "RoR2/Base/Captain/CaptainTazerNova.prefab", "Game effect used for the burst (an Addressables key); it's recolored green. Leave empty for no visual."); VisualScale = Config.Bind<float>("Phase Burst", "SizeMultiplier", 1f, "Multiplies the visual's size. 1 = drawn at the damage radius. Tweak if it looks bigger or smaller than the hit area."); CreateSkill(); if (Object.op_Implicit((Object)(object)PhaseBurstSkillDef)) { BHContent.SkillDefs.Add(PhaseBurstSkillDef); } BHContent.StateTypes.Add(typeof(PhaseBurstState)); CreateBurstEffect(); GreenBlinkEffect = GreenFx.CloneEffect(GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.MiniBlinkState.asset", "blinkPrefab") ?? GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.BlinkState.asset", "blinkPrefab")); Log.LogInfo((object)("Green visuals: burst " + (Object.op_Implicit((Object)(object)BurstEffectPrefab) ? "ok" : "missing") + ", blink " + (Object.op_Implicit((Object)(object)GreenBlinkEffect) ? "ok" : "missing") + ".")); LanguagePatches.ApplyToLoaded(); Log.LogInfo((object)"Phase Burst loaded."); } private static void CreateBurstEffect() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) string value = VisualEffectKey.Value; if (string.IsNullOrEmpty(value)) { return; } GameObject val = null; try { val = Addressables.LoadAssetAsync<GameObject>((object)value).WaitForCompletion(); } catch (Exception ex) { Log.LogWarning((object)("Burst visual '" + value + "' failed to load: " + ex.Message)); } if (!Object.op_Implicit((Object)(object)val)) { Log.LogWarning((object)("Burst visual '" + value + "' not found; the burst will be invisible.")); return; } GameObject val2 = GreenFx.CloneEffect(val); EffectComponent val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<EffectComponent>() : null); if (!Object.op_Implicit((Object)(object)val3)) { Log.LogWarning((object)("Burst visual '" + value + "' isn't a game effect; the burst will be invisible.")); return; } val3.applyScale = true; BurstEffectPrefab = val2; } private static void CreateSkill() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0046: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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_015b: Expected O, but got Unknown //IL_015b: 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_0076: Unknown result type (might be due to invalid IL or missing references) SkillFamily val = Addressables.LoadAssetAsync<SkillFamily>((object)"RoR2/Base/Huntress/HuntressBodyUtilityFamily.asset").WaitForCompletion(); if (!Object.op_Implicit((Object)(object)val)) { Log.LogError((object)"Could not load Huntress's utility skill family."); return; } SkillDef val2 = null; Variant[] variants = val.variants; foreach (Variant val3 in variants) { if (Object.op_Implicit((Object)(object)val3.skillDef) && ((SerializableEntityStateType)(ref val3.skillDef.activationState)).stateType == typeof(MiniBlinkState)) { val2 = val3.skillDef; break; } } if (!Object.op_Implicit((Object)(object)val2)) { Log.LogError((object)"Could not find Phase Blink in Huntress's utility skills."); return; } SkillDef val4 = Object.Instantiate<SkillDef>(val2); ((Object)val4).name = "HuntressBodyPhaseBurst"; val4.skillName = "PhaseBurst"; val4.skillNameToken = "HUNTRESS_UTILITY_PHASEBURST_NAME"; val4.skillDescriptionToken = "HUNTRESS_UTILITY_PHASEBURST_DESCRIPTION"; val4.activationState = new SerializableEntityStateType(typeof(PhaseBurstState)); val4.icon = GreenFx.GreenIcon(val2.icon); PhaseBurstSkillDef = val4; int num = val.variants.Length; Array.Resize(ref val.variants, num + 1); Variant[] variants2 = val.variants; Variant val5 = new Variant { skillDef = val4, unlockableName = "", unlockableDef = null }; ((Variant)(ref val5)).viewableNode = new Node(val4.skillNameToken, false, (Node)null); variants2[num] = val5; } } internal static class LanguagePatches { private static string Description() { return "<style=cIsUtility>Agile</style>. <style=cIsUtility>Disappear</style> and <style=cIsUtility>teleport</style> a short distance, then release a burst that deals <style=cIsDamage>" + Mathf.RoundToInt(PhaseBurstModule.DamageCoefficient.Value * 100f) + "% damage</style> around you. If it kills, <style=cIsUtility>restore a charge</style>. Can store up to <style=cIsUtility>3</style> charges."; } private static void Apply(Language language) { if (language != null) { language.SetStringByToken("HUNTRESS_UTILITY_PHASEBURST_NAME", "Phase Burst"); language.SetStringByToken("HUNTRESS_UTILITY_PHASEBURST_DESCRIPTION", Description()); } } internal static void ApplyToLoaded() { try { Apply(Language.currentLanguage); } catch { } } [HarmonyPatch(typeof(Language), "LoadStrings")] [HarmonyPostfix] private static void LoadStrings_Postfix(Language __instance) { Apply(__instance); } } public class PhaseBurstState : MiniBlinkState { private static readonly FieldInfo[] tunedFields = typeof(BlinkState).GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); public PhaseBurstState() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown MiniBlinkState obj = new MiniBlinkState(); FieldInfo[] array = tunedFields; foreach (FieldInfo fieldInfo in array) { fieldInfo.SetValue(this, fieldInfo.GetValue(obj)); } } public override void OnEnter() { GameObject blinkPrefab = BlinkState.blinkPrefab; if (Object.op_Implicit((Object)(object)PhaseBurstModule.GreenBlinkEffect)) { BlinkState.blinkPrefab = PhaseBurstModule.GreenBlinkEffect; } try { ((BlinkState)this).OnEnter(); } finally { BlinkState.blinkPrefab = blinkPrefab; } } public override void OnExit() { bool flag = Object.op_Implicit((Object)(object)((EntityState)this).outer) && ((EntityState)this).outer.destroying; GameObject blinkPrefab = BlinkState.blinkPrefab; if (Object.op_Implicit((Object)(object)PhaseBurstModule.GreenBlinkEffect)) { BlinkState.blinkPrefab = PhaseBurstModule.GreenBlinkEffect; } GreenFx.GreenOverlays = true; try { ((BlinkState)this).OnExit(); } finally { BlinkState.blinkPrefab = blinkPrefab; GreenFx.GreenOverlays = false; } if (!flag && ((EntityState)this).isAuthority && Object.op_Implicit((Object)(object)((EntityState)this).characterBody)) { PhaseBurstAttack.Fire(((EntityState)this).characterBody); } } } internal static class PhaseBurstAttack { private static bool loggedFirst; internal static float GlaiveFinalBounceCoefficient() { float num = ThrowGlaive.damageCoefficient * Mathf.Pow(ThrowGlaive.damageCoefficientPerBounce, (float)ThrowGlaive.maxBounceCount); if (!(num > 0f)) { return 4.43f; } return num; } internal static void Fire(CharacterBody body) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00e2: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Expected O, but got Unknown //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Max(0.5f, PhaseBurstModule.Radius.Value); Vector3 corePosition = body.corePosition; TeamIndex teamIndex = (TeamIndex)((!Object.op_Implicit((Object)(object)body.teamComponent)) ? 1 : ((int)body.teamComponent.teamIndex)); HashSet<HealthComponent> hashSet = new HashSet<HealthComponent>(); float num2 = num + 2f; LayerIndex entityPrecise = LayerIndex.entityPrecise; Collider[] array = Physics.OverlapSphere(corePosition, num2, LayerMask.op_Implicit(((LayerIndex)(ref entityPrecise)).mask), (QueryTriggerInteraction)2); for (int i = 0; i < array.Length; i++) { HurtBox component = ((Component)array[i]).GetComponent<HurtBox>(); HealthComponent val = (Object.op_Implicit((Object)(object)component) ? component.healthComponent : null); if (Object.op_Implicit((Object)(object)val) && val.alive && (Object)(object)((Component)val).gameObject != (Object)(object)((Component)body).gameObject) { hashSet.Add(val); } } BlastAttack val2 = new BlastAttack { attacker = ((Component)body).gameObject, inflictor = ((Component)body).gameObject, teamIndex = teamIndex, attackerFiltering = (AttackerFiltering)2, position = corePosition, radius = num, falloffModel = (FalloffModel)0, baseDamage = body.damage * Mathf.Max(0f, PhaseBurstModule.DamageCoefficient.Value), baseForce = 0f, bonusForce = Vector3.zero, crit = body.RollCrit(), procCoefficient = ((ThrowGlaive.glaiveProcCoefficient > 0f) ? ThrowGlaive.glaiveProcCoefficient : 1f), damageColorIndex = (DamageColorIndex)0, losType = (LoSType)0 }; DamageTypeCombo damageType = DamageTypeCombo.op_Implicit((DamageType)0); damageType.damageSource = (DamageSource)4; val2.damageType = damageType; Result val3 = val2.Fire(); if (Object.op_Implicit((Object)(object)PhaseBurstModule.BurstEffectPrefab)) { EffectManager.SpawnEffect(PhaseBurstModule.BurstEffectPrefab, new EffectData { origin = corePosition, scale = num * Mathf.Max(0.01f, PhaseBurstModule.VisualScale.Value) }, true); } if (!loggedFirst) { loggedFirst = true; PhaseBurstModule.Log.LogInfo((object)("First Phase Burst: " + (PhaseBurstModule.DamageCoefficient.Value * 100f).ToString("0") + "% damage, radius " + num + "m, hit " + val3.hitCount + ".")); } List<HealthComponent> list = new List<HealthComponent>(); if (val3.hitPoints != null) { HitPoint[] hitPoints = val3.hitPoints; foreach (HitPoint val4 in hitPoints) { HealthComponent val5 = (Object.op_Implicit((Object)(object)val4.hurtBox) ? val4.hurtBox.healthComponent : null); if (Object.op_Implicit((Object)(object)val5) && hashSet.Contains(val5) && !list.Contains(val5)) { list.Add(val5); } } } if (list.Count != 0) { PhaseBurstRefund phaseBurstRefund = ((Component)body).GetComponent<PhaseBurstRefund>(); if (!Object.op_Implicit((Object)(object)phaseBurstRefund)) { phaseBurstRefund = ((Component)body).gameObject.AddComponent<PhaseBurstRefund>(); } phaseBurstRefund.Watch(list); } } } internal class PhaseBurstRefund : MonoBehaviour { private class Pending { public List<HealthComponent> victims; public float timeLeft; } private const float WatchSeconds = 1f; private readonly List<Pending> pending = new List<Pending>(); private CharacterBody body; private void Awake() { body = ((Component)this).GetComponent<CharacterBody>(); } public void Watch(List<HealthComponent> victims) { Pending pending = new Pending { victims = victims, timeLeft = 1f }; if (!TryRefund(pending) && !NetworkServer.active) { this.pending.Add(pending); } } private void FixedUpdate() { for (int num = this.pending.Count - 1; num >= 0; num--) { Pending pending = this.pending[num]; pending.timeLeft -= Time.fixedDeltaTime; if (TryRefund(pending) || pending.timeLeft <= 0f) { this.pending.RemoveAt(num); } } } private bool TryRefund(Pending p) { foreach (HealthComponent victim in p.victims) { if (!Object.op_Implicit((Object)(object)victim) || !victim.alive) { RefundOneCharge(); return true; } } return false; } private void RefundOneCharge() { GenericSkill val = ((Object.op_Implicit((Object)(object)body) && Object.op_Implicit((Object)(object)body.skillLocator)) ? body.skillLocator.utility : null); if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val.skillDef != (Object)(object)PhaseBurstModule.PhaseBurstSkillDef) && val.stock < val.maxStock) { val.stock += 1; } } } } namespace BouncingHuntress.Glaive { public enum BounceMode { KeepBouncing, OncePerEnemy } internal static class GlaiveModule { private const string Section = "Endless Glaive"; public const string NameToken = "HUNTRESS_SECONDARY_ENDLESSGLAIVE_NAME"; public const string DescriptionToken = "HUNTRESS_SECONDARY_ENDLESSGLAIVE_DESCRIPTION"; private const string VanillaGlaiveKey = "RoR2/Base/Huntress/HuntressBodyGlaive.asset"; private const string SecondaryFamilyKey = "RoR2/Base/Huntress/HuntressBodySecondaryFamily.asset"; internal static ManualLogSource Log; internal static ConfigEntry<BounceMode> Mode; internal static ConfigEntry<int> GrowthStopsAfterBounce; internal static SkillDef EndlessGlaiveSkillDef; internal static GameObject GreenGlaiveOrb; internal static GameObject GreenChargeEffect; internal static GameObject GreenMuzzleFlash; private const string ThrowGlaiveConfigKey = "RoR2/Base/Huntress/EntityStates.Huntress.HuntressWeapon.ThrowGlaive.asset"; internal static void Init(ConfigFile Config, ManualLogSource logger) { Log = logger; Mode = Config.Bind<BounceMode>("Endless Glaive", "BounceMode", BounceMode.KeepBouncing, "KeepBouncing: the glaive hits every enemy in range, then starts another round, and only stops when there is no other living enemy within bounce range.\nOncePerEnemy: like vanilla (never hits the same enemy twice), but with no limit on the number of bounces.\nOnly the host's setting matters in multiplayer."); GrowthStopsAfterBounce = Config.Bind<int>("Endless Glaive", "GrowthStopsAfterBounce", 6, "The +10% damage per bounce stops after this many bounces (6 = vanilla Laser Glaive's last bounce, ~443%). Every bounce after that hits for the same damage. 0 = no limit (damage keeps growing forever)."); CreateSkill(); if (Object.op_Implicit((Object)(object)EndlessGlaiveSkillDef)) { BHContent.SkillDefs.Add(EndlessGlaiveSkillDef); } BHContent.StateTypes.Add(typeof(ThrowEndlessGlaive)); CreateGreenVisuals(); GlaivePatches.ApplyLanguageToLoaded(); Log.LogInfo((object)("Endless Glaive loaded. Mode = " + Mode.Value)); } private static void CreateGreenVisuals() { GreenGlaiveOrb = GreenFx.CloneEffect(GreenFx.LoadLegacy("Prefabs/Effects/OrbEffects/HuntressGlaiveOrbEffect")); GreenChargeEffect = GreenFx.CloneEffect(GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.HuntressWeapon.ThrowGlaive.asset", "chargePrefab")); GreenMuzzleFlash = GreenFx.CloneEffect(GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.HuntressWeapon.ThrowGlaive.asset", "muzzleFlashPrefab")); Log.LogInfo((object)("Green visuals: glaive " + (Object.op_Implicit((Object)(object)GreenGlaiveOrb) ? "ok" : "missing") + ", charge " + (Object.op_Implicit((Object)(object)GreenChargeEffect) ? "ok" : "missing") + ", flash " + (Object.op_Implicit((Object)(object)GreenMuzzleFlash) ? "ok" : "missing") + ".")); } private static void CreateSkill() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0086: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Huntress/HuntressBodyGlaive.asset").WaitForCompletion(); SkillFamily val2 = Addressables.LoadAssetAsync<SkillFamily>((object)"RoR2/Base/Huntress/HuntressBodySecondaryFamily.asset").WaitForCompletion(); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2)) { Log.LogError((object)"Could not load the vanilla Laser Glaive skill or Huntress secondary family. The game's asset paths may have changed."); return; } SkillDef val3 = Object.Instantiate<SkillDef>(val); ((Object)val3).name = "HuntressBodyEndlessGlaive"; val3.skillName = "EndlessGlaive"; val3.skillNameToken = "HUNTRESS_SECONDARY_ENDLESSGLAIVE_NAME"; val3.skillDescriptionToken = "HUNTRESS_SECONDARY_ENDLESSGLAIVE_DESCRIPTION"; val3.activationState = new SerializableEntityStateType(typeof(ThrowEndlessGlaive)); val3.icon = GreenFx.GreenIcon(val.icon); EndlessGlaiveSkillDef = val3; int num = val2.variants.Length; Array.Resize(ref val2.variants, num + 1); Variant[] variants = val2.variants; Variant val4 = new Variant { skillDef = val3, unlockableName = "", unlockableDef = null }; ((Variant)(ref val4)).viewableNode = new Node(val3.skillNameToken, false, (Node)null); variants[num] = val4; } } public class ThrowEndlessGlaive : ThrowGlaive { public override void OnEnter() { GameObject chargePrefab = ThrowGlaive.chargePrefab; if (Object.op_Implicit((Object)(object)GlaiveModule.GreenChargeEffect)) { ThrowGlaive.chargePrefab = GlaiveModule.GreenChargeEffect; } try { ((ThrowGlaive)this).OnEnter(); } finally { ThrowGlaive.chargePrefab = chargePrefab; } } } internal static class GlaivePatches { private const int EndlessBounceCount = int.MaxValue; private const int EndlessThreshold = 1073741823; private const float MaxDamage = 1E+30f; private const int MaxPicksPerSearch = 512; private static bool swappedBounceCount; private static int savedBounceCount; private static GameObject savedMuzzleFlash; private static bool beginningEndlessOrb; private static bool inOurPick; private static bool loggedFirstThrow; [HarmonyPatch(typeof(ThrowGlaive), "FireOrbGlaive")] [HarmonyPrefix] private static void FireOrbGlaive_Prefix(ThrowGlaive __instance) { if (__instance is ThrowEndlessGlaive) { savedBounceCount = ThrowGlaive.maxBounceCount; ThrowGlaive.maxBounceCount = int.MaxValue; savedMuzzleFlash = ThrowGlaive.muzzleFlashPrefab; if (Object.op_Implicit((Object)(object)GlaiveModule.GreenMuzzleFlash)) { ThrowGlaive.muzzleFlashPrefab = GlaiveModule.GreenMuzzleFlash; } swappedBounceCount = true; if (!loggedFirstThrow) { loggedFirstThrow = true; GlaiveModule.Log.LogInfo((object)("First Endless Glaive thrown (vanilla bounce count is " + savedBounceCount + ").")); } } } [HarmonyPatch(typeof(ThrowGlaive), "FireOrbGlaive")] [HarmonyFinalizer] private static Exception FireOrbGlaive_Finalizer(Exception __exception) { if (swappedBounceCount) { ThrowGlaive.maxBounceCount = savedBounceCount; ThrowGlaive.muzzleFlashPrefab = savedMuzzleFlash; swappedBounceCount = false; } return __exception; } private static bool IsEndless(LightningOrb orb) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)orb.lightningType == 4) { return orb.bouncesRemaining > 1073741823; } return false; } private static bool IsAlive(HurtBox hurtBox) { if (Object.op_Implicit((Object)(object)hurtBox) && Object.op_Implicit((Object)(object)hurtBox.healthComponent)) { return hurtBox.healthComponent.alive; } return false; } private static HurtBox PickLivingTarget(LightningOrb orb, Vector3 position) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 512; i++) { HurtBox val = orb.PickNextTarget(position); if (!Object.op_Implicit((Object)(object)val)) { return null; } if (IsAlive(val)) { return val; } } return null; } [HarmonyPatch(typeof(LightningOrb), "PickNextTarget")] [HarmonyPostfix] private static void PickNextTarget_Postfix(LightningOrb __instance, Vector3 position, ref HurtBox __result) { //IL_006d: 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) if (inOurPick || !IsEndless(__instance)) { return; } inOurPick = true; try { if (__instance.damageValue > 1E+30f) { __instance.damageValue = 1E+30f; } int value = GlaiveModule.GrowthStopsAfterBounce.Value; int num = int.MaxValue - __instance.bouncesRemaining; if (value > 0 && num >= value) { __instance.damageCoefficientPerBounce = 1f; } if (Object.op_Implicit((Object)(object)__result) && !IsAlive(__result)) { __result = PickLivingTarget(__instance, position); } if (!Object.op_Implicit((Object)(object)__result) && GlaiveModule.Mode.Value == BounceMode.KeepBouncing && __instance.bouncedObjects != null) { __instance.bouncedObjects.Clear(); if (Object.op_Implicit((Object)(object)((Orb)__instance).target) && Object.op_Implicit((Object)(object)((Orb)__instance).target.healthComponent)) { __instance.bouncedObjects.Add(((Orb)__instance).target.healthComponent); } __result = PickLivingTarget(__instance, position); } } finally { inOurPick = false; } } [HarmonyPatch(typeof(LightningOrb), "Begin")] [HarmonyPrefix] private static void LightningOrbBegin_Prefix(LightningOrb __instance) { beginningEndlessOrb = IsEndless(__instance); } [HarmonyPatch(typeof(LightningOrb), "Begin")] [HarmonyFinalizer] private static Exception LightningOrbBegin_Finalizer(Exception __exception) { beginningEndlessOrb = false; return __exception; } [HarmonyPatch(typeof(OrbStorageUtility), "Get")] [HarmonyPostfix] private static void OrbStorageGet_Postfix(string __0, ref GameObject __result) { if (beginningEndlessOrb && Object.op_Implicit((Object)(object)GlaiveModule.GreenGlaiveOrb) && __0 != null && __0.Contains("HuntressGlaiveOrbEffect")) { __result = GlaiveModule.GreenGlaiveOrb; } } private static string Description() { string text = ((GlaiveModule.Mode.Value == BounceMode.KeepBouncing) ? "bounces <style=cIsUtility>endlessly</style> between enemies" : "bounces to <style=cIsUtility>every enemy in range</style>"); int value = GlaiveModule.GrowthStopsAfterBounce.Value; string text2 = ((value > 0) ? ("Damage increases by <style=cIsDamage>10%</style> per bounce, up to the <style=cIsDamage>" + Ordinal(value) + "</style> bounce.") : "Damage increases by <style=cIsDamage>10%</style> per bounce."); return "Throw a seeking glaive that " + text + " for <style=cIsDamage>250% damage</style>. " + text2; } private static string Ordinal(int n) { if (n % 100 >= 11 && n % 100 <= 13) { return n + "th"; } return (n % 10) switch { 1 => n + "st", 2 => n + "nd", 3 => n + "rd", _ => n + "th", }; } private static void ApplyLanguage(Language language) { if (language != null) { language.SetStringByToken("HUNTRESS_SECONDARY_ENDLESSGLAIVE_NAME", "Endless Glaive"); language.SetStringByToken("HUNTRESS_SECONDARY_ENDLESSGLAIVE_DESCRIPTION", Description()); } } internal static void ApplyLanguageToLoaded() { try { ApplyLanguage(Language.currentLanguage); } catch { } } [HarmonyPatch(typeof(Language), "LoadStrings")] [HarmonyPostfix] private static void LoadStrings_Postfix(Language __instance) { ApplyLanguage(__instance); } } } namespace BouncingHuntress.ChainBallista { internal static class ChainBallistaModule { private const string Section = "Chain Ballista"; public const string NameToken = "HUNTRESS_SPECIAL_CHAINBALLISTA_NAME"; public const string DescriptionToken = "HUNTRESS_SPECIAL_CHAINBALLISTA_DESCRIPTION"; private const string SpecialFamilyKey = "RoR2/Base/Huntress/HuntressBodySpecialFamily.asset"; private static readonly string[] SnipeShotKeys = new string[3] { "RoR2/Base/Huntress/FireArrowSnipe.asset", "RoR2/Base/Huntress/AimArrowSnipe.asset", "RoR2/Base/Huntress/Skills.Huntress.Snipe.asset" }; internal static ManualLogSource Log; internal static ConfigEntry<int> MaxBounces; internal static ConfigEntry<float> FinaleRadius; internal static ConfigEntry<float> FinaleDamageFraction; internal static ConfigEntry<float> BounceDelay; internal static ConfigEntry<string> VisualEffectKey; internal static ConfigEntry<float> VisualScale; internal static SkillDef ChainBallistaSkillDef; internal static SkillDef ChainShotSkillDef; internal static GameObject FinaleEffectPrefab; internal static GameObject GreenTracer; internal static GameObject GreenHitEffect; internal static GameObject GreenMuzzleFlash; internal static GameObject GreenLeapFlash; private const string FireArrowSnipeConfigKey = "RoR2/Base/Huntress/EntityStates.Huntress.Weapon.FireArrowSnipe.asset"; internal static void Init(ConfigFile Config, ManualLogSource logger) { Log = logger; MaxBounces = Config.Bind<int>("Chain Ballista", "MaxBounces", 6, "Most bounces a killing final shot can make. The big blast only happens if the chain reaches this many."); FinaleRadius = Config.Bind<float>("Chain Ballista", "FinaleRadius", 12f, "Radius (meters) of the green blast after the last bounce."); FinaleDamageFraction = Config.Bind<float>("Chain Ballista", "FinaleDamageFraction", 0.5f, "Blast damage as a fraction of one Ballista shot (0.5 = half)."); BounceDelay = Config.Bind<float>("Chain Ballista", "BounceDelay", 0.15f, "Seconds between bounces, so you can see the chain travel."); VisualEffectKey = Config.Bind<string>("Chain Ballista", "EffectAsset", "RoR2/Base/Captain/CaptainTazerNova.prefab", "Game effect used for the blast (an Addressables key); it's recolored green. Leave empty for no visual."); VisualScale = Config.Bind<float>("Chain Ballista", "SizeMultiplier", 1f, "Multiplies the blast visual's size. 1 = drawn at the damage radius."); CreateSkills(); if (Object.op_Implicit((Object)(object)ChainBallistaSkillDef) && Object.op_Implicit((Object)(object)ChainShotSkillDef)) { BHContent.SkillDefs.Add(ChainBallistaSkillDef); BHContent.SkillDefs.Add(ChainShotSkillDef); } BHContent.StateTypes.Add(typeof(BeginChainSnipe)); BHContent.StateTypes.Add(typeof(AimChainSnipe)); BHContent.StateTypes.Add(typeof(FireChainSnipe)); CreateFinaleEffect(); GreenTracer = GreenFx.CloneEffect(GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.Weapon.FireArrowSnipe.asset", "tracerEffectPrefab")); GreenHitEffect = GreenFx.CloneEffect(GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.Weapon.FireArrowSnipe.asset", "hitEffectPrefab")); GreenMuzzleFlash = GreenFx.CloneEffect(GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.Weapon.FireArrowSnipe.asset", "muzzleFlashPrefab")); GreenLeapFlash = GreenFx.CloneEffect(GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.BeginArrowSnipe.asset", "blinkPrefab") ?? GreenFx.FromStateConfig<GameObject>("RoR2/Base/Huntress/EntityStates.Huntress.BaseBeginArrowBarrage.asset", "blinkPrefab")); Log.LogInfo((object)("Green visuals: bolt " + (Object.op_Implicit((Object)(object)GreenTracer) ? "ok" : "missing") + ", hit " + (Object.op_Implicit((Object)(object)GreenHitEffect) ? "ok" : "missing") + ", flash " + (Object.op_Implicit((Object)(object)GreenMuzzleFlash) ? "ok" : "missing") + ", leap " + (Object.op_Implicit((Object)(object)GreenLeapFlash) ? "ok" : "missing") + ", blast " + (Object.op_Implicit((Object)(object)FinaleEffectPrefab) ? "ok" : "missing") + ".")); LanguagePatches.ApplyToLoaded(); Log.LogInfo((object)"Chain Ballista loaded."); } private static void CreateSkills() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Expected O, but got Unknown //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: 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_010b: 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) SkillDef val = null; string[] snipeShotKeys = SnipeShotKeys; foreach (string text in snipeShotKeys) { SkillDef val2 = null; try { val2 = Addressables.LoadAssetAsync<SkillDef>((object)text).WaitForCompletion(); } catch { } if (Object.op_Implicit((Object)(object)val2) && ((SerializableEntityStateType)(ref val2.activationState)).stateType == typeof(FireArrowSnipe)) { val = val2; break; } } if (!Object.op_Implicit((Object)(object)val)) { Log.LogError((object)"Could not find Ballista's shot skill; Chain Ballista won't be added."); return; } SkillDef obj2 = Object.Instantiate<SkillDef>(val); ((Object)obj2).name = "HuntressBodyChainBallistaShot"; obj2.skillName = "ChainBallistaShot"; obj2.activationState = new SerializableEntityStateType(typeof(FireChainSnipe)); obj2.icon = GreenFx.GreenIcon(val.icon); ChainShotSkillDef = obj2; SkillFamily val3 = Addressables.LoadAssetAsync<SkillFamily>((object)"RoR2/Base/Huntress/HuntressBodySpecialFamily.asset").WaitForCompletion(); SkillDef val4 = null; if (Object.op_Implicit((Object)(object)val3)) { Variant[] variants = val3.variants; foreach (Variant val5 in variants) { if (Object.op_Implicit((Object)(object)val5.skillDef) && ((SerializableEntityStateType)(ref val5.skillDef.activationState)).stateType == typeof(BeginArrowSnipe)) { val4 = val5.skillDef; break; } } } if (!Object.op_Implicit((Object)(object)val4)) { Log.LogError((object)"Could not find Ballista in Huntress's special skills; Chain Ballista won't be added."); ChainShotSkillDef = null; return; } SkillDef val6 = Object.Instantiate<SkillDef>(val4); ((Object)val6).name = "HuntressBodyChainBallista"; val6.skillName = "ChainBallista"; val6.skillNameToken = "HUNTRESS_SPECIAL_CHAINBALLISTA_NAME"; val6.skillDescriptionToken = "HUNTRESS_SPECIAL_CHAINBALLISTA_DESCRIPTION"; val6.activationState = new SerializableEntityStateType(typeof(BeginChainSnipe)); val6.icon = GreenFx.GreenIcon(val4.icon); ChainBallistaSkillDef = val6; int num = val3.variants.Length; Array.Resize(ref val3.variants, num + 1); Variant[] variants2 = val3.variants; Variant val7 = new Variant { skillDef = val6, unlockableName = "", unlockableDef = null }; ((Variant)(ref val7)).viewableNode = new Node(val6.skillNameToken, false, (Node)null); variants2[num] = val7; } private static void CreateFinaleEffect() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) string value = VisualEffectKey.Value; if (string.IsNullOrEmpty(value)) { return; } GameObject val = null; try { val = Addressables.LoadAssetAsync<GameObject>((object)value).WaitForCompletion(); } catch (Exception ex) { Log.LogWarning((object)("Blast visual '" + value + "' failed to load: " + ex.Message)); } if (Object.op_Implicit((Object)(object)val)) { GameObject val2 = GreenFx.CloneEffect(val); EffectComponent val3 = (Object.op_Implicit((Object)(object)val2) ? val2.GetComponent<EffectComponent>() : null); if (Object.op_Implicit((Object)(object)val3)) { val3.applyScale = true; FinaleEffectPrefab = val2; } } } internal static void CopyTuning(object target, object template, params Type[] declaringTypes) { for (int i = 0; i < declaringTypes.Length; i++) { FieldInfo[] fields = declaringTypes[i].GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { fieldInfo.SetValue(target, fieldInfo.GetValue(template)); } } } } internal static class LanguagePatches { private static void Apply(Language language) { if (language != null) { int value = ChainBallistaModule.MaxBounces.Value; int num = Mathf.RoundToInt(900f * ChainBallistaModule.FinaleDamageFraction.Value); language.SetStringByToken("HUNTRESS_SPECIAL_CHAINBALLISTA_NAME", "Chain Ballista"); language.SetStringByToken("HUNTRESS_SPECIAL_CHAINBALLISTA_DESCRIPTION", "<style=cIsUtility>Teleport</style> backwards into the sky. Fire up to <style=cIsDamage>3</style> energy bolts, dealing <style=cIsDamage>3x900% damage</style>. If the last bolt <style=cIsHealth>kills</style>, it jumps to the nearest enemy for <style=cIsDamage>900% damage</style>, and keeps jumping while it kills, up to <style=cIsUtility>" + value + "</style> times. The " + Ordinal(value) + " jump detonates for <style=cIsDamage>" + num + "% damage</style> in a large area."); } } private static string Ordinal(int n) { if (n % 100 >= 11 && n % 100 <= 13) { return n + "th"; } return (n % 10) switch { 1 => n + "st", 2 => n + "nd", 3 => n + "rd", _ => n + "th", }; } internal static void ApplyToLoaded() { try { Apply(Language.currentLanguage); } catch { } } [HarmonyPatch(typeof(Language), "LoadStrings")] [HarmonyPostfix] private static void LoadStrings_Postfix(Language __instance) { Apply(__instance); } } internal class ChainShot { public GameObject owner; public TeamIndex team; public float damage; public bool isCrit; public float procCoefficient; public float force; public DamageTypeCombo damageType; public GameObject tracerEffectPrefab; public GameObject hitEffectPrefab; public float radius; public static ChainShot From(BulletAttack bullet, CharacterBody body) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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) return new ChainShot { owner = ((Component)body).gameObject, team = (TeamIndex)((!Object.op_Implicit((Object)(object)body.teamComponent)) ? 1 : ((int)body.teamComponent.teamIndex)), damage = bullet.damage, isCrit = bullet.isCrit, procCoefficient = bullet.procCoefficient, force = bullet.force, damageType = bullet.damageType, tracerEffectPrefab = bullet.tracerEffectPrefab, hitEffectPrefab = bullet.hitEffectPrefab, radius = bullet.radius }; } } internal class ChainRunner : MonoBehaviour { private const float ClientKillWait = 1f; private static readonly BullseyeSearch search = new BullseyeSearch(); public void Begin(ChainShot shot, List<HealthComponent> victims, List<Vector3> positions) { ((MonoBehaviour)this).StartCoroutine(Run(shot, victims, positions)); } private IEnumerator Run(ChainShot shot, List<HealthComponent> victims, List<Vector3> positions) { float waited = 0f; int num; while (true) { num = FirstDeadIndex(victims); if (num >= 0 || NetworkServer.active || waited >= 1f) { break; } waited += Time.fixedDeltaTime; yield return (object)new WaitForFixedUpdate(); } if (num < 0) { yield break; } HealthComponent current = victims[num]; Vector3 from = positions[num]; int maxBounces = Mathf.Max(1, ChainBallistaModule.MaxBounces.Value); float delay = Mathf.Max(0f, ChainBallistaModule.BounceDelay.Value); for (int bounce = 1; bounce <= maxBounces; bounce++) { if (delay > 0f) { yield return (object)new WaitForSeconds(delay); } HurtBox val = FindNearestEnemy(from, current, shot.team); if (!Object.op_Implicit((Object)(object)val)) { break; } HealthComponent target = val.healthComponent; Vector3 targetPosition = (Object.op_Implicit((Object)(object)target.body) ? target.body.corePosition : ((Component)val).transform.position); FireBounce(shot, from, ((Component)val).transform.position); if (bounce == maxBounces) { Detonate(shot, targetPosition); break; } waited = 0f; while (Object.op_Implicit((Object)(object)target) && target.alive && !NetworkServer.active && waited < 1f) { waited += Time.fixedDeltaTime; yield return (object)new WaitForFixedUpdate(); } if (Object.op_Implicit((Object)(object)target) && target.alive) { break; } current = target; from = targetPosition; } } private static int FirstDeadIndex(List<HealthComponent> victims) { for (int i = 0; i < victims.Count; i++) { HealthComponent val = victims[i]; if (!Object.op_Implicit((Object)(object)val) || !val.alive) { return i; } } return -1; } private static HurtBox FindNearestEnemy(Vector3 from, HealthComponent exclude, TeamIndex attackerTeam) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) TeamMask allButNeutral = TeamMask.allButNeutral; ((TeamMask)(ref allButNeutral)).RemoveTeam(attackerTeam); search.searchOrigin = from; search.searchDirection = Vector3.zero; search.teamMaskFilter = allButNeutral; search.filterByLoS = false; search.filterByDistinctEntity = true; search.sortMode = (SortMode)1; search.maxDistanceFilter = 100000f; search.RefreshCandidates(); foreach (HurtBox result in search.GetResults()) { HealthComponent val = (Object.op_Implicit((Object)(object)result) ? result.healthComponent : null); if (Object.op_Implicit((Object)(object)val) && val.alive && !((Object)(object)val == (Object)(object)exclude)) { return result; } } return null; } private static void FireBounce(ChainShot shot, Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown Vector3 val = to - from; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.01f) { val = Vector3.up; } BulletAttack val2 = new BulletAttack { owner = shot.owner, weapon = null, muzzleName = "", origin = from, aimVector = ((Vector3)(ref val)).normalized, maxDistance = magnitude + 2f, bulletCount = 1u, minSpread = 0f, maxSpread = 0f, radius = Mathf.Max(0.5f, shot.radius), smartCollision = false, damage = shot.damage, isCrit = shot.isCrit, procCoefficient = shot.procCoefficient, force = shot.force, damageType = shot.damageType, damageColorIndex = (DamageColorIndex)0, falloffModel = (FalloffModel)0, tracerEffectPrefab = null, hitEffectPrefab = shot.hitEffectPrefab }; LayerIndex entityPrecise = LayerIndex.entityPrecise; val2.hitMask = ((LayerIndex)(ref entityPrecise)).mask; val2.stopperMask = LayerMask.op_Implicit(0); val2.Fire(); if (Object.op_Implicit((Object)(object)shot.tracerEffectPrefab)) { EffectManager.SpawnEffect(shot.tracerEffectPrefab, new EffectData { origin = to, start = from }, true); } } private unsafe static void Detonate(ChainShot shot, Vector3 position) { //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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007c: 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_0082: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_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_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown float num = Mathf.Max(0.5f, ChainBallistaModule.FinaleRadius.Value); BlastAttack val = new BlastAttack { attacker = shot.owner, inflictor = shot.owner, teamIndex = shot.team, attackerFiltering = (AttackerFiltering)2, position = position, radius = num, falloffModel = (FalloffModel)0, baseDamage = shot.damage * ChainBallistaModule.FinaleDamageFraction.Value, baseForce = 0f, bonusForce = Vector3.zero, crit = shot.isCrit, procCoefficient = 1f, damageColorIndex = (DamageColorIndex)0, losType = (LoSType)0 }; DamageTypeCombo damageType = DamageTypeCombo.op_Implicit((DamageType)0); damageType.damageSource = (DamageSource)8; val.damageType = damageType; val.Fire(); if (Object.op_Implicit((Object)(object)ChainBallistaModule.FinaleEffectPrefab)) { EffectManager.SpawnEffect(ChainBallistaModule.FinaleEffectPrefab, new EffectData { origin = position, scale = num * Mathf.Max(0.01f, ChainBallistaModule.VisualScale.Value) }, true); } ManualLogSource log = ChainBallistaModule.Log; Vector3 val2 = position; log.LogInfo((object)("Chain Ballista: full chain! Detonated at " + ((object)(*(Vector3*)(&val2))/*cast due to .constrained prefix*/).ToString() + ".")); } } public class BeginChainSnipe : BeginArrowSnipe { public BeginChainSnipe() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown ChainBallistaModule.CopyTuning(this, (object)new BeginArrowSnipe(), typeof(BaseBeginArrowBarrage)); } protected override EntityState InstantiateNextState() { return (EntityState)(object)new AimChainSnipe(); } public override void OnEnter() { GameObject blinkPrefab = BaseBeginArrowBarrage.blinkPrefab; if (Object.op_Implicit((Object)(object)ChainBallistaModule.GreenLeapFlash)) { BaseBeginArrowBarrage.blinkPrefab = ChainBallistaModule.GreenLeapFlash; } try { ((BaseBeginArrowBarrage)this).OnEnter(); } finally { BaseBeginArrowBarrage.blinkPrefab = blinkPrefab; } } public override void FixedUpdate() { GameObject blinkPrefab = BaseBeginArrowBarrage.blinkPrefab; if (Object.op_Implicit((Object)(object)ChainBallistaModule.GreenLeapFlash)) { BaseBeginArrowBarrage.blinkPrefab = ChainBallistaModule.GreenLeapFlash; } try { ((BaseBeginArrowBarrage)this).FixedUpdate(); } finally { BaseBeginArrowBarrage.blinkPrefab = blinkPrefab; } } public override void OnExit() { GameObject blinkPrefab = BaseBeginArrowBarrage.blinkPrefab; if (Object.op_Implicit((Object)(object)ChainBallistaModule.GreenLeapFlash)) { BaseBeginArrowBarrage.blinkPrefab = ChainBallistaModule.GreenLeapFlash; } GreenFx.GreenOverlays = true; try { ((BaseBeginArrowBarrage)this).OnExit(); } finally { BaseBeginArrowBarrage.blinkPrefab = blinkPrefab; GreenFx.GreenOverlays = false; } } } public class AimChainSnipe : AimArrowSnipe { private GenericSkill primary; public AimChainSnipe() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown ChainBallistaModule.CopyTuning(this, (object)new AimArrowSnipe(), typeof(BaseArrowBarrage)); } public override void OnEnter() { ((AimArrowSnipe)this).OnEnter(); primary = (Object.op_Implicit((Object)(object)((EntityState)this).skillLocator) ? ((EntityState)this).skillLocator.primary : null); if (Object.op_Implicit((Object)(object)primary) && Object.op_Implicit((Object)(object)ChainBallistaModule.ChainShotSkillDef)) { primary.UnsetSkillOverride((object)this, AimArrowSnipe.primarySkillDef, (SkillOverridePriority)4); primary.SetSkillOverride((object)this, ChainBallistaModule.ChainShotSkillDef, (SkillOverridePriority)4); } } public override void OnExit() { if (Object.op_Implicit((Object)(object)primary) && Object.op_Implicit((Object)(object)ChainBallistaModule.ChainShotSkillDef)) { primary.UnsetSkillOverride((object)this, ChainBallistaModule.ChainShotSkillDef, (SkillOverridePriority)4); } ((AimArrowSnipe)this).OnExit(); } } public class FireChainSnipe : FireArrowSnipe { private bool isFinalShot; private BulletAttack firedBullet; private readonly List<HealthComponent> victims = new List<HealthComponent>(); private readonly List<Vector3> victimPositions = new List<Vector3>(); public FireChainSnipe() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown ChainBallistaModule.CopyTuning(this, (object)new FireArrowSnipe(), typeof(GenericBulletBaseState), typeof(FireArrowSnipe)); if (Object.op_Implicit((Object)(object)ChainBallistaModule.GreenTracer)) { ((GenericBulletBaseState)this).tracerEffectPrefab = ChainBallistaModule.GreenTracer; } if (Object.op_Implicit((Object)(object)ChainBallistaModule.GreenHitEffect)) { ((GenericBulletBaseState)this).hitEffectPrefab = ChainBallistaModule.GreenHitEffect; } if (Object.op_Implicit((Object)(object)ChainBallistaModule.GreenMuzzleFlash)) { ((GenericBulletBaseState)this).muzzleFlashPrefab = ChainBallistaModule.GreenMuzzleFlash; } } public override void OnEnter() { isFinalShot = ((EntityState)this).isAuthority && Object.op_Implicit((Object)(object)((EntityState)this).skillLocator) && Object.op_Implicit((Object)(object)((EntityState)this).skillLocator.primary) && ((EntityState)this).skillLocator.primary.stock == 0; ((GenericBulletBaseState)this).OnEnter(); } protected override void ModifyBullet(BulletAttack bulletAttack) { ((FireArrowSnipe)this).ModifyBullet(bulletAttack); firedBullet = bulletAttack; } protected override bool OnBulletImpact(BulletAttack bulletAttack, ref BulletHit hitInfo) { //IL_0077: 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) if (isFinalS