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 HarpoonExtended v1.2.0
HarpoonExtended.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using ConditionalConfigSync; using HarmonyLib; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Harpoon Extended")] [assembly: AssemblyDescription("Extended harpoon targets, line control and configurable fall protection for Valheim.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Harpoon Extended")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("756572be-76c2-4a52-9d30-8c7dfb11e236")] [assembly: AssemblyFileVersion("1.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] namespace HarpoonExtended; [BepInPlugin("shudnal.HarpoonExtended", "Harpoon Extended", "1.2.0")] [BepInDependency("_shudnal.ConditionalConfigSync", "1.0.5")] public class HarpoonExtended : BaseUnityPlugin { [HarmonyPatch(typeof(SE_Harpooned), "UpdateStatusEffect")] public static class SE_Harpooned_UpdateStatusEffect_HarpoonPull { [HarmonyPriority(800)] private static void Postfix(SE_Harpooned __instance, float dt, Character ___m_attacker, Character ___m_character, ref float ___m_baseDistance) { if (targetPulling.Value && !((Object)(object)___m_attacker == (Object)null) && !((Object)(object)___m_attacker != (Object)(object)Player.m_localPlayer) && !((Object)(object)___m_character == (Object)null) && !___m_character.IsPlayer() && (KeyPressPullHarpoon() || KeyPressReleaseHarpoon()) && !KeyPressStopHarpoon() && !((Object)(object)___m_character.m_nview == (Object)null) && ___m_character.m_nview.IsValid()) { if (!___m_character.IsOwner()) { ___m_character.m_nview.ClaimOwnership(); } if (KeyPressReleaseHarpoon()) { ___m_baseDistance += 4f * dt * pullSpeedMultiplier.Value; } else if (KeyPressPullHarpoon()) { ___m_baseDistance -= 2f * dt * pullSpeedMultiplier.Value; } ___m_baseDistance = Mathf.Max(___m_baseDistance, 2f); } } } [HarmonyPatch(typeof(SE_Harpooned), "IsDone")] public static class SE_Harpooned_IsDone_HarpoonPull { [HarmonyPriority(800)] private static bool Prefix(SE_Harpooned __instance, Character ___m_attacker, Character ___m_character, ref bool __result) { if ((Object)(object)__instance == (Object)null || (Object)(object)___m_attacker == (Object)null || (Object)(object)___m_character == (Object)null || (Object)(object)___m_attacker != (Object)(object)Player.m_localPlayer || !targetPulling.Value) { return true; } if (!KeyPressStopHarpoon()) { return true; } ___m_attacker.Message((MessageType)2, ___m_character.m_name + Localization.instance.Localize(" $msg_harpoon_released"), 0, (Sprite)null, false); __result = true; return false; } } [HarmonyPatch(typeof(Player), "UpdateCrouch")] public static class Player_UpdateCrouch_DisableCrouchOnHarpooning { private static void Prefix(Player __instance, ref bool ___m_crouchToggled) { if (((Object)(object)Player.m_localPlayer == (Object)(object)__instance && harpoonActive) & ___m_crouchToggled) { ___m_crouchToggled = false; } } } [HarmonyPatch(typeof(Player), "TeleportTo")] public static class Player_TeleportTo_HarpoonStat { private static void Postfix(Player __instance) { if (harpoonActive && (Object)(object)m_attacker == (Object)(object)__instance && ((Character)__instance).IsTeleporting()) { DestroyHarpooned("Teleport initiated"); } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] public static class ObjectDB_Awake_HarpoonStat { public static void PatchHarpoonStatusEffectAndRecipe(ObjectDB db) { HarpoonSlowFall.Register(db); GameObject itemPrefab = db.GetItemPrefab("SpearChitin"); ItemDrop val = default(ItemDrop); if ((Object)(object)itemPrefab == (Object)null || !itemPrefab.TryGetComponent<ItemDrop>(ref val)) { return; } PatchHarpoonItemData(val.m_itemData); foreach (StatusEffect statusEffect in db.m_StatusEffects) { if ((Object)(object)statusEffect != (Object)null && ((Object)statusEffect).name == "Harpooned") { SE_Harpooned val2 = (SE_Harpooned)(object)((statusEffect is SE_Harpooned) ? statusEffect : null); if (val2 != null) { harpoonedStatusEffect = val2; PatchHarpoonStatusEffect(val2); break; } } } Recipe recipe = db.GetRecipe(val.m_itemData); if (!((Object)(object)recipe != (Object)null)) { return; } Requirement[] resources = recipe.m_resources; foreach (Requirement val3 in resources) { if (val3 != null && (Object)(object)val3.m_resItem != (Object)null) { val3.m_amountPerLevel = ((val3.m_resItem.m_itemData.m_shared.m_name == "$item_chitin") ? 15 : 0); val3.m_upgraderResource = false; } } } private static void Postfix(ObjectDB __instance) { PatchHarpoonStatusEffectAndRecipe(__instance); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] public static class ObjectDB_CopyOtherDB_HarpoonStat { private static void Postfix(ObjectDB __instance) { ObjectDB_Awake_HarpoonStat.PatchHarpoonStatusEffectAndRecipe(__instance); } } [HarmonyPatch] private static class Inventory_Load_HarpoonStats { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Inventory), "Load", new Type[2] { typeof(ZPackage), typeof(bool) }, (Type[])null); yield return AccessTools.Method(typeof(Inventory), "Load", new Type[1] { typeof(ZPackage) }, (Type[])null); } private static void Postfix(Inventory __instance) { PatchInventory(__instance); } } [HarmonyPatch(typeof(ItemDrop), "Start")] public static class ItemDrop_Start_HarpoonStats { private static void Postfix(ItemDrop __instance) { if (!(Utils.GetPrefabName(((Component)__instance).gameObject) != "SpearChitin")) { PatchHarpoonItemData(__instance.m_itemData); StatusEffect attackStatusEffect = __instance.m_itemData.m_shared.m_attackStatusEffect; PatchHarpoonStatusEffect((SE_Harpooned)(object)((attackStatusEffect is SE_Harpooned) ? attackStatusEffect : null)); } } } [HarmonyPatch(typeof(Player), "OnSpawned")] public static class Player_OnSpawned_HarpoonStats { private static void Postfix(Player __instance) { PatchInventory(((Humanoid)__instance).GetInventory()); } } [HarmonyPatch(typeof(Ship), "UpdateOwner")] public static class Ship_UpdateOwner_ShipPulling { private static bool Prefix(Ship __instance, ZNetView ___m_nview) { if (!harpoonActive || (Object)(object)harpooned == (Object)null || (Object)(object)m_nview != (Object)(object)___m_nview || (Object)(object)___m_nview == (Object)null || !___m_nview.IsValid()) { return true; } m_nview.ClaimOwnership(); return false; } } [HarmonyPatch(typeof(Projectile), "Awake")] public static class Projectile_Awake_HarpoonStats { private static void Postfix(Projectile __instance) { if (IsHarpoonProjectile(__instance) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { __instance.m_gravity *= projectileGravityMiltiplier.Value; __instance.m_rayRadius = Mathf.Clamp(hitboxSize.Value, 0f, 0.5f); } } } [HarmonyPatch(typeof(Projectile), "Setup")] public static class Projectile_Setup_HarpoonStats { private static void Postfix(Projectile __instance) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (IsHarpoonProjectile(__instance) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { if (disableDamage.Value) { ((DamageTypes)(ref __instance.m_damage)).Modify(0f); } __instance.m_vel *= projectileVelocityMultiplier.Value; } } } [HarmonyPatch(typeof(Projectile), "FixedUpdate")] public static class Projectile_FixedUpdate_HarpoonMask { public struct MaskState { public bool Applied; public int Original; } private static void Prefix(Projectile __instance, out MaskState __state) { __state = default(MaskState); if (targetItems.Value && IsHarpoonProjectile(__instance) && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && __instance.m_nview.IsOwner()) { __state.Original = Projectile.s_rayMaskSolids; __state.Applied = true; Projectile.s_rayMaskSolids |= LayerMask.GetMask(new string[1] { "item" }); } } private static void Finalizer(MaskState __state) { if (__state.Applied) { Projectile.s_rayMaskSolids = __state.Original; } } } [HarmonyPatch(typeof(Projectile), "OnHit")] public static class Projectile_OnHit_HarpoonStats { public sealed class HitState { public Player Attacker; public GameObject Target; public Collider Collider; public Vector3 Point; public bool PullTo; public bool Attach; public bool SuppressedStatus; public int OriginalStatus; } private static void Prefix(Projectile __instance, Collider collider, Vector3 hitPoint, out HitState __state) { //IL_00b7: 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_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) __state = null; if (!IsHarpoonProjectile(__instance) || __instance.m_didHit || (Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid() || !__instance.m_nview.IsOwner()) { return; } Character owner = __instance.m_owner; Player val = (Player)(object)((owner is Player) ? owner : null); if ((Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || (Object)(object)collider == (Object)null) { return; } GameObject val2 = Projectile.FindHitObject(collider); if ((Object)(object)val2 == (Object)null) { return; } __state = new HitState { Attacker = val, Target = val2, Collider = collider, Point = hitPoint, PullTo = KeyPressPullTo(), OriginalStatus = __instance.m_statusEffectHash }; if (IsRopeForbidden(val2, collider)) { SuppressStatus(__instance, __state); return; } Character componentInParent = val2.GetComponentInParent<Character>(); if ((Object)(object)componentInParent != (Object)null && (componentInParent.IsPlayer() || !targetCreatures.Value || !targetPulling.Value)) { return; } if ((Object)(object)val2 == (Object)(object)((Component)val).gameObject || (Object)(object)val2.GetComponentInParent<FollowPlayer>() != (Object)null) { SuppressStatus(__instance, __state); } else { if (!IsCustomTarget(val2)) { return; } SuppressStatus(__instance, __state); if ((Object)(object)componentInParent != (Object)null && componentInParent.IsBoss() && !targetBosses.Value) { return; } float num = Vector3.Distance(hitPoint, ((Component)val).transform.position); if (IsFinite(hitPoint) && IsFinite(num) && IsFinite(maxDistance.Value) && !(maxDistance.Value <= 0f) && !(num > maxDistance.Value)) { ZNetView componentInParent2 = val2.GetComponentInParent<ZNetView>(); if (!((Object)(object)componentInParent2 != (Object)null) || componentInParent2.IsValid()) { __state.Attach = true; } } } } private static void SuppressStatus(Projectile projectile, HitState state) { state.SuppressedStatus = true; projectile.m_statusEffectHash = 0; } private static void Postfix(Projectile __instance, HitState __state) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (__state == null || !__state.Attach || (Object)(object)__instance == (Object)null || !__instance.m_didHit || __instance.m_didBounce || (Object)(object)__state.Target == (Object)null || (Object)(object)__state.Collider == (Object)null || (Object)(object)__state.Attacker == (Object)null || (harpoonActive && (Object)(object)harpooned != (Object)null && m_time < 0.5f)) { return; } try { SetHarpooned(__state.Attacker, __state.Target, __state.Point, __state.PullTo, __state.Collider); } catch (Exception arg) { ((BaseUnityPlugin)instance).Logger.LogError((object)$"Harpoon attachment failed; releasing the rope. {arg}"); DestroyHarpooned("Attachment failed"); } } private static void Finalizer(Projectile __instance, HitState __state) { if (__state != null && __state.SuppressedStatus && (Object)(object)__instance != (Object)null) { __instance.m_statusEffectHash = __state.OriginalStatus; } } } [HarmonyPatch(typeof(Player), "FixedUpdate")] public static class Player_FixedUpdate_SlowFallControl { private static void RemoveSlowFall(SEMan effects, string reason) { effects.RemoveStatusEffect(HarpoonSlowFall.EffectHash, true); slowFallCasted = false; slowFallPlayer = null; LogInfo(reason); } private static void CheckSlowFallStatus(Player player, SEMan effects) { if (!harpoonActive) { if (removeSlowFallonGroundThreshold.Value > 0f && onGroundTimer >= removeSlowFallonGroundThreshold.Value) { RemoveSlowFall(effects, "Remove slow fall on ground"); } else if (((Character)player).IsAttached()) { RemoveSlowFall(effects, "Remove slow fall on attached"); } else if (((Character)player).IsSwimming()) { RemoveSlowFall(effects, "Remove slow fall on swimming"); } else if (((Character)player).IsDebugFlying()) { RemoveSlowFall(effects, "Remove slow fall on flying"); } else if (removeSlowFallWithoutHarpoon.Value && (((Humanoid)player).GetLeftItem() == null || ((Humanoid)player).GetLeftItem().m_shared.m_name != "$item_spear_chitin") && (((Humanoid)player).GetRightItem() == null || ((Humanoid)player).GetRightItem().m_shared.m_name != "$item_spear_chitin")) { RemoveSlowFall(effects, "Remove slow fall without harpoon"); } } } private static void Postfix(Player __instance, SEMan ___m_seman) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || (Object)(object)((Character)__instance).m_nview == (Object)null || !((Character)__instance).m_nview.IsValid() || ___m_seman == null) { return; } if ((Object)(object)slowFallPlayer != (Object)null && (Object)(object)slowFallPlayer != (Object)(object)__instance) { ResetSlowFallState(removeEffect: true); } if (castSlowFall) { HarpoonSlowFall.Apply(__instance, slowFallSpeed.Value, slowFallDamageMultiplier.Value); slowFallCasted = ___m_seman.HaveStatusEffect(HarpoonSlowFall.EffectHash); slowFallPlayer = (slowFallCasted ? __instance : null); castSlowFall = false; onGroundTimer = 0f; } if (!slowFallCasted) { return; } if (!___m_seman.HaveStatusEffect(HarpoonSlowFall.EffectHash)) { ResetSlowFallState(removeEffect: false); return; } if (((Character)__instance).IsOnGround()) { onGroundTimer += Time.fixedDeltaTime; } CheckSlowFallStatus(__instance, ___m_seman); } } [HarmonyPatch(typeof(ZNetScene), "Destroy")] public static class ZNetScene_Destroy_CheckParentDestroy { private static void Prefix(GameObject go) { if (harpoonActive && !destroyingHarpoon && !((Object)(object)go == (Object)null) && !((Object)(object)go == (Object)(object)harpooned) && (((Object)(object)targetHarpooned != (Object)null && ((Object)(object)go == (Object)(object)targetHarpooned || targetHarpooned.transform.IsChildOf(go.transform))) || ((Object)(object)m_attacker != (Object)null && ((Object)(object)go == (Object)(object)((Component)m_attacker).gameObject || ((Component)m_attacker).transform.IsChildOf(go.transform))))) { DestroyHarpooned("Participant destroyed"); } } } [HarmonyPatch(typeof(Player), "OnDestroy")] public static class Player_OnDestroy_HarpoonCleanup { private static void Prefix(Player __instance) { if (harpoonActive && (Object)(object)m_attacker == (Object)(object)__instance) { DestroyHarpooned("Attacker destroyed"); } if ((Object)(object)slowFallPlayer == (Object)(object)__instance || (Object)(object)__instance == (Object)(object)Player.m_localPlayer) { ResetSlowFallState(removeEffect: false); } } } [HarmonyPatch(typeof(ZNetScene), "Shutdown")] public static class ZNetScene_Shutdown_HarpoonCleanup { private static void Prefix() { DestroyHarpooned("World shutdown"); ResetSlowFallState(removeEffect: true); } } [HarmonyPatch(typeof(ZNetScene), "OnDestroy")] public static class ZNetScene_OnDestroy_HarpoonCleanup { private static void Prefix(ZNetScene __instance) { if ((Object)(object)connectionScene == (Object)(object)__instance) { DestroyHarpooned("World destroyed"); } ResetSlowFallState(removeEffect: false); } } internal const string pluginID = "shudnal.HarpoonExtended"; internal const string pluginName = "Harpoon Extended"; internal const string pluginVersion = "1.2.0"; private readonly Harmony harmony = new Harmony("shudnal.HarpoonExtended"); internal static readonly ConfigSync configSync = new ConfigSync("shudnal.HarpoonExtended") { DisplayName = "Harpoon Extended", CurrentVersion = "1.2.0", MinimumRequiredVersion = "1.2.0", ModRequired = true }; public static ConfigEntry<bool> configLocked; public static ConfigEntry<bool> loggingEnabled; public static ConfigEntry<bool> deepLoggingEnabled; public static ConfigEntry<bool> messagesEnabled; public static ConfigEntry<bool> targetMessagesEnabled; public static ConfigEntry<float> timeBeforeStop; public static ConfigEntry<bool> applySlowFall; public static ConfigEntry<bool> attachedShipStamina; public static ConfigEntry<bool> pullUnderWater; public static ConfigEntry<bool> removeSlowFallWithoutHarpoon; public static ConfigEntry<float> removeSlowFallonGroundThreshold; public static ConfigEntry<float> slowFallSpeed; public static ConfigEntry<float> slowFallDamageMultiplier; public static ConfigEntry<bool> targetPulling; public static ConfigEntry<float> pullSpeedMultiplier; public static ConfigEntry<float> maxBodyMassToPull; public static ConfigEntry<float> containerInventoryWeightMassFactor; public static ConfigEntry<bool> targetCreatures; public static ConfigEntry<bool> targetShip; public static ConfigEntry<bool> targetTreeLog; public static ConfigEntry<bool> targetTreeBase; public static ConfigEntry<bool> targetFish; public static ConfigEntry<bool> targetPiece; public static ConfigEntry<bool> targetDestructibles; public static ConfigEntry<bool> targetLeviathan; public static ConfigEntry<bool> targetItems; public static ConfigEntry<bool> targetBosses; public static ConfigEntry<bool> targetGround; public static ConfigEntry<string> targetWhitelist; public static ConfigEntry<string> targetBlacklist; public static ConfigEntry<float> breakDistance; public static ConfigEntry<float> maxDistance; public static ConfigEntry<float> drainStamina; public static ConfigEntry<float> minDistanceShip; public static ConfigEntry<float> minDistanceCreature; public static ConfigEntry<float> minDistanceItem; public static ConfigEntry<float> minDistancePullToTarget; public static ConfigEntry<float> minDistancePullToPlayer; public static ConfigEntry<float> pullSpeed; public static ConfigEntry<float> smoothDistance; public static ConfigEntry<float> pullForceMultiplier; public static ConfigEntry<float> forcePower; public static ConfigEntry<bool> useForce; public static ConfigEntry<bool> alwaysPullTo; public static ConfigEntry<float> maximumVelocity; public static ConfigEntry<float> projectileGravityMiltiplier; public static ConfigEntry<float> hitboxSize; public static ConfigEntry<float> projectileVelocityMultiplier; public static ConfigEntry<int> maxQuality; public static ConfigEntry<float> durabilityPerLevel; public static ConfigEntry<bool> disableDurability; public static ConfigEntry<float> durabilityDrain; public static ConfigEntry<float> attackStamina; public static ConfigEntry<bool> disableDamage; public static ConfigEntry<bool> disableStamina; public static ConfigEntry<KeyboardShortcut> shortcutPull; public static ConfigEntry<KeyboardShortcut> shortcutPullTo; public static ConfigEntry<KeyboardShortcut> shortcutRelease; public static ConfigEntry<KeyboardShortcut> shortcutStop; internal const string prefabNameSpearChitin = "SpearChitin"; internal const string itemDropNameSpearChitin = "$item_spear_chitin"; internal const string statusEffectNameHarpooned = "Harpooned"; internal static HarpoonExtended instance; public static float m_pullSpeed = 1000f; public static float m_smoothDistance = 2f; public static float m_maxLineSlack = 0.3f; public static float m_breakDistance = 15f; public static float m_minDistance = 2f; public static float m_maxDistance = 50f; public static float m_staminaDrain = 0.1f; public static float m_staminaDrainInterval = 0.1f; public static bool m_broken; public static float m_time; public static Player m_attacker; public static float targetDistance = 999999f; public static LineConnect m_line; public static float m_drainStaminaTimer; public static GameObject harpooned; public static Rigidbody objectRbody; public static Rigidbody attackerRbody; public static GameObject targetHarpooned; public static string targetName; public static bool noUpForce; public static ZNetView m_nview; public static Ship m_ship; public static Character m_character; public static float objectMass; public static LineRenderer m_lineRenderer; public static bool isPullingTo; public static bool castSlowFall; public static bool slowFallCasted; public static float onGroundTimer; public static SE_Harpooned harpoonedStatusEffect; private static readonly HashSet<string> allowedPrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static readonly HashSet<string> deniedPrefabs = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static Player slowFallPlayer; private static bool harpoonActive; private static bool destroyingHarpoon; private static bool hadTargetView; private static bool hadTargetBody; private static bool hadTargetCharacter; private static Collider targetCollider; private static ZNetView attackerView; private static ZNetView ropeView; private static ZNetScene connectionScene; private static ZDOID ropeID = ZDOID.None; private static HarpoonLine lineVisual; private static Rigidbody temporarilyDynamicBody; private void Awake() { instance = this; ConfigInit(); ((ConditionalConfigSync)configSync).AddLockingConfigEntry<bool>(configLocked); harmony.PatchAll(); Game.isModded = true; } private void OnDestroy() { DestroyHarpooned("Plugin destroyed"); ResetSlowFallState(removeEffect: true); ((BaseUnityPlugin)this).Config.Save(); harmony.UnpatchSelf(); instance = null; } public static void LogInfo(object data) { if ((Object)(object)instance != (Object)null && loggingEnabled != null && loggingEnabled.Value && data != null && !string.IsNullOrWhiteSpace(data.ToString())) { ((BaseUnityPlugin)instance).Logger.LogInfo(data); } } private void ConfigInit() { //IL_0332: Unknown result type (might be due to invalid IL or missing references) //IL_033d: Expected O, but got Unknown //IL_05c0: Unknown result type (might be due to invalid IL or missing references) //IL_05ea: Unknown result type (might be due to invalid IL or missing references) //IL_061a: Unknown result type (might be due to invalid IL or missing references) //IL_0652: Unknown result type (might be due to invalid IL or missing references) config("1 - General", "NexusID", 2528, "Nexus mod ID for updates", synchronizedSetting: false); configLocked = config("1 - General", "Lock Configuration", defaultValue: true, "Configuration is locked and can be changed by server admins only."); loggingEnabled = config("1 - General", "Logging enabled", defaultValue: false, "Enable logging for debug events. [Not Synced with Server]", synchronizedSetting: false); targetCreatures = config("2 - Targets", "Creatures (override)", defaultValue: true, "Enable pulling creatures. Overrides vanilla behaviour. Restart required after change."); targetShip = config("2 - Targets", "Ship", defaultValue: true, "Enable pulling ships."); targetTreeLog = config("2 - Targets", "Tree log", defaultValue: true, "Enable pulling logs."); targetTreeBase = config("2 - Targets", "Trees", defaultValue: true, "Enable pulling to trees."); targetFish = config("2 - Targets", "Fish", defaultValue: true, "Enable pulling fish."); targetPiece = config("2 - Targets", "Buildings", defaultValue: true, "Enable pulling to buildings."); targetDestructibles = config("2 - Targets", "Destructibles", defaultValue: true, "Enable pulling to destructibles."); targetLeviathan = config("2 - Targets", "Leviathan", defaultValue: false, "Enable pulling a Leviathan. Use with caution. Can cause deadly effect"); targetItems = config("2 - Targets", "Items", defaultValue: true, "Enable pulling an items. Fish considered as item."); targetBosses = config("2 - Targets", "Bosses", defaultValue: false, "Enable pulling a boss."); targetGround = config("2 - Targets", "Any target", defaultValue: false, "Track any hitpoint. Every hit collision. Terrain included."); targetWhitelist = config("2 - Targets", "Prefab whitelist", "", "Comma-separated prefab names allowed to attach a rope. Empty means no additional restriction. Does not bypass other target rules. Hits and damage still occur."); targetBlacklist = config("2 - Targets", "Prefab blacklist", "", "Comma-separated prefab names forbidden to attach a rope. Takes priority over the whitelist. Hits and damage still occur."); targetWhitelist.SettingChanged += OnTargetFilterChanged; targetBlacklist.SettingChanged += OnTargetFilterChanged; RebuildTargetFilters(); messagesEnabled = config("6 - Misc", "Enabled harpooning messages", defaultValue: true, "Enable localized notification of current state. [Not Synced with Server]", synchronizedSetting: false); timeBeforeStop = config("6 - Misc", "Time before harpoon can be dropped", 1f, "Time in seconds the harpoon should exists before it can be released. To prevent spam mistakes. [Not Synced with Server]", synchronizedSetting: false); applySlowFall = config("6 - Misc", "Apply Feather Fall while harpooning around", defaultValue: true, "Apply Feather Fall while using the harpoon to prevent fall damage"); drainStamina = config("6 - Misc", "Stamina drain multiplier", 1f, "Stamina drain for target pulling."); attachedShipStamina = config("6 - Misc", "No stamina usage while attached to ship", defaultValue: true, "Disable stamina usage while attached to ship"); pullUnderWater = config("6 - Misc", "Pull to underwater", defaultValue: true, "Pull to underwater terrain."); removeSlowFallWithoutHarpoon = config("6 - Misc", "Remove Feather Fall without harpoon", defaultValue: false, "Remove Feather Fall if harpoon is not equipped."); removeSlowFallonGroundThreshold = config("6 - Misc", "Remove Feather Fall after seconds on ground", 2f, "Remove Feather Fall if a player stays without harpoon line on the ground for set amount of seconds."); slowFallSpeed = config("6 - Misc", "Feather Fall maximum fall speed", 7f, "Maximum downward speed in meters per second. Zero disables the speed limit. Applied only when the harpoon's own Feather Fall effect is added."); slowFallDamageMultiplier = config("6 - Misc", "Feather Fall damage multiplier", 0f, new ConfigDescription("Fall damage multiplier: 0 prevents base fall damage, 0.5 halves it, 1 leaves it unchanged. Other status effects still contribute normally. Applied only when the harpoon's own Feather Fall effect is added.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); targetPulling = config("3 - Pull", "Enable pulling", defaultValue: true, "Enable active pulling harpooned target or yourself. Hold Use button to retrieve line or Crouch + Use buttons to cast line."); pullSpeedMultiplier = config("3 - Pull", "Harpoon line casting and retrieving speed multiplier", 1f, "Speed of line casting and retrieving"); maxBodyMassToPull = config("3 - Pull", "Maximum mass you can pull", 1000f, "Objects with mass more than set will not be pulled but instead you will be pulled to them.\nLeviathan mass is 1000, Lox 60, Serpent 30. Ships excluded from this restriction.\nContainers and items weight depends on \"Pulled container inventory weight mass factor\""); containerInventoryWeightMassFactor = config("3 - Pull", "Pulled container inventory weight mass factor", 0.1f, "If pulled object contains inventory, like CargoCrate, the inventory total weight will be multiplied by that factor.\nThis calculation also applies to pulling items but this effect is mostly negligible except some heavy stack"); breakDistance = config("4 - Line", "Break distance", 15f, "Line will break if distance between you and target will be more than target line length + break distance."); maxDistance = config("4 - Line", "Max distance", 50f, "Max distance. Balanced is 100. Big numbers (>200) will work but may cause unwanted net code effects."); minDistanceShip = config("4 - Line", "Min distance (Ship)", 5f, "Minimal distance where the line broke to avoid unwanted collisions (Ships)"); minDistanceCreature = config("4 - Line", "Min distance (Creature)", 0.5f, "Minimal distance where the line broke to avoid unwanted collisions (living creatures)"); minDistanceItem = config("4 - Line", "Min distance (Item)", 0.1f, "Minimal distance where the line broke to avoid unwanted collisions (items)"); minDistancePullToTarget = config("4 - Line", "Min distance (pull to target)", 1f, "Minimal distance where the line broke to avoid unwanted collisions (When pulling player to general target)"); minDistancePullToPlayer = config("4 - Line", "Min distance (pull to player)", 2f, "Minimal distance where the line broke to avoid unwanted collisions (When pulling general target to player)"); maxQuality = config("5 - Item", "Max quality", 4, "Maximum quality level"); durabilityPerLevel = config("5 - Item", "Durability per level", 100f, "Durability added per level"); durabilityDrain = config("5 - Item", "Durability drain on attack", 1f, "Durability drain on usage"); attackStamina = config("5 - Item", "Stamina drain on attack", 15f, "Stamina drain on usage"); disableDurability = config("5 - Item", "Disable harpoon durability usage", defaultValue: false, "Make harpoon to not use durability. Restart required after change."); disableDamage = config("5 - Item", "Disable harpoon damage", defaultValue: false, "Make harpoon to deal no damage. Handy to ride a deathsquito without killing it. Or even birds. Restart required after change."); disableStamina = config("5 - Item", "Disable harpoon stamina usage", defaultValue: false, "Make harpoon to not use stamina. Restart required after change."); projectileGravityMiltiplier = config("5 - Item", "Projectile gravity multiplier", 1f, "Multiplier of gravity affecting harpoon projectile"); projectileVelocityMultiplier = config("5 - Item", "Projectile velocity multiplier", 1f, "Basically speed of initial harpoon flight"); shortcutPull = config<KeyboardShortcut>("7 - Shortcuts", "Pull", new KeyboardShortcut((KeyCode)116, Array.Empty<KeyCode>()), "Pull target closer if applicable [Not Synced with Server]", synchronizedSetting: false); shortcutPullTo = config<KeyboardShortcut>("7 - Shortcuts", "Pull To Target mode", new KeyboardShortcut((KeyCode)304, Array.Empty<KeyCode>()), "Hold why harpoon is flying to make you always pull to target [Not Synced with Server]", synchronizedSetting: false); shortcutRelease = config<KeyboardShortcut>("7 - Shortcuts", "Release", new KeyboardShortcut((KeyCode)116, (KeyCode[])(object)new KeyCode[1] { (KeyCode)306 }), "Release line [Not Synced with Server]", synchronizedSetting: false); shortcutStop = config<KeyboardShortcut>("7 - Shortcuts", "Stop harpooning", new KeyboardShortcut((KeyCode)116, (KeyCode[])(object)new KeyCode[2] { (KeyCode)304, (KeyCode)306 }), "Stop harpooning [Not Synced with Server]", synchronizedSetting: false); pullSpeed = config("8 - Debug", "Pull speed", 1000f, "[Math] Pull speed of static line. Used in velocity math. No actual need to mess with it."); pullForceMultiplier = config("8 - Debug", "Pull force multiplier", 1f, "[Math] Pull force multiplier. Depends on moved body mass. No actual need to mess with it."); smoothDistance = config("8 - Debug", "Smooth distance", 2f, "[Math] Makes the applied force smoother. No actual need to mess with it."); forcePower = config("8 - Debug", "Force power", 1f, "[Math] Power (exponentiation part) of the actual force. No actual need to mess with it."); useForce = config("8 - Debug", "Use force", defaultValue: true, "[Math] If true - pull physics use force applied to moved body. If false - uses velocity calculation. No actual need to mess with it."); targetMessagesEnabled = config("8 - Debug", "Enabled harpooning target message for all objects", defaultValue: false, "Enable unlocalized target name for any object you hit. [Not Synced with Server]", synchronizedSetting: false); deepLoggingEnabled = config("8 - Debug", "Logging deep stats", defaultValue: false, "Enable deep logging to debug physics events. [Not Synced with Server]", synchronizedSetting: false); hitboxSize = config("8 - Debug", "Hitbox size", 0f, "Hitbox size. 0.0 min - 0.5 max. You can try to change it if you have difficulties with aiming small targets"); alwaysPullTo = config("8 - Debug", "Always pull to", defaultValue: false, "Always pull to target regardress hotkey"); maximumVelocity = config("8 - Debug", "Maximum velocity", 10f, "Maximum velocity imparted to player rigidbody by harpoon pulling"); } private ConfigEntry<T> config<T>(string group, string name, T defaultValue, ConfigDescription description, bool synchronizedSetting = true) { ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, defaultValue, description); ((ConditionalConfigSync)configSync).AddConfigEntry<T>(val, (ConfigSyncMode)((!synchronizedSetting) ? 2 : 0)); return val; } private ConfigEntry<T> config<T>(string group, string name, T defaultValue, string description, bool synchronizedSetting = true) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return config(group, name, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synchronizedSetting); } private static bool KeyPressStopHarpoon() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = shortcutStop.Value; return ((KeyboardShortcut)(ref value)).IsDown() || ZInput.GetButton("Block") || ZInput.GetButton("JoyBlock"); } private static bool KeyPressPullHarpoon() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) int result; if (!ZInput.GetButton("Use") && !ZInput.GetButton("JoyUse")) { KeyboardShortcut value = shortcutPull.Value; result = (((KeyboardShortcut)(ref value)).IsPressed() ? 1 : 0); } else { result = 1; } return (byte)result != 0; } private static bool KeyPressReleaseHarpoon() { //IL_0024: 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) int result; if (!KeyPressPullHarpoon() || (!ZInput.GetButton("Crouch") && !ZInput.GetButton("JoyCrouch"))) { KeyboardShortcut value = shortcutRelease.Value; result = (((KeyboardShortcut)(ref value)).IsPressed() ? 1 : 0); } else { result = 1; } return (byte)result != 0; } private static bool KeyPressPullTo() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) int result; if (!ZInput.GetButton("AltPlace") && !ZInput.GetButton("JoyAltPlace")) { KeyboardShortcut value = shortcutPullTo.Value; result = (((KeyboardShortcut)(ref value)).IsPressed() ? 1 : 0); } else { result = 1; } return (byte)result != 0; } private static void PatchHarpoonStatusEffect(SE_Harpooned effect) { if (!((Object)(object)effect == (Object)null)) { effect.m_breakDistance = breakDistance.Value; effect.m_maxDistance = maxDistance.Value; effect.m_staminaDrain = 0.1f * drainStamina.Value; effect.m_pullSpeed = pullSpeed.Value; effect.m_smoothDistance = smoothDistance.Value; effect.m_forcePower = forcePower.Value; } } private static void PatchInventory(Inventory inventory) { if (inventory.m_temoraryInventory) { return; } List<ItemData> list = new List<ItemData>(); inventory.GetAllItems("$item_spear_chitin", list); foreach (ItemData item in list) { PatchHarpoonItemData(item); StatusEffect attackStatusEffect = item.m_shared.m_attackStatusEffect; PatchHarpoonStatusEffect((SE_Harpooned)(object)((attackStatusEffect is SE_Harpooned) ? attackStatusEffect : null)); } } private static void PatchHarpoonItemData(ItemData item) { item.m_shared.m_maxQuality = Math.Max(Math.Min(maxQuality.Value, 4), 1); item.m_shared.m_durabilityPerLevel = Mathf.Clamp(durabilityPerLevel.Value, 50f, 500f); item.m_shared.m_useDurability = !disableDurability.Value; item.m_shared.m_useDurabilityDrain = durabilityDrain.Value; item.m_shared.m_attack.m_attackStamina = (disableStamina.Value ? 0f : attackStamina.Value); } public static void SetHarpooned(Player attacker, GameObject hitObject, Vector3 hitPoint, bool pullTo, Collider collider) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_0485: Unknown result type (might be due to invalid IL or missing references) //IL_048a: Unknown result type (might be due to invalid IL or missing references) //IL_0530: Unknown result type (might be due to invalid IL or missing references) //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_057d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)attacker == (Object)null || (Object)(object)hitObject == (Object)null || (Object)(object)collider == (Object)null || (Object)(object)ZNetScene.instance == (Object)null || !IsFinite(hitPoint)) { return; } if (harpoonActive) { DestroyHarpooned("Reinstantiate"); } m_attacker = attacker; targetHarpooned = hitObject; targetCollider = collider; connectionScene = ZNetScene.instance; attackerView = ((Component)attacker).GetComponent<ZNetView>(); attackerRbody = ((Component)attacker).GetComponent<Rigidbody>(); m_nview = hitObject.GetComponentInParent<ZNetView>(); m_ship = hitObject.GetComponentInParent<Ship>(); m_character = hitObject.GetComponentInParent<Character>(); objectRbody = hitObject.GetComponentInParent<Rigidbody>() ?? collider.attachedRigidbody ?? hitObject.GetComponentInChildren<Rigidbody>(); hadTargetView = (Object)(object)m_nview != (Object)null; hadTargetBody = (Object)(object)objectRbody != (Object)null; hadTargetCharacter = (Object)(object)m_character != (Object)null; harpoonActive = true; if ((Object)(object)attackerView == (Object)null || !attackerView.IsValid() || (Object)(object)attackerRbody == (Object)null || (hadTargetView && !m_nview.IsValid())) { DestroyHarpooned("Missing initial participant state"); return; } m_time = 0f; m_broken = false; m_drainStaminaTimer = 0f; m_breakDistance = breakDistance.Value; m_maxDistance = maxDistance.Value; m_staminaDrain = 0.1f * drainStamina.Value; m_pullSpeed = pullSpeed.Value; m_smoothDistance = smoothDistance.Value; targetDistance = Vector3.Distance(hitPoint, ((Component)attacker).transform.position); objectMass = CalculateHitObjectMass(hitObject); targetName = GetHarpoonedTargetName(hitObject, collider); isPullingTo = false; if (targetLeviathan.Value && (Object)(object)hitObject.GetComponentInParent<Leviathan>() != (Object)null && (Object)(object)objectRbody != (Object)null && objectRbody.isKinematic) { temporarilyDynamicBody = objectRbody; objectRbody.isKinematic = false; } if ((Object)(object)hitObject.GetComponentInParent<RandomFlyingBird>() != (Object)null || (Object)(object)objectRbody == (Object)null || objectRbody.isKinematic || pullTo) { isPullingTo = true; } else if ((Object)(object)m_character != (Object)null && m_character.IsAttached()) { isPullingTo = true; } else if ((Object)(object)m_ship != (Object)null && m_ship.HaveControllingPlayer()) { isPullingTo = true; } else { Vagon componentInParent = hitObject.GetComponentInParent<Vagon>(); if (componentInParent != null && componentInParent.InUse()) { isPullingTo = true; } else if ((Object)(object)m_ship == (Object)null && objectMass > maxBodyMassToPull.Value) { isPullingTo = true; } else if ((Object)(object)hitObject.GetComponentInParent<ZSyncTransform>() == (Object)null || (Object)(object)m_nview == (Object)null) { isPullingTo = true; } else if (!m_nview.IsOwner()) { m_nview.ClaimOwnership(); } } if ((Object)(object)hitObject.GetComponent<ItemDrop>() != (Object)null) { m_pullSpeed = 100f; } noUpForce = (Object)(object)m_ship != (Object)null; if ((Object)(object)hitObject.GetComponentInParent<Leviathan>() != (Object)null) { m_minDistance = 20f; } else if ((Object)(object)m_ship != (Object)null) { m_minDistance = minDistanceShip.Value; } else if ((Object)(object)m_character != (Object)null) { m_minDistance = minDistanceCreature.Value; } else if ((Object)(object)hitObject.GetComponent<ItemDrop>() != (Object)null) { m_minDistance = minDistanceItem.Value; } else if (isPullingTo) { m_minDistance = minDistancePullToTarget.Value; } else { m_minDistance = minDistancePullToPlayer.Value; } GameObject prefab = connectionScene.GetPrefab("vfx_Harpooned"); if ((Object)(object)prefab == (Object)null) { DestroyHarpooned("Missing rope prefab"); return; } harpooned = Object.Instantiate<GameObject>(prefab, ((Component)attacker).transform.position, Quaternion.identity, hitObject.transform); m_line = harpooned.GetComponent<LineConnect>(); m_lineRenderer = harpooned.GetComponent<LineRenderer>(); ropeView = harpooned.GetComponent<ZNetView>(); if ((Object)(object)m_line == (Object)null || (Object)(object)m_lineRenderer == (Object)null || (Object)(object)ropeView == (Object)null || !ropeView.IsValid() || !ropeView.IsOwner()) { DestroyHarpooned("Missing rope components"); return; } ropeID = ropeView.GetZDO().m_uid; m_line.SetPeer(attackerView); m_line.m_maxDistance = m_maxDistance; m_line.m_dynamicThickness = true; m_line.m_minThickness = 0.04f; ((Component)m_lineRenderer).transform.position = hitPoint; ropeView.GetZDO().Set(HarpoonLine.VisualMarker, true); lineVisual = harpooned.AddComponent<HarpoonLine>(); if (!lineVisual.Initialize(m_line) || !ValidateConnection(out var _)) { DestroyHarpooned("Invalid initial rope state"); return; } if (applySlowFall.Value) { castSlowFall = true; } LogInfo($"Attacker: {((Character)attacker).m_name}, target: {((Object)hitObject).name}, name: {targetName}, mass: {objectMass}, pull to: {isPullingTo}"); HarpoonMessage("$msg_harpoon_harpooned"); } public static bool IsPullingTo() { return isPullingTo || (Object)(object)m_nview == (Object)null || !m_nview.IsOwner() || alwaysPullTo.Value; } public static Rigidbody RBody() { return IsPullingTo() ? attackerRbody : objectRbody; } public static float Mass() { return IsPullingTo() ? (attackerRbody.mass + ((Humanoid)m_attacker).GetInventory().GetTotalWeight() * containerInventoryWeightMassFactor.Value) : objectMass; } public static Vector3 TargetPosition() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) return IsPullingTo() ? ((Component)m_lineRenderer).transform.position : ((Component)m_attacker).transform.position; } public static float CalculateHitObjectMass(GameObject hitObject) { float num = 0f; Rigidbody[] componentsInChildren = hitObject.GetComponentsInChildren<Rigidbody>(); foreach (Rigidbody val in componentsInChildren) { num += val.mass; } if ((Object)(object)m_ship == (Object)null && (Object)(object)hitObject.GetComponent<Vagon>() == (Object)null) { Container[] componentsInChildren2 = hitObject.GetComponentsInChildren<Container>(); foreach (Container val2 in componentsInChildren2) { num += val2.GetInventory().GetTotalWeight() * containerInventoryWeightMassFactor.Value; } } ItemDrop val3 = default(ItemDrop); if (hitObject.TryGetComponent<ItemDrop>(ref val3)) { num += val3.m_itemData.GetWeight(-1) * containerInventoryWeightMassFactor.Value; } return num; } public void FixedUpdate() { if (!harpoonActive) { return; } try { UpdateHarpoonEffect(Time.fixedDeltaTime); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Harpoon update failed; releasing the rope. {arg}"); DestroyHarpooned("Update failed"); } } public static void UpdateHarpoonEffect(float dt) { //IL_0029: 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_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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) m_time += dt; if (IsDone()) { DestroyHarpooned("Harpooning ended"); return; } float num = Vector3.Distance(TargetPosition(), ((Component)RBody()).transform.position); if (!CheckDistance(num)) { return; } Vector3 position = ((Component)m_lineRenderer).transform.position; float num2 = (IsPullingTo() ? 1f : ((Mass() > 999f) ? 1f : ((!(Mass() <= 1f)) ? ((1f - 1f / Mathf.Sqrt(Mass())) * (RBody().mass / Mass()) * pullForceMultiplier.Value) : (0.05f * pullForceMultiplier.Value)))); float speed = ((((Character)m_attacker).IsAttachedToShip() && (Object)(object)m_ship != (Object)null) ? 10000f : m_pullSpeed); float num3 = Pull(RBody(), TargetPosition(), targetDistance, speed, num2, m_smoothDistance, IsPullingTo() ? Vector3.zero : position, (Object)(object)m_character != (Object)null, noUpForce, useForce.Value, forcePower.Value); m_drainStaminaTimer += dt; float num4 = 0f; if (m_drainStaminaTimer > m_staminaDrainInterval && num3 > 0f) { m_drainStaminaTimer = 0f; if (!attachedShipStamina.Value || IsPullingTo() || !((Character)m_attacker).IsAttachedToShip()) { num4 = m_staminaDrain * num3 * (IsPullingTo() ? 10f : ((Mass() > 999f) ? 20f : (10f + 20f * num2))); ((Character)m_attacker).UseStamina(num4); } } m_line.SetSlack((1f - Utils.LerpStep(targetDistance / 2f, targetDistance, num)) * m_maxLineSlack); if (deepLoggingEnabled.Value) { LogInfo($"dist: {num,-5:F3} targetDist: {targetDistance,-5:F3} force: {num2,-5:F3} dt: {num3,-5:F3} stam: {num4,-5:F3} break: {num - targetDistance,-5:F3} < {m_breakDistance}"); } if (!((Character)m_attacker).HaveStamina(0f)) { m_broken = true; HarpoonMessage("$msg_harpoon_released"); } if (IsDone()) { DestroyHarpooned(); } else if (targetPulling.Value && (KeyPressPullHarpoon() || KeyPressReleaseHarpoon()) && !KeyPressStopHarpoon()) { float num5 = (IsPullingTo() ? 4f : 2f); if (KeyPressReleaseHarpoon()) { targetDistance += num5 * dt * 2f * pullSpeedMultiplier.Value; } else if (KeyPressPullHarpoon()) { targetDistance -= num5 * dt * pullSpeedMultiplier.Value; } targetDistance = Mathf.Max(targetDistance, m_minDistance + 0.5f); } } public static float Pull(Rigidbody body, Vector3 target, float targetDistance, float speed, float force, float smoothDistance, Vector3 forcePoint, bool checkFreezeRotation = false, bool noUpForce = false, bool useForce = false, float power = 1f) { //IL_0001: 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) //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_0024: 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) //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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((forcePoint != Vector3.zero) ? Vector3.Lerp(body.position, forcePoint, 0.5f) : body.position); Vector3 val2 = target - val; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < targetDistance) { return 0f; } Vector3 normalized = ((Vector3)(ref val2)).normalized; float num = Mathf.Clamp01((magnitude - targetDistance) / smoothDistance); num = (float)Math.Pow(num, power); Vector3 val3 = Vector3.Project(body.linearVelocity, ((Vector3)(ref normalized)).normalized); Vector3 val4 = ((Vector3)(ref normalized)).normalized * speed - val3; if (noUpForce && val4.y > 0f) { val4.y = 0f; } ForceMode val5 = (ForceMode)(useForce ? 1 : 2); Vector3 val6 = val4 * num * Mathf.Clamp01(force); bool flag = checkFreezeRotation && body.freezeRotation; if (forcePoint != Vector3.zero) { if (flag) { RigidbodyConstraints constraints = body.constraints; body.freezeRotation = false; body.constraints = (RigidbodyConstraints)64; body.AddForceAtPosition(val6, val, val5); body.constraints = constraints; body.freezeRotation = true; } else { body.AddForceAtPosition(val6, val, val5); } } else { body.AddForce(val6, val5); } body.linearVelocity = Vector3.ClampMagnitude(body.linearVelocity, maximumVelocity.Value); return num; } public static void HarpoonMessage(string message) { if (messagesEnabled.Value && !string.IsNullOrEmpty(message) && !((Object)(object)m_attacker == (Object)null) && Localization.instance != null) { string text = (string.IsNullOrEmpty(targetName) ? message : (targetName + " " + message)); text = Localization.instance.Localize(text); if (text.Length > 1) { text = text.ToUpper().Substring(0, 1) + text.Substring(1); } ((Character)m_attacker).Message((MessageType)2, text, 0, (Sprite)null, false); } } public static bool IsDone() { //IL_017c: Unknown result type (might be due to invalid IL or missing references) if (m_broken) { return true; } if (!ValidateConnection(out var reason)) { LogInfo(reason); return true; } if (m_time > timeBeforeStop.Value && (KeyPressStopHarpoon() || ((Character)m_attacker).IsBlocking())) { HarpoonMessage("$msg_harpoon_released"); return true; } if (((Character)m_attacker).IsDead() || ((Character)m_attacker).IsTeleporting() || ((Character)m_attacker).InCutscene() || ((Character)m_attacker).IsEncumbered()) { return true; } if ((Object)(object)m_character != (Object)null && (m_character.IsDead() || m_character.IsTeleporting())) { return true; } if ((IsPullingTo() && ((Character)m_attacker).IsAttached()) || (!targetBosses.Value && (Object)(object)m_character != (Object)null && m_character.IsBoss()) || ((Object)(object)Ship.GetLocalShip() != (Object)null && (Object)(object)Ship.GetLocalShip() == (Object)(object)m_ship)) { ((Character)m_attacker).Message((MessageType)2, "$msg_wontwork", 0, (Sprite)null, false); return true; } if (IsPullingTo() && !pullUnderWater.Value && ((Object)(object)ZoneSystem.instance == (Object)null || TargetPosition().y < ZoneSystem.instance.m_waterLevel)) { ((Character)m_attacker).Message((MessageType)2, "$msg_wontwork", 0, (Sprite)null, false); return true; } return false; } private static string GetHarpoonedTargetName(GameObject hitObject, Collider collider) { HoverText val = default(HoverText); if (hitObject.TryGetComponent<HoverText>(ref val)) { return val.m_text; } ItemDrop val2 = default(ItemDrop); if (hitObject.TryGetComponent<ItemDrop>(ref val2)) { return val2.m_itemData.m_shared.m_name; } if ((Object)(object)hitObject.GetComponent<Location>() != (Object)null) { return "$piece_lorestone"; } ResourceRoot val3 = default(ResourceRoot); if (hitObject.TryGetComponent<ResourceRoot>(ref val3)) { return val3.m_name; } Piece val4 = default(Piece); if ((Object)(object)hitObject.GetComponent<Ship>() != (Object)null && hitObject.TryGetComponent<Piece>(ref val4)) { return val4.m_name; } if (!targetMessagesEnabled.Value) { return string.Empty; } Piece val5 = default(Piece); if (hitObject.TryGetComponent<Piece>(ref val5)) { return val5.m_name; } if ((Object)(object)collider != (Object)null && ((Object)collider).name.StartsWith("Terrain", StringComparison.Ordinal)) { return ((Object)collider).name; } string prefabName = Utils.GetPrefabName(hitObject); return string.IsNullOrEmpty(prefabName) ? string.Empty : (char.ToUpper(prefabName[0]) + prefabName.Substring(1)); } private static void OnTargetFilterChanged(object sender, EventArgs args) { RebuildTargetFilters(); } private static void RebuildTargetFilters() { ParsePrefabNames(targetWhitelist.Value, allowedPrefabs); ParsePrefabNames(targetBlacklist.Value, deniedPrefabs); } private static void ParsePrefabNames(string value, HashSet<string> result) { result.Clear(); string[] array = (value ?? string.Empty).Split(new char[4] { ',', ';', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length != 0) { result.Add(text2); } } } private static bool IsHarpoonProjectile(Projectile projectile) { return (Object)(object)projectile != (Object)null && ((Object)projectile).name.StartsWith("projectile_chitinharpoon", StringComparison.Ordinal); } private static bool IsRopeForbidden(GameObject target, Collider collider) { if ((Object)(object)target == (Object)null || (Object)(object)collider == (Object)null || (Object)(object)target.GetComponentInParent<GrapplingBlocker>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<GrapplingBlocker>() != (Object)null) { return true; } ZNetView componentInParent = target.GetComponentInParent<ZNetView>(); GameObject val = (((Object)(object)componentInParent != (Object)null && componentInParent.IsValid() && (Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(componentInParent.GetZDO().GetPrefab()) : null); string item = (((Object)(object)val != (Object)null) ? ((Object)val).name : Utils.GetPrefabName(((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).gameObject : target)); return deniedPrefabs.Contains(item) || (allowedPrefabs.Count != 0 && !allowedPrefabs.Contains(item)); } private static bool IsCustomTarget(GameObject target) { return targetGround.Value || (targetShip.Value && (Object)(object)target.GetComponentInParent<Ship>() != (Object)null) || (targetCreatures.Value && (Object)(object)target.GetComponentInParent<Character>() != (Object)null) || (targetTreeLog.Value && (Object)(object)target.GetComponentInParent<TreeLog>() != (Object)null) || (targetTreeBase.Value && (Object)(object)target.GetComponentInParent<TreeBase>() != (Object)null) || (targetPiece.Value && (Object)(object)target.GetComponentInParent<Piece>() != (Object)null) || (targetDestructibles.Value && ((Object)(object)target.GetComponentInParent<Destructible>() != (Object)null || (Object)(object)target.GetComponentInParent<MineRock>() != (Object)null || (Object)(object)target.GetComponentInParent<MineRock5>() != (Object)null)) || (targetFish.Value && (Object)(object)target.GetComponentInParent<Fish>() != (Object)null) || (targetLeviathan.Value && (Object)(object)target.GetComponentInParent<Leviathan>() != (Object)null) || (targetItems.Value && (Object)(object)target.GetComponentInParent<ItemDrop>() != (Object)null); } private static void ResetSlowFallState(bool removeEffect) { if (removeEffect && (Object)(object)slowFallPlayer != (Object)null) { SEMan sEMan = ((Character)slowFallPlayer).GetSEMan(); if (sEMan != null) { sEMan.RemoveStatusEffect(HarpoonSlowFall.EffectHash, true); } } slowFallPlayer = null; castSlowFall = false; slowFallCasted = false; onGroundTimer = 0f; } internal static bool IsFinite(float value) { return !float.IsNaN(value) && !float.IsInfinity(value); } internal static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return IsFinite(value.x) && IsFinite(value.y) && IsFinite(value.z); } internal static bool HasValidTransform(Transform value) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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) if ((Object)(object)value == (Object)null || !IsFinite(value.position)) { return false; } Quaternion rotation = value.rotation; Vector3 lossyScale = value.lossyScale; return IsFinite(rotation.x) && IsFinite(rotation.y) && IsFinite(rotation.z) && IsFinite(rotation.w) && IsFinite(lossyScale) && Mathf.Abs(lossyScale.x) > Mathf.Epsilon && Mathf.Abs(lossyScale.y) > Mathf.Epsilon && Mathf.Abs(lossyScale.z) > Mathf.Epsilon; } private static bool ValidateConnection(out string reason) { //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) reason = null; if (!harpoonActive || (Object)(object)connectionScene == (Object)null || (Object)(object)connectionScene != (Object)(object)ZNetScene.instance) { reason = "Harpoon scene is no longer available"; } else if ((Object)(object)m_attacker == (Object)null || (Object)(object)m_attacker != (Object)(object)Player.m_localPlayer || !((Component)m_attacker).gameObject.activeInHierarchy || (Object)(object)attackerView == (Object)null || !attackerView.IsValid() || !attackerView.IsOwner()) { reason = "Harpoon attacker is no longer available"; } else if ((Object)(object)targetHarpooned == (Object)null || !targetHarpooned.activeInHierarchy || (Object)(object)targetCollider == (Object)null || !targetCollider.enabled) { reason = "Harpoon target or hit collider is no longer available"; } else if (hadTargetView && ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())) { reason = "Harpoon target network view was lost"; } else if ((hadTargetBody && (Object)(object)objectRbody == (Object)null) || (hadTargetCharacter && (Object)(object)m_character == (Object)null)) { reason = "Harpoon target component was destroyed"; } else if ((Object)(object)harpooned == (Object)null || !harpooned.activeInHierarchy || (Object)(object)m_line == (Object)null || (Object)(object)m_lineRenderer == (Object)null || (Object)(object)lineVisual == (Object)null) { reason = "Harpoon line component was destroyed"; } else if ((Object)(object)ropeView == (Object)null || !ropeView.IsValid() || !ropeView.IsOwner() || (Object)(object)m_line.m_nview != (Object)(object)ropeView || ropeView.GetZDO().m_uid != ropeID) { reason = "Harpoon line network state was lost"; } else if ((Object)(object)harpooned.transform.parent != (Object)(object)targetHarpooned.transform || !((Behaviour)m_line).isActiveAndEnabled || !lineVisual.IsValid()) { reason = "Harpoon line attachment or visual state was lost"; } else if (!HasValidTransform(targetHarpooned.transform) || !HasValidTransform(((Component)m_attacker).transform) || !HasValidTransform(harpooned.transform)) { reason = "Harpoon participant transform is invalid"; } else if ((Object)(object)attackerRbody == (Object)null || !IsFinite(attackerRbody.position) || !IsFinite(attackerRbody.linearVelocity)) { reason = "Harpoon attacker body is invalid"; } else if ((Object)(object)RBody() == (Object)null || RBody().isKinematic || !((Component)RBody()).gameObject.activeInHierarchy || !IsFinite(RBody().position) || !IsFinite(RBody().linearVelocity) || !IsFinite(RBody().angularVelocity) || !HasValidTransform(((Component)RBody()).transform) || !IsFinite(RBody().mass) || RBody().mass <= 0f) { reason = "Harpoon moved body is invalid"; } else if (!IsFinite(targetDistance) || targetDistance <= 0f || !IsFinite(m_minDistance) || m_minDistance < 0f || !IsFinite(m_breakDistance) || m_breakDistance < 0f || !IsFinite(m_maxDistance) || m_maxDistance <= 0f) { reason = "Harpoon distance parameters are invalid"; } else if (!IsFinite(m_smoothDistance) || m_smoothDistance <= 0f || !IsFinite(m_pullSpeed) || !IsFinite(m_staminaDrain) || !IsFinite(objectMass) || !IsFinite(Mass()) || !IsFinite(m_maxLineSlack)) { reason = "Harpoon force parameters are invalid"; } else if (!IsFinite(pullForceMultiplier.Value) || !IsFinite(forcePower.Value) || forcePower.Value < 0f || !IsFinite(maximumVelocity.Value) || maximumVelocity.Value < 0f || !IsFinite(pullSpeedMultiplier.Value)) { reason = "Harpoon live force settings are invalid"; } return reason == null; } private static bool CheckDistance(float distance) { if (!IsFinite(distance)) { DestroyHarpooned("Invalid distance"); return false; } if (distance < m_minDistance) { HarpoonMessage("$msg_harpoon_released"); DestroyHarpooned("Too close"); return false; } if (distance - targetDistance > m_breakDistance) { HarpoonMessage("$msg_harpoon_linebroke"); DestroyHarpooned("Line broke"); return false; } return true; } internal static void LogVisualFailure(Exception exception) { if ((Object)(object)instance != (Object)null) { ((BaseUnityPlugin)instance).Logger.LogError((object)$"Harpoon rendering failed; releasing the rope. {exception}"); } } internal static bool IsLocalLine(HarpoonLine line) { return harpoonActive && lineVisual == line; } internal static bool ValidateLineBeforeRendering(HarpoonLine line) { //IL_002b: 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 (!IsLocalLine(line)) { return false; } if (IsDone()) { DestroyHarpooned("Invalid state before rendering"); return false; } return CheckDistance(Vector3.Distance(TargetPosition(), ((Component)RBody()).transform.position)); } internal static void OnLineDestroyed(HarpoonLine line) { if (IsLocalLine(line)) { DestroyHarpooned("Line destroyed or disabled"); } } public static void DestroyHarpooned(string logEntry = "") { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) if (destroyingHarpoon) { return; } destroyingHarpoon = true; GameObject val = harpooned; ZNetScene val2 = connectionScene; ZDOID val3 = ropeID; Rigidbody val4 = temporarilyDynamicBody; bool flag = false; harpoonActive = false; harpooned = null; lineVisual = null; ropeView = null; ropeID = ZDOID.None; connectionScene = null; m_line = null; m_lineRenderer = null; targetHarpooned = null; targetCollider = null; m_attacker = null; attackerView = null; attackerRbody = null; objectRbody = null; m_nview = null; m_ship = null; m_character = null; temporarilyDynamicBody = null; hadTargetView = false; hadTargetBody = false; hadTargetCharacter = false; m_broken = false; m_time = 0f; m_drainStaminaTimer = 0f; targetName = string.Empty; targetDistance = 999999f; objectMass = 0f; noUpForce = false; isPullingTo = false; try { LogInfo(logEntry); if ((Object)(object)val4 != (Object)null) { val4.isKinematic = true; } if ((Object)(object)val != (Object)null) { LineRenderer component = val.GetComponent<LineRenderer>(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = false; } LineConnect component2 = val.GetComponent<LineConnect>(); if ((Object)(object)component2 != (Object)null) { ((Behaviour)component2).enabled = false; } if ((Object)(object)val2 != (Object)null && (Object)(object)val2 == (Object)(object)ZNetScene.instance && ZDOMan.instance != null) { ZNetView component3 = val.GetComponent<ZNetView>(); flag = (Object)(object)component3 != (Object)null && component3.IsValid() && component3.GetZDO().m_uid == val3; val2.Destroy(val); } else { Object.Destroy((Object)(object)val); } } if (!flag && (Object)(object)val2 != (Object)null && (Object)(object)val2 == (Object)(object)ZNetScene.instance && !((ZDOID)(ref val3)).IsNone() && ZDOMan.instance != null) { ZDO zDO = ZDOMan.instance.GetZDO(val3); if (zDO != null && zDO.IsOwner()) { ZDOMan.instance.DestroyZDO(zDO); } } } catch (Exception arg) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } if ((Object)(object)instance != (Object)null) { ((BaseUnityPlugin)instance).Logger.LogError((object)$"Harpoon cleanup failed after clearing the connection state. {arg}"); } } finally { destroyingHarpoon = false; } } } internal static class HarpoonSlowFall { internal const string EffectName = "HarpoonExtendedSlowFall"; internal static readonly int EffectHash = StringExtensionMethods.GetStableHashCode("HarpoonExtendedSlowFall"); private static readonly int sourceHash = StringExtensionMethods.GetStableHashCode("SlowFall"); private static SE_Stats template; internal static void Register(ObjectDB db) { if ((Object)(object)db == (Object)null || (Object)(object)db.GetStatusEffect(EffectHash) != (Object)null) { return; } if ((Object)(object)template == (Object)null) { StatusEffect statusEffect = db.GetStatusEffect(sourceHash); SE_Stats val = (SE_Stats)(object)((statusEffect is SE_Stats) ? statusEffect : null); if ((Object)(object)val == (Object)null) { return; } template = Object.Instantiate<SE_Stats>(val); ((Object)template).name = "HarpoonExtendedSlowFall"; ((StatusEffect)template).m_nameHash = 0; } db.m_StatusEffects.Add((StatusEffect)(object)template); } internal static void Apply(Player player, float speed, float damageMultiplier) { SEMan sEMan = ((Character)player).GetSEMan(); if (!sEMan.HaveStatusEffect(EffectHash)) { Register(ObjectDB.instance); StatusEffect obj = sEMan.AddStatusEffect(EffectHash, false, 0, 0f, (short)(-1)); SE_Stats val = (SE_Stats)(object)((obj is SE_Stats) ? obj : null); if (val != null) { val.m_maxMaxFallSpeed = (HarpoonExtended.IsFinite(speed) ? Mathf.Max(0f, speed) : 5f); val.m_fallDamageModifier = (HarpoonExtended.IsFinite(damageMultiplier) ? Mathf.Max(0f, damageMultiplier) : 0f) - 1f; } } } } public sealed class HarpoonLine : MonoBehaviour { [HarmonyPatch(typeof(LineConnect), "LateUpdate")] public static class LineConnect_LateUpdate_HarpoonHand { private static bool Prefix(LineConnect __instance) { HarpoonLine harpoonLine = default(HarpoonLine); if (((Component)__instance).TryGetComponent<HarpoonLine>(ref harpoonLine)) { return false; } ZNetView nview = __instance.m_nview; if ((Object)(object)nview == (Object)null || !nview.IsValid() || !nview.GetZDO().GetBool(VisualMarker, false)) { return true; } harpoonLine = ((Component)__instance).gameObject.AddComponent<HarpoonLine>(); if (!harpoonLine.Initialize(__instance)) { harpoonLine.Retire(); } return false; } } internal static readonly int VisualMarker = StringExtensionMethods.GetStableHashCode("shudnal.HarpoonExtended.line"); private LineConnect line; private LineRenderer lineRenderer; private ZNetView view; private ZNetView peerView; private Player peer; private Transform hand; private ZDOID peerID; private bool retired; internal bool Initialize(LineConnect connector) { //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_00a4: Unknown result type (might be due to invalid IL or missing references) line = connector; if ((Object)(object)line == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return false; } lineRenderer = ((Component)line).GetComponent<LineRenderer>(); view = line.m_nview; if ((Object)(object)view == (Object)null || !view.IsValid()) { return false; } peerID = view.GetZDO().GetZDOID(line.m_linePeerID); GameObject val = ZNetScene.instance.FindInstance(peerID); if ((Object)(object)val == (Object)null) { return false; } peer = val.GetComponent<Player>(); peerView = val.GetComponent<ZNetView>(); if ((Object)(object)peer == (Object)null) { return false; } VisEquipment visEquipment = ((Humanoid)peer).GetVisEquipment(); hand = (((Object)(object)visEquipment != (Object)null) ? visEquipment.m_leftHand : null); return IsValid(); } internal bool IsValid() { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) return !retired && (Object)(object)line != (Object)null && ((Behaviour)line).isActiveAndEnabled && (Object)(object)lineRenderer != (Object)null && lineRenderer.positionCount >= 2 && !lineRenderer.useWorldSpace && (Object)(object)((Renderer)lineRenderer).sharedMaterial != (Object)null && (Object)(object)view != (Object)null && view.IsValid() && (Object)(object)peer != (Object)null && ((Component)peer).gameObject.activeInHierarchy && (Object)(object)peerView != (Object)null && peerView.IsValid() && peerView.GetZDO().m_uid == peerID && view.GetZDO().GetZDOID(line.m_linePeerID) == peerID && (Object)(object)hand != (Object)null && ((Component)hand).gameObject.activeInHierarchy && HarpoonExtended.HasValidTransform(hand) && HarpoonExtended.HasValidTransform(((Component)this).transform) && HarpoonExtended.IsFinite(lineRenderer.GetPosition(0)) && HarpoonExtended.IsFinite(line.m_minDistance) && HarpoonExtended.IsFinite(line.m_maxDistance) && (!line.m_dynamicThickness || line.m_minDistance != line.m_maxDistance); } private void LateUpdate() { if (retired) { return; } try { Render(); } catch (Exception exception) { HarpoonExtended.LogVisualFailure(exception); Retire(); } } private void Render() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!IsValid()) { Retire(); return; } if (view.IsOwner() && !HarpoonExtended.ValidateLineBeforeRendering(this)) { Retire(); return; } line.SetEndpoint(hand.position); ((Renderer)lineRenderer).enabled = true; } private void Retire() { if (retired) { return; } retired = true; if (HarpoonExtended.IsLocalLine(this)) { HarpoonExtended.DestroyHarpooned("Missing rope rendering state"); return; } if ((Object)(object)lineRenderer != (Object)null) { ((Renderer)lineRenderer).enabled = false; } if ((Object)(object)line != (Object)null) { ((Behaviour)line).enabled = false; } if ((Object)(object)ZNetScene.instance != (Object)null) { ZNetScene.instance.Destroy(((Component)this).gameObject); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void OnDisable() { HarpoonExtended.OnLineDestroyed(this); } private void OnDestroy() { HarpoonExtended.OnLineDestroyed(this); } }