using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn.Configs; using Jotunn.Managers; using UnityEngine; using UnityEngine.Animations; using UnityEngine.Playables; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("ShieldBash")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ShieldBash")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("be1580d5-2dda-4cf4-b5c8-d4f902314e67")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")] [assembly: AssemblyVersion("1.0.0.0")] namespace ShieldBashMod; [BepInPlugin("mexanik.shieldbash", "ShieldBash", "1.5.5")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class ShieldBashPlugin : BaseUnityPlugin { [HarmonyPatch(typeof(Player), "Awake")] private static class PlayerAwakePatch { private static void Postfix(Player __instance) { ShieldBashPlugin instance = Instance; if (!((Object)(object)instance == (Object)null)) { instance.RegisterPlayerRpc(__instance); } } } [HarmonyPatch] private static class ShieldTooltipPatch { private static IEnumerable TargetMethods() { MethodInfo[] methods = typeof(ItemData).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo method in methods) { if (method != null && method.Name == "GetTooltip" && method.ReturnType == typeof(string)) { yield return method; } } } private static void Postfix(ItemData __instance, ref string __result) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Invalid comparison between Unknown and I4 try { ShieldBashPlugin instance = Instance; if ((Object)(object)instance == (Object)null || !instance.ShowShieldBashInTooltip.Value || __instance == null || __instance.m_shared == null || (int)__instance.m_shared.m_itemType != 5) { return; } string text = __result ?? string.Empty; if (text.IndexOf("Shield Bash:", StringComparison.Ordinal) < 0 && text.IndexOf("Удар щитом:", StringComparison.Ordinal) < 0) { string text2 = instance.BuildTooltipLineForShield(__instance); if (!string.IsNullOrEmpty(text2)) { __result = text + text2; } } } catch (Exception ex) { ShieldBashPlugin instance2 = Instance; if ((Object)(object)instance2 != (Object)null && instance2.DebugLog != null && instance2.DebugLog.Value) { ((BaseUnityPlugin)instance2).Logger.LogWarning((object)("[ShieldBash] Tooltip patch error: " + ex.Message)); } } } } public const string PluginGUID = "mexanik.shieldbash"; public const string PluginName = "ShieldBash"; public const string PluginVersion = "1.5.5"; private const string InputName = "ShieldBash_Bash"; private const string RpcPlayBashVisual = "ShieldBash_PlayVisual"; internal static ShieldBashPlugin Instance; internal ConfigEntry BashKey; internal ConfigEntry Cooldown; internal ConfigEntry RequireShield; internal ConfigEntry BaseStaminaCost; internal ConfigEntry BlockPowerStaminaScale; internal ConfigEntry SkillStaminaReduction; internal ConfigEntry MinStaminaCost; internal ConfigEntry MaxStaminaCost; internal ConfigEntry AntiSlideTime; internal ConfigEntry BaseDamage; internal ConfigEntry BlockPowerScale; internal ConfigEntry QualityBonusPerLevel; internal ConfigEntry MinDamage; internal ConfigEntry MaxDamage; internal ConfigEntry BlockingSkillMultiplier; internal ConfigEntry DamageRandomMin; internal ConfigEntry DamageRandomMax; internal ConfigEntry HitDelay; internal ConfigEntry DamageWorldObjects; internal ConfigEntry WorldDamageScale; internal ConfigEntry WorldDamageUseRandom; internal ConfigEntry Range; internal ConfigEntry Radius; internal ConfigEntry PushForce; internal ConfigEntry Angle; internal ConfigEntry LineOfSightCheck; internal ConfigEntry MaxLoSRaycastsPerBash; internal ConfigEntry HitTamed; internal ConfigEntry HitPlayers; internal ConfigEntry OverlapBufferSize; internal ConfigEntry ShowShieldBashInTooltip; internal ConfigEntry DebugLog; internal ConfigEntry DebugLogDamageAfterArmor; internal ConfigEntry HitClipName; internal ConfigEntry MissClipName; internal ConfigEntry PlayHitSfxPerTarget; internal ConfigEntry HitSfxVolumeMin; internal ConfigEntry HitSfxVolumeMax; internal ConfigEntry MissSfxVolume; internal ConfigEntry RandomVolJitterMin; internal ConfigEntry RandomVolJitterMax; internal ConfigEntry RandomPitchJitterMin; internal ConfigEntry RandomPitchJitterMax; internal ConfigEntry MetalVolumeMul; internal ConfigEntry WoodVolumeMul; internal ConfigEntry MetalPitchMul; internal ConfigEntry WoodPitchMul; internal ConfigEntry MultiHitBonusMin; internal ConfigEntry MultiHitBonusMax; internal ConfigEntry LocalClipVolumeMul; private ButtonConfig _bashButton; private Harmony _harmony; private AnimationClip _bashClip; private AudioClip _hitClip; private AudioClip _missClip; private float _nextUseTime; private bool _isBashing; private Collider[] _overlapCols; private int[] _hitOnceIds; private int _hitOnceCount; private int _overlapMask = -1; private int _losWorldMask = -1; private float _cachedAngle = -999f; private float _cachedCosHalf = -2f; private AudioSource _localSfxSource; private static bool _locRefReady; private static Type _locType; private static PropertyInfo _locInstanceProp; private static MethodInfo _locGetSelectedLanguage; private static readonly FieldInfo CharacterAnimatorField = AccessTools.Field(typeof(Character), "m_animator"); private static readonly FieldInfo CharacterBodyField = AccessTools.Field(typeof(Character), "m_body"); private static readonly FieldInfo CharacterMoveDirField = AccessTools.Field(typeof(Character), "m_moveDir"); private static readonly FieldInfo HumanoidLeftItemField = AccessTools.Field(typeof(Humanoid), "m_leftItem"); private static readonly FieldInfo CharacterNViewField = AccessTools.Field(typeof(Character), "m_nview"); private void Awake() { //IL_0710: Unknown result type (might be due to invalid IL or missing references) //IL_071a: Expected O, but got Unknown //IL_078b: Unknown result type (might be due to invalid IL or missing references) //IL_0795: Expected O, but got Unknown Instance = this; BashKey = ((BaseUnityPlugin)this).Config.Bind("Input", "BashKey", (KeyCode)102, "Key for Shield Bash"); Cooldown = ((BaseUnityPlugin)this).Config.Bind("Balance", "Cooldown", 0.9f, "Cooldown seconds"); RequireShield = ((BaseUnityPlugin)this).Config.Bind("Balance", "RequireShield", true, "Require shield in left hand"); BaseStaminaCost = ((BaseUnityPlugin)this).Config.Bind("Stamina", "BaseStaminaCost", 10f, "Base stamina cost of Shield Bash"); BlockPowerStaminaScale = ((BaseUnityPlugin)this).Config.Bind("Stamina", "BlockPowerStaminaScale", 0.08f, "Additional stamina cost per point of shield block power"); SkillStaminaReduction = ((BaseUnityPlugin)this).Config.Bind("Stamina", "SkillStaminaReduction", 0.25f, "Maximum stamina cost reduction at Blocking skill 100"); MinStaminaCost = ((BaseUnityPlugin)this).Config.Bind("Stamina", "MinStaminaCost", 8f, "Minimum stamina cost of Shield Bash"); MaxStaminaCost = ((BaseUnityPlugin)this).Config.Bind("Stamina", "MaxStaminaCost", 18f, "Maximum stamina cost of Shield Bash"); AntiSlideTime = ((BaseUnityPlugin)this).Config.Bind("Feel", "AntiSlideTime", 0.2f, "Anti-slide duration seconds (0 = off)"); BaseDamage = ((BaseUnityPlugin)this).Config.Bind("Damage", "BaseDamage", 4f, "Flat blunt damage added to bash"); BlockPowerScale = ((BaseUnityPlugin)this).Config.Bind("Damage", "BlockPowerScale", 0.16f, "Damage per 1 shield block power"); QualityBonusPerLevel = ((BaseUnityPlugin)this).Config.Bind("Damage", "QualityBonusPerLevel", 0.4f, "Bonus damage per shield upgrade level (quality-1)"); MinDamage = ((BaseUnityPlugin)this).Config.Bind("Damage", "MinDamage", 3f, "Minimum final damage"); MaxDamage = ((BaseUnityPlugin)this).Config.Bind("Damage", "MaxDamage", 20f, "Maximum final damage cap"); BlockingSkillMultiplier = ((BaseUnityPlugin)this).Config.Bind("Damage", "BlockingSkillMultiplier", 0.3f, "At Blocking skill 100, damage is increased by 30 percent"); DamageRandomMin = ((BaseUnityPlugin)this).Config.Bind("Damage", "DamageRandomMin", 0.92f, "Per-bash random damage multiplier min."); DamageRandomMax = ((BaseUnityPlugin)this).Config.Bind("Damage", "DamageRandomMax", 1.05f, "Per-bash random damage multiplier max."); HitDelay = ((BaseUnityPlugin)this).Config.Bind("Damage", "HitDelay", 0.12f, "Seconds after animation start when damage is applied"); DamageWorldObjects = ((BaseUnityPlugin)this).Config.Bind("WorldDamage", "DamageWorldObjects", true, "Allow Shield Bash to damage trees/rocks/buildings."); WorldDamageScale = ((BaseUnityPlugin)this).Config.Bind("WorldDamage", "WorldDamageScale", 0.85f, "Multiplier for world-object damage."); WorldDamageUseRandom = ((BaseUnityPlugin)this).Config.Bind("WorldDamage", "WorldDamageUseRandom", false, "If true: world damage uses per-bash random multiplier."); Range = ((BaseUnityPlugin)this).Config.Bind("Hitbox", "Range", 1.6f, "Forward distance of hit center"); Radius = ((BaseUnityPlugin)this).Config.Bind("Hitbox", "Radius", 0.9f, "Hit radius"); PushForce = ((BaseUnityPlugin)this).Config.Bind("Hitbox", "PushForce", 20f, "Push force applied to Characters"); Angle = ((BaseUnityPlugin)this).Config.Bind("Hitbox", "AngleDegrees", 110f, "Cone angle filter (degrees). 180 = no cone."); LineOfSightCheck = ((BaseUnityPlugin)this).Config.Bind("Hitbox", "LineOfSightCheck", true, "Raycast visibility check (avoid hitting through walls)"); MaxLoSRaycastsPerBash = ((BaseUnityPlugin)this).Config.Bind("Hitbox", "MaxLoSRaycastsPerBash", 6, "Max LoS raycasts per bash (CPU saver)."); HitTamed = ((BaseUnityPlugin)this).Config.Bind("Targets", "HitTamed", false, "Hit tamed creatures"); HitPlayers = ((BaseUnityPlugin)this).Config.Bind("Targets", "HitPlayers", false, "Hit other players (PvP)"); OverlapBufferSize = ((BaseUnityPlugin)this).Config.Bind("Performance", "OverlapBufferSize", 64, "NonAlloc overlap collider buffer size (64/96/128)"); ShowShieldBashInTooltip = ((BaseUnityPlugin)this).Config.Bind("UI", "ShowShieldBashInTooltip", true, "Add Shield Bash damage line to shield tooltip (RU/EN)"); DebugLog = ((BaseUnityPlugin)this).Config.Bind("Debug", "Log", false, "General debug logging"); DebugLogDamageAfterArmor = ((BaseUnityPlugin)this).Config.Bind("Debug", "LogDamageAfterArmor", false, "Log dealt damage per hit target"); HitClipName = ((BaseUnityPlugin)this).Config.Bind("SFX", "HitClipName", "shield_bash_hit", "AudioClip.name inside AssetBundle for HIT sound."); MissClipName = ((BaseUnityPlugin)this).Config.Bind("SFX", "MissClipName", "shield_bash_miss", "AudioClip.name inside AssetBundle for MISS sound."); PlayHitSfxPerTarget = ((BaseUnityPlugin)this).Config.Bind("SFX", "PlayHitSfxPerTarget", false, "If true: play hit sound for each target."); HitSfxVolumeMin = ((BaseUnityPlugin)this).Config.Bind("SFX", "HitSfxVolumeMin", 0.6f, "Min hit volume at MinDamage."); HitSfxVolumeMax = ((BaseUnityPlugin)this).Config.Bind("SFX", "HitSfxVolumeMax", 1.1f, "Max hit volume at MaxDamage."); MissSfxVolume = ((BaseUnityPlugin)this).Config.Bind("SFX", "MissSfxVolume", 0.7f, "Base miss whoosh volume."); RandomVolJitterMin = ((BaseUnityPlugin)this).Config.Bind("SFX", "RandomVolJitterMin", 0.95f, "Random volume multiplier min."); RandomVolJitterMax = ((BaseUnityPlugin)this).Config.Bind("SFX", "RandomVolJitterMax", 1.05f, "Random volume multiplier max."); RandomPitchJitterMin = ((BaseUnityPlugin)this).Config.Bind("SFX", "RandomPitchJitterMin", 0.97f, "Random pitch multiplier min."); RandomPitchJitterMax = ((BaseUnityPlugin)this).Config.Bind("SFX", "RandomPitchJitterMax", 1.03f, "Random pitch multiplier max."); MetalVolumeMul = ((BaseUnityPlugin)this).Config.Bind("SFX", "MetalVolumeMul", 1.07f, "Volume multiplier for metal shields."); WoodVolumeMul = ((BaseUnityPlugin)this).Config.Bind("SFX", "WoodVolumeMul", 0.92f, "Volume multiplier for wood shields."); MetalPitchMul = ((BaseUnityPlugin)this).Config.Bind("SFX", "MetalPitchMul", 1.02f, "Pitch multiplier for metal shields."); WoodPitchMul = ((BaseUnityPlugin)this).Config.Bind("SFX", "WoodPitchMul", 0.96f, "Pitch multiplier for wood shields."); MultiHitBonusMin = ((BaseUnityPlugin)this).Config.Bind("SFX", "MultiHitBonusMin", 0.05f, "Bonus volume add when hits>1, min."); MultiHitBonusMax = ((BaseUnityPlugin)this).Config.Bind("SFX", "MultiHitBonusMax", 0.1f, "Bonus volume add when hits>1, max."); LocalClipVolumeMul = ((BaseUnityPlugin)this).Config.Bind("SFX", "LocalClipVolumeMul", 1f, "Multiplier for local AudioClips."); _bashButton = new ButtonConfig(); _bashButton.Name = "ShieldBash_Bash"; _bashButton.Config = BashKey; _bashButton.HintToken = "Shield Bash"; _bashButton.ActiveInGUI = false; _bashButton.ActiveInCustomGUI = false; InputManager.Instance.AddButton("mexanik.shieldbash", _bashButton); EnsureBuffers(); _harmony = new Harmony("mexanik.shieldbash"); _harmony.PatchAll(); bool flag = LoadAssetsFromBundle(); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] Assets loaded: {1} (anim={2}, hit={3}, miss={4})", "ShieldBash", flag, ((Object)(object)_bashClip != (Object)null) ? ((Object)_bashClip).name : "null", ((Object)(object)_hitClip != (Object)null) ? ((Object)_hitClip).name : "null", ((Object)(object)_missClip != (Object)null) ? ((Object)_missClip).name : "null")); } private void OnDestroy() { try { if (_harmony != null) { _harmony.UnpatchSelf(); } } catch { } try { if ((Object)(object)_localSfxSource != (Object)null && (Object)(object)((Component)_localSfxSource).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)_localSfxSource).gameObject); } } catch { } } private void EnsureBuffers() { int num = Mathf.Clamp(OverlapBufferSize.Value, 16, 256); if (_overlapCols == null) { _overlapCols = (Collider[])(object)new Collider[num]; } else if (_overlapCols.Length != num) { _overlapCols = (Collider[])(object)new Collider[num]; } int num2 = Mathf.Clamp(num * 2, 32, 1024); if (_hitOnceIds == null) { _hitOnceIds = new int[num2]; } else if (_hitOnceIds.Length != num2) { _hitOnceIds = new int[num2]; } _hitOnceCount = 0; } private void Update() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Invalid comparison between Unknown and I4 if (ZInput.instance == null || !ZInput.GetButtonDown(_bashButton.Name)) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || _isBashing || Time.time < _nextUseTime) { return; } if ((Object)(object)_bashClip == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[ShieldBash] Bash clip is null. Bundle/clip not loaded."); return; } ItemData leftItem = GetLeftItem((Humanoid)localPlayer); if (RequireShield.Value && (leftItem == null || leftItem.m_shared == null || (int)leftItem.m_shared.m_itemType != 5)) { return; } float cost = ComputeStaminaCost(localPlayer, leftItem); if (TryUseStaminaNoMessage(localPlayer, cost)) { Animator animator = GetAnimator((Character)localPlayer); if (!((Object)(object)animator == (Object)null)) { EnsureBuffers(); _nextUseTime = Time.time + Cooldown.Value; ((MonoBehaviour)this).StartCoroutine(DoBash(localPlayer, animator, _bashClip, applyDamage: true)); BroadcastBashVisual(localPlayer); } } } private IEnumerator DoBash(Player player, Animator animator, AnimationClip clip, bool applyDamage) { if (applyDamage) { _isBashing = true; } bool prevRootMotion = animator.applyRootMotion; PlayableGraph graph = default(PlayableGraph); try { if (AntiSlideTime.Value > 0.0001f) { ((MonoBehaviour)this).StartCoroutine(AntiSlideRoutine(player, AntiSlideTime.Value)); } animator.applyRootMotion = false; graph = PlayableGraph.Create("ShieldBashGraph"); AnimatorControllerPlayable controllerPlayable = AnimatorControllerPlayable.Create(graph, animator.runtimeAnimatorController); AnimationClipPlayable clipPlayable = AnimationClipPlayable.Create(graph, clip); ((AnimationClipPlayable)(ref clipPlayable)).SetApplyFootIK(false); ((AnimationClipPlayable)(ref clipPlayable)).SetApplyPlayableIK(false); AnimationLayerMixerPlayable mixer = AnimationLayerMixerPlayable.Create(graph, 2); ((PlayableGraph)(ref graph)).Connect(controllerPlayable, 0, mixer, 0); ((PlayableGraph)(ref graph)).Connect(clipPlayable, 0, mixer, 1); PlayableExtensions.SetInputWeight(mixer, 0, 0f); PlayableExtensions.SetInputWeight(mixer, 1, 1f); AnimationPlayableOutput output = AnimationPlayableOutput.Create(graph, "ShieldBashOutput", animator); PlayableOutputExtensions.SetSourcePlayable(output, mixer); ((PlayableGraph)(ref graph)).Play(); float hitAt = Mathf.Clamp(HitDelay.Value, 0.01f, Mathf.Max(0.01f, clip.length)); yield return (object)new WaitForSeconds(hitAt); if ((Object)(object)player != (Object)null) { if (applyDamage) { ApplyBashDamageAndSfx(player); } else { PlayRemoteBashSfx(player); } } float remain = Mathf.Max(0.01f, clip.length - hitAt); yield return (object)new WaitForSeconds(remain); } finally { if (((PlayableGraph)(ref graph)).IsValid()) { ((PlayableGraph)(ref graph)).Destroy(); } if ((Object)(object)animator != (Object)null) { animator.applyRootMotion = prevRootMotion; } if (applyDamage) { _isBashing = false; } } } private void BroadcastBashVisual(Player player) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown ZNetView zNetView = GetZNetView((Character)player); if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid() || !zNetView.IsOwner()) { return; } try { zNetView.InvokeRPC(ZNetView.Everybody, "ShieldBash_PlayVisual", Array.Empty()); } catch (Exception ex) { if (DebugLog != null && DebugLog.Value) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] RPC send failed: " + ex.Message)); } } } internal void RegisterPlayerRpc(Player player) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown if ((Object)(object)player == (Object)null) { return; } ZNetView zNetView = GetZNetView((Character)player); if ((Object)(object)zNetView == (Object)null || !zNetView.IsValid()) { return; } try { zNetView.Register("ShieldBash_PlayVisual", (Action)delegate(long sender) { RpcPlayRemoteBashVisual(player, sender); }); } catch { } } private void RpcPlayRemoteBashVisual(Player player, long sender) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if ((Object)(object)player == (Object)null) { return; } ZNetView zNetView = GetZNetView((Character)player); if (!((Object)(object)zNetView == (Object)null) && zNetView.IsValid() && !zNetView.IsOwner() && !((Object)(object)_bashClip == (Object)null)) { Animator animator = GetAnimator((Character)player); if (!((Object)(object)animator == (Object)null)) { ((MonoBehaviour)this).StartCoroutine(DoBash(player, animator, _bashClip, applyDamage: false)); } } } private void PlayRemoteBashSfx(Player player) { //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) //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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { Vector3 pos = ((Component)player).transform.position + ((Component)player).transform.forward * 0.6f + Vector3.up * 1f; PlayLocalMissAt(player, pos, Mathf.Max(0f, MissSfxVolume.Value), 1f); } } private IEnumerator AntiSlideRoutine(Player player, float duration) { if ((Object)(object)player == (Object)null) { yield break; } Rigidbody body; try { body = GetCharacterBody((Character)(object)player); } catch { body = null; } if (!((Object)(object)body == (Object)null) && !body.isKinematic) { float t = 0f; SetMoveDirZero(player); body.linearVelocity = Vector3.zero; while (t < duration && !((Object)(object)player == (Object)null) && !((Object)(object)body == (Object)null)) { Vector3 v = body.linearVelocity; v.x = 0f; v.z = 0f; body.linearVelocity = v; SetMoveDirZero(player); t += Time.deltaTime; yield return null; } } } private static void SetMoveDirZero(Player player) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || CharacterMoveDirField == null) { return; } try { CharacterMoveDirField.SetValue(player, Vector3.zero); } catch { } } private float ComputeStaminaCost(Player player, ItemData shield) { float num = 0f; if (shield != null && shield.m_shared != null) { int num2 = Mathf.Max(1, shield.m_quality); num = shield.m_shared.m_blockPower + shield.m_shared.m_blockPowerPerLevel * (float)(num2 - 1); } float blockingSkillFactor = GetBlockingSkillFactor(player); float num3 = Mathf.Max(0f, BaseStaminaCost.Value) + num * Mathf.Max(0f, BlockPowerStaminaScale.Value); float num4 = blockingSkillFactor * Mathf.Clamp01(SkillStaminaReduction.Value); float num5 = num3 * (1f - num4); float num6 = Mathf.Max(0f, MinStaminaCost.Value); float num7 = Mathf.Max(num6, MaxStaminaCost.Value); return Mathf.Clamp(num5, num6, num7); } private bool TryUseStaminaNoMessage(Player player, float cost) { if (cost <= 0f) { return true; } if (player.GetStamina() + 0.001f < cost) { return false; } ((Character)player).UseStamina(cost); return true; } internal float ComputeShieldBaseDamage(ItemData shield) { int num = 1; float num2 = 0f; if (shield != null && shield.m_shared != null) { num = Mathf.Max(1, shield.m_quality); num2 = shield.m_shared.m_blockPower + shield.m_shared.m_blockPowerPerLevel * (float)(num - 1); } return BaseDamage.Value + num2 * BlockPowerScale.Value + (float)Mathf.Max(0, num - 1) * Mathf.Max(0f, QualityBonusPerLevel.Value); } private float GetBlockingSkillFactor(Player player) { if ((Object)(object)player == (Object)null) { return 0f; } try { return Mathf.Clamp01(((Character)player).GetSkillFactor((SkillType)6)); } catch { return 0f; } } private float ApplySkillAndRandom(float baseDamage, float skillFactor, float randMul) { float num = Mathf.Max(0f, BlockingSkillMultiplier.Value); float num2 = baseDamage * (1f + skillFactor * num); num2 *= randMul; return Mathf.Clamp(num2, MinDamage.Value, MaxDamage.Value); } private int GetOverlapMask() { if (_overlapMask != -1) { return _overlapMask; } _overlapMask = LayerMask.GetMask(new string[7] { "character", "character_net", "Default", "static_solid", "piece", "Hitbox", "hitbox" }); if (_overlapMask == 0) { _overlapMask = -1; } return _overlapMask; } private int GetWorldLosMask() { if (_losWorldMask != -1) { return _losWorldMask; } _losWorldMask = LayerMask.GetMask(new string[7] { "Default", "static_solid", "piece", "Hitbox", "hitbox", "character", "character_net" }); if (_losWorldMask == 0) { _losWorldMask = -1; } return _losWorldMask; } private float GetCosHalfAngle() { float num = Mathf.Clamp(Angle.Value, 1f, 180f); if (Mathf.Abs(num - _cachedAngle) < 0.001f && _cachedCosHalf > -1f) { return _cachedCosHalf; } _cachedAngle = num; _cachedCosHalf = Mathf.Cos(num * ((float)Math.PI / 180f) * 0.5f); return _cachedCosHalf; } private void HitOnceReset() { _hitOnceCount = 0; } private bool HitOnceTryAdd(int id) { for (int i = 0; i < _hitOnceCount; i++) { if (_hitOnceIds[i] == id) { return false; } } if (_hitOnceCount >= _hitOnceIds.Length) { return false; } _hitOnceIds[_hitOnceCount] = id; _hitOnceCount++; return true; } private static Vector3 GetSafeHitPoint(Collider col, Vector3 nearPoint, Vector3 fallback) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_002d: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) if ((Object)(object)col == (Object)null) { return fallback; } Vector3 val = col.ClosestPointOnBounds(nearPoint); if (float.IsNaN(val.x)) { return fallback; } if (float.IsInfinity(val.x)) { return fallback; } return val; } private void ApplyBashDamageAndSfx(Player player) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: 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_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0208: 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_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0237: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_07c0: Unknown result type (might be due to invalid IL or missing references) //IL_07cb: Unknown result type (might be due to invalid IL or missing references) //IL_07d5: Unknown result type (might be due to invalid IL or missing references) //IL_07da: Unknown result type (might be due to invalid IL or missing references) //IL_07df: Unknown result type (might be due to invalid IL or missing references) //IL_07e9: Unknown result type (might be due to invalid IL or missing references) //IL_07ee: Unknown result type (might be due to invalid IL or missing references) //IL_07f3: Unknown result type (might be due to invalid IL or missing references) //IL_0822: Unknown result type (might be due to invalid IL or missing references) //IL_0669: Unknown result type (might be due to invalid IL or missing references) //IL_066b: Unknown result type (might be due to invalid IL or missing references) //IL_0671: Unknown result type (might be due to invalid IL or missing references) //IL_0673: Unknown result type (might be due to invalid IL or missing references) //IL_067d: Unknown result type (might be due to invalid IL or missing references) //IL_07aa: Unknown result type (might be due to invalid IL or missing references) //IL_06a3: Unknown result type (might be due to invalid IL or missing references) //IL_06a5: Unknown result type (might be due to invalid IL or missing references) //IL_06e1: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_038f: Unknown result type (might be due to invalid IL or missing references) //IL_0391: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03be: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03c5: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Unknown result type (might be due to invalid IL or missing references) //IL_04c2: Unknown result type (might be due to invalid IL or missing references) //IL_04c4: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04cb: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Unknown result type (might be due to invalid IL or missing references) //IL_04f7: Expected O, but got Unknown //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_04ff: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_0508: Unknown result type (might be due to invalid IL or missing references) //IL_0516: Unknown result type (might be due to invalid IL or missing references) //IL_0521: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Unknown result type (might be due to invalid IL or missing references) //IL_052b: Unknown result type (might be due to invalid IL or missing references) //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0534: Unknown result type (might be due to invalid IL or missing references) //IL_0420: Unknown result type (might be due to invalid IL or missing references) //IL_0426: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_0604: Unknown result type (might be due to invalid IL or missing references) //IL_0606: Unknown result type (might be due to invalid IL or missing references) //IL_0642: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } HitOnceReset(); ItemData leftItem = GetLeftItem((Humanoid)player); float num = ComputeShieldBaseDamage(leftItem); float num2 = DamageRandomMin.Value; float num3 = DamageRandomMax.Value; if (num2 > num3) { float num4 = num2; num2 = num3; num3 = num4; } float num5 = Random.Range(num2, num3); float blockingSkillFactor = GetBlockingSkillFactor(player); float num6 = ApplySkillAndRandom(num, blockingSkillFactor, num5); float randMul = ((!WorldDamageUseRandom.Value) ? 1f : num5); float num7 = ApplySkillAndRandom(num, blockingSkillFactor, randMul) * Mathf.Clamp(WorldDamageScale.Value, 0f, 5f); float num8 = Mathf.Clamp01(Mathf.InverseLerp(MinDamage.Value, MaxDamage.Value, num6)); float num9 = Mathf.Lerp(HitSfxVolumeMin.Value, HitSfxVolumeMax.Value, num8); float num10 = Mathf.Max(0f, MissSfxVolume.Value); GetMaterialMix(leftItem, out var volMul, out var pitchMul); float num11 = Random.Range(Mathf.Min(RandomVolJitterMin.Value, RandomVolJitterMax.Value), Mathf.Max(RandomVolJitterMin.Value, RandomVolJitterMax.Value)); float num12 = Random.Range(Mathf.Min(RandomPitchJitterMin.Value, RandomPitchJitterMax.Value), Mathf.Max(RandomPitchJitterMin.Value, RandomPitchJitterMax.Value)); Vector3 forward = ((Component)player).transform.forward; Vector3 val = ((Component)player).transform.position + Vector3.up * 1.3f; Vector3 val2 = ((Component)player).transform.position + forward * Range.Value; Vector3 val3 = val2 + Vector3.up * 0.6f; Vector3 val4 = val2 + Vector3.up * 1.6f; int overlapMask = GetOverlapMask(); float cosHalfAngle = GetCosHalfAngle(); int num13 = Physics.OverlapCapsuleNonAlloc(val3, val4, Radius.Value, _overlapCols, overlapMask, (QueryTriggerInteraction)2); int num14 = 0; Vector3 pos = val; int losChecks = 0; int num15 = Mathf.Clamp(MaxLoSRaycastsPerBash.Value, 0, 64); Vector3 nearPoint = ((Component)player).transform.position + forward * 0.5f; for (int i = 0; i < num13; i++) { Collider val5 = _overlapCols[i]; if ((Object)(object)val5 == (Object)null) { continue; } Character componentInParent = ((Component)val5).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { if ((object)componentInParent == player || componentInParent.IsDead()) { continue; } if (!HitTamed.Value) { Tameable component = ((Component)componentInParent).GetComponent(); if ((Object)(object)component != (Object)null && component.IsTamed()) { continue; } } if (!HitPlayers.Value) { Player val6 = (Player)(object)((componentInParent is Player) ? componentInParent : null); if ((Object)(object)val6 != (Object)null) { continue; } } Vector3 val7 = ((Component)componentInParent).transform.position + Vector3.up * 1.1f; Vector3 val8 = val7 - val; float magnitude = ((Vector3)(ref val8)).magnitude; if (magnitude < 0.001f) { continue; } Vector3 val9 = val8 / magnitude; float num16 = Vector3.Dot(forward, val9); if (num16 < cosHalfAngle) { continue; } if (LineOfSightCheck.Value && num15 > 0 && losChecks < num15) { losChecks++; int worldLosMask = GetWorldLosMask(); RaycastHit val10 = default(RaycastHit); if (Physics.Raycast(val, val9, ref val10, magnitude, worldLosMask, (QueryTriggerInteraction)1)) { Character val11 = null; if ((Object)(object)((RaycastHit)(ref val10)).collider != (Object)null) { val11 = ((Component)((RaycastHit)(ref val10)).collider).GetComponentInParent(); } if (val11 != componentInParent) { continue; } } } if (HitOnceTryAdd(((Object)((Component)componentInParent).gameObject).GetInstanceID())) { float num17 = Mathf.Clamp(num6, MinDamage.Value, MaxDamage.Value); Vector3 safeHitPoint = GetSafeHitPoint(val5, nearPoint, val7); float num18 = 0f; if (DebugLogDamageAfterArmor.Value) { num18 = componentInParent.GetHealth(); } HitData val12 = new HitData(); val12.m_attacker = ((Character)player).GetZDOID(); val12.m_point = safeHitPoint; Vector3 val13 = ((Component)componentInParent).transform.position - ((Component)player).transform.position; val12.m_dir = ((Vector3)(ref val13)).normalized; val12.m_pushForce = PushForce.Value; val12.m_backstabBonus = 1f; val12.m_damage.m_blunt = num17; componentInParent.Damage(val12); if (DebugLogDamageAfterArmor.Value) { float health = componentInParent.GetHealth(); float num19 = Mathf.Max(0f, num18 - health); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] DEALT '{1}': {2:0.0} (damage={3:0.0}) hp {4:0.0}->{5:0.0}", "ShieldBash", ((Object)componentInParent).name, num19, num17, num18, health)); } num14++; if (num14 == 1) { pos = safeHitPoint; } if (PlayHitSfxPerTarget.Value) { float volumeMul = Mathf.Max(0f, num9 * volMul * num11); float pitchMul2 = Mathf.Max(0.01f, pitchMul * num12); PlayLocalHitAt(player, safeHitPoint, volumeMul, pitchMul2); } } } else { if (!DamageWorldObjects.Value) { continue; } Vector3 hitPoint = val; if (TryDamageWorldObject(val5, player, val, forward, cosHalfAngle, ref losChecks, num15, num7, nearPoint, out hitPoint)) { num14++; if (num14 == 1) { pos = hitPoint; } if (PlayHitSfxPerTarget.Value) { float volumeMul2 = Mathf.Max(0f, num9 * volMul * num11); float pitchMul3 = Mathf.Max(0.01f, pitchMul * num12); PlayLocalHitAt(player, hitPoint, volumeMul2, pitchMul3); } } } } if (!PlayHitSfxPerTarget.Value) { if (num14 > 0) { float num20 = 0f; if (num14 > 1) { float num21 = MultiHitBonusMin.Value; float num22 = MultiHitBonusMax.Value; if (num21 > num22) { float num23 = num21; num21 = num22; num22 = num23; } num20 = Random.Range(num21, num22); } float volumeMul3 = Mathf.Max(0f, (num9 + num20) * volMul * num11); float pitchMul4 = Mathf.Max(0.01f, pitchMul * num12); PlayLocalHitAt(player, pos, volumeMul3, pitchMul4); } else { Vector3 pos2 = ((Component)player).transform.position + ((Component)player).transform.forward * 0.6f + Vector3.up * 1f; float volumeMul4 = Mathf.Max(0f, num10 * volMul * num11); float pitchMul5 = Mathf.Max(0.01f, 1.02f * pitchMul * num12); PlayLocalMissAt(player, pos2, volumeMul4, pitchMul5); } } if (DebugLog.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}] Bash: shieldBase={1:0.0}, sf={2:0.00}, rand={3:0.00}, char={4:0.0}, world={5:0.0}, hits={6}, LoS={7}/{8}, overlap={9}", "ShieldBash", num, blockingSkillFactor, num5, num6, num7, num14, losChecks, num15, num13)); } } private bool TryDamageWorldObject(Collider col, Player player, Vector3 origin, Vector3 forward, float cosHalf, ref int losChecks, int maxLos, float worldDamage, Vector3 nearPoint, out Vector3 hitPoint) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0123: 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_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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Expected O, but got Unknown //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0371: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) //IL_037f: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) hitPoint = origin; if ((Object)(object)col == (Object)null) { return false; } if ((Object)(object)player == (Object)null) { return false; } TreeBase componentInParent = ((Component)col).GetComponentInParent(); TreeLog componentInParent2 = ((Component)col).GetComponentInParent(); MineRock componentInParent3 = ((Component)col).GetComponentInParent(); MineRock5 componentInParent4 = ((Component)col).GetComponentInParent(); Destructible componentInParent5 = ((Component)col).GetComponentInParent(); WearNTear componentInParent6 = ((Component)col).GetComponentInParent(); Component val = null; if ((Object)(object)componentInParent != (Object)null) { val = (Component)(object)componentInParent; } else if ((Object)(object)componentInParent2 != (Object)null) { val = (Component)(object)componentInParent2; } else if ((Object)(object)componentInParent3 != (Object)null) { val = (Component)(object)componentInParent3; } else if ((Object)(object)componentInParent4 != (Object)null) { val = (Component)(object)componentInParent4; } else if ((Object)(object)componentInParent5 != (Object)null) { val = (Component)(object)componentInParent5; } else if ((Object)(object)componentInParent6 != (Object)null) { val = (Component)(object)componentInParent6; } if ((Object)(object)val == (Object)null) { return false; } if (!HitOnceTryAdd(((Object)val.gameObject).GetInstanceID())) { return false; } Bounds bounds = col.bounds; Vector3 center = ((Bounds)(ref bounds)).center; Vector3 val2 = center - origin; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < 0.001f) { return false; } Vector3 val3 = val2 / magnitude; if (Vector3.Dot(forward, val3) < cosHalf) { return false; } if (LineOfSightCheck.Value && maxLos > 0 && losChecks < maxLos) { losChecks++; int worldLosMask = GetWorldLosMask(); RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(origin, val3, ref val4, magnitude, worldLosMask, (QueryTriggerInteraction)1)) { Component val5 = null; if ((Object)(object)((RaycastHit)(ref val4)).collider != (Object)null) { TreeBase componentInParent7 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent(); if ((Object)(object)componentInParent7 != (Object)null) { val5 = (Component)(object)componentInParent7; } else { TreeLog componentInParent8 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent(); if ((Object)(object)componentInParent8 != (Object)null) { val5 = (Component)(object)componentInParent8; } else { MineRock componentInParent9 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent(); if ((Object)(object)componentInParent9 != (Object)null) { val5 = (Component)(object)componentInParent9; } else { MineRock5 componentInParent10 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent(); if ((Object)(object)componentInParent10 != (Object)null) { val5 = (Component)(object)componentInParent10; } else { Destructible componentInParent11 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent(); if ((Object)(object)componentInParent11 != (Object)null) { val5 = (Component)(object)componentInParent11; } else { WearNTear componentInParent12 = ((Component)((RaycastHit)(ref val4)).collider).GetComponentInParent(); if ((Object)(object)componentInParent12 != (Object)null) { val5 = (Component)(object)componentInParent12; } } } } } } } if (val5 != val) { return false; } } } hitPoint = GetSafeHitPoint(col, nearPoint, center); bool flag = false; if ((Object)(object)componentInParent != (Object)null) { flag = true; } if ((Object)(object)componentInParent2 != (Object)null) { flag = true; } bool flag2 = false; if ((Object)(object)componentInParent3 != (Object)null) { flag2 = true; } if ((Object)(object)componentInParent4 != (Object)null) { flag2 = true; } HitData val6 = new HitData(); val6.m_attacker = ((Character)player).GetZDOID(); val6.m_point = hitPoint; val6.m_dir = val3; val6.m_pushForce = 0f; float num = Mathf.Max(0f, worldDamage); if (flag) { val6.m_damage.m_chop = num; } else if (flag2) { val6.m_damage.m_pickaxe = num; } else { val6.m_damage.m_blunt = num; } if ((Object)(object)componentInParent != (Object)null) { componentInParent.Damage(val6); } else if ((Object)(object)componentInParent2 != (Object)null) { componentInParent2.Damage(val6); } else if ((Object)(object)componentInParent3 != (Object)null) { componentInParent3.Damage(val6); } else if ((Object)(object)componentInParent4 != (Object)null) { componentInParent4.Damage(val6); } else if ((Object)(object)componentInParent5 != (Object)null) { componentInParent5.Damage(val6); } else { if (!((Object)(object)componentInParent6 != (Object)null)) { return false; } componentInParent6.Damage(val6); } return true; } private void GetMaterialMix(ItemData shield, out float volMul, out float pitchMul) { volMul = 1f; pitchMul = 1f; string text = ""; text = ((shield == null) ? "" : ((shield.m_shared == null) ? "" : ((shield.m_shared.m_name != null) ? shield.m_shared.m_name : ""))); string text2 = text.ToLowerInvariant(); bool flag = text2.Contains("iron") || text2.Contains("blackmetal") || text2.Contains("silver") || text2.Contains("bronze") || text2.Contains("metal"); bool flag2 = false; if (!flag) { flag2 = text2.Contains("wood") || text2.Contains("tower"); } if (flag) { volMul *= Mathf.Max(0.01f, MetalVolumeMul.Value); pitchMul *= Mathf.Max(0.01f, MetalPitchMul.Value); } else if (flag2) { volMul *= Mathf.Max(0.01f, WoodVolumeMul.Value); pitchMul *= Mathf.Max(0.01f, WoodPitchMul.Value); } } private AudioSource GetOrCreateLocalSfxSource(Player player) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown if ((Object)(object)player == (Object)null) { return null; } if ((Object)(object)_localSfxSource != (Object)null && (Object)(object)((Component)_localSfxSource).gameObject != (Object)null) { Transform transform = ((Component)_localSfxSource).transform; if ((Object)(object)transform != (Object)null && transform.IsChildOf(((Component)player).transform)) { return _localSfxSource; } } try { if ((Object)(object)_localSfxSource != (Object)null && (Object)(object)((Component)_localSfxSource).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)_localSfxSource).gameObject); } } catch { } GameObject val = new GameObject("ShieldBash_LocalSFX_Source"); val.transform.SetParent(((Component)player).transform, false); AudioSource val2 = val.AddComponent(); val2.spatialBlend = 1f; val2.rolloffMode = (AudioRolloffMode)0; val2.minDistance = 1f; val2.maxDistance = 35f; val2.playOnAwake = false; val2.loop = false; val2.dopplerLevel = 0f; _localSfxSource = val2; return _localSfxSource; } private void PlayLocalHitAt(Player player, Vector3 pos, float volumeMul, float pitchMul) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) PlayLocalAt(player, _hitClip, pos, volumeMul, pitchMul); } private void PlayLocalMissAt(Player player, Vector3 pos, float volumeMul, float pitchMul) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) PlayLocalAt(player, _missClip, pos, volumeMul, pitchMul); } private void PlayLocalAt(Player player, AudioClip clip, Vector3 pos, float volumeMul, float pitchMul) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && !((Object)(object)clip == (Object)null)) { AudioSource orCreateLocalSfxSource = GetOrCreateLocalSfxSource(player); if (!((Object)(object)orCreateLocalSfxSource == (Object)null)) { ((Component)orCreateLocalSfxSource).transform.position = pos; orCreateLocalSfxSource.pitch = Mathf.Clamp(pitchMul, 0.5f, 2f); float num = Mathf.Clamp01(volumeMul) * Mathf.Clamp(LocalClipVolumeMul.Value, 0f, 3f); orCreateLocalSfxSource.PlayOneShot(clip, num); } } } private bool LoadAssetsFromBundle() { string text = null; string text2 = null; try { text = Assembly.GetExecutingAssembly().Location; text2 = Path.GetDirectoryName(text); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] Could not resolve DLL location: " + ex.Message)); } List list = new List(); AddBundleCandidates(list, text2); AddBundleCandidates(list, Path.Combine(text2 ?? string.Empty, "Assets")); AddBundleCandidates(list, Path.Combine(Paths.PluginPath, "ShieldBash")); AddBundleCandidates(list, Path.Combine(Paths.PluginPath, "ShieldBash", "Assets")); AddBundleCandidates(list, Paths.PluginPath); string text3 = null; for (int i = 0; i < list.Count; i++) { string text4 = list[i]; if (!string.IsNullOrEmpty(text4) && File.Exists(text4)) { text3 = text4; break; } } if (text3 == null && !string.IsNullOrEmpty(text2) && Directory.Exists(text2)) { try { string[] files = Directory.GetFiles(text2, "*", SearchOption.AllDirectories); for (int i = 0; i < files.Length; i++) { string fileName = Path.GetFileName(files[i]); if (fileName.Equals("shieldbashbundle", StringComparison.OrdinalIgnoreCase) || fileName.Equals("shieldbashbundle.bundle", StringComparison.OrdinalIgnoreCase)) { text3 = files[i]; break; } } } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] Bundle fallback search failed: " + ex2.Message)); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] DLL: " + (text ?? "unknown"))); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] AssetBundle: " + (text3 ?? "NOT FOUND"))); if (text3 == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Put 'shieldbashbundle' next to ShieldBash.dll or into an Assets subfolder."); return false; } AssetBundle val = null; try { val = AssetBundle.LoadFromFile(text3); if ((Object)(object)val == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Unity returned null while loading the AssetBundle. Rebuild it with Unity 6000.0.61f1 for StandaloneWindows64."); return false; } string[] allAssetNames = val.GetAllAssetNames(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[ShieldBash] Bundle contains " + allAssetNames.Length + " assets.")); _bashClip = FindAnimationClip(val, "AttackShield01"); _hitClip = FindAudioClip(val, HitClipName.Value); _missClip = FindAudioClip(val, MissClipName.Value); if ((Object)(object)_bashClip == (Object)null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] AnimationClip 'AttackShield01' was not found in the AssetBundle."); ((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] Assets:\n - " + string.Join("\n - ", allAssetNames))); return false; } if ((Object)(object)_hitClip == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] Hit AudioClip was not found: " + HitClipName.Value)); } if ((Object)(object)_missClip == (Object)null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[ShieldBash] Miss AudioClip was not found: " + MissClipName.Value)); } return true; } catch (Exception ex3) { ((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] AssetBundle load exception: " + ex3)); return false; } finally { if ((Object)(object)val != (Object)null) { val.Unload(false); } } } private static void AddBundleCandidates(List candidates, string directory) { if (!string.IsNullOrEmpty(directory)) { candidates.Add(Path.Combine(directory, "shieldbashbundle")); candidates.Add(Path.Combine(directory, "shieldbashbundle.bundle")); } } private static AnimationClip FindAnimationClip(AssetBundle bundle, string preferredName) { AnimationClip[] array = bundle.LoadAllAssets(); if (array == null || array.Length == 0) { return null; } foreach (AnimationClip val in array) { if ((Object)(object)val != (Object)null && ((Object)val).name.Equals(preferredName, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static AudioClip FindAudioClip(AssetBundle bundle, string preferredName) { AudioClip[] array = bundle.LoadAllAssets(); if (array == null || array.Length == 0) { return null; } string value = (preferredName ?? string.Empty).Trim(); foreach (AudioClip val in array) { if ((Object)(object)val != (Object)null && ((Object)val).name.Equals(value, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private ZNetView GetZNetView(Character character) { if ((Object)(object)character == (Object)null || CharacterNViewField == null) { return null; } try { object? value = CharacterNViewField.GetValue(character); return (ZNetView)((value is ZNetView) ? value : null); } catch { return null; } } private Animator GetAnimator(Character character) { if ((Object)(object)character == (Object)null || CharacterAnimatorField == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Character.m_animator was not found."); return null; } try { object? value = CharacterAnimatorField.GetValue(character); return (Animator)((value is Animator) ? value : null); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] Cannot read Character.m_animator: " + ex.Message)); return null; } } private Rigidbody GetCharacterBody(Character character) { if ((Object)(object)character == (Object)null || CharacterBodyField == null) { return null; } try { object? value = CharacterBodyField.GetValue(character); return (Rigidbody)((value is Rigidbody) ? value : null); } catch { return null; } } private ItemData GetLeftItem(Humanoid humanoid) { if ((Object)(object)humanoid == (Object)null || HumanoidLeftItemField == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"[ShieldBash] Humanoid.m_leftItem was not found."); return null; } try { object? value = HumanoidLeftItemField.GetValue(humanoid); return (ItemData)((value is ItemData) ? value : null); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[ShieldBash] Cannot read Humanoid.m_leftItem: " + ex.Message)); return null; } } private static void EnsureLocalizationReflection() { if (_locRefReady) { return; } _locRefReady = true; try { _locType = AccessTools.TypeByName("Localization"); if (!(_locType == null)) { _locInstanceProp = _locType.GetProperty("instance", BindingFlags.Static | BindingFlags.Public); _locGetSelectedLanguage = _locType.GetMethod("GetSelectedLanguage", BindingFlags.Instance | BindingFlags.Public); } } catch { _locType = null; _locInstanceProp = null; _locGetSelectedLanguage = null; } } private static string GetGameLanguage() { EnsureLocalizationReflection(); if (_locInstanceProp == null || _locGetSelectedLanguage == null) { return null; } try { object value = _locInstanceProp.GetValue(null, null); if (value == null) { return null; } return _locGetSelectedLanguage.Invoke(value, null) as string; } catch { return null; } } private static bool IsRussianUi() { string gameLanguage = GetGameLanguage(); if (string.IsNullOrEmpty(gameLanguage)) { return false; } gameLanguage = gameLanguage.ToLowerInvariant(); return gameLanguage.Contains("russian") || gameLanguage.StartsWith("ru"); } internal string BuildTooltipLineForShield(ItemData item) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 if (item == null || item.m_shared == null) { return null; } if ((int)item.m_shared.m_itemType != 5) { return null; } Player localPlayer = Player.m_localPlayer; float blockingSkillFactor = GetBlockingSkillFactor(localPlayer); float baseDamage = ComputeShieldBaseDamage(item); float num = DamageRandomMin.Value; float num2 = DamageRandomMax.Value; if (num > num2) { float num3 = num; num = num2; num2 = num3; } float num4 = ApplySkillAndRandom(baseDamage, blockingSkillFactor, num); float num5 = ApplySkillAndRandom(baseDamage, blockingSkillFactor, num2); float num6 = ComputeStaminaCost(localPlayer, item); if (IsRussianUi()) { return $"\nУдар щитом: {num4:0}–{num5:0} (дробящий)\nВыносливость: {num6:0.#}\n"; } return $"\nShield Bash: {num4:0}–{num5:0} (blunt)\nStamina: {num6:0.#}\n"; } }