Decompiled source of CaptainSkillTree v0.1.447
AnimationSpeedManager.dll
Decompiled 15 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using JetBrains.Annotations; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("AnimationSpeedManager")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AnimationSpeedManager")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("B3A6D52C-449A-4665-9FD0-BB48C8CF2CDF")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class AnimationSpeedManager { public delegate double Handler(Character character, double speed); private static readonly Harmony harmony = new Harmony("AnimationSpeedManager"); private static bool hasMarkerPatch = false; private static readonly MethodInfo method = AccessTools.DeclaredMethod(typeof(CharacterAnimEvent), "CustomFixedUpdate", (Type[])null, (Type[])null); private static int index = 0; private static bool changed = false; private static Handler[][] handlers = Array.Empty<Handler[]>(); private static readonly Dictionary<int, List<Handler>> handlersPriorities = new Dictionary<int, List<Handler>>(); [PublicAPI] public static void Add(Handler handler, int priority = 400) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Expected O, but got Unknown if (!hasMarkerPatch) { harmony.Patch((MethodBase)method, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(AnimationSpeedManager), "markerPatch", (Type[])null, (Type[])null)), (HarmonyMethod)null); hasMarkerPatch = true; } if (!handlersPriorities.TryGetValue(priority, out List<Handler> value)) { handlersPriorities.Add(priority, value = new List<Handler>()); harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(AnimationSpeedManager), "wrapper", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } value.Add(handler); handlers = (from kv in handlersPriorities orderby kv.Key select kv.Value.ToArray()).ToArray(); } private static void wrapper(Character ___m_character, Animator ___m_animator) { Character ___m_character2 = ___m_character; double num = (double)___m_animator.speed * 10000000.0 % 100.0; if ((!(num > 10.0) || !(num < 30.0)) && !(___m_animator.speed <= 0.001f)) { double num2 = ___m_animator.speed; double num3 = handlers[index++].Aggregate(num2, (double current, Handler handler) => handler(___m_character2, current)); if (num3 != num2) { ___m_animator.speed = (float)(num3 - num3 % 1E-05); changed = true; } } } private static void markerPatch(Animator ___m_animator) { if (changed) { double num = (double)___m_animator.speed * 10000000.0 % 100.0; if ((num < 10.0 || num > 30.0) ? true : false) { ___m_animator.speed += 1.9E-06f; } changed = false; } index = 0; } }
CaptainSkillTree.dll
Decompiled 15 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CaptainSkillTree.Audio; using CaptainSkillTree.Gui; using CaptainSkillTree.MMO_System; using CaptainSkillTree.Prefab; using CaptainSkillTree.SkillTree; using CaptainSkillTree.SkillTree.CriticalSystem; using CaptainSkillTree.VFX; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("CaptainSkillTree")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("CaptainSkillTree")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("d1b6e7e2-1c2a-4b8a-9e2b-123456789abc")] [assembly: AssemblyFileVersion("0.1.477.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.477.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CaptainSkillTree { public class SkillTreeInputListener : MonoBehaviour { public SkillTreeUI? skillTreeUI; private float lastLogTime = 0f; public static SkillTreeInputListener? Instance { get; private set; } private void Awake() { lastLogTime = Time.time; if ((Object)(object)Instance == (Object)null) { Instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); LevelSyncManager.Instance.Initialize(); } else { Debug.LogWarning((object)"[SkillTreeInputListener] 중복 생성 감지, 즉시 파괴, this={this.GetHashCode()} (name={gameObject.name})"); Object.Destroy((Object)(object)((Component)this).gameObject); } } private void Update() { try { SkillTreeManager.Instance?.OnUpdate(); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[SkillTree] SkillTreeManager 업데이트 실패: " + ex.Message)); } try { LevelSyncManager.Instance?.Update(); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[SkillTree] LevelSyncManager 업데이트 실패: " + ex2.Message)); } if (IsChatOrConsoleOpen()) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead()) { if (Input.GetKeyDown((KeyCode)114)) { SkillEffect.HandleRKeySkills(localPlayer); } if (Input.GetKeyDown((KeyCode)103)) { SkillEffect.HandleGKeySkills(localPlayer); } if (Input.GetKeyUp((KeyCode)103)) { SkillEffect.HandleGKeyUpSkills(localPlayer); } if (Input.GetKeyDown((KeyCode)104)) { SkillEffect.HandleHKeySkills(localPlayer); } if (Input.GetKeyUp((KeyCode)104)) { SkillEffect.HandleHKeyUpSkills(localPlayer); } if (Input.GetKeyDown((KeyCode)121)) { SkillTreeManager.Instance.HandleActiveSkillKeyInput(); } if (Input.GetKeyDown((KeyCode)93)) { try { long expToNextLevel = CaptainMMOBridge.GetExpToNextLevel(); CaptainMMOBridge.AddExp((int)expToNextLevel); Plugin.SkillTreePoint += 3; } catch (Exception ex3) { Plugin.Log.LogWarning((object)("[SkillTree] 레벨업 실패 (경험치 추가): " + ex3.Message)); } } } if ((Object)(object)skillTreeUI == (Object)null || (Object)(object)skillTreeUI.panel == (Object)null || !skillTreeUI.panel.activeInHierarchy) { return; } bool keyDown = Input.GetKeyDown((KeyCode)27); bool keyDown2 = Input.GetKeyDown((KeyCode)9); if (keyDown) { skillTreeUI.panel.SetActive(false); if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null) { SkillTreeBGMManager.Instance.PauseSkillTreeBGM(); } else { Plugin.Log.LogError((object)"[\ud83d\udd11 ESC] ❌ SkillTreeBGMManager.Instance가 null - ESC키 처리 실패"); } } if (keyDown2) { skillTreeUI.panel.SetActive(false); if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null) { SkillTreeBGMManager.Instance.PauseSkillTreeBGM(); } else { Plugin.Log.LogError((object)"[\ud83d\udd11 TAB] ❌ SkillTreeBGMManager.Instance가 null - Tab키 처리 실패"); } } } private bool IsChatOrConsoleOpen() { try { if (IsChatInputActive()) { Plugin.Log.LogDebug((object)"[키 입력 차단] 채팅 입력이 활성화됨 - 스킬 키 입력 차단"); return true; } if (IsConsoleActive()) { Plugin.Log.LogDebug((object)"[키 입력 차단] 콘솔이 활성화됨 - 스킬 키 입력 차단"); return true; } return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[키 입력 차단] 채팅/콘솔 상태 확인 중 오류: " + ex.Message)); return false; } } private bool IsChatInputActive() { try { EventSystem current = EventSystem.current; if ((Object)(object)((current != null) ? current.currentSelectedGameObject : null) != (Object)null) { InputField component = current.currentSelectedGameObject.GetComponent<InputField>(); if ((Object)(object)component != (Object)null && component.isFocused) { return true; } } if ((Object)(object)Chat.instance != (Object)null) { GameObject gameObject = ((Component)Chat.instance).gameObject; if ((Object)(object)gameObject != (Object)null && gameObject.activeInHierarchy) { try { InputField componentInChildren = ((Component)Chat.instance).GetComponentInChildren<InputField>(true); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.isFocused) { return true; } } catch (Exception ex) { Plugin.Log.LogDebug((object)("[채팅 감지] GetComponentInChildren 실패: " + ex.Message)); } } } return false; } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[채팅 감지] 오류: " + ex2.Message)); return false; } } private bool IsConsoleActive() { try { Type type = Type.GetType("Console, assembly_valheim"); if (type != null) { MethodInfo method = type.GetMethod("IsVisible", BindingFlags.Static | BindingFlags.Public); if (method != null && (bool)method.Invoke(null, null)) { return true; } } return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("[콘솔 감지] 오류: " + ex.Message)); return false; } } private void OnDestroy() { ((MonoBehaviour)this).StopAllCoroutines(); LevelSyncManager.Instance?.Cleanup(); if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } } [HarmonyPatch(typeof(Player), "OnDeath")] public static class Player_OnDeath_StopCoroutines_Patch { [HarmonyPostfix] public static void Postfix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && (Object)(object)SkillTreeInputListener.Instance != (Object)null) { ((MonoBehaviour)SkillTreeInputListener.Instance).StopAllCoroutines(); } } } [BepInPlugin("CaptainSkillTree.SkillTreeMod", "Captain SkillTree Mod", "0.1.477")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(InventoryGui), "Show")] public static class InventoryShowPatch { private static bool Prepare() { return true; } public static void Postfix() { try { ShowSkillTreeIcon(); } catch (Exception ex) { Log.LogError((object)("[스킬트리] InventoryShowPatch 오류: " + ex.Message)); Log.LogError((object)("[스킬트리] StackTrace: " + ex.StackTrace)); } } } [HarmonyPatch(typeof(Character), "ApplyDamage")] [HarmonyPriority(400)] public static class WeaponCriticalSystemPatch { public static void Prefix(Character __instance, ref bool showDamageText, ref HitData hit) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Invalid comparison between Unknown and I4 //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } ItemData currentWeapon = ((Humanoid)Player.m_localPlayer).GetCurrentWeapon(); if (currentWeapon == null) { return; } Player localPlayer = Player.m_localPlayer; SkillType skillType = currentWeapon.m_shared.m_skillType; if ((int)skillType == 5 && SkillEffect.spearEnhancedThrowBuffEndTime.TryGetValue(localPlayer, out var value) && Time.time < value) { float spearStep6ComboDamageValue = SkillTreeConfig.SpearStep6ComboDamageValue; float num = 1f + spearStep6ComboDamageValue / 100f; hit.m_damage.m_pierce *= num; hit.m_damage.m_blunt *= num; hit.m_damage.m_slash *= num; hit.m_damage.m_chop *= num; Log.LogInfo((object)$"[연공창] ✅ 강화된 투창 데미지 +{spearStep6ComboDamageValue}% 적용!"); if ((Object)(object)__instance != (Object)null && !__instance.IsPlayer()) { Vector3 position = ((Component)__instance).transform.position + Vector3.up * 1f; SimpleVFX.Play("confetti_directional_multicolor", position, 2f); Log.LogDebug((object)"[연공창] confetti 효과 재생"); } SkillEffect.spearEnhancedThrowBuffEndTime.Remove(localPlayer); return; } if ((int)skillType == 5 && SkillEffect.HasSkill("spear_Step1_throw") && SkillEffect.CanUseSpearThrowPassive(localPlayer)) { float spearStep2ThrowDamageValue = SkillTreeConfig.SpearStep2ThrowDamageValue; float num2 = 1f + spearStep2ThrowDamageValue / 100f; hit.m_damage.m_pierce *= num2; hit.m_damage.m_blunt *= num2; hit.m_damage.m_slash *= num2; hit.m_damage.m_chop *= num2; Log.LogInfo((object)$"[투창 전문가] ✅ 투창 공격력 +{spearStep2ThrowDamageValue}% 적용!"); SkillEffect.ShowSkillEffectText(localPlayer, $"\ud83d\udca5 투창 +{spearStep2ThrowDamageValue}%!", new Color(1f, 0.8f, 0.2f), SkillEffect.SkillEffectTextType.Combat); SkillEffect.SetSpearThrowPassiveCooldown(localPlayer); } float critChance = Critical.CalculateCritChance(localPlayer, skillType); if (Critical.RollCritical(critChance)) { float critMultiplier = CriticalDamage.CalculateCritDamageMultiplier(localPlayer, skillType); CriticalDamage.ApplyCriticalDamage(localPlayer, ref hit, critMultiplier, skillType); showDamageText = false; } } } [HarmonyPatch(typeof(SEMan), "ModifyAttackStaminaUsage")] public static class KnifeSkillTreeStaminaPatch { public static void Postfix(SEMan __instance, ref float staminaUse) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Invalid comparison between Unknown and I4 Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ItemData currentWeapon = ((Humanoid)localPlayer).GetCurrentWeapon(); if (currentWeapon != null && (int)currentWeapon.m_shared.m_skillType == 2) { float knifeStaminaReduction = SkillEffect.GetKnifeStaminaReduction(0f); staminaUse *= 1f - knifeStaminaReduction / 100f; } } } } [HarmonyPatch(typeof(SEMan), "ModifyStaminaRegen")] public static class KnifeSkillTreeStaminaRegenPatch { public static void Postfix(SEMan __instance, ref float staminaMultiplier) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { staminaMultiplier += SkillEffect.GetStaminaRegen(0f) / 100f; } } } [HarmonyPatch(typeof(SEMan), "ModifyRunStaminaDrain")] public static class KnifeSkillTreeRunStaminaPatch { public static void Postfix(ref float drain) { float staminaReduction = SkillEffect.GetStaminaReduction(0f); drain *= 1f - staminaReduction / 100f; } } [HarmonyPatch(typeof(SEMan), "ModifyJumpStaminaUsage")] public static class KnifeSkillTreeJumpStaminaPatch { public static void Postfix(ref float staminaUse) { float staminaReduction = SkillEffect.GetStaminaReduction(0f); staminaUse *= 1f - staminaReduction / 100f; float jumpStaminaReduction = SkillEffect.GetJumpStaminaReduction(); staminaUse *= 1f - jumpStaminaReduction / 100f; } } [HarmonyPatch(typeof(Character), "ApplyDamage")] [HarmonyPriority(600)] public static class KnifeSkillTreeArmorPatch { public static void Prefix(Character __instance, HitData hit) { if (__instance.IsPlayer()) { float physicArmor = SkillEffect.GetPhysicArmor(0f); float num = 1f - physicArmor / 100f; hit.m_damage.m_blunt *= num; hit.m_damage.m_slash *= num; hit.m_damage.m_pierce *= num; hit.m_damage.m_chop *= num; hit.m_damage.m_pickaxe *= num; float magicArmor = SkillEffect.GetMagicArmor(0f); float num2 = 1f - magicArmor / 100f; hit.m_damage.m_fire *= num2; hit.m_damage.m_frost *= num2; hit.m_damage.m_lightning *= num2; hit.m_damage.m_poison *= num2; hit.m_damage.m_spirit *= num2; } } } [HarmonyPatch(typeof(Humanoid), "BlockAttack")] public static class SwordSkillTreeParryPatch { public static void Postfix(Character __instance, bool __result, HitData hit, Character attacker) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 if (!__result) { return; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if (val == null || !((Character)val).IsPlayer()) { return; } ItemData currentWeapon = ((Humanoid)val).GetCurrentWeapon(); if (currentWeapon != null && (int)currentWeapon.m_shared.m_skillType == 1) { SkillTreeManager instance = SkillTreeManager.Instance; SEMan sEMan = ((Character)val).GetSEMan(); if (instance.GetSkillLevel("sword_counter") > 0) { SE_SwordCounter sE_SwordCounter = ScriptableObject.CreateInstance<SE_SwordCounter>(); ((StatusEffect)sE_SwordCounter).m_ttl = 5f; sEMan.AddStatusEffect((StatusEffect)(object)sE_SwordCounter, true, 0, 0f); } if (instance.GetSkillLevel("sword_riposte") > 0) { SE_SwordRiposte sE_SwordRiposte = ScriptableObject.CreateInstance<SE_SwordRiposte>(); ((StatusEffect)sE_SwordRiposte).m_ttl = 5f; sEMan.AddStatusEffect((StatusEffect)(object)sE_SwordRiposte, true, 0, 0f); } } } } [HarmonyPatch(typeof(Character), "Stagger")] public static class ParryRush_Stagger_Patch { public static void Postfix(Character __instance) { try { if (!((Object)(object)__instance == (Object)null) && !__instance.IsPlayer()) { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead() && Sword_Skill.IsParryRushActive(localPlayer) && ((Character)localPlayer).IsBlocking()) { Sword_Skill.OnParryRushTrigger(localPlayer, __instance); Log.LogInfo((object)"[패링 돌격] Stagger 감지 → 패링 돌격 발동"); } } } catch (Exception ex) { Log.LogError((object)("[패링 돌격] Stagger 패치 오류: " + ex.Message)); } } } public class SE_SwordCounter : StatusEffect { public SE_SwordCounter() { base.m_name = "칼날 되치기"; base.m_tooltip = "다음 공격의 피해량이 20% 증가합니다."; base.m_icon = null; base.m_ttl = 5f; } public override void ModifyAttack(SkillType skill, ref HitData hitData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)skill == 1) { ((DamageTypes)(ref hitData.m_damage)).Modify(1.2f); base.m_character.GetSEMan().RemoveStatusEffect((StatusEffect)(object)this, true); } } } public class SE_SwordRiposte : StatusEffect { public SE_SwordRiposte() { base.m_name = "칼날 되치기"; base.m_tooltip = "다음 공격의 피해량이 20% 증가합니다."; base.m_icon = null; } } [HarmonyPatch(typeof(Character), "ApplyDamage")] public static class SwordRiposteDamagePatch { private static readonly int SwordCounterHash = Animator.StringToHash("칼날 되치기"); private static readonly int SwordRiposteHash = Animator.StringToHash("반격 자세"); private static void Prefix(Character __instance, HitData hit) { Character attacker = hit.GetAttacker(); Player val = (Player)(object)((attacker is Player) ? attacker : null); if (val != null) { SEMan sEMan = ((Character)val).GetSEMan(); if (sEMan.HaveStatusEffect(SwordRiposteHash)) { hit.m_damage.m_blunt *= 1.2f; hit.m_damage.m_slash *= 1.2f; hit.m_damage.m_pierce *= 1.2f; sEMan.RemoveStatusEffect(SwordRiposteHash, false); } } } } [HarmonyPatch(typeof(InventoryGui), "Hide")] public static class InventoryHidePatch { public static void Postfix() { try { if ((Object)(object)skillTreeUI != (Object)null && (Object)(object)skillTreeUI.panel != (Object)null && skillTreeUI.panel.activeSelf) { skillTreeUI.panel.SetActive(false); if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null) { SkillTreeBGMManager.Instance.PauseSkillTreeBGM(); } } if ((Object)(object)skillTreeIconObj != (Object)null) { skillTreeIconObj.SetActive(false); } } catch (Exception ex) { Log.LogError((object)("[스킬트리] InventoryHidePatch 오류: " + ex.Message)); } } } [HarmonyPatch(typeof(InventoryGui), "Show")] public static class InventoryShowIconPositionPatch { private static bool _iconPositionAdjusted; public static void Postfix(InventoryGui __instance) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)skillTreeIconObj == (Object)null) { return; } skillTreeIconObj.SetActive(true); if (!EpicMMOReflectionHelper.IsInitialized) { EpicMMOReflectionHelper.Initialize(); } if (EpicMMOReflectionHelper.IsAvailable || _iconPositionAdjusted) { return; } RectTransform component = skillTreeIconObj.GetComponent<RectTransform>(); if (!((Object)(object)component == (Object)null)) { Canvas componentInParent = skillTreeIconObj.GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent != (Object)null) { ((Transform)component).SetParent(((Component)componentInParent).transform, false); component.anchorMin = new Vector2(0.5f, 0.5f); component.anchorMax = new Vector2(0.5f, 0.5f); component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = new Vector2(0f, 150f); component.sizeDelta = new Vector2(60f, 60f); _iconPositionAdjusted = true; Log.LogInfo((object)"[스킬트리] 아이콘 위치 조정: 화면 중앙 캐릭터 머리 위 (EpicMMO 미사용)"); } } } catch (Exception ex) { Log.LogError((object)("[스킬트리] 아이콘 위치 조정 실패: " + ex.Message)); } } } [HarmonyPatch(typeof(Hud), "Awake")] public static class HudAwakeHideIconPatch { [CompilerGenerated] private sealed class <DelayedHideIcon>d__1 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedHideIcon>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)skillTreeIconObj != (Object)null) { skillTreeIconObj.SetActive(false); Log.LogInfo((object)"[스킬트리] 아이콘 초기 숨김 완료 - 인벤토리(Tab) 열 때 표시됨"); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static void Postfix() { if ((Object)(object)Instance != (Object)null) { ((MonoBehaviour)Instance).StartCoroutine(DelayedHideIcon()); } } [IteratorStateMachine(typeof(<DelayedHideIcon>d__1))] private static IEnumerator DelayedHideIcon() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedHideIcon>d__1(0); } } [HarmonyPatch(typeof(ZNet), "Awake")] public static class ZNet_Awake_Patch { private static void Postfix() { InitializeServerSync(); } } [HarmonyPatch(typeof(ZNet), "OnNewConnection")] public static class ZNet_OnNewConnection_Patch { [CompilerGenerated] private sealed class <DelayedConfigBroadcast>d__1 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedConfigBroadcast>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; case 1: <>1__state = -1; SkillTreeConfig.BroadcastConfigToClients(); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static void Postfix(ZNet __instance) { if (__instance.IsServer()) { ((MonoBehaviour)__instance).StartCoroutine(DelayedConfigBroadcast()); } } [IteratorStateMachine(typeof(<DelayedConfigBroadcast>d__1))] private static IEnumerator DelayedConfigBroadcast() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedConfigBroadcast>d__1(0); } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] public static class Terminal_InitTerminal_Patch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__0_0; public static ConsoleEvent <>9__0_1; public static ConsoleEvent <>9__0_2; public static ConsoleEvent <>9__0_3; public static ConsoleEvent <>9__0_4; public static ConsoleEvent <>9__0_5; public static ConsoleEvent <>9__0_6; public static ConsoleEvent <>9__0_7; public static ConsoleEvent <>9__0_8; public static ConsoleEvent <>9__0_9; public static ConsoleEvent <>9__0_10; public static ConsoleEvent <>9__0_11; public static ConsoleEvent <>9__0_12; public static ConsoleEvent <>9__0_13; public static ConsoleEvent <>9__0_14; public static ConsoleEvent <>9__0_15; public static ConsoleEvent <>9__0_16; public static ConsoleEvent <>9__0_17; public static ConsoleEvent <>9__0_18; public static ConsoleEvent <>9__0_19; internal void <Postfix>b__0_0(ConsoleEventArgs args) { SetAttackConfig("AttackRootDamageBonus", args); } internal void <Postfix>b__0_1(ConsoleEventArgs args) { SetAttackConfig("AttackMeleeBonusChance", args); } internal void <Postfix>b__0_2(ConsoleEventArgs args) { SetAttackConfig("AttackMeleeBonusDamage", args); } internal void <Postfix>b__0_3(ConsoleEventArgs args) { SetAttackConfig("AttackBowBonusChance", args); } internal void <Postfix>b__0_4(ConsoleEventArgs args) { SetAttackConfig("AttackBowBonusDamage", args); } internal void <Postfix>b__0_5(ConsoleEventArgs args) { SetSpeedConfig("Speed_Expert_MoveSpeed", args); } internal void <Postfix>b__0_6(ConsoleEventArgs args) { SetSpeedConfig("Speed_Step1_DodgeSpeed", args); } internal void <Postfix>b__0_7(ConsoleEventArgs args) { SetSpeedConfig("Speed_Step2_MeleeComboBonus", args); } internal void <Postfix>b__0_8(ConsoleEventArgs args) { SetSpeedConfig("Speed_Step2_BowHitBonus", args); } internal void <Postfix>b__0_9(ConsoleEventArgs args) { SetSpeedConfig("Speed_Step8_MeleeAttackSpeed", args); } internal void <Postfix>b__0_10(ConsoleEventArgs args) { SkillTreeConfig.ReloadAndBroadcast(); } internal void <Postfix>b__0_11(ConsoleEventArgs args) { ShowCurrentConfig(); } internal void <Postfix>b__0_12(ConsoleEventArgs args) { SetArcherConfig("Archer_MultiShot_ArrowCount", args); } internal void <Postfix>b__0_13(ConsoleEventArgs args) { SetArcherConfig("Archer_MultiShot_ArrowConsumption", args); } internal void <Postfix>b__0_14(ConsoleEventArgs args) { SetArcherConfig("Archer_MultiShot_DamagePercent", args); } internal void <Postfix>b__0_15(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_Lv1_Chance", args); } internal void <Postfix>b__0_16(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_Lv2_Chance", args); } internal void <Postfix>b__0_17(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_ArrowCount", args); } internal void <Postfix>b__0_18(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_ArrowConsumption", args); } internal void <Postfix>b__0_19(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_DamagePercent", args); } } private static void Postfix() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_006b: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_00a3: 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_009a: Expected O, but got Unknown //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_016f: 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_017a: Expected O, but got Unknown //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Expected O, but got Unknown //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Expected O, but got Unknown //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Expected O, but got Unknown //IL_029b: 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_0292: Expected O, but got Unknown //IL_02d3: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Expected O, but got Unknown //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Expected O, but got Unknown //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Expected O, but got Unknown //IL_037b: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Expected O, but got Unknown //IL_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03aa: Expected O, but got Unknown //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03dc: Unknown result type (might be due to invalid IL or missing references) //IL_03e2: Expected O, but got Unknown //IL_0423: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Expected O, but got Unknown //IL_045b: Unknown result type (might be due to invalid IL or missing references) //IL_0447: Unknown result type (might be due to invalid IL or missing references) //IL_044c: Unknown result type (might be due to invalid IL or missing references) //IL_0452: Expected O, but got Unknown object obj = <>c.<>9__0_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { SetAttackConfig("AttackRootDamageBonus", args); }; <>c.<>9__0_0 = val; obj = (object)val; } new ConsoleCommand("skilltree_attack_root", "공격 전문가 루트 데미지 보너스 설정 (예: skilltree_attack_root 7)", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__0_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { SetAttackConfig("AttackMeleeBonusChance", args); }; <>c.<>9__0_1 = val2; obj2 = (object)val2; } new ConsoleCommand("skilltree_melee_chance", "근접 특화 발동 확률 설정 (예: skilltree_melee_chance 25)", (ConsoleEvent)obj2, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj3 = <>c.<>9__0_2; if (obj3 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { SetAttackConfig("AttackMeleeBonusDamage", args); }; <>c.<>9__0_2 = val3; obj3 = (object)val3; } new ConsoleCommand("skilltree_melee_damage", "근접 특화 피해량 설정 (예: skilltree_melee_damage 15)", (ConsoleEvent)obj3, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj4 = <>c.<>9__0_3; if (obj4 == null) { ConsoleEvent val4 = delegate(ConsoleEventArgs args) { SetAttackConfig("AttackBowBonusChance", args); }; <>c.<>9__0_3 = val4; obj4 = (object)val4; } new ConsoleCommand("skilltree_bow_chance", "활 특화 발동 확률 설정 (예: skilltree_bow_chance 30)", (ConsoleEvent)obj4, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj5 = <>c.<>9__0_4; if (obj5 == null) { ConsoleEvent val5 = delegate(ConsoleEventArgs args) { SetAttackConfig("AttackBowBonusDamage", args); }; <>c.<>9__0_4 = val5; obj5 = (object)val5; } new ConsoleCommand("skilltree_bow_damage", "활 특화 피해량 설정 (예: skilltree_bow_damage 18)", (ConsoleEvent)obj5, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj6 = <>c.<>9__0_5; if (obj6 == null) { ConsoleEvent val6 = delegate(ConsoleEventArgs args) { SetSpeedConfig("Speed_Expert_MoveSpeed", args); }; <>c.<>9__0_5 = val6; obj6 = (object)val6; } new ConsoleCommand("skilltree_speed_root", "속도 전문가 루트 이동속도 설정 (예: skilltree_speed_root 5)", (ConsoleEvent)obj6, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj7 = <>c.<>9__0_6; if (obj7 == null) { ConsoleEvent val7 = delegate(ConsoleEventArgs args) { SetSpeedConfig("Speed_Step1_DodgeSpeed", args); }; <>c.<>9__0_6 = val7; obj7 = (object)val7; } new ConsoleCommand("skilltree_speed_dodge", "구르기 속도 보너스 설정 (예: skilltree_speed_dodge 15)", (ConsoleEvent)obj7, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj8 = <>c.<>9__0_7; if (obj8 == null) { ConsoleEvent val8 = delegate(ConsoleEventArgs args) { SetSpeedConfig("Speed_Step2_MeleeComboBonus", args); }; <>c.<>9__0_7 = val8; obj8 = (object)val8; } new ConsoleCommand("skilltree_speed_melee_combo", "근접 콤보 이동속도 설정 (예: skilltree_speed_melee_combo 6)", (ConsoleEvent)obj8, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj9 = <>c.<>9__0_8; if (obj9 == null) { ConsoleEvent val9 = delegate(ConsoleEventArgs args) { SetSpeedConfig("Speed_Step2_BowHitBonus", args); }; <>c.<>9__0_8 = val9; obj9 = (object)val9; } new ConsoleCommand("skilltree_speed_bow_hit", "활 적중 이동속도 설정 (예: skilltree_speed_bow_hit 8)", (ConsoleEvent)obj9, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj10 = <>c.<>9__0_9; if (obj10 == null) { ConsoleEvent val10 = delegate(ConsoleEventArgs args) { SetSpeedConfig("Speed_Step8_MeleeAttackSpeed", args); }; <>c.<>9__0_9 = val10; obj10 = (object)val10; } new ConsoleCommand("skilltree_speed_attack", "공격속도 증가 설정 (예: skilltree_speed_attack 10)", (ConsoleEvent)obj10, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj11 = <>c.<>9__0_10; if (obj11 == null) { ConsoleEvent val11 = delegate { SkillTreeConfig.ReloadAndBroadcast(); }; <>c.<>9__0_10 = val11; obj11 = (object)val11; } new ConsoleCommand("skilltree_config_reload", "설정 리로드 및 재전송", (ConsoleEvent)obj11, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj12 = <>c.<>9__0_11; if (obj12 == null) { ConsoleEvent val12 = delegate { ShowCurrentConfig(); }; <>c.<>9__0_11 = val12; obj12 = (object)val12; } new ConsoleCommand("skilltree_config_show", "현재 설정 표시", (ConsoleEvent)obj12, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj13 = <>c.<>9__0_12; if (obj13 == null) { ConsoleEvent val13 = delegate(ConsoleEventArgs args) { SetArcherConfig("Archer_MultiShot_ArrowCount", args); }; <>c.<>9__0_12 = val13; obj13 = (object)val13; } new ConsoleCommand("skilltree_archer_arrows", "아처 멀티샷 화살 수 설정 (예: skilltree_archer_arrows 7)", (ConsoleEvent)obj13, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj14 = <>c.<>9__0_13; if (obj14 == null) { ConsoleEvent val14 = delegate(ConsoleEventArgs args) { SetArcherConfig("Archer_MultiShot_ArrowConsumption", args); }; <>c.<>9__0_13 = val14; obj14 = (object)val14; } new ConsoleCommand("skilltree_archer_consume", "아처 멀티샷 화살 소모량 설정 (예: skilltree_archer_consume 2)", (ConsoleEvent)obj14, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj15 = <>c.<>9__0_14; if (obj15 == null) { ConsoleEvent val15 = delegate(ConsoleEventArgs args) { SetArcherConfig("Archer_MultiShot_DamagePercent", args); }; <>c.<>9__0_14 = val15; obj15 = (object)val15; } new ConsoleCommand("skilltree_archer_damage", "아처 멀티샷 데미지 비율 설정 (예: skilltree_archer_damage 80)", (ConsoleEvent)obj15, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj16 = <>c.<>9__0_15; if (obj16 == null) { ConsoleEvent val16 = delegate(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_Lv1_Chance", args); }; <>c.<>9__0_15 = val16; obj16 = (object)val16; } new ConsoleCommand("skilltree_bow_lv1_chance", "활 전문가 멀티샷 Lv1 확률 설정 (예: skilltree_bow_lv1_chance 15)", (ConsoleEvent)obj16, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj17 = <>c.<>9__0_16; if (obj17 == null) { ConsoleEvent val17 = delegate(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_Lv2_Chance", args); }; <>c.<>9__0_16 = val17; obj17 = (object)val17; } new ConsoleCommand("skilltree_bow_lv2_chance", "활 전문가 멀티샷 Lv2 확률 설정 (예: skilltree_bow_lv2_chance 36)", (ConsoleEvent)obj17, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj18 = <>c.<>9__0_17; if (obj18 == null) { ConsoleEvent val18 = delegate(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_ArrowCount", args); }; <>c.<>9__0_17 = val18; obj18 = (object)val18; } new ConsoleCommand("skilltree_bow_arrows", "활 전문가 멀티샷 화살 수 설정 (예: skilltree_bow_arrows 2)", (ConsoleEvent)obj18, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj19 = <>c.<>9__0_18; if (obj19 == null) { ConsoleEvent val19 = delegate(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_ArrowConsumption", args); }; <>c.<>9__0_18 = val19; obj19 = (object)val19; } new ConsoleCommand("skilltree_bow_consume", "활 전문가 멀티샷 화살 소모량 설정 (예: skilltree_bow_consume 0)", (ConsoleEvent)obj19, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj20 = <>c.<>9__0_19; if (obj20 == null) { ConsoleEvent val20 = delegate(ConsoleEventArgs args) { SetBowConfig("Bow_MultiShot_DamagePercent", args); }; <>c.<>9__0_19 = val20; obj20 = (object)val20; } new ConsoleCommand("skilltree_bow_damage", "활 전문가 멀티샷 데미지 비율 설정 (예: skilltree_bow_damage 70)", (ConsoleEvent)obj20, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__44_0; internal void <SetupIconClickEvent>b__44_0() { //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown Log.LogDebug((object)"[시작 아이콘] 클릭 이벤트 감지됨!"); if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null && SkillTreeBGMManager.Instance.IsBGMEnabled) { SkillTreeBGMManager.Instance.PlaySkillTreeBGM(); Log.LogInfo((object)"[BGM] 스킬트리 BGM 재생 시작 (BGM 활성화 상태)"); } else if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null) { Log.LogInfo((object)"[BGM] BGM이 비활성화되어 있어 재생하지 않음"); } InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { Debug.LogWarning((object)"[스킬트리] InventoryGui.instance를 찾을 수 없음"); return; } Canvas componentInChildren = ((Component)instance).GetComponentInChildren<Canvas>(); if ((Object)(object)skillTreeUI == (Object)null || (Object)(object)skillTreeUI.panel == (Object)null || (Object)(object)skillTreeUI.panel.transform.parent != (Object)(object)((Component)componentInChildren).transform) { if ((Object)(object)skillTreeUI != (Object)null && (Object)(object)skillTreeUI.panel != (Object)null) { Object.Destroy((Object)(object)skillTreeUI.panel); } GameObject val = new GameObject("SkillTreeUI"); val.transform.SetParent(((Component)componentInChildren).transform, false); skillTreeUI = val.AddComponent<SkillTreeUI>(); skillTreeUI.CreateUI(componentInChildren); Log.LogInfo((object)"[스킬트리] skillTreeUI 새로 생성 및 Canvas 하위에 배치"); } if (!skillTreeUI.panel.activeSelf) { skillTreeUI.RefreshUI(); skillTreeUI.panel.SetActive(true); return; } skillTreeUI.panel.SetActive(false); if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null) { SkillTreeBGMManager.Instance.PauseSkillTreeBGM(); } } } public static ManualLogSource Log; private static GameObject skillTreeIconObj; private static Sprite swordIcon; private static AssetBundle iconAssetBundle; private static AssetBundle uiAssetBundle; private static AssetBundle customIconBundle; private static AssetBundle jobIconBundle; private static AssetBundle vfxBundle; private static AssetBundle jobVfxBundle; public static int SkillTreePoint; private static SkillTreeUI skillTreeUI; private static Sprite customSkillTreeIcon; private static Plugin? _instance; private static bool _coreSystemsInitialized; private static bool _emergencyMode; private static int _iconCreationAttempts; private const int MAX_ICON_ATTEMPTS = 5; public static bool IsSkillTreeOpen => (Object)(object)skillTreeUI != (Object)null && (Object)(object)skillTreeUI.panel != (Object)null && skillTreeUI.panel.activeSelf; public static Plugin? Instance => _instance; private void Awake() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; _instance = this; CaptainLevelConfig.Bind(((BaseUnityPlugin)this).Config); Log.LogInfo((object)"[Captain Level System] Config 바인딩 완료"); SkillTreeConfig.Initialize(((BaseUnityPlugin)this).Config); Staff_Config.InitConfig(((BaseUnityPlugin)this).Config); CaptainMMOBridge.Initialize(); InitializeCoreSafeguards(); Harmony val = new Harmony("CaptainSkillTree.Mod"); Log.LogInfo((object)"========== Captain SkillTree 초기화 중... =========="); try { val.PatchAll(); Log.LogInfo((object)("========== Captain SkillTree 초기화 완료! (MMO: " + (EpicMMOReflectionHelper.IsAvailable ? "연동" : "독립") + ") ==========")); Log.LogDebug((object)"[Harmony] 패치 등록 완료"); } catch (Exception ex) { Log.LogError((object)("=== [CRITICAL] Harmony.PatchAll() 실패: " + ex.Message + " ===")); Log.LogError((object)("=== [CRITICAL] StackTrace: " + ex.StackTrace + " ===")); } InitializeInputListener(); SkillTreeData.RegisterAll(); SafeLoadCustomIcon(); InitializeBGMSystem(); InitializePrefabSystem(); RegisterJotunnCommands(); _coreSystemsInitialized = true; Log.LogWarning((object)"========== Captain SkillTree Mod 로딩 성공 =========="); } private void RegisterJotunnCommands() { try { CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SkillAddConsoleCommand()); CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new SkillResetConsoleCommand()); Log.LogInfo((object)"[Jotunn] 콘솔 명령어 등록 완료: skilladd, skillreset"); } catch (Exception ex) { Log.LogError((object)("[Jotunn] 콘솔 명령어 등록 실패: " + ex.Message)); } } private static void InitializeCoreSafeguards() { try { if (!_coreSystemsInitialized) { ValidateEssentialResources(); } } catch (Exception ex) { Log.LogError((object)("[안전 장치] 초기화 실패: " + ex.Message)); _emergencyMode = true; } } private static void InitializeInputListener() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown try { if ((Object)(object)SkillTreeInputListener.Instance == (Object)null) { GameObject val = new GameObject("SkillTreeInputListener"); val.AddComponent<SkillTreeInputListener>(); Object.DontDestroyOnLoad((Object)(object)val); } } catch (Exception ex) { Log.LogError((object)("[안전 장치] InputListener 초기화 실패: " + ex.Message)); } } private static void ValidateEssentialResources() { string[] array = new string[4] { "CaptainSkillTree.asset.Resources.skill_node", "CaptainSkillTree.asset.Resources.captainskilltreeui", "CaptainSkillTree.asset.Resources.skill_start", "CaptainSkillTree.asset.Resources.job_icon" }; string[] array2 = array; foreach (string text in array2) { Assembly assembly = typeof(Plugin).Assembly; Stream manifestResourceStream = assembly.GetManifestResourceStream(text); if (manifestResourceStream == null) { throw new Exception("필수 리소스 누락: " + text); } manifestResourceStream.Close(); } ResetEmergencyMode(); } private static void ResetEmergencyMode() { _emergencyMode = false; _iconCreationAttempts = 0; } private static void SafeLoadCustomIcon() { try { Log.LogDebug((object)"[아이콘] 커스텀 아이콘 로드 시작"); AssetBundle val = GetJobIconBundle(); if ((Object)(object)val != (Object)null) { Log.LogDebug((object)"[아이콘] job_icon 번들 로드 성공"); string[] array = new string[12] { "Paladin_unlock", "Tanker_unlock", "Berserker_unlock", "Archer_unlock", "Mage_unlock", "Rogue_unlock", "Paladin", "Tanker", "Berserker", "Archer", "Mage", "Rogue" }; string[] array2 = array; foreach (string text in array2) { Sprite val2 = val.LoadAsset<Sprite>(text); if ((Object)(object)val2 != (Object)null) { Log.LogDebug((object)("[아이콘] job_icon에서 " + text + " 로드 성공: " + ((Object)val2).name)); } } } AssetBundle val3 = GetCustomIconBundle(); if ((Object)(object)val3 != (Object)null) { Log.LogDebug((object)"[아이콘] 커스텀 아이콘 번들 로드 성공"); string[] allAssetNames = val3.GetAllAssetNames(); Log.LogDebug((object)$"[아이콘] 번들 에셋 수: {allAssetNames.Length}"); string[] array3 = allAssetNames; foreach (string text2 in array3) { Log.LogDebug((object)("[아이콘] 번들 에셋: " + text2)); } customSkillTreeIcon = val3.LoadAsset<Sprite>("skill_start"); if ((Object)(object)customSkillTreeIcon != (Object)null) { Log.LogDebug((object)"[아이콘] skill_start 스프라이트 로드 성공"); } else { TryAlternativeIconNames(val3); } } } catch (Exception ex) { Log.LogError((object)("[아이콘] 커스텀 아이콘 로드 중 오류: " + ex.Message)); Log.LogError((object)("[아이콘] StackTrace: " + ex.StackTrace)); } } private static void TryAlternativeIconNames(AssetBundle bundle) { string[] array = new string[7] { "skill_start", "SkillStart", "skill_tree_start", "captainskilltreeicon", "CaptainSkillTreeIcon", "SkillTreeIcon", "skilltreeicon" }; string[] array2 = array; foreach (string text in array2) { Sprite val = bundle.LoadAsset<Sprite>(text); if ((Object)(object)val != (Object)null) { customSkillTreeIcon = val; Log.LogDebug((object)("[아이콘] 대체 이름으로 아이콘 로드 성공: " + text)); return; } } Log.LogWarning((object)"[아이콘] 모든 아이콘 이름 시도 실패 - 게임 기본 아이콘 사용"); } public static AssetBundle GetIconAssetBundle() { if ((Object)(object)iconAssetBundle == (Object)null) { Assembly assembly = typeof(Plugin).Assembly; Stream manifestResourceStream = assembly.GetManifestResourceStream("CaptainSkillTree.asset.Resources.skill_node"); if (manifestResourceStream != null) { iconAssetBundle = AssetBundle.LoadFromStream(manifestResourceStream); } } return iconAssetBundle; } public static AssetBundle GetUIAssetBundle() { if ((Object)(object)uiAssetBundle == (Object)null) { Assembly assembly = typeof(Plugin).Assembly; Stream manifestResourceStream = assembly.GetManifestResourceStream("CaptainSkillTree.asset.Resources.captainskilltreeui"); if (manifestResourceStream != null) { uiAssetBundle = AssetBundle.LoadFromStream(manifestResourceStream); } } return uiAssetBundle; } public static AssetBundle GetCustomIconBundle() { if ((Object)(object)customIconBundle == (Object)null) { try { Assembly assembly = typeof(Plugin).Assembly; Log.LogDebug((object)("[번들] Assembly: " + assembly.FullName)); string[] manifestResourceNames = assembly.GetManifestResourceNames(); Log.LogDebug((object)$"[번들] 사용 가능한 리소스 수: {manifestResourceNames.Length}"); bool flag = false; string[] array = manifestResourceNames; foreach (string text in array) { Log.LogDebug((object)("[번들] 리소스: " + text)); if (text.Contains("skill_start")) { flag = true; Log.LogDebug((object)("[번들] 시작 아이콘 리소스 발견: " + text)); } } if (!flag) { Log.LogError((object)"[번들] skill_start 리소스가 DLL에 포함되지 않음!"); } Stream manifestResourceStream = assembly.GetManifestResourceStream("CaptainSkillTree.asset.Resources.skill_start"); if (manifestResourceStream != null) { Log.LogDebug((object)$"[번들] 스트림 로드 성공, 크기: {manifestResourceStream.Length} bytes"); customIconBundle = AssetBundle.LoadFromStream(manifestResourceStream); if ((Object)(object)customIconBundle != (Object)null) { Log.LogDebug((object)"[번들] AssetBundle 로드 성공"); } else { Log.LogError((object)"[번들] AssetBundle.LoadFromStream 실패"); } } else { Log.LogError((object)"[번들] 리소스 스트림이 null"); } } catch (Exception ex) { Log.LogError((object)("[번들] GetCustomIconBundle 오류: " + ex.Message)); } } return customIconBundle; } public static AssetBundle GetJobIconBundle() { if ((Object)(object)jobIconBundle == (Object)null) { Assembly assembly = typeof(Plugin).Assembly; Stream manifestResourceStream = assembly.GetManifestResourceStream("CaptainSkillTree.asset.Resources.job_icon"); if (manifestResourceStream != null) { jobIconBundle = AssetBundle.LoadFromStream(manifestResourceStream); if ((Object)(object)jobIconBundle != (Object)null) { Log.LogDebug((object)"[아이콘] job_icon 번들 로드 성공"); string[] allAssetNames = jobIconBundle.GetAllAssetNames(); Log.LogDebug((object)$"[아이콘] job_icon 번들 에셋 수: {allAssetNames.Length}"); string[] array = allAssetNames; foreach (string text in array) { Log.LogDebug((object)("[아이콘] job_icon 에셋: " + text)); } } else { Log.LogError((object)"[아이콘] job_icon AssetBundle.LoadFromStream 실패"); } } else { Log.LogWarning((object)"[아이콘] job_icon 리소스 스트림이 null"); } } return jobIconBundle; } public static AssetBundle GetVfxBundle() { if ((Object)(object)vfxBundle == (Object)null) { Assembly assembly = typeof(Plugin).Assembly; Stream manifestResourceStream = assembly.GetManifestResourceStream("CaptainSkillTree.asset.VFX.vfxbundle"); if (manifestResourceStream != null) { vfxBundle = AssetBundle.LoadFromStream(manifestResourceStream); if ((Object)(object)vfxBundle != (Object)null) { Log.LogDebug((object)"[VFX] VFX 폴더에서 vfxbundle 번들 로드 성공"); } else { Log.LogError((object)"[VFX] VFX 폴더에서 vfxbundle 번들 로드 실패"); } } else { Log.LogError((object)"[VFX] VFX 폴더에서 vfxbundle 리소스 스트림을 찾을 수 없음"); } } return vfxBundle; } public static AssetBundle GetJobVfxBundle() { if ((Object)(object)jobVfxBundle == (Object)null) { Assembly assembly = typeof(Plugin).Assembly; Stream manifestResourceStream = assembly.GetManifestResourceStream("CaptainSkillTree.asset.Resources.job_vfx"); if (manifestResourceStream != null) { jobVfxBundle = AssetBundle.LoadFromStream(manifestResourceStream); if ((Object)(object)jobVfxBundle != (Object)null) { Log.LogDebug((object)"[VFX] job_vfx 번들 로드 성공"); } else { Log.LogError((object)"[VFX] job_vfx 번들 로드 실패"); } } else { Log.LogError((object)"[VFX] job_vfx 리소스 스트림을 찾을 수 없음"); } } return jobVfxBundle; } public static T LoadEmbeddedAsset<T>(string resourcePath) where T : Object { try { Assembly assembly = typeof(Plugin).Assembly; Stream manifestResourceStream = assembly.GetManifestResourceStream(resourcePath); if (manifestResourceStream == null) { Log.LogWarning((object)("[LoadEmbeddedAsset] 리소스를 찾을 수 없음: " + resourcePath)); return default(T); } AssetBundle val = AssetBundle.LoadFromStream(manifestResourceStream); if ((Object)(object)val == (Object)null) { Log.LogWarning((object)("[LoadEmbeddedAsset] AssetBundle 로드 실패: " + resourcePath)); manifestResourceStream.Close(); return default(T); } T[] array = val.LoadAllAssets<T>(); if (array.Length != 0) { T val2 = array[0]; Log.LogInfo((object)("[LoadEmbeddedAsset] 에셋 로드 성공: " + resourcePath + " -> " + ((Object)val2).name)); return val2; } Log.LogWarning((object)("[LoadEmbeddedAsset] " + typeof(T).Name + " 타입의 에셋을 찾을 수 없음: " + resourcePath)); val.Unload(false); manifestResourceStream.Close(); return default(T); } catch (Exception ex) { Log.LogError((object)("[LoadEmbeddedAsset] 에셋 로드 오류: " + resourcePath + " - " + ex.Message)); return default(T); } } private static void ShowSkillTreeIcon() { if (_emergencyMode || _iconCreationAttempts >= 5) { Log.LogWarning((object)"[안전 장치] 비상 모드 또는 최대 시도 횟수 초과 - 아이콘 생성 건너뛰기"); return; } try { if (!ValidatePrerequisites()) { Log.LogWarning((object)"[안전 장치] 전제 조건 미충족 - 아이콘 생성 연기"); return; } Type type = Type.GetType("EpicMMOSystem.MyUI, EpicMMOSystem"); if (type != null && TryCreateMMOStyleIcon()) { ResetIconAttempts(); } else { CreateFallbackSkillTreeIcon(); } } catch (Exception ex) { _iconCreationAttempts++; Log.LogError((object)$"[안전 장치] SkillTreeIcon 생성 중 예외 (시도 {_iconCreationAttempts}/{5}): {ex.Message}"); Log.LogError((object)("[안전 장치] StackTrace: " + ex.StackTrace)); if (_iconCreationAttempts < 5) { try { CreateFallbackSkillTreeIcon(); return; } catch (Exception ex2) { Log.LogError((object)("[안전 장치] 대체 아이콘 생성도 실패: " + ex2.Message)); return; } } Log.LogError((object)"[안전 장치] 최대 시도 횟수 도달 - 비상 모드 활성화"); _emergencyMode = true; } } private static bool ValidatePrerequisites() { try { if ((Object)(object)Player.m_localPlayer == (Object)null) { Log.LogDebug((object)"[안전 장치] Player가 아직 로드되지 않음"); return false; } if ((Object)(object)InventoryGui.instance == (Object)null) { Log.LogDebug((object)"[안전 장치] InventoryGui가 아직 준비되지 않음"); return false; } if ((Object)(object)GetCustomIconBundle() == (Object)null && (Object)(object)swordIcon == (Object)null) { Log.LogWarning((object)"[안전 장치] 아이콘 리소스가 준비되지 않음 - 로드 시도"); SafeLoadCustomIcon(); LoadGameDefaultIcon(); } return true; } catch (Exception ex) { Log.LogError((object)("[안전 장치] 전제 조건 검증 실패: " + ex.Message)); return false; } } private static void LoadGameDefaultIcon() { try { if (!((Object)(object)swordIcon == (Object)null) || !((Object)(object)ObjectDB.instance != (Object)null)) { return; } GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("SwordIron"); if ((Object)(object)itemPrefab != (Object)null) { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { swordIcon = component.m_itemData.GetIcon(); Log.LogDebug((object)"[안전 장치] 게임 기본 아이콘 로드 성공"); } } } catch (Exception) { } } private static void ResetIconAttempts() { _iconCreationAttempts = 0; } private static bool TryCreateMMOStyleIcon() { //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02ec: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: 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_0319: Unknown result type (might be due to invalid IL or missing references) //IL_033f: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Expected O, but got Unknown try { Type type = Type.GetType("EpicMMOSystem.MyUI, EpicMMOSystem"); if (type == null) { Log.LogWarning((object)"EpicMMOSystem.MyUI 타입을 찾을 수 없음"); return false; } FieldInfo field = type.GetField("navigationPanel", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field == null) { Log.LogWarning((object)"navigationPanel 필드를 찾을 수 없음"); return false; } object? value = field.GetValue(null); GameObject val = (GameObject)((value is GameObject) ? value : null); if ((Object)(object)val == (Object)null) { Log.LogWarning((object)"navigationPanel이 null"); return false; } Transform val2 = val.transform.Find("Buttons"); if ((Object)(object)val2 == (Object)null) { Log.LogWarning((object)"Buttons 오브젝트를 찾을 수 없음"); return false; } Transform val3 = val2.Find("ButtonSkillTree"); if ((Object)(object)val3 != (Object)null) { skillTreeIconObj = ((Component)val3).gameObject; skillTreeIconObj.SetActive(true); return true; } Transform val4 = val2.Find("ButtonLevelSystem"); if ((Object)(object)val4 == (Object)null) { Log.LogWarning((object)"ButtonLevelSystem 오브젝트를 찾을 수 없음"); return false; } skillTreeIconObj = Object.Instantiate<GameObject>(((Component)val4).gameObject, val2); ((Object)skillTreeIconObj).name = "ButtonSkillTree"; Image val5 = skillTreeIconObj.GetComponent<Image>(); if ((Object)(object)val5 == (Object)null) { val5 = skillTreeIconObj.GetComponentInChildren<Image>(); } if ((Object)(object)customSkillTreeIcon != (Object)null) { val5.sprite = customSkillTreeIcon; } else { if ((Object)(object)swordIcon == (Object)null) { ObjectDB instance = ObjectDB.instance; if ((Object)(object)instance == (Object)null) { Log.LogWarning((object)"ObjectDB.instance가 null"); return false; } GameObject itemPrefab = instance.GetItemPrefab("SwordIron"); if ((Object)(object)itemPrefab == (Object)null) { Log.LogWarning((object)"SwordIron 프리팹을 찾을 수 없음"); return false; } ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component == (Object)null) { Log.LogWarning((object)"SwordIron에 ItemDrop 컴포넌트가 없음"); return false; } swordIcon = component.m_itemData.GetIcon(); if ((Object)(object)swordIcon == (Object)null) { Log.LogWarning((object)"SwordIron 아이콘(Sprite)을 찾을 수 없음"); return false; } } val5.sprite = swordIcon; } RectTransform component2 = skillTreeIconObj.GetComponent<RectTransform>(); RectTransform component3 = ((Component)val4).GetComponent<RectTransform>(); component2.anchoredPosition = component3.anchoredPosition + new Vector2(80f, 0f); component2.sizeDelta = component3.sizeDelta; component2.anchorMin = component3.anchorMin; component2.anchorMax = component3.anchorMax; component2.pivot = component3.pivot; ((Transform)component2).localScale = ((Transform)component3).localScale; foreach (Transform item in skillTreeIconObj.transform) { Transform val6 = item; if ((Object)(object)((Component)val6).GetComponent<Image>() == (Object)null) { ((Component)val6).gameObject.SetActive(false); } } SetupIconClickEvent(); Canvas componentInParent = skillTreeIconObj.GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent != (Object)null) { Log.LogDebug((object)$"[시작 아이콘] 부모 Canvas sortingOrder: {componentInParent.sortingOrder}"); } skillTreeIconObj.SetActive(true); Log.LogDebug((object)"[시작 아이콘] 아이콘 생성 및 활성화 완료"); return true; } catch (Exception ex) { Log.LogWarning((object)("아이콘 생성 실패: " + ex.Message)); return false; } } private static void CreateFallbackSkillTreeIcon() { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { Log.LogWarning((object)"[디버그] InventoryGui.instance가 null, 아이콘 생성 불가"); return; } Log.LogInfo((object)"[디버그] InventoryGui 인스턴스 확인됨"); if ((Object)(object)skillTreeIconObj != (Object)null) { skillTreeIconObj.SetActive(true); Log.LogDebug((object)"기존 대체 아이콘 활성화"); return; } try { Canvas componentInChildren = ((Component)instance).GetComponentInChildren<Canvas>(); if ((Object)(object)componentInChildren == (Object)null) { Log.LogWarning((object)"InventoryGui에서 Canvas를 찾을 수 없음"); return; } Transform val = ((Component)componentInChildren).transform.Find("Player"); if ((Object)(object)val == (Object)null) { Log.LogWarning((object)"Player 패널을 찾을 수 없음, Canvas에 직접 배치"); val = ((Component)componentInChildren).transform; } GameObject val2 = new GameObject("ButtonSkillTree_Fallback"); val2.transform.SetParent(val, false); RectTransform val3 = val2.AddComponent<RectTransform>(); val3.anchorMin = new Vector2(0.5f, 0f); val3.anchorMax = new Vector2(0.5f, 0f); val3.pivot = new Vector2(0.5f, 0f); val3.anchoredPosition = new Vector2(100f, 10f); val3.sizeDelta = new Vector2(60f, 60f); Image val4 = val2.AddComponent<Image>(); if ((Object)(object)customSkillTreeIcon != (Object)null) { val4.sprite = customSkillTreeIcon; } else { if ((Object)(object)swordIcon == (Object)null) { ObjectDB instance2 = ObjectDB.instance; if ((Object)(object)instance2 != (Object)null) { GameObject itemPrefab = instance2.GetItemPrefab("SwordIron"); if ((Object)(object)itemPrefab != (Object)null) { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { swordIcon = component.m_itemData.GetIcon(); } } } } val4.sprite = swordIcon; } if ((Object)(object)val4.sprite == (Object)null) { ((Graphic)val4).color = new Color(0.2f, 0.6f, 1f, 0.8f); Log.LogInfo((object)"스프라이트가 없어 단색으로 표시"); } Button val5 = val2.AddComponent<Button>(); ((Selectable)val5).targetGraphic = (Graphic)(object)val4; skillTreeIconObj = val2; SetupIconClickEvent(); Canvas componentInParent = skillTreeIconObj.GetComponentInParent<Canvas>(); if ((Object)(object)componentInParent != (Object)null) { Log.LogDebug((object)$"[대체 아이콘] 부모 Canvas sortingOrder: {componentInParent.sortingOrder}"); } skillTreeIconObj.SetActive(true); Log.LogDebug((object)"아이콘 생성 성공"); } catch (Exception ex) { Log.LogError((object)("대체 아이콘 생성 실패: " + ex.Message)); } } private static void SetupIconSprite(Image image) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_01aa: 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_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: 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_00e9: Unknown result type (might be due to invalid IL or missing references) bool flag = false; try { SafeLoadCustomIcon(); if ((Object)(object)customSkillTreeIcon != (Object)null) { image.sprite = customSkillTreeIcon; ((Graphic)image).color = Color.white; flag = true; Log.LogDebug((object)"[아이콘] 커스텀 아이콘 적용 성공"); } } catch (Exception ex) { Log.LogDebug((object)("[아이콘] 커스텀 아이콘 로드 실패: " + ex.Message)); } if (!flag) { try { if ((Object)(object)ObjectDB.instance != (Object)null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab("SwordIron"); if ((Object)(object)itemPrefab != (Object)null) { ItemDrop component = itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component != (Object)null) { Sprite icon = component.m_itemData.GetIcon(); if ((Object)(object)icon != (Object)null) { image.sprite = icon; ((Graphic)image).color = Color.white; flag = true; Log.LogDebug((object)"[아이콘] 게임 기본 아이콘(검) 적용 성공"); } } } } } catch (Exception ex2) { Log.LogDebug((object)("[아이콘] 기본 아이콘 로드 실패: " + ex2.Message)); } } if (!flag && (Object)(object)((Component)image).transform.parent != (Object)null) { GameObject val = new GameObject("IconText"); val.transform.SetParent(((Component)image).transform.parent, false); Text val2 = val.AddComponent<Text>(); val2.text = "스킬\n트리"; val2.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val2.fontSize = 14; ((Graphic)val2).color = Color.white; val2.alignment = (TextAnchor)4; RectTransform component2 = ((Component)val2).GetComponent<RectTransform>(); component2.anchorMin = Vector2.zero; component2.anchorMax = Vector2.one; component2.offsetMin = Vector2.zero; component2.offsetMax = Vector2.zero; } } private static void SetupIconClickEvent() { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown Button val = skillTreeIconObj.GetComponent<Button>() ?? skillTreeIconObj.AddComponent<Button>(); ((Selectable)val).interactable = true; Image component = skillTreeIconObj.GetComponent<Image>(); if ((Object)(object)component != (Object)null) { ((Graphic)component).raycastTarget = true; } ((UnityEventBase)val.onClick).RemoveAllListeners(); ButtonClickedEvent onClick = val.onClick; object obj = <>c.<>9__44_0; if (obj == null) { UnityAction val2 = delegate { //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown Log.LogDebug((object)"[시작 아이콘] 클릭 이벤트 감지됨!"); if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null && SkillTreeBGMManager.Instance.IsBGMEnabled) { SkillTreeBGMManager.Instance.PlaySkillTreeBGM(); Log.LogInfo((object)"[BGM] 스킬트리 BGM 재생 시작 (BGM 활성화 상태)"); } else if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null) { Log.LogInfo((object)"[BGM] BGM이 비활성화되어 있어 재생하지 않음"); } InventoryGui instance = InventoryGui.instance; if ((Object)(object)instance == (Object)null) { Debug.LogWarning((object)"[스킬트리] InventoryGui.instance를 찾을 수 없음"); } else { Canvas componentInChildren = ((Component)instance).GetComponentInChildren<Canvas>(); if ((Object)(object)skillTreeUI == (Object)null || (Object)(object)skillTreeUI.panel == (Object)null || (Object)(object)skillTreeUI.panel.transform.parent != (Object)(object)((Component)componentInChildren).transform) { if ((Object)(object)skillTreeUI != (Object)null && (Object)(object)skillTreeUI.panel != (Object)null) { Object.Destroy((Object)(object)skillTreeUI.panel); } GameObject val3 = new GameObject("SkillTreeUI"); val3.transform.SetParent(((Component)componentInChildren).transform, false); skillTreeUI = val3.AddComponent<SkillTreeUI>(); skillTreeUI.CreateUI(componentInChildren); Log.LogInfo((object)"[스킬트리] skillTreeUI 새로 생성 및 Canvas 하위에 배치"); } if (!skillTreeUI.panel.activeSelf) { skillTreeUI.RefreshUI(); skillTreeUI.panel.SetActive(true); } else { skillTreeUI.panel.SetActive(false); if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null) { SkillTreeBGMManager.Instance.PauseSkillTreeBGM(); } } } }; <>c.<>9__44_0 = val2; obj = (object)val2; } ((UnityEvent)onClick).AddListener((UnityAction)obj); } private void OnGUI() { try { SkillTreeManager.Instance.OnGUIShowMessage(); } catch (Exception ex) { Log.LogWarning((object)("OnGUI 메시지 표시 중 오류: " + ex.Message)); } } private static void InitializeBGMSystem() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown try { GameObject val = new GameObject("SkillTreeBGMManager"); val.AddComponent<SkillTreeBGMManager>(); Object.DontDestroyOnLoad((Object)(object)val); if ((Object)(object)SkillTreeBGMManager.Instance != (Object)null) { SkillTreeBGMManager.Instance.Initialize(); Log.LogDebug((object)"[BGM] 스킬트리 BGM 시스템 초기화 완료"); } else { Log.LogWarning((object)"[BGM] SkillTreeBGMManager.Instance가 null"); } } catch (Exception ex) { Log.LogError((object)("[BGM] 초기화 실패: " + ex.Message)); } } private static void InitializePrefabSystem() { try { PrefabRegistry.Initialize(); } catch (Exception ex) { Log.LogError((object)("[프리팹] 초기화 실패: " + ex.Message)); } } internal static void InitializeServerSync() { if (ZRoutedRpc.instance != null) { try { ZRoutedRpc.instance.Register<string>("CaptainSkillTree.SkillTreeMod_ConfigSync", (Action<long, string>)RPC_ReceiveConfigSync); return; } catch (ArgumentException ex) { Log.LogWarning((object)("[서버 싱크] RPC가 이미 등록되어 있습니다: " + ex.Message)); return; } catch (Exception ex2) { Log.LogError((object)("[서버 싱크] RPC 등록 중 예외 발생: " + ex2.Message)); return; } } Log.LogWarning((object)"[서버 싱크] ZRoutedRpc.instance가 null입니다. 월드 로드 후 재시도 필요."); } private static void RPC_ReceiveConfigSync(long sender, string jsonData) { try { SkillTreeConfig.ReceiveServerConfig(jsonData); } catch (Exception ex) { Log.LogError((object)("[서버 싱크] 설정 수신 실패: " + ex.Message)); } } internal static void SetAttackConfig(string key, ConsoleEventArgs args) { float result; if (args.Length < 2) { args.Context.AddString("사용법: " + args[0] + " <값>"); } else if (float.TryParse(args[1], out result)) { if (SkillTreeConfig.SetConfigValue(key, result)) { args.Context.AddString($"[SkillTree] {key} = {result} 설정 완료"); } else { args.Context.AddString("[SkillTree] 설정 실패 (서버만 가능)"); } } else { args.Context.AddString("[SkillTree] 잘못된 값: " + args[1]); } } internal static void SetSpeedConfig(string key, ConsoleEventArgs args) { float result; if (args.Length < 2) { args.Context.AddString("사용법: " + args[0] + " <값>"); } else if (float.TryParse(args[1], out result)) { if (SkillTreeConfig.SetConfigValue(key, result)) { args.Context.AddString($"[SkillTree] {key} = {result} 설정 완료"); } else { args.Context.AddString("[SkillTree] 설정 실패 (서버만 가능)"); } } else { args.Context.AddString("[SkillTree] 잘못된 값: " + args[1]); } } internal static void SetArcherConfig(string key, ConsoleEventArgs args) { float result; if (args.Length < 2) { args.Context.AddString("사용법: " + args[0] + " <값>"); } else if (float.TryParse(args[1], out result)) { if (SkillTreeConfig.SetConfigValue(key, result)) { args.Context.AddString($"[SkillTree] {key} = {result} 설정 완료"); } else { args.Context.AddString("[SkillTree] 설정 실패 (서버만 가능)"); } } else { args.Context.AddString("[SkillTree] 잘못된 값: " + args[1]); } } internal static void SetBowConfig(string key, ConsoleEventArgs args) { float result; if (args.Length < 2) { args.Context.AddString("사용법: " + args[0] + " <값>"); } else if (float.TryParse(args[1], out result)) { if (SkillTreeConfig.SetConfigValue(key, result)) { args.Context.AddString($"[SkillTree] {key} = {result} 설정 완료"); } else { args.Context.AddString("[SkillTree] 설정 실패 (서버만 가능)"); } } else { args.Context.AddString("[SkillTree] 잘못된 값: " + args[1]); } } internal static void ShowCurrentConfig() { Log.LogInfo((object)"=== 현재 공격 전문가 설정 ==="); Log.LogInfo((object)$"공격 루트 데미지: {SkillTreeConfig.AttackRootDamageBonusValue}%"); Log.LogInfo((object)$"근접 특화 확률: {SkillTreeConfig.AttackMeleeBonusChanceValue}%"); Log.LogInfo((object)$"근접 특화 피해: {SkillTreeConfig.AttackMeleeBonusDamageValue}%"); Log.LogInfo((object)$"활 특화 확률: {SkillTreeConfig.AttackBowBonusChanceValue}%"); Log.LogInfo((object)$"활 특화 피해: {SkillTreeConfig.AttackBowBonusDamageValue}%"); Log.LogInfo((object)$"석궁 특화 확률: {SkillTreeConfig.AttackCrossbowBonusChanceValue}%"); Log.LogInfo((object)$"석궁 특화 피해: {SkillTreeConfig.AttackCrossbowBonusDamageValue}%"); Log.LogInfo((object)$"지팡이 특화 확률: {SkillTreeConfig.AttackStaffBonusChanceValue}%"); Log.LogInfo((object)$"지팡이 특화 피해: {SkillTreeConfig.AttackStaffBonusDamageValue}%"); Log.LogInfo((object)$"치명타 피해 보너스: {SkillTreeConfig.AttackCritDamageBonusValue}%"); Log.LogInfo((object)$"양손 무기 보너스: {SkillTreeConfig.AttackTwoHandedBonusValue}%"); Log.LogInfo((object)$"한손 무기 보너스: {SkillTreeConfig.AttackOneHandedBonusValue}%"); Log.LogInfo((object)$"연속 근접 보너스: {SkillTreeConfig.AttackFinisherMeleeBonusValue}%"); Log.LogInfo((object)"=== 현재 속도 전문가 설정 ==="); Log.LogInfo((object)$"속도 루트 이동속도: {SkillTreeConfig.SpeedRootMoveSpeedValue}%"); Log.LogInfo((object)$"기초 이동속도: {SkillTreeConfig.SpeedBaseMoveSpeedValue}%"); Log.LogInfo((object)$"구르기 속도: {SkillTreeConfig.SpeedBaseDodgeSpeedValue}%"); Log.LogInfo((object)$"근접 콤보 보너스: {SkillTreeConfig.SpeedMeleeComboBonusValue}%"); Log.LogInfo((object)$"근접 콤보 지속시간: {SkillTreeConfig.SpeedMeleeComboDurationValue}초"); Log.LogInfo((object)$"석궁 장전 속도: {SkillTreeConfig.SpeedCrossbowReloadSpeedValue}%"); Log.LogInfo((object)$"활 적중 보너스: {SkillTreeConfig.SpeedBowHitBonusValue}%"); Log.LogInfo((object)$"활 적중 지속시간: {SkillTreeConfig.SpeedBowHitDurationValue}초"); Log.LogInfo((object)$"지팡이 시전 속도: {SkillTreeConfig.SpeedStaffCastSpeedValue}%"); Log.LogInfo((object)$"음식 효율: {SkillTreeConfig.SpeedFoodEfficiencyValue}%"); Log.LogInfo((object)$"배 속도: {SkillTreeConfig.SpeedShipBonusValue}%"); Log.LogInfo((object)$"쿨타임 감소: {SkillTreeConfig.SpeedCooldownReductionValue}초"); Log.LogInfo((object)$"근접 공격속도: {SkillTreeConfig.SpeedMeleeAttackSpeedValue}%"); Log.LogInfo((object)$"석궁 장전속도: {SkillTreeConfig.SpeedCrossbowDrawSpeedValue}%"); Log.LogInfo((object)$"활 장전속도: {SkillTreeConfig.SpeedBowDrawSpeedValue}%"); Log.LogInfo((object)$"지팡이 시전속도: {SkillTreeConfig.SpeedStaffCastSpeedFinalValue}%"); Log.LogInfo((object)"=== 현재 아처 멀티샷 설정 ==="); Log.LogInfo((object)$"발사할 화살 수: {Archer_Config.ArcherMultiShotArrowCountValue}발"); Log.LogInfo((object)$"화살 소모량: {Archer_Config.ArcherMultiShotArrowConsumptionValue}개"); Log.LogInfo((object)$"화살당 데미지: {Archer_Config.ArcherMultiShotDamagePercentValue}%"); Log.LogInfo((object)"=== 현재 활 전문가 멀티샷 설정 ==="); Log.LogInfo((object)$"Lv1 발동 확률: {SkillTreeConfig.BowMultishotLv1ChanceValue}%"); Log.LogInfo((object)$"Lv2 발동 확률: {SkillTreeConfig.BowMultishotLv2ChanceValue}%"); Log.LogInfo((object)$"추가 화살 수: {SkillTreeConfig.BowMultishotArrowCountValue}발"); Log.LogInfo((object)$"화살 소모량: {SkillTreeConfig.BowMultishotArrowConsumptionValue}개"); Log.LogInfo((object)$"화살당 데미지: {SkillTreeConfig.BowMultishotDamagePercentValue}%"); } } [HarmonyPatch(typeof(Player), "OnDeath")] public static class Player_OnDeath_StopPluginCoroutines_Patch { [HarmonyPostfix] public static void Postfix(Player __instance) { if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && (Object)(object)Plugin.Instance != (Object)null) { try { TankerSkills.CleanupTankerOnDeath(__instance); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[탱커 정리] 실패 (무시): " + ex.Message)); } try { JobSkills.CleanupAllJobSkillsOnDeath(__instance); } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[스킬 정리] 실패 (무시): " + ex2.Message)); } Plugin.Log.LogInfo((object)"[플레이어 사망] 모든 정리 완료 후 코루틴 중지"); ((MonoBehaviour)Plugin.Instance).StopAllCoroutines(); } } } [HarmonyPatch(typeof(Game), "Awake")] public static class AttackSpeedHandler_Game_Awake_Patch { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Handler <>9__1_0; internal double <Postfix>b__1_0(Character character, double speed) { Player val = (Player)(object)((character is Player) ? character : null); if (val != null && ((Character)val).InAttack()) { if (Sword_Skill.IsSlashActive(val)) { return 1.0 + (double)Sword_Config.RushSlashAttackSpeedBonusValue / 100.0; } float totalAttackSpeedBonus = SkillEffect.GetTotalAttackSpeedBonus(val); if (totalAttackSpeedBonus > 0f) { double num = 1.0 + (double)totalAttackSpeedBonus / 100.0; return speed * num; } return speed; } return speed; } } private static bool _attackSpeedHandlerRegistered; [HarmonyPostfix] public static void Postfix() { //IL_0022: 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_002d: Expected O, but got Unknown if (_attackSpeedHandlerRegistered) { return; } try { object obj = <>c.<>9__1_0; if (obj == null) { Handler val = delegate(Character character, double speed) { Player val2 = (Player)(object)((character is Player) ? character : null); if (val2 != null && ((Character)val2).InAttack()) { if (Sword_Skill.IsSlashActive(val2)) { return 1.0 + (double)Sword_Config.RushSlashAttackSpeedBonusValue / 100.0; } float totalAttackSpeedBonus = SkillEffect.GetTotalAttackSpeedBonus(val2); if (totalAttackSpeedBonus > 0f) { double num = 1.0 + (double)totalAttackSpeedBonus / 100.0; return speed * num; } return speed; } return speed; }; <>c.<>9__1_0 = val; obj = (object)val; } AnimationSpeedManager.Add((Handler)obj, 400); _attackSpeedHandlerRegistered = true; } catch (Exception ex) { Plugin.Log.LogError((object)("[공격 속도] AnimationSpeedManager 등록 실패: " + ex.Message)); } } } public static class NerveEnhancementSystem { public class SE_NerveEnhancement : SE_Stats { public SE_NerveEnhancement() { ((StatusEffect)this).m_name = "신경 강화"; ((StatusEffect)this).m_tooltip = "이동속도 +12%"; ((StatusEffect)this).m_ttl = 4f; base.m_speedModifier = 1.12f; } } [HarmonyPatch(typeof(Character), "Damage")] public static class Damage_Patch { private static Dictionary<Player, float> stompCooldowns = new Dictionary<Player, float>(); private static bool Prefix(Character __instance, HitData hit) { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) if (__instance.IsPlayer()) { Player val = (Player)(object)((__instance is Player) ? __instance : null); SkillEffect.SaveOriginalDamage(val, hit); float customDodgeChance = val.GetCustomDodgeChance(); if (customDodgeChance > 0f) { float num = Random.Range(0f, 1f); if (num < customDodgeChance) { hit.m_damage.m_blunt = 0f; hit.m_damage.m_slash = 0f; hit.m_damage.m_pierce = 0f; hit.m_damage.m_chop = 0f; hit.m_damage.m_pickaxe = 0f; hit.m_damage.m_fire = 0f; hit.m_damage.m_frost = 0f; hit.m_damage.m_lightning = 0f; hit.m_damage.m_poison = 0f; hit.m_damage.m_spirit = 0f; val.m_dodgeEffects.Create(((Component)val).transform.position, Quaternion.identity, (Transform)null, 1f, -1); SkillTreeManager instance = SkillTreeManager.Instance; bool flag = instance != null && instance.GetSkillLevel("knife_step2_evasion") > 0; bool flag2 = (instance != null && instance.GetSkillLevel("defense_Step3_agile") > 0) || (instance != null && instance.GetSkillLevel("defense_Step5_stamina") > 0) || (instance != null && instance.GetSkillLevel("defense_Step6_attack") > 0); string text = "회피 성공!"; if (flag && flag2) { text = "\ud83d\udde1\ufe0f 회피 숙련 + 방어 트리 회피!"; } else if (flag) { text = "\ud83d\udde1\ufe0f 회피 숙련!"; } else if (flag2) { text = "\ud83d\udee1\ufe0f 방어 트리 회피!"; } ((Character)val).Message((MessageType)2, text, 0, (Sprite)null); return false; } } SkillTreeManager instance2 = SkillTreeManager.Instance; if (instance2 != null && instance2.GetSkillLevel("Tanker") > 0) { float totalDamage = hit.GetTotalDamage(); if (totalDamage > 0f) { float num2 = 1f - Tanker_Config.TankerPassiveDamageReductionValue / 100f; hit.m_damage.m_damage *= num2; hit.m_damage.m_blunt *= num2; hit.m_damage.m_slash *= num2; hit.m_damage.m_pierce *= num2; hit.m_damage.m_chop *= num2; hit.m_damage.m_pickaxe *= num2; hit.m_damage.m_fire *= num2; hit.m_damage.m_frost *= num2; hit.m_damage.m_lightning *= num2; hit.m_damage.m_poison *= num2; hit.m_damage.m_spirit *= num2; float totalDamage2 = hit.GetTotalDamage(); float num3 = totalDamage - totalDamage2; if (num3 > 0f) { Plugin.Log.LogDebug((object)$"[탱커 패시브] {val.GetPlayerName()} 피해 감소 적용 - 원래: {totalDamage:F1} → 감소후: {totalDamage2:F1} (감소량: {num3:F1})"); ((Character)val).Message((MessageType)1, $"탱커 방어: -{num3:F0} 피해 차단!", 0, (Sprite)null); } } } } Character attacker = hit.GetAttacker(); if ((Object)(object)attacker != (Object)null && attacker.IsPlayer()) { Player player = (Player)(object)((attacker is Player) ? attacker : null); SkillTreeManager instance3 = SkillTreeManager.Instance; if (instance3 != null && instance3.GetSkillLevel("knife_step8_assassination") > 0) { Knife_Skill.ApplyKnifeAssassinationBonus(player, ref hit, __instance); } } return true; } private static void Postfix(Character __instance, HitData hit) { Character attacker = hit.GetAttacker(); if ((Object)(object)attacker != (Object)null && attacker.IsPlayer()) { TryApplyDodgeAndSpeedBuff((Player)(object)((attacker is Player) ? attacker : null)); } if (__instance.IsPlayer()) { Player player = (Player)(object)((__instance is Player) ? __instance : null); CheckStompAutoTrigger(player); } } private static void CheckStompAutoTrigger(Player player) { if ((Object)(object)player == (Object)null || ((Character)player).IsDead()) { return; } SkillTreeManager instance = SkillTreeManager.Instance; if (instance != null && instance.GetSkillLevel("defense_Step4_instant") <= 0) { return; } float healthPercentage = ((Character)player).GetHealthPercentage(); float stompHealthThresholdValue = Defense_Config.StompHealthThresholdValue; if (healthPercentage > stompHealthThresholdValue) { return; } float stompCooldownValue = Defense_Config.StompCooldownValue; if (stompCooldowns.ContainsKey(player)) { float num = Time.time - stompCooldowns[player]; if (num < stompCooldownValue) { float num2 = stompCooldownValue - num; ((Character)player).Message((MessageType)2, $"발구르기 쿨타임 ({num2:F0}초 남음)", 0, (Sprite)null); return; } } SkillEffect.ExecuteStompSkill(player); stompCooldowns[player] = Time.time; } } private static readonly Dictionary<long, float> lastTriggeredTime = new Dictionary<long, float>(); private static readonly Dictionary<long, float> dodgeChanceMap = new Dictionary<long, float>(); private const float BuffDuration = 4f; private const float BuffCooldown = 8f; public static float GetCustomDodgeChance(this Player player) { float value; return dodgeChanceMap.TryGetValue(player.GetPlayerID(), out value) ? value : 0f; } public static void SetCustomDodgeChance(this Player player, float value) { dodgeChanceMap[player.GetPlayerID()] = value; } public static void TryApplyDodgeAndSpeedBuff(Player player) { if (SkillTreeManager.Instance.GetSkillLevel("defense_Step6_attack") > 0) { } } } public static class SimpleVFX { private static Dictionary<string, GameObject> _cachedPrefabs = new Dictionary<string, GameObject>(); private static AssetBundle _debuffBundle = null; private static bool _initialized = false; private static readonly HashSet<string> _customVFXNames = new HashSet<string> { "area_circles_blue", "area_fire_red", "area_heal_green", "area_magic_multicolor", "area_star_ellow", "buff_01", "buff_02a", "buff_03a", "buff_03a_aura", "debuff", "debuff_03", "debuff_03_aura", "statusailment_01", "statusailment_01_aura", "confetti_blast_multicolor", "confetti_directional_multicolor", "dust_permanently_blue", "flash_blue_purple", "flash_ellow", "flash_ellow_pink", "flash_magic_blue_pink", "flash_magic_ellow_blue", "flash_round_ellow", "flash_star_ellow_green", "flash_star_ellow_purple", "guard_01", "healing", "hit_01", "hit_02", "hit_03", "hit_04", "plexus", "shine_blue", "shine_ellow", "shine_pink", "sparkle_ellow", "taunt", "water_blast_blue", "water_blast_green" }; public static GameObject PlayerVFX = null; public static GameObject MonsterVFX = null; public static bool IsInitialized => _initialized && ((Object)(object)PlayerVFX != (Object)null || (Object)(object)MonsterVFX != (Object)null); public static void Initialize() { if (_initialized) { return; } try { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[SimpleVFX] 초기화 시작..."); } LoadFromPrefabRegistry(); LoadDebuffBundle(); CacheValheimPrefabs(); _initialized = true; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[SimpleVFX] 초기화 완료 - 캐시된 프리팹: {_cachedPrefabs.Count}개"); } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogError((object)("[SimpleVFX] 초기화 실패: " + ex.Message)); } } } private static void LoadFromPrefabRegistry() { try { Dictionary<string, GameObject> allRegisteredPrefabs = PrefabRegistry.GetAllRegisteredPrefabs(); int num = 0; foreach (KeyValuePair<string, GameObject> item in allRegisteredPrefabs) { string key = item.Key; GameObject value = item.Value; if (!((Object)(object)value == (Object)null)) { if (_customVFXNames.Contains(key) && !_cachedPrefabs.ContainsKey(key)) { _cachedPrefabs[key] = value; num++; } string text = key.ToLowerInvariant(); if (_customVFXNames.Contains(text) && !_cachedPrefabs.ContainsKey(text)) { _cachedPrefabs[text] = value; num++; } } } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[SimpleVFX] PrefabRegistry에서 {num}개 VFX 로드됨"); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[SimpleVFX] PrefabRegistry 로드 실패: " + ex.Message)); } } } private static void LoadDebuffBundle() { try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string text = null; string[] manifestResourceNames = executingAssembly.GetManifestResourceNames(); foreach (string text2 in manifestResourceNames) { if (text2.EndsWith(".debuff") || text2.Contains(".VFX.debuff")) { text = text2; break; } } if (text == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[SimpleVFX] 'debuff' 리소스 없음"); } return; } using (Stream stream = executingAssembly.GetManifestResourceStream(text)) { if (stream == null) { return; } _debuffBundle = AssetBundle.LoadFromStream(stream); } if (!((Object)(object)_debuffBundle != (Object)null)) { return; } GameObject[] array = _debuffBundle.LoadAllAssets<GameObject>(); if (array.Length != 0) { _cachedPrefabs["debuff"] = array[0]; PlayerVFX = array[0]; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[SimpleVFX] 'debuff' 프리팹 로드 완료: " + ((Object)array[0]).name)); } } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogError((object)("[SimpleVFX] debuff 번들 로드 실패: " + ex.Message)); } } } public static void