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 SecondaryAttacks v1.0.1
SecondaryAttacks.dll
Decompiled 6 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.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.IO.Compression; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using LocalizationManager; using Microsoft.CodeAnalysis; using ServerSync; using TMPro; using UnityEngine; using UnityEngine.UI; using YamlDotNet.Core; using YamlDotNet.Core.Events; using YamlDotNet.Core.ObjectPool; using YamlDotNet.Core.Tokens; using YamlDotNet.Helpers; using YamlDotNet.RepresentationModel; using YamlDotNet.Serialization; using YamlDotNet.Serialization.BufferedDeserialization; using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators; using YamlDotNet.Serialization.Callbacks; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.EventEmitters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NodeDeserializers; using YamlDotNet.Serialization.NodeTypeResolvers; using YamlDotNet.Serialization.ObjectFactories; using YamlDotNet.Serialization.ObjectGraphTraversalStrategies; using YamlDotNet.Serialization.ObjectGraphVisitors; using YamlDotNet.Serialization.Schemas; using YamlDotNet.Serialization.TypeInspectors; using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("SecondaryAttacks")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("sighsorry")] [assembly: AssemblyProduct("SecondaryAttacks")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyFileVersion("1.0.1")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class ExtensionMarkerAttribute : Attribute { private readonly string <Name>k__BackingField; public string Name => <Name>k__BackingField; public ExtensionMarkerAttribute(string name) { <Name>k__BackingField = name; } } } namespace LocalizationManager { [PublicAPI] public class Localizer { private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; private static BaseUnityPlugin? _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin plugin { get { //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } public static event Action? OnLocalizationComplete; private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out string value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out Dictionary<string, Func<string>> value2)) { text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull { if (convertConfigValue == null) { convertConfigValue = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += delegate { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { _ = plugin; if (Localization.instance != null) { LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage()); } } public static void LoadLocalizationLater() { if (Localization.instance != null) { LoadLocalization(Localization.instance, Localization.instance.GetSelectedLanguage()); } } public static void SafeCallLocalizeComplete() { Localizer.OnLocalizationComplete?.Invoke(); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string[] array = Path.GetFileNameWithoutExtension(item).Split('.'); if (array.Length >= 2) { string text = array[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } } byte[] array2 = LoadTranslationFromAssembly("English"); if (array2 == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(Encoding.UTF8.GetString(array2)); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array3 = LoadTranslationFromAssembly(language); if (array3 != null) { text2 = Encoding.UTF8.GetString(array3); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_008f: 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_00ca: Expected O, but got Unknown //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string>(2) { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static byte[]? LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } public static class LocalizationManagerVersion { public const string Version = "1.4.0"; } } namespace SecondaryAttacks { internal static class AftershockSystem { internal sealed class AftershockController : MonoBehaviour { private int _nextWave; private float _nextWaveTime; private bool _registered; private bool _durabilityDrained; private bool _finished; internal Attack Attack { get; private set; } internal AftershockDefinition Aftershock { get; private set; } internal Vector3 BaseOrigin { get; private set; } internal Vector3 Forward { get; private set; } internal Quaternion Rotation { get; private set; } internal void Initialize(Attack attack, AftershockDefinition aftershock) { //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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_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) Attack = attack; Aftershock = aftershock; Transform transform = ((Component)attack.m_character).transform; Transform val = ResolveAttackOrigin(attack); Forward = transform.forward; Rotation = transform.rotation; BaseOrigin = val.position + Vector3.up * attack.m_attackHeight + Forward * attack.m_attackRange + transform.right * attack.m_attackOffset; _nextWave = 0; _nextWaveTime = Time.time; _registered = true; SecondaryAttackManager.RegisterAsyncSecondaryWork((Character?)(object)attack.m_character); ((Behaviour)this).enabled = true; } private void Update() { if ((Object)(object)Attack?.m_character == (Object)null || Attack.m_weapon == null || ((Character)Attack.m_character).IsDead() || !SecondaryAttackManager.HasCharacterAuthority((Character?)(object)Attack.m_character)) { Finish(); return; } while (_nextWave <= Aftershock.Waves && Time.time >= _nextWaveTime) { ApplyWave(this, _nextWave); _nextWave++; float num = Mathf.Max(0f, Aftershock.Interval); _nextWaveTime += num; if (num > 0f) { break; } } if (_nextWave > Aftershock.Waves) { Finish(); } } internal void DrainDurabilityOnce() { if (!_durabilityDrained) { SecondaryAttackManager.DrainAttackDurability(Attack, Aftershock.DurabilityFactor); _durabilityDrained = true; } } private void Finish() { if (!_finished) { _finished = true; Object.Destroy((Object)(object)this); } } private void OnDestroy() { if (_registered) { SecondaryAttackManager.UnregisterAsyncSecondaryWork((Character?)(object)Attack?.m_character); _registered = false; } } } private static readonly Collider[] Hits = (Collider[])(object)new Collider[128]; private static readonly HashSet<GameObject> HitObjects = new HashSet<GameObject>(); private static int _attackMask; private static int _attackMaskTerrain; private static int _attackMaskCharacters; internal static bool CanHandle(Attack attack, SecondaryAttackDefinition definition) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 if (attack != null && definition?.Aftershock != null && (Object)(object)attack.m_character != (Object)null && attack.m_weapon != null && (int)attack.m_attackType == 4) { return attack.m_attackRayWidth > 0f; } return false; } internal static void Trigger(Attack attack, SecondaryAttackDefinition definition) { if (CanHandle(attack, definition) && SecondaryAttackManager.HasCharacterAuthority((Character?)(object)attack.m_character)) { AftershockDefinition aftershock = definition.Aftershock; ApplyAttackTriggerSideEffects(attack); ((Component)attack.m_character).gameObject.AddComponent<AftershockController>().Initialize(attack, aftershock); } } private static void ApplyAttackTriggerSideEffects(Attack attack) { //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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown if (attack.m_toggleFlying) { if (((Character)attack.m_character).IsFlying()) { ((Character)attack.m_character).Land(); } else { ((Character)attack.m_character).TakeOff(); } } if (attack.m_recoilPushback != 0f) { ((Character)attack.m_character).ApplyPushback(-((Component)attack.m_character).transform.forward, attack.m_recoilPushback); } if ((float)attack.m_selfDamage > 0f) { HitData val = new HitData(); val.m_damage.m_damage = attack.m_selfDamage; ((Character)attack.m_character).Damage(val); } if (attack.m_consumeItem) { attack.ConsumeItem(); } if (attack.m_requiresReload) { attack.m_character.ResetLoadedWeapon(); } } private static void ApplyWave(AftershockController controller, int waveIndex) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_017c: 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_0180: 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_01cc: 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_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0290: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) Attack attack = controller.Attack; AftershockDefinition aftershock = controller.Aftershock; Character character = (Character)(object)attack.m_character; ItemData weapon = attack.m_weapon; if ((Object)(object)character == (Object)null || weapon?.m_shared == null) { return; } float visualScale; float pushScale; float num; float damageScale; float volumeScale = (visualScale = (pushScale = (num = (damageScale = ((waveIndex <= 0) ? 1f : Mathf.Pow(1f - aftershock.WaveDecay, (float)waveIndex)))))); float num2 = Mathf.Max(0.01f, attack.m_attackRayWidth * num); float num3 = Mathf.Max(0.01f, (attack.m_attackRayWidth + attack.m_attackRayWidthCharExtra) * num); Vector3 val = controller.BaseOrigin + controller.Forward * aftershock.ForwardStep * (float)waveIndex; Transform parent = ResolveAttackOrigin(attack); CreateScaledEffects(weapon.m_shared.m_triggerEffect, val, controller.Rotation, parent, visualScale, volumeScale); CreateScaledEffects(attack.m_triggerEffect, val, controller.Rotation, parent, visualScale, volumeScale); int hitCount = 0; Vector3 averageHitPoint = Vector3.zero; float randomSkillFactor = character.GetRandomSkillFactor(weapon.m_shared.m_skillType); float maxAdrenalineMultiplier = 0f; HitObjects.Clear(); int num4 = (attack.m_hitTerrain ? GetAttackMaskTerrain() : GetAttackMask()); CheckHits(controller, val, Physics.OverlapSphereNonAlloc(val, num2, Hits, num4, (QueryTriggerInteraction)0), damageScale, pushScale, randomSkillFactor, ref hitCount, ref averageHitPoint, ref maxAdrenalineMultiplier); if (attack.m_attackRayWidthCharExtra > 0f || attack.m_attackHeightChar1 != 0f) { CheckHits(controller, val, Physics.OverlapSphereNonAlloc(val + Vector3.up * attack.m_attackHeightChar1, num3, Hits, GetAttackMaskCharacters(), (QueryTriggerInteraction)0), damageScale, pushScale, randomSkillFactor, ref hitCount, ref averageHitPoint, ref maxAdrenalineMultiplier); if (!Mathf.Approximately(attack.m_attackHeightChar2, attack.m_attackHeightChar1)) { CheckHits(controller, val, Physics.OverlapSphereNonAlloc(val + Vector3.up * attack.m_attackHeightChar2, num3, Hits, GetAttackMaskCharacters(), (QueryTriggerInteraction)0), damageScale, pushScale, randomSkillFactor, ref hitCount, ref averageHitPoint, ref maxAdrenalineMultiplier); } } if (hitCount > 0) { averageHitPoint /= (float)hitCount; CreateScaledEffects(weapon.m_shared.m_hitEffect, averageHitPoint, Quaternion.identity, null, visualScale, volumeScale); CreateScaledEffects(attack.m_hitEffect, averageHitPoint, Quaternion.identity, null, visualScale, volumeScale); controller.DrainDurabilityOnce(); character.AddNoise(attack.m_attackHitNoise); if (maxAdrenalineMultiplier > 0f) { SecondaryAttackAdrenalineSystem.TryGrantOnce(attack, maxAdrenalineMultiplier, 1f, "aftershock"); } } if ((Object)(object)attack.m_spawnOnTrigger != (Object)null) { IProjectile component = Object.Instantiate<GameObject>(attack.m_spawnOnTrigger, val, Quaternion.identity).GetComponent<IProjectile>(); if (component != null) { component.Setup(character, ((Component)character).transform.forward, -1f, (HitData)null, (ItemData)null, attack.m_lastUsedAmmo); } } } private static void CheckHits(AftershockController controller, Vector3 origin, int count, float damageScale, float pushScale, float skillDamageFactor, ref int hitCount, ref Vector3 averageHitPoint, ref float maxAdrenalineMultiplier) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: 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_00cf: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) Attack attack = controller.Attack; Character character = (Character)(object)attack.m_character; ItemData weapon = attack.m_weapon; Transform transform = ((Component)character).transform; for (int i = 0; i < count; i++) { Collider val = Hits[i]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)(object)((Component)character).gameObject) { continue; } GameObject val2 = Projectile.FindHitObject(val); if ((Object)(object)val2 == (Object)null || (Object)(object)val2 == (Object)(object)((Component)character).gameObject || !HitObjects.Add(val2)) { continue; } Vector3 val3 = SecondaryAttackManager.ResolveSafeClosestPoint(val, origin); Vector3 val4 = val3 - origin; if (((Vector3)(ref val4)).sqrMagnitude < 0.0001f) { Bounds bounds = val.bounds; val3 = ((Bounds)(ref bounds)).center; } IDestructible component = val2.GetComponent<IDestructible>(); if (component == null) { continue; } Vector3 val5 = val3 - origin; val5.y = 0f; Vector3 val6 = val3 - transform.position; if (Vector3.Dot(val6, val5) < 0f) { val5 = val6; } if (((Vector3)(ref val5)).sqrMagnitude < 0.0001f) { val5 = transform.forward; } ((Vector3)(ref val5)).Normalize(); HitData val7 = CreateHitData(attack, val, val3, val5, skillDamageFactor, damageScale, pushScale); Character val8 = (Character)(object)((component is Character) ? component : null); bool flag = false; if ((Object)(object)val8 != (Object)null) { flag = BaseAI.IsEnemy(character, val8) || ((Object)(object)val8.GetBaseAI() != (Object)null && val8.GetBaseAI().IsAggravatable() && character.IsPlayer()); if (((!attack.m_hitFriendly || character.IsTamed()) && !character.IsPlayer() && !flag) || (!weapon.m_shared.m_tamedOnly && character.IsPlayer() && !character.IsPVPEnabled() && !flag) || (weapon.m_shared.m_tamedOnly && !val8.IsTamed())) { continue; } if (flag && val8.m_enemyAdrenalineMultiplier > maxAdrenalineMultiplier) { maxAdrenalineMultiplier = val8.m_enemyAdrenalineMultiplier; } if (val7.m_dodgeable && val8.IsDodgeInvincible()) { if (val8.IsPlayer()) { Character obj = ((val8 is Player) ? val8 : null); if (obj != null) { ((Player)obj).HitWhileDodging(); } } continue; } } else if (weapon.m_shared.m_tamedOnly) { continue; } TrySpawnOnHit(attack, val2); character.GetSEMan().ModifyAttack(weapon.m_shared.m_skillType, ref val7); if (attack.m_attackHealthReturnHit > 0f && flag) { character.Heal(attack.m_attackHealthReturnHit, true); } component.Damage(val7); hitCount++; averageHitPoint += val3; } } private static HitData CreateHitData(Attack attack, Collider collider, Vector3 hitPoint, Vector3 hitDirection, float skillDamageFactor, float damageScale, float pushScale) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) return SecondaryAttackHitDataFactory.CreateMeleeHit(attack, collider, hitPoint, hitDirection, skillDamageFactor, damageScale, pushScale); } private static void TrySpawnOnHit(Attack attack, GameObject hitObject) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (!(attack.m_spawnOnHitChance <= 0f) && !((Object)(object)attack.m_spawnOnHit == (Object)null) && !(Random.Range(0f, 1f) >= attack.m_spawnOnHitChance)) { IProjectile componentInChildren = Object.Instantiate<GameObject>(attack.m_spawnOnHit, hitObject.transform.position, hitObject.transform.rotation).GetComponentInChildren<IProjectile>(); if (componentInChildren != null) { componentInChildren.Setup((Character)(object)attack.m_character, ((Component)attack.m_character).transform.forward, -1f, (HitData)null, attack.m_weapon, attack.m_lastUsedAmmo); } } } private static Transform ResolveAttackOrigin(Attack attack) { if (!string.IsNullOrWhiteSpace(attack.m_attackOriginJoint)) { GameObject visual = ((Character)attack.m_character).GetVisual(); if ((Object)(object)visual != (Object)null) { Transform val = Utils.FindChild(visual.transform, attack.m_attackOriginJoint, (IterativeSearchType)0); if ((Object)(object)val != (Object)null) { return val; } } } return ((Component)attack.m_character).transform; } private static void CreateScaledEffects(EffectList effects, Vector3 position, Quaternion rotation, Transform? parent, float visualScale, float volumeScale) { //IL_001a: 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) if (effects == null || !effects.HasEffects()) { return; } float num = Mathf.Max(0f, visualScale); GameObject[] array = effects.Create(position, rotation, parent, num, -1); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null) { continue; } ScaleParticleSystems(val, num); ZSFX[] componentsInChildren = val.GetComponentsInChildren<ZSFX>(true); foreach (ZSFX obj in componentsInChildren) { obj.SetVolumeModifier(obj.GetVolumeModifier() * volumeScale); } AudioSource[] componentsInChildren2 = val.GetComponentsInChildren<AudioSource>(true); foreach (AudioSource val2 in componentsInChildren2) { if ((Object)(object)((Component)val2).GetComponent<ZSFX>() == (Object)null) { val2.volume *= volumeScale; } } } } private static void ScaleParticleSystems(GameObject instance, float visualScale) { //IL_0021: 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_0072: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_005c: 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_0086: 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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_00f6: Unknown result type (might be due to invalid IL or missing references) if (Mathf.Approximately(visualScale, 1f)) { return; } ParticleSystem[] componentsInChildren = instance.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem obj in componentsInChildren) { MainModule main = obj.main; if (((MainModule)(ref main)).startSize3D) { ((MainModule)(ref main)).startSizeX = ScaleCurve(((MainModule)(ref main)).startSizeX, visualScale); ((MainModule)(ref main)).startSizeY = ScaleCurve(((MainModule)(ref main)).startSizeY, visualScale); ((MainModule)(ref main)).startSizeZ = ScaleCurve(((MainModule)(ref main)).startSizeZ, visualScale); } else { ((MainModule)(ref main)).startSize = ScaleCurve(((MainModule)(ref main)).startSize, visualScale); } ((MainModule)(ref main)).startSpeed = ScaleCurve(((MainModule)(ref main)).startSpeed, visualScale); ShapeModule shape = obj.shape; if (((ShapeModule)(ref shape)).enabled) { ((ShapeModule)(ref shape)).radius = ((ShapeModule)(ref shape)).radius * visualScale; ((ShapeModule)(ref shape)).scale = ((ShapeModule)(ref shape)).scale * visualScale; ((ShapeModule)(ref shape)).position = ((ShapeModule)(ref shape)).position * visualScale; } TrailModule trails = obj.trails; if (((TrailModule)(ref trails)).enabled) { ((TrailModule)(ref trails)).widthOverTrail = ScaleCurve(((TrailModule)(ref trails)).widthOverTrail, visualScale); } ParticleSystemRenderer component = ((Component)obj).GetComponent<ParticleSystemRenderer>(); if ((Object)(object)component != (Object)null) { component.lengthScale *= visualScale; component.velocityScale *= visualScale; } } } private static MinMaxCurve ScaleCurve(MinMaxCurve curve, float scale) { //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_001e: Expected I4, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) ParticleSystemCurveMode mode = ((MinMaxCurve)(ref curve)).mode; switch ((int)mode) { case 0: ((MinMaxCurve)(ref curve)).constant = ((MinMaxCurve)(ref curve)).constant * scale; break; case 3: ((MinMaxCurve)(ref curve)).constantMin = ((MinMaxCurve)(ref curve)).constantMin * scale; ((MinMaxCurve)(ref curve)).constantMax = ((MinMaxCurve)(ref curve)).constantMax * scale; break; case 1: case 2: ((MinMaxCurve)(ref curve)).curveMultiplier = ((MinMaxCurve)(ref curve)).curveMultiplier * scale; break; } return curve; } private static int GetAttackMask() { if (_attackMask == 0) { _attackMask = LayerMask.GetMask(new string[11] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle" }); } return _attackMask; } private static int GetAttackMaskTerrain() { if (_attackMaskTerrain == 0) { _attackMaskTerrain = LayerMask.GetMask(new string[12] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "terrain", "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle" }); } return _attackMaskTerrain; } private static int GetAttackMaskCharacters() { if (_attackMaskCharacters == 0) { _attackMaskCharacters = LayerMask.GetMask(new string[6] { "character", "character_net", "character_ghost", "hitbox", "character_noenv", "vehicle" }); } return _attackMaskCharacters; } } internal static class BackstabSkillGainSystem { internal readonly struct BackstabDamageState { internal static BackstabDamageState Inactive => new BackstabDamageState(active: false, 0f); internal bool Active { get; } internal float PreviousBackstabTime { get; } internal BackstabDamageState(bool active, float previousBackstabTime) { Active = active; PreviousBackstabTime = previousBackstabTime; } } internal const string GrantSneakSkillRpcName = "SecondaryAttacks_GrantBackstabSneakSkill"; internal const float BackstabCooldownSeconds = 300f; private const float BackstabTimeDetectionWindow = 1f; private static readonly FieldRef<Character, float>? BackstabTimeField = TryCreateBackstabTimeFieldRef(); internal static BackstabDamageState CaptureBackstabState(Character target, HitData hit) { if ((Object)(object)target == (Object)null || hit == null || hit.m_backstabBonus <= 1f) { return BackstabDamageState.Inactive; } return new BackstabDamageState(active: true, GetBackstabTime(target)); } internal static void TryGrantForBackstab(Character target, HitData hit, BackstabDamageState state) { if (!state.Active || (Object)(object)target == (Object)null || hit == null) { return; } float raiseAmount = GetRaiseAmount(); if (!(raiseAmount <= 0f) && DidBackstabSucceed(target, state.PreviousBackstabTime)) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null) { GrantToPlayer(val, raiseAmount); } } } internal static void GrantLocal(Player player, float amount) { if (!((Object)(object)player == (Object)null) && !(amount <= 0f)) { float num = Mathf.Min(Mathf.Max(0f, amount), GetRaiseAmount()); if (!(num <= 0f)) { ((Character)player).RaiseSkill((SkillType)101, num); } } } private static float GetRaiseAmount() { return Mathf.Max(0f, SecondaryAttacksPlugin.BackstabSneakSkillRaiseAmount?.Value ?? 0f); } private static bool DidBackstabSucceed(Character target, float previousBackstabTime) { float backstabTime = GetBackstabTime(target); if (backstabTime > previousBackstabTime + 0.001f && backstabTime >= Time.time - 1f) { return backstabTime <= Time.time + 0.001f; } return false; } private static void GrantToPlayer(Player player, float amount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0015: Expected O, but got Unknown ZNetView nview; ZDO zdo; if ((Object)player == (Object)Player.m_localPlayer) { GrantLocal(player, amount); } else if (SecondaryAttackManager.TryGetCharacterZdo((Character?)(object)player, out nview, out zdo)) { nview.InvokeRPC("SecondaryAttacks_GrantBackstabSneakSkill", new object[1] { amount }); } } internal static float GetBackstabTime(Character target) { if ((Object)(object)target == (Object)null || BackstabTimeField == null) { return 0f; } return BackstabTimeField.Invoke(target); } private static FieldRef<Character, float>? TryCreateBackstabTimeFieldRef() { try { return AccessTools.FieldRefAccess<Character, float>("m_backstabTime"); } catch (Exception) { return null; } } } internal static class BloodMagicSkillGainSystem { private static bool _allowConfiguredBloodMagicRaise; private static float GetHealthCostSkillRaiseFactor() { return Mathf.Max(0f, SecondaryAttacksPlugin.BloodMagicHealthCostSkillRaiseFactor?.Value ?? 0f); } internal static bool IsHealthCostSkillGainEnabled() { return GetHealthCostSkillRaiseFactor() > 0f; } internal static bool ShouldUseMaxHealthForPercentageCost() { ConfigEntry<SecondaryAttacksPlugin.Toggle> bloodMagicHealthCostUsesMaxHealth = SecondaryAttacksPlugin.BloodMagicHealthCostUsesMaxHealth; if (bloodMagicHealthCostUsesMaxHealth == null) { return false; } return bloodMagicHealthCostUsesMaxHealth.Value == SecondaryAttacksPlugin.Toggle.On; } internal static void ApplyMaxHealthPercentageCost(Attack attack, ref float healthCost) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 if (!ShouldUseMaxHealthForPercentageCost() || attack == null || (Object)(object)attack.m_character == (Object)null) { return; } ItemData weapon = attack.m_weapon; if (weapon != null && (int)weapon.m_shared.m_skillType == 10 && !(attack.m_attackHealthPercentage <= 0f)) { float num = Mathf.Max(0f, attack.m_attackHealth) + Mathf.Max(0f, ((Character)attack.m_character).GetMaxHealth()) * Mathf.Max(0f, attack.m_attackHealthPercentage) / 100f; if (num <= 0f) { healthCost = 0f; return; } float num2 = Mathf.Clamp01(((Character)attack.m_character).GetSkillFactor((SkillType)10)); healthCost = num - num * 0.33f * num2; } } internal static bool ShouldBlockBloodMagicRaise(SkillType skillType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)skillType == 10 && IsHealthCostSkillGainEnabled()) { return !_allowConfiguredBloodMagicRaise; } return false; } internal static void TryGrantForHealthUse(Character character, float previousHealth) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Invalid comparison between Unknown and I4 if (!IsHealthCostSkillGainEnabled()) { return; } Player val = (Player)(object)((character is Player) ? character : null); if (val == null) { return; } Humanoid val2 = (Humanoid)(object)((character is Humanoid) ? character : null); if (val2 == null) { return; } float num = previousHealth - character.GetHealth(); if (num <= 0.001f) { return; } Attack currentAttack = val2.m_currentAttack; if (currentAttack == null || (Object)(object)currentAttack.m_character != (Object)(object)val2) { return; } ItemData weapon = currentAttack.m_weapon; if (weapon == null || (int)weapon.m_shared.m_skillType != 10) { return; } float healthCostSkillRaiseFactor = GetHealthCostSkillRaiseFactor(); float num2 = num * healthCostSkillRaiseFactor; if (num2 <= 0f) { return; } _allowConfiguredBloodMagicRaise = true; try { ((Character)val).RaiseSkill((SkillType)10, num2); } finally { _allowConfiguredBloodMagicRaise = false; } } } internal static class BowSecondaryKeyHintSystem { private const int MissingBlockHintRefreshFrames = 30; private static readonly string[] BowSecondaryHintKeys = new string[1]; private static readonly string[] DetonateBlockHintKeys = new string[1]; private static KeyHints? _activeKeyHints; private static KeyHintCell? _bowSecondaryHint; private static KeyHintCell? _detonateBlockHint; private static GameObject? _bowSecondaryHintTemplate; private static KeyHints? _cachedTemplateHints; private static GameObject? _cachedCombatHintTemplate; private static KeyHints? _cachedBlockHintHints; private static GameObject? _cachedBlockHint; private static bool _showingBowSecondaryHint; private static bool _showingDetonateBlockHint; private static bool _cachedTemplateGamepadActive; private static bool _cachedBlockHintGamepadActive; private static bool _cachedBlockHintResolved; private static bool _lastGamepadActive; private static bool _lastDetonateBlockGamepadActive; private static bool _keyHintApplied; private static bool _detonateBlockHintApplied; private static int _cachedBlockHintFrame; private static string _lastButtonLabel = string.Empty; private static string _lastDetonateBlockButtonLabel = string.Empty; internal static void InitializeKeyHints(KeyHints hints) { _activeKeyHints = hints; DestroyBowSecondaryHint(); RestoreDetonateBlockHint(); _detonateBlockHint = null; ClearBlockHintCache(); _showingBowSecondaryHint = false; UpdateKeyHint(hints); } internal static void RefreshKeyHintUi() { if ((Object)(object)_activeKeyHints != (Object)null) { UpdateKeyHint(_activeKeyHints); } } internal static void UpdateKeyHint(KeyHints hints) { if ((Object)(object)hints == (Object)null) { return; } _activeKeyHints = hints; if (!ShouldAllowCustomCombatHints(hints)) { HideBowSecondaryHint(); RestoreDetonateBlockHint(); if ((Object)(object)hints.m_combatHints != (Object)null) { hints.m_combatHints.SetActive(false); } return; } UpdateDetonateBlockHint(hints); if (!ShouldShowBowSecondaryHint()) { HideBowSecondaryHint(); return; } bool flag = ZInput.IsGamepadActive(); EnsureBowSecondaryHint(hints, flag); KeyHintCell? bowSecondaryHint = _bowSecondaryHint; if (bowSecondaryHint != null && bowSecondaryHint.IsValid) { if ((Object)(object)hints.m_combatHints != (Object)null) { hints.m_combatHints.SetActive(true); } SetVanillaCombatHintActive(hints.m_secondaryAttackGP, active: false); SetVanillaCombatHintActive(hints.m_secondaryAttackKB, active: false); bool flag2 = !_showingBowSecondaryHint; string text = ResolveSecondaryAttackButtonLabel(flag); if (!_keyHintApplied || _lastGamepadActive != flag || !string.Equals(_lastButtonLabel, text, StringComparison.Ordinal)) { BowSecondaryHintKeys[0] = text; _bowSecondaryHint.SetKeys(BowSecondaryHintKeys, hideExtraTexts: true); _lastButtonLabel = text; _lastGamepadActive = flag; _keyHintApplied = true; flag2 = true; } if ((Object)(object)_bowSecondaryHint.Root != (Object)null && _bowSecondaryHint.Root.transform.GetSiblingIndex() != 0) { _bowSecondaryHint.MoveToStart(); flag2 = true; } if (flag2) { _bowSecondaryHint.RebuildParentLayout(); } _showingBowSecondaryHint = true; } } private static void UpdateDetonateBlockHint(KeyHints hints) { Player localPlayer = Player.m_localPlayer; if (!ShouldShowCombatHints(localPlayer) || !StickyDetonatorSystem.ShouldShowDetonateBlockHint(localPlayer)) { RestoreDetonateBlockHint(); return; } bool flag = ZInput.IsGamepadActive(); GameObject val = ResolveCachedBlockHint(hints, flag); if ((Object)(object)val == (Object)null) { RestoreDetonateBlockHint(); return; } if (_detonateBlockHint == null || (Object)(object)_detonateBlockHint.Root != (Object)(object)val) { RestoreDetonateBlockHint(); _detonateBlockHint = KeyHintCell.FromGameObject(val); _detonateBlockHintApplied = false; } KeyHintCell? detonateBlockHint = _detonateBlockHint; if (detonateBlockHint != null && detonateBlockHint.IsValid) { if ((Object)(object)hints.m_combatHints != (Object)null) { hints.m_combatHints.SetActive(true); } string text = ResolveBlockButtonLabel(flag); if (!_detonateBlockHintApplied || _lastDetonateBlockGamepadActive != flag || !string.Equals(_lastDetonateBlockButtonLabel, text, StringComparison.Ordinal)) { ApplyDetonateBlockHint(_detonateBlockHint, text); _lastDetonateBlockButtonLabel = text; _lastDetonateBlockGamepadActive = flag; _detonateBlockHintApplied = true; _detonateBlockHint.RebuildParentLayout(); } _showingDetonateBlockHint = true; } } private static bool ShouldShowBowSecondaryHint() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 Player localPlayer = Player.m_localPlayer; if (!ShouldShowCombatHints(localPlayer)) { return false; } ItemData val = ResolveEquippedBow(localPlayer); if (val?.m_shared == null) { return false; } if ((int)val.m_shared.m_itemType != 4) { return false; } if (!val.m_shared.m_attack.m_bowDraw) { return false; } return HasVisibleSecondaryAttack(val); } private static bool HasVisibleSecondaryAttack(ItemData weapon) { if (weapon == null) { return false; } if (!SecondaryAttackRuntimeFacade.TryGetDefinition(weapon, out SecondaryAttackDefinition definition)) { return false; } if (definition.BehaviorType != SecondaryAttackBehaviorType.Projectile) { return false; } return true; } private static bool ShouldAllowCustomCombatHints(KeyHints hints) { if (hints.m_keyHintsEnabled && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Console.IsVisible() && !Game.IsPaused() && ((Object)(object)Chat.instance == (Object)null || !Chat.instance.HasFocus())) { if (!((Object)(object)InventoryGui.instance == (Object)null)) { if (!InventoryGui.instance.IsSkillsPanelOpen && !InventoryGui.instance.IsTrophisPanelOpen) { return !InventoryGui.instance.IsTextPanelOpen; } return false; } return true; } return false; } private static bool ShouldShowCombatHints(Player? player) { if ((Object)(object)player != (Object)null && !((Character)player).IsDead() && !Hud.IsPieceSelectionVisible() && !Hud.InRadial() && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Console.IsVisible() && !Game.IsPaused() && ((Object)(object)Chat.instance == (Object)null || !Chat.instance.HasFocus()) && ((Object)(object)InventoryGui.instance == (Object)null || (!InventoryGui.instance.IsSkillsPanelOpen && !InventoryGui.instance.IsTrophisPanelOpen && !InventoryGui.instance.IsTextPanelOpen)) && !PlayerCustomizaton.IsBarberGuiVisible()) { return player.GetDoodadController() == null; } return false; } private static void SetVanillaCombatHintActive(GameObject? hint, bool active) { if ((Object)(object)hint != (Object)null && hint.activeSelf != active) { hint.SetActive(active); } } private static void EnsureBowSecondaryHint(KeyHints hints, bool gamepadActive) { if (_bowSecondaryHint != null && (Object)(object)_bowSecondaryHint.Root != (Object)null && (Object)(object)_bowSecondaryHintTemplate != (Object)null && (Object)(object)_bowSecondaryHintTemplate.transform.parent != (Object)null && (Object)(object)_cachedTemplateHints == (Object)(object)hints && _cachedTemplateGamepadActive == gamepadActive && (Object)(object)_bowSecondaryHint.Root.transform.parent == (Object)(object)_bowSecondaryHintTemplate.transform.parent) { return; } GameObject val = ResolveCachedCombatHintTemplate(hints, gamepadActive); if (!((Object)(object)val == (Object)null) && !((Object)(object)val.transform.parent == (Object)null)) { if (_bowSecondaryHint != null && (Object)(object)_bowSecondaryHint.Root != (Object)null && (Object)(object)_bowSecondaryHint.Root.transform.parent == (Object)(object)val.transform.parent) { _bowSecondaryHintTemplate = val; return; } DestroyBowSecondaryHint(); _bowSecondaryHint = KeyHintCell.CloneFrom(val, "SecondaryAttacks_BowSecondaryHint", hideOnRestore: true); _bowSecondaryHintTemplate = val; _cachedTemplateHints = hints; _cachedTemplateGamepadActive = gamepadActive; _cachedCombatHintTemplate = val; _keyHintApplied = false; } } private static GameObject? ResolveCachedCombatHintTemplate(KeyHints hints, bool gamepadActive) { if ((Object)(object)_cachedTemplateHints == (Object)(object)hints && _cachedTemplateGamepadActive == gamepadActive && (Object)(object)_cachedCombatHintTemplate != (Object)null && (Object)(object)_cachedCombatHintTemplate.transform.parent != (Object)null) { return _cachedCombatHintTemplate; } _cachedTemplateHints = hints; _cachedTemplateGamepadActive = gamepadActive; _cachedCombatHintTemplate = ResolveCombatHintTemplate(hints, gamepadActive); return _cachedCombatHintTemplate; } private static string ResolveSecondaryAttackButtonLabel(bool gamepadActive) { string text = (gamepadActive ? "JoySecondaryAttack" : "SecondaryAttack"); ZInput instance = ZInput.instance; string text2 = ((instance != null) ? instance.GetBoundKeyString(text, true) : null) ?? ""; if (!string.IsNullOrWhiteSpace(text2)) { if (Localization.instance == null) { return text2; } return Localization.instance.Localize(text2); } if (!gamepadActive) { return "MMB"; } return "RB"; } private static string ResolveBlockButtonLabel(bool gamepadActive) { string text = (gamepadActive ? "JoyBlock" : "Block"); ZInput instance = ZInput.instance; string text2 = ((instance != null) ? instance.GetBoundKeyString(text, true) : null) ?? ""; if (!string.IsNullOrWhiteSpace(text2)) { if (Localization.instance == null) { return text2; } return Localization.instance.Localize(text2); } if (!gamepadActive) { return "Mouse-2"; } return "LT"; } private static void ApplyDetonateBlockHint(KeyHintCell hint, string buttonLabel) { string text = SecondaryAttackLocalization.Localize("$sa_hint_detonate", "Detonate"); if (hint.HasKeyTexts) { DetonateBlockHintKeys[0] = buttonLabel; hint.Set(text, DetonateBlockHintKeys, 0f, hideExtraTexts: true); } else { hint.SetText(text + " <mspace=0.6em>" + buttonLabel + "</mspace>"); } } private static GameObject? ResolveCachedBlockHint(KeyHints hints, bool gamepadActive) { if (_cachedBlockHintResolved && (Object)(object)_cachedBlockHintHints == (Object)(object)hints && _cachedBlockHintGamepadActive == gamepadActive) { if ((Object)(object)_cachedBlockHint != (Object)null && (Object)(object)_cachedBlockHint.transform.parent != (Object)null) { return _cachedBlockHint; } if ((Object)(object)_cachedBlockHint == (Object)null && Time.frameCount - _cachedBlockHintFrame < 30) { return null; } } _cachedBlockHintHints = hints; _cachedBlockHintGamepadActive = gamepadActive; _cachedBlockHint = ResolveBlockHintUncached(hints, gamepadActive); _cachedBlockHintResolved = true; _cachedBlockHintFrame = Time.frameCount; return _cachedBlockHint; } private static GameObject? ResolveBlockHintUncached(KeyHints hints, bool gamepadActive) { GameObject val = FindBlockHint(ResolveCombatInputGroup(hints, gamepadActive)); if ((Object)(object)val != (Object)null) { return val; } return FindBlockHint(ResolveCombatInputGroup(hints, !gamepadActive)); } private static void ClearBlockHintCache() { _cachedBlockHintHints = null; _cachedBlockHint = null; _cachedBlockHintResolved = false; _cachedBlockHintFrame = 0; } private static Transform? ResolveCombatInputGroup(KeyHints hints, bool gamepadActive) { GameObject val = (gamepadActive ? hints.m_primaryAttackGP : hints.m_primaryAttackKB); if ((Object)(object)((val != null) ? val.transform.parent : null) != (Object)null) { return val.transform.parent; } val = (gamepadActive ? hints.m_secondaryAttackGP : hints.m_secondaryAttackKB); if (val == null) { return null; } return val.transform.parent; } private static GameObject? FindBlockHint(Transform? group) { if ((Object)(object)group == (Object)null) { return null; } for (int i = 0; i < group.childCount; i++) { GameObject gameObject = ((Component)group.GetChild(i)).gameObject; if ((string.Equals(((Object)gameObject).name, "Block", StringComparison.OrdinalIgnoreCase) || string.Equals(((Object)gameObject).name, "Text - Block", StringComparison.OrdinalIgnoreCase)) && KeyHintCell.IsUsableTemplate(gameObject)) { return gameObject; } } TMP_Text[] componentsInChildren = ((Component)group).GetComponentsInChildren<TMP_Text>(true); foreach (TMP_Text val in componentsInChildren) { if ((Object)(object)val == (Object)null || !ContainsBlockHintText(val.text)) { continue; } Transform val2 = val.transform; while ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)group.parent) { GameObject gameObject2 = ((Component)val2).gameObject; if (KeyHintCell.IsUsableTemplate(gameObject2)) { return gameObject2; } val2 = val2.parent; } } return null; } private static bool ContainsBlockHintText(string? value) { if (string.IsNullOrWhiteSpace(value)) { return false; } if (value.IndexOf("$settings_block", StringComparison.OrdinalIgnoreCase) < 0) { return value.IndexOf("Block", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static ItemData? ResolveEquippedBow(Player? player) { if ((Object)(object)player == (Object)null) { return null; } ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (IsBowDrawWeapon(currentWeapon)) { return currentWeapon; } ItemData rightItem = ((Humanoid)player).GetRightItem(); if (IsBowDrawWeapon(rightItem)) { return rightItem; } ItemData leftItem = ((Humanoid)player).GetLeftItem(); if (!IsBowDrawWeapon(leftItem)) { return null; } return leftItem; } private static bool IsBowDrawWeapon(ItemData? weapon) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 if (weapon?.m_shared != null && (int)weapon.m_shared.m_itemType == 4) { return weapon.m_shared.m_attack.m_bowDraw; } return false; } private static GameObject? ResolveCombatHintTemplate(KeyHints hints, bool gamepadActive) { GameObject val = (gamepadActive ? hints.m_secondaryAttackGP : hints.m_secondaryAttackKB); if (KeyHintCell.IsUsableTemplate(val)) { return val; } GameObject val2 = (gamepadActive ? hints.m_secondaryAttackKB : hints.m_secondaryAttackGP); if (KeyHintCell.IsUsableTemplate(val2)) { return val2; } GameObject val3 = (gamepadActive ? hints.m_bowDrawGP : hints.m_bowDrawKB); if (KeyHintCell.IsUsableTemplate(val3)) { return val3; } GameObject val4 = (gamepadActive ? hints.m_bowDrawKB : hints.m_bowDrawGP); if (KeyHintCell.IsUsableTemplate(val4)) { return val4; } GameObject val5 = (gamepadActive ? hints.m_primaryAttackGP : hints.m_primaryAttackKB); if (KeyHintCell.IsUsableTemplate(val5)) { return val5; } GameObject val6 = (gamepadActive ? hints.m_primaryAttackKB : hints.m_primaryAttackGP); if (KeyHintCell.IsUsableTemplate(val6)) { return val6; } return null; } private static void HideBowSecondaryHint() { if (_showingBowSecondaryHint) { _bowSecondaryHint?.Restore(); _bowSecondaryHint?.RebuildParentLayout(); _showingBowSecondaryHint = false; _keyHintApplied = false; _lastButtonLabel = string.Empty; } } private static void RestoreDetonateBlockHint() { if (_showingDetonateBlockHint || _detonateBlockHintApplied) { _detonateBlockHint?.Restore(); _detonateBlockHint?.RebuildParentLayout(); _showingDetonateBlockHint = false; _detonateBlockHintApplied = false; _lastDetonateBlockButtonLabel = string.Empty; } } private static void DestroyBowSecondaryHint() { if ((Object)(object)_bowSecondaryHint?.Root != (Object)null) { Object.Destroy((Object)(object)_bowSecondaryHint.Root); } _bowSecondaryHint = null; _bowSecondaryHintTemplate = null; _cachedTemplateHints = null; _cachedCombatHintTemplate = null; _keyHintApplied = false; _lastButtonLabel = string.Empty; } } [HarmonyPatch(typeof(KeyHints), "Awake")] internal static class KeyHintsAwakeBowSecondaryPatch { private static void Postfix(KeyHints __instance) { BowSecondaryKeyHintSystem.InitializeKeyHints(__instance); } } [HarmonyPatch(typeof(KeyHints), "UpdateHints")] internal static class KeyHintsUpdateBowSecondaryPatch { private static void Postfix(KeyHints __instance) { BowSecondaryKeyHintSystem.UpdateKeyHint(__instance); } } internal static class CopiedThrowProjectileVisualSystem { internal readonly struct BurstScope { public Attack? Attack { get; } public bool Active => Attack != null; public BurstScope(Attack attack) { Attack = attack; } } internal readonly struct SpawnedProjectileVisualContext { public ItemData? Weapon { get; } public string VisualPrefabName { get; } public GameObject? AttachPrefab { get; } public EffectData[]? HitEffectPrefabs { get; } public ThrowProjectileVisualSpin.AxisMode SpinAxisMode { get; } public Vector3 VisualRotationOffset { get; } public bool SkipVisualSwap { get; } public bool Active { get { if ((Object)(object)Weapon?.m_dropPrefab != (Object)null) { return !string.IsNullOrEmpty(VisualPrefabName); } return false; } } public SpawnedProjectileVisualContext(ItemData weapon, string visualPrefabName, GameObject? attachPrefab, EffectData[]? hitEffectPrefabs, ThrowProjectileVisualSpin.AxisMode spinAxisMode, Vector3 visualRotationOffset, bool skipVisualSwap) { //IL_0026: 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) Weapon = weapon; VisualPrefabName = visualPrefabName; AttachPrefab = attachPrefab; HitEffectPrefabs = hitEffectPrefabs; SpinAxisMode = spinAxisMode; VisualRotationOffset = visualRotationOffset; SkipVisualSwap = skipVisualSwap; } } private sealed class CopiedThrowSpinState : MonoBehaviour { private ThrowProjectileVisualSpin.AxisMode _axisMode; private Vector3 _rotationOffset; private Vector3 _horizontalForward; private bool _configured; internal bool IsCurrent(ThrowProjectileVisualSpin.AxisMode axisMode, Vector3 rotationOffset, Vector3 horizontalForward) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0033: 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_004e: Unknown result type (might be due to invalid IL or missing references) if (_configured && _axisMode == axisMode) { Vector3 val = _rotationOffset - rotationOffset; if (((Vector3)(ref val)).sqrMagnitude <= 0.0001f) { val = _horizontalForward - horizontalForward; if (((Vector3)(ref val)).sqrMagnitude <= 0.0001f) { return ThrowProjectileVisualSpin.IsConfigured(((Component)this).gameObject, axisMode, horizontalForward); } } } return false; } internal void Configure(ThrowProjectileVisualSpin.AxisMode axisMode, Vector3 rotationOffset, Vector3 horizontalForward) { //IL_0008: 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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) _axisMode = axisMode; _rotationOffset = rotationOffset; _horizontalForward = horizontalForward; _configured = true; } } private const string CopiedThrowProjectileMarkerKey = "SecondaryAttacks_CopiedThrowProjectile"; private const string CopiedThrowProjectileSpinAxisKey = "SecondaryAttacks_CopiedThrowSpinAxis"; private const string CopiedThrowProjectileRotationOffsetKey = "SecondaryAttacks_CopiedThrowRotationOffset"; private const string CopiedThrowProjectileVisualRootName = "SecondaryAttacks_CopiedThrowVisualRoot"; private const string CopiedThrowProjectileSpinRootName = "SecondaryAttacks_CopiedThrowSpinRoot"; private const float SpinStateEpsilonSqr = 0.0001f; private static readonly List<Attack> ActiveCopiedThrowBursts = new List<Attack>(); private static readonly List<Renderer> RendererBuffer = new List<Renderer>(); internal static BurstScope BeginBurst(Attack attack) { if (!ShouldApplyCopiedThrowVisuals(attack)) { return default(BurstScope); } ActiveCopiedThrowBursts.Add(attack); return new BurstScope(attack); } internal static void EndBurst(BurstScope scope) { if (scope.Active) { int num = ActiveCopiedThrowBursts.Count - 1; if (num >= 0 && ActiveCopiedThrowBursts[num] == scope.Attack) { ActiveCopiedThrowBursts.RemoveAt(num); } else { ActiveCopiedThrowBursts.Remove(scope.Attack); } } } internal static void TryApplyToProjectileSetup(Projectile projectile, ItemData item) { MeleeProjectileHitCascadeSystem.TryDescribeSpearRainFollowupProjectile(projectile, out string _); if ((Object)(object)projectile == (Object)null || ActiveCopiedThrowBursts.Count == 0) { return; } Attack val = ActiveCopiedThrowBursts[ActiveCopiedThrowBursts.Count - 1]; if (val == null) { return; } ItemData val2 = val.m_weapon ?? item; if (!((Object)(object)val2?.m_dropPrefab == (Object)null)) { MoveProjectileClearOfOwner(projectile, val); SecondaryAttackDefinition definition = ResolveCopiedThrowDefinition(val, val2, ((Object)val2.m_dropPrefab).name); SpawnedProjectileVisualContext context = CreateSpawnedProjectileVisualContext(val2, val.m_attackProjectile, definition, includeHitEffects: false); ApplyCurrentWeaponVisual(projectile, context); ApplyCurrentWeaponHitEffects(projectile, val2); ApplyCopiedThrowAttribution(projectile, val2); if (!SecondaryAttackStartAttackDispatch.ShouldSkipProjectilePresetEffectsForCooldown(val, out string _)) { MeleeBoomerangProjectileSystem.TryApplyToProjectileSetup(projectile, val, val2); MeleeProjectileHitCascadeSystem.RegisterOnProjectileHitSource(projectile, val, val2); } } } internal static void PrepareProjectileIfNeeded(Projectile projectile) { if ((Object)(object)projectile == (Object)null) { return; } ZNetView component = ((Component)projectile).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.GetZDO() != null && component.GetZDO().GetBool("SecondaryAttacks_CopiedThrowProjectile", false)) { TryApplyHitEffectsFromSyncedVisual(projectile, component); if (!projectile.m_changedVisual) { PrepareProjectileForVisualSwap(projectile); } } } internal static void EnsureProjectileVisualSpinIfNeeded(Projectile projectile) { if (IsMarkedCopiedThrowProjectile(projectile)) { string visualPrefabName = TryResolveSyncedVisualPrefabName(projectile); ApplyCopiedThrowVisualSpin(projectile, TryResolveSyncedVisualItem(visualPrefabName)?.m_itemData, visualPrefabName); } } internal static void ApplyCurrentWeaponVisualForSpawnedProjectile(Projectile projectile, ItemData weapon) { ApplyCurrentWeaponVisualForSpawnedProjectile(projectile, CreateSpawnedProjectileVisualContext(weapon)); } internal static void ApplyCurrentWeaponVisualForSpawnedProjectile(Projectile projectile, SpawnedProjectileVisualContext context) { if (!((Object)(object)projectile == (Object)null) && context.Active) { if (!context.SkipVisualSwap) { ApplyCurrentWeaponVisual(projectile, context); } ApplyHitEffects(projectile, context.HitEffectPrefabs); } } internal static SpawnedProjectileVisualContext CreateSpawnedProjectileVisualContext(ItemData weapon) { return CreateSpawnedProjectileVisualContext(weapon, includeHitEffects: true); } internal static SpawnedProjectileVisualContext CreateSpawnedProjectileVisualContext(ItemData weapon, GameObject? sourceProjectilePrefab) { return CreateSpawnedProjectileVisualContext(weapon, sourceProjectilePrefab, includeHitEffects: true); } private static SpawnedProjectileVisualContext CreateSpawnedProjectileVisualContext(ItemData weapon, bool includeHitEffects) { return CreateSpawnedProjectileVisualContext(weapon, null, includeHitEffects); } private static SpawnedProjectileVisualContext CreateSpawnedProjectileVisualContext(ItemData weapon, GameObject? sourceProjectilePrefab, bool includeHitEffects) { return CreateSpawnedProjectileVisualContext(weapon, sourceProjectilePrefab, null, includeHitEffects); } private static SpawnedProjectileVisualContext CreateSpawnedProjectileVisualContext(ItemData weapon, GameObject? sourceProjectilePrefab, SecondaryAttackDefinition? definition, bool includeHitEffects) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)weapon?.m_dropPrefab == (Object)null) { return default(SpawnedProjectileVisualContext); } bool flag = UsesNativeProjectileVisual(weapon, sourceProjectilePrefab); GameObject attachPrefab = null; if (!flag) { attachPrefab = ResolveAttachGameObject(weapon.m_dropPrefab); } if (definition == null) { definition = ResolveCopiedThrowDefinition(weapon, ((Object)weapon.m_dropPrefab).name); } ThrowProjectileVisualSpin.AxisMode valueOrDefault = ResolveConfiguredCopiedThrowSpinAxisMode(definition).GetValueOrDefault(); return new SpawnedProjectileVisualContext(weapon, ((Object)weapon.m_dropPrefab).name, attachPrefab, includeHitEffects ? CopyHitEffectPrefabs(weapon.m_shared?.m_hitEffect) : null, valueOrDefault, ResolveConfiguredCopiedThrowVisualRotationOffset(definition), flag); } internal static bool UsesNativeProjectileVisual(ItemData weapon, GameObject? sourceProjectilePrefab) { if ((Object)(object)weapon?.m_dropPrefab == (Object)null || (Object)(object)sourceProjectilePrefab == (Object)null) { return false; } return IsSameProjectilePrefab(sourceProjectilePrefab, weapon.m_shared?.m_secondaryAttack?.m_attackProjectile); } private static bool IsSameProjectilePrefab(GameObject sourceProjectilePrefab, GameObject? weaponProjectilePrefab) { if ((Object)(object)weaponProjectilePrefab != (Object)null) { if (sourceProjectilePrefab != weaponProjectilePrefab) { return string.Equals(((Object)sourceProjectilePrefab).name, ((Object)weaponProjectilePrefab).name, StringComparison.OrdinalIgnoreCase); } return true; } return false; } private static GameObject? ResolveAttachGameObject(GameObject itemPrefab) { Transform val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.transform.Find("attach") : null); if ((Object)(object)val == (Object)null) { return null; } Transform val2 = val.Find("attachobj"); if (!((Object)(object)val2 != (Object)null)) { return ((Component)val).gameObject; } return ((Component)val2).gameObject; } private static bool ShouldApplyCopiedThrowVisuals(Attack attack) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 if ((Object)(object)attack?.m_weapon?.m_dropPrefab == (Object)null || (Object)(object)attack.m_attackProjectile == (Object)null || (int)attack.m_attackType != 2) { return false; } if (SecondaryAttackStartAttackDispatch.IsProjectilePresetOriginalCooldownFallback(attack, out string _)) { return false; } if (SecondaryAttackRuntimeContext.TryGetActiveAttack(attack, out ActiveSecondaryAttack activeAttack) && activeAttack?.Definition.Behavior is CopiedSecondaryBehavior) { return true; } if (!IsConfiguredCopiedSecondaryAttack(attack)) { return false; } return true; } private static bool IsConfiguredCopiedSecondaryAttack(Attack attack) { if (!SecondaryAttackRuntimeFacade.TryGetDefinition(attack.m_weapon, out SecondaryAttackDefinition definition) || !(definition.Behavior is CopiedSecondaryBehavior)) { return false; } Humanoid character = attack.m_character; if (character != null && character.m_currentAttack == attack) { return character.m_currentAttackIsSecondary; } return attack == attack.m_weapon.m_shared.m_secondaryAttack; } private static void MoveProjectileClearOfOwner(Projectile projectile, Attack attack) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0044: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) Character val = (Character)(((object)ProjectileAccess.GetOwner(projectile)) ?? ((object)attack.m_character)); if ((Object)(object)val == (Object)null) { return; } Vector3 velocity = ProjectileAccess.GetVelocity(projectile); Vector3 val2 = ((((Vector3)(ref velocity)).sqrMagnitude > 0.001f) ? ((Vector3)(ref velocity)).normalized : ((Component)projectile).transform.forward); if (!(((Vector3)(ref val2)).sqrMagnitude < 0.001f)) { Vector3 centerPoint = val.GetCenterPoint(); float num = Mathf.Max(val.GetRadius() + Mathf.Max(0.1f, projectile.m_rayRadius) + 0.35f, 1.25f); Vector3 position = ((Component)projectile).transform.position; float num2 = Vector3.Dot(position - centerPoint, val2); if (!(num2 >= num)) { Vector3 position2 = position + val2 * (num - num2); ((Component)projectile).transform.position = position2; } } } private static void ApplyCopiedThrowAttribution(Projectile projectile, ItemData weapon) { if (SecondaryAttackRuntimeFacade.TryGetDefinition(weapon, out SecondaryAttackDefinition definition) && definition.Behavior is CopiedSecondaryBehavior) { SecondaryAttackRuntimeFacade.SetProjectileAttackAttribution(projectile, definition.PrefabName, secondaryAttack: true, definition, disableCurrentAttackFallback: false); SecondaryAttackProjectileToolTierSystem.ApplyToHitData(ProjectileAccess.GetOriginalHitData(projectile), projectile, weapon, "CopiedThrowProjectileVisualSystem.Setup"); } } private static void ApplyCurrentWeaponVisual(Projectile projectile, ItemData weapon) { ApplyCurrentWeaponVisual(projectile, CreateSpawnedProjectileVisualContext(weapon, includeHitEffects: false)); } private static void ApplyCurrentWeaponVisual(Projectile projectile, SpawnedProjectileVisualContext context) { if (!context.Active || context.SkipVisualSwap) { return; } SecondaryAttackPerformanceLog.Start(); try { SecondaryAttackPerformanceLog.Start(); PrepareProjectileForVisualSwap(projectile); SecondaryAttackPerformanceLog.Start(); MarkCopiedThrowProjectile(projectile, context); SecondaryAttackPerformanceLog.Start(); ZNetView component = ((Component)projectile).GetComponent<ZNetView>(); bool flag = (Object)(object)component != (Object)null && component.IsValid(); if (projectile.m_canChangeVisuals && (Object)(object)projectile.m_visual != (Object)null && flag) { if (component.IsOwner()) { SecondaryAttackPerformanceLog.Start(); component.GetZDO().Set(ZDOVars.s_visual, context.VisualPrefabName); } SecondaryAttackPerformanceLog.Start(); projectile.UpdateVisual(); SecondaryAttackPerformanceLog.Start(); ApplyCopiedThrowVisualSpin(projectile, context); } else { SecondaryAttackPerformanceLog.Start(); ApplyLocalFallbackVisual(projectile, context); } } finally { } } private static void ApplyCurrentWeaponHitEffects(Projectile projectile, ItemData weapon) { ApplyHitEffects(projectile, weapon.m_shared?.m_hitEffect); } private static void TryApplyHitEffectsFromSyncedVisual(Projectile projectile, ZNetView nview) { ApplyHitEffects(projectile, TryResolveSyncedVisualItem(nview)?.m_itemData?.m_shared?.m_hitEffect); } private static void ApplyHitEffects(Projectile projectile, EffectList? hitEffect) { if (hitEffect != null && hitEffect.HasEffects()) { ApplyHitEffects(projectile, CopyHitEffectPrefabs(hitEffect)); } } private static void ApplyHitEffects(Projectile projectile, EffectData[]? hitEffectPrefabs) { //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) //IL_001a: Expected O, but got Unknown if (hitEffectPrefabs != null && hitEffectPrefabs.Length != 0) { projectile.m_hitEffects = new EffectList { m_effectPrefabs = hitEffectPrefabs }; } } private static EffectData[]? CopyHitEffectPrefabs(EffectList? hitEffect) { if (hitEffect?.m_effectPrefabs == null || !hitEffect.HasEffects()) { return null; } return (EffectData[])hitEffect.m_effectPrefabs.Clone(); } private static void MarkCopiedThrowProjectile(Projectile projectile, SpawnedProjectileVisualContext context) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) ZNetView component = ((Component)projectile).GetComponent<ZNetView>(); if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner() && component.GetZDO() != null) { ZDO zDO = component.GetZDO(); zDO.Set("SecondaryAttacks_CopiedThrowProjectile", true); zDO.Set("SecondaryAttacks_CopiedThrowSpinAxis", ToProjectileSpinAxisString(context.SpinAxisMode)); zDO.Set("SecondaryAttacks_CopiedThrowRotationOffset", SerializeVector3(context.VisualRotationOffset)); } } private static bool IsMarkedCopiedThrowProjectile(Projectile projectile) { if ((Object)(object)projectile == (Object)null) { return false; } ZNetView component = ((Component)projectile).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO() != null) { return component.GetZDO().GetBool("SecondaryAttacks_CopiedThrowProjectile", false); } return false; } private static void PrepareProjectileForVisualSwap(Projectile projectile) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown SecondaryAttackPerformanceLog.Start(); Transform val = ((Component)projectile).transform.Find("SecondaryAttacks_CopiedThrowVisualRoot"); if ((Object)(object)val != (Object)null) { projectile.m_visual = ((Component)val).gameObject; projectile.m_canChangeVisuals = true; return; } SecondaryAttackPerformanceLog.Start(); HideSourcePresentation(projectile); SecondaryAttackPerformanceLog.Start(); GameObject val2 = new GameObject("SecondaryAttacks_CopiedThrowVisualRoot"); val2.transform.SetParent(((Component)projectile).transform, false); val2.layer = ((Component)projectile).gameObject.layer; projectile.m_visual = val2; projectile.m_canChangeVisuals = true; } private static void HideSourcePresentation(Projectile projectile) { RendererBuffer.Clear(); ((Component)projectile).GetComponentsInChildren<Renderer>(true, RendererBuffer); foreach (Renderer item in RendererBuffer) { if (!(item is TrailRenderer) && !(item is ParticleSystemRenderer)) { item.enabled = false; } } RendererBuffer.Clear(); } private static void ApplyLocalFallbackVisual(Projectile projectile, ItemData weapon) { ApplyLocalFallbackVisual(projectile, CreateSpawnedProjectileVisualContext(weapon, includeHitEffects: false)); } private static void ApplyLocalFallbackVisual(Projectile projectile, SpawnedProjectileVisualContext context) { ApplyLocalFallbackVisual(projectile, context, "copiedThrow.visual.fallback"); } private static void ApplyLocalFallbackVisual(Projectile projectile, SpawnedProjectileVisualContext context, string perfScopePrefix) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if (context.Active && !((Object)(object)context.AttachPrefab == (Object)null)) { GameObject visual = projectile.m_visual; SecondaryAttackPerformanceLog.Start(); GameObject val = Object.Instantiate<GameObject>(context.AttachPrefab, ((Component)projectile).transform, false); ((Object)val).name = ((Object)context.AttachPrefab).name + "(ProjectileVisual)"; val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; if ((Object)(object)visual != (Object)null && (Object)(object)visual != (Object)(object)val) { visual.SetActive(false); } SecondaryAttackPerformanceLog.Start(); IEquipmentVisual componentInChildren = val.GetComponentInChildren<IEquipmentVisual>(); if (componentInChildren != null) { componentInChildren.Setup(context.Weapon.m_variant); } projectile.m_visual = val; SecondaryAttackPerformanceLog.Start(); ApplyCopiedThrowVisualSpin(projectile, context); } } private static void ApplyCopiedThrowVisualSpin(Projectile projectile, ItemData? weapon, string? visualPrefabName = null) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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) if (!((Object)(object)projectile == (Object)null)) { SecondaryAttackDefinition definition = ResolveCopiedThrowDefinition(weapon, visualPrefabName); ThrowProjectileVisualSpin.AxisMode axisMode; Vector3 rotationOffset; bool num = TryResolveSyncedProjectileSpin(projectile, out axisMode, out rotationOffset); ThrowProjectileVisualSpin.AxisMode valueOrDefault = (num ? new ThrowProjectileVisualSpin.AxisMode?(axisMode) : ResolveConfiguredCopiedThrowSpinAxisMode(definition)).GetValueOrDefault(); Vector3 rotationOffset2 = (num ? rotationOffset : ResolveConfiguredCopiedThrowVisualRotationOffset(definition)); Vector3 horizontalForward = ((valueOrDefault == ThrowProjectileVisualSpin.AxisMode.HorizontalSide) ? ResolveOwnerHorizontalForward(projectile) : Vector3.zero); ApplyCopiedThrowSpinConfiguration(projectile, valueOrDefault, rotationOffset2, horizontalForward); } } private static void ApplyCopiedThrowVisualSpin(Projectile projectile, SpawnedProjectileVisualContext context) { //IL_0025: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)projectile == (Object)null) && context.Active) { Vector3 horizontalForward = ((context.SpinAxisMode == ThrowProjectileVisualSpin.AxisMode.HorizontalSide) ? ResolveOwnerHorizontalForward(projectile) : Vector3.zero); ApplyCopiedThrowSpinConfiguration(projectile, context.SpinAxisMode, context.VisualRotationOffset, horizontalForward); } } private static void ApplyCopiedThrowSpinConfiguration(Projectile projectile, ThrowProjectileVisualSpin.AxisMode axisMode, Vector3 rotationOffset, Vector3 horizontalForward) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) GameObject val = ResolveCopiedThrowSpinVisual(projectile.m_visual); if (!((Object)(object)val == (Object)null)) { CopiedThrowSpinState copiedThrowSpinState = val.GetComponent<CopiedThrowSpinState>() ?? val.AddComponent<CopiedThrowSpinState>(); if (!IsProjectileVisualSpinCleared(projectile) || !copiedThrowSpinState.IsCurrent(axisMode, rotationOffset, horizontalForward)) { ClearProjectileVisualSpin(projectile); ThrowProjectileVisualRotationOffset.Ensure(val, rotationOffset); ThrowProjectileVisualSpin.Ensure(val, axisMode, horizontalForward); copiedThrowSpinState.Configure(axisMode, rotationOffset, horizontalForward); } } } private static SecondaryAttackDefinition? ResolveCopiedThrowDefinition(Attack? attack, ItemData? weapon, string? visualPrefabName) { if (attack != null && SecondaryAttackRuntimeContext.TryGetActiveAttack(attack, out ActiveSecondaryAttack activeAttack) && activeAttack?.Definition != null) { return activeAttack.Definition; } return ResolveCopiedThrowDefinition(weapon, visualPrefabName); } private static SecondaryAttackDefinition? ResolveCopiedThrowDefinition(ItemData? weapon, string? visualPrefabName) { if (weapon != null && SecondaryAttackRuntimeFacade.TryGetDefinition(weapon, out SecondaryAttackDefinition definition)) { return definition; } string text = visualPrefabName?.Trim() ?? ""; if (text.Length > 0 && SecondaryAttackRuntimeFacade.TryGetDefinition(text, out SecondaryAttackDefinition definition2)) { return definition2; } return null; } private static ThrowProjectileVisualSpin.AxisMode? ResolveConfiguredCopiedThrowSpinAxisMode(SecondaryAttackDefinition? definition) { if (definition == null) { return null; } if (definition.Boomerang != null && ProjectileSpinAxis.TryResolveAxisMode(definition.Boomerang.ProjectileSpinAxis, out var axisMode)) { return axisMode; } if (definition.OnProjectileHit == null || !ProjectileSpinAxis.TryResolveAxisMode(definition.OnProjectileHit.ProjectileSpinAxis, out var axisMode2)) { return null; } return axisMode2; } private static Vector3 ResolveConfiguredCopiedThrowVisualRotationOffset(SecondaryAttackDefinition? definition) { //IL_0014: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (definition?.Boomerang != null) { return definition.Boomerang.ProjectileVisualRotationOffset; } return (Vector3)(((??)definition?.OnProjectileHit?.ProjectileVisualRotationOffset) ?? Vector3.zero); } private static GameObject? ResolveCopiedThrowSpinVisual(GameObject? visual) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0055: 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_006b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)visual == (Object)null) { return null; } Transform transform = visual.transform; Transform val = transform.Find("SecondaryAttacks_CopiedThrowSpinRoot"); if ((Object)(object)val != (Object)null) { return ((Component)val).gameObject; } GameObject val2 = new GameObject("SecondaryAttacks_CopiedThrowSpinRoot"); val2.layer = visual.layer; Transform transform2 = val2.transform; transform2.SetParent(transform, false); transform2.localPosition = Vector3.zero; transform2.localRotation = Quaternion.identity; transform2.localScale = Vector3.one; bool flag = false; for (int num = transform.childCount - 1; num >= 0; num--) { Transform child = transform.GetChild(num); if (!((Object)(object)child == (Object)(object)transform2)) { child.SetParent(transform2, false); flag = true; } } if (flag) { return val2; } Object.Destroy((Object)(object)val2); return visual; } private static bool TryResolveSyncedProjectileSpin(Projectile projectile, out ThrowProjectileVisualSpin.AxisMode axisMode, out Vector3 rotationOffset) { //IL_0004: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) axisMode = ThrowProjectileVisualSpin.AxisMode.None; rotationOffset = Vector3.zero; ZNetView val = (((Object)(object)projectile != (Object)null) ? ((Component)projectile).GetComponent<ZNetView>() : null); string raw = default(string); if ((Object)(object)val == (Object)null || !val.IsValid() || val.GetZDO() == null || !val.GetZDO().GetString("SecondaryAttacks_CopiedThrowSpinAxis", ref raw) || !ProjectileSpinAxis.TryResolveAxisMode(raw, out axisMode)) { return false; } string raw2 = default(string); if (val.GetZDO().GetString("SecondaryAttacks_CopiedThrowRotationOffset", ref raw2) && TryParseVector3(raw2, out var value)) { rotationOffset = value; } return true; } private static string ToProjectileSpinAxisString(ThrowProjectileVisualSpin.AxisMode axisMode) { return axisMode switch { ThrowProjectileVisualSpin.AxisMode.HorizontalSide => "horizontal", ThrowProjectileVisualSpin.AxisMode.WorldUp => "vertical", _ => "none", }; } private static string SerializeVector3(Vector3 value) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) return string.Format(CultureInfo.InvariantCulture, "{0},{1},{2}", value.x, value.y, value.z); } private static bool TryParseVector3(string raw, out Vector3 value) { //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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) value = Vector3.zero; if (string.IsNullOrWhiteSpace(raw)) { return false; } string[] array = raw.Split(','); if (array.Length != 3) { return false; } if (!float.TryParse(array[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || !float.TryParse(array[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) || !float.TryParse(array[2].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result3)) { return false; } value = new Vector3(result, result2, result3); return true; } private static Vector3 ResolveOwnerHorizontalForward(Projectile projectile) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0043: Unknown result type (might be due to invalid IL or missing references) Character owner = ProjectileAccess.GetOwner(projectile); Vector3 val = (((Object)(object)owner != (Object)null) ? ((Component)owner).transform.forward : ((Component)projectile).transform.forward); val = Vector3.ProjectOnPlane(val, Vector3.up); if (!(((Vector3)(ref val)).sqrMagnitude > 0.001f)) { return Vector3.zero; } return ((Vector3)(ref val)).normalized; } private static void ClearProjectileVisualSpin(Projectile projectile) { projectile.m_rotateVisual = 0f; projectile.m_rotateVisualY = 0f; projectile.m_rotateVisualZ = 0f; } private static bool IsProjectileVisualSpinCleared(Projectile projectile) { if (Mathf.Approximately(projectile.m_rotateVisual, 0f) && Mathf.Approximately(projectile.m_rotateVisualY, 0f)) { return Mathf.Approximately(projectile.m_rotateVisualZ, 0f); } return false; } private static string? TryResolveSyncedVisualPrefabName(Projectile projectile) { ZNetView val = ((projectile != null) ? ((Component)projectile).GetComponent<ZNetView>() : null); if (!((Object)(object)val == (Object)null)) { return TryResolveSyncedVisualPrefabName(val); } return null; } private static string? TryResolveSyncedVisualPrefabName(ZNetView nview) { string result = default(string); if ((Object)(object)nview == (Object)null || !nview.IsValid() || nview.GetZDO() == null || !nview.GetZDO().GetString(ZDOVars.s_visual, ref result)) { return null; } return result; } private static ItemDrop? TryResolveSyncedVisualItem(ZNetView nview) { return TryResolveSyncedVisualItem(TryResolveSyncedVisualPrefabName(nview)); } private static ItemDrop? TryResolveSyncedVisualItem(string? visualPrefabName) { if ((Object)(object)ObjectDB.instance == (Object)null || string.IsNullOrWhiteSpace(visualPrefabName)) { return null; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(visualPrefabName); if (itemPrefab == null) { return null; } return itemPrefab.GetComponent<ItemDrop>(); } private static string FormatVector(Vector3 value) { return ((Vector3)(ref value)).ToString("F2"); } } internal static class CleavingThrustSystem { private readonly struct CleavingThrustHitTarget { public IDestructible Destructible { get; } public Character? Character { get; } public Collider? Collider { get; } public Vector3 Point { get; } public float Distance { get; } public CleavingThrustHitTarget(IDestructible destructible, Character? character, Collider? collider, Vector3 point, float distance) { //IL_0016: 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) Destructible = destructible; Character = character; Collider = collider; Point = point; Distance = distance; } } private readonly struct CleavingThrustAttackShape { public float Range { get; } public float Angle { get; } public float RayWidth { get; } public float CharacterRayWidth { get; } public CleavingThrustAttackShape(float range, float angle, floa