using System.Collections.Generic; using System.Linq; using UnityEngine; using Invector.vItemManager; namespace Beyond { public class TrinketManager : MonoBehaviour { [Header("References")] [Tooltip("Drag the bEquipArea used for Trinkets here")] [SerializeField] private bEquipArea trinketEquipArea; [Header("Debug")] [SerializeField] private TrinketStats currentStats; // Struct to pass calculated data to Player [System.Serializable] public struct TrinketStats { // Multipliers (1.0 = 100% / Normal) public float healthMult; public float defenseMult; public float faithMult; public float damageMult; public float speedMult; public float attackSpeedMult; public float faithRegenMult; public float thornDamageMult; // --- NEW ATTRIBUTES --- public float staminaMult; // For Stamina UI Scaling public float soulfireDamageMult; // For Magic Damage (Fireball, etc) // Harmony Flags (Effects from table) public bool effectBalance; // Balance (Flask bonus) public bool effectCalmness; // Calmness (Longer shield) public bool effectFaithVampirism; // Trust (Faith vampirism) public bool effectBreeze; // Zora's Focus (Buff Covert Gaze Radius/Length) public bool effectDetermination; // Determination (Combo damage) public bool effectHealthVampirism; // Vitality (Health vampirism) public bool effectEagerness; // Eagerness (Dash cooldown) public bool effectBloom; // Bloom (Spell cost reduced) public bool effectGrowth; // Growth (Cast restores HP) public bool effectRose; // Rose (Thorn damage) public bool effectDarkening; // The Darkening (Bonus dmg) public bool effectEclipse; // Eclipse (Bonus all) // --- NEW EFFECTS --- public bool effectAngelEye; // Angel Eye (Silent Peek Cost = 0) } private void Start() { if (!trinketEquipArea) { Debug.LogError($"[TrinketManager] No bEquipArea assigned on {gameObject.name}"); return; } // Subscribe to changes trinketEquipArea.onEquipItem.AddListener(OnTrinketChanged); trinketEquipArea.onUnequipItem.AddListener(OnTrinketChanged); // Initial Calculation Invoke(nameof(RecalculateStats), 0.2f); } private void OnTrinketChanged(bEquipArea area, bItem item) { RecalculateStats(); } public void RecalculateStats() { // 1. Reset Stats to Default TrinketStats stats = new TrinketStats { healthMult = 1f, defenseMult = 1f, faithMult = 1f, damageMult = 1f, speedMult = 1f, attackSpeedMult = 1f, faithRegenMult = 1f, thornDamageMult = 1f, // Initialize New Stats staminaMult = 1f, soulfireDamageMult = 1f }; // 2. Get Currently Equipped Items List equippedItems = new List(); foreach (var slot in trinketEquipArea.equipSlots) { if (slot.isValid && slot.item != null) { equippedItems.Add(slot.item); } } // 3. Sum up Percentage Attributes foreach (var item in equippedItems) { stats.healthMult += GetPct(item, bItemAttributes.HealthBonusPercent); stats.defenseMult -= GetPct(item, bItemAttributes.DefenseBonusPercent); stats.faithMult += GetPct(item, bItemAttributes.FaithBonusPercent); stats.damageMult += GetPct(item, bItemAttributes.DamageBonusPercent); stats.speedMult += GetPct(item, bItemAttributes.MoveSpeedBonusPercent); stats.attackSpeedMult += GetPct(item, bItemAttributes.AttackSpeedBonusPercent); stats.faithRegenMult += GetPct(item, bItemAttributes.FaithRegenBonusPercent); stats.thornDamageMult += GetPct(item, bItemAttributes.ThornDamageBonusPercent); // New Attributes stats.staminaMult += GetPct(item, bItemAttributes.StaminaBonusPercent); stats.soulfireDamageMult += GetPct(item, bItemAttributes.SoulfireDamageBonusPercent); } // 4. Apply Harmonies (Based on Table) ApplyHarmonies(equippedItems, ref stats); currentStats = stats; // 5. Send to Player if (Player.Instance != null) { Player.Instance.UpdateTrinketStats(stats); } } private void ApplyHarmonies(List items, ref TrinketStats stats) { int azure = items.Count(i => i.trinketColor == TrinketColor.Azure); int crimson = items.Count(i => i.trinketColor == TrinketColor.Crimson); int viridian = items.Count(i => i.trinketColor == TrinketColor.Viridian); int bright = items.Count(i => i.trinketColor == TrinketColor.Bright); int dark = items.Count(i => i.trinketColor == TrinketColor.Dark); // Balance (A C V) if (azure >= 1 && crimson >= 1 && viridian >= 1) stats.effectBalance = true; // Calmness (A A A) if (azure >= 3) stats.effectCalmness = true; // Trust (A A C) if (azure >= 2 && crimson >= 1) stats.effectFaithVampirism = true; // Zora's Focus / Breeze (A A V) -> Covert Gaze Radius/Length if (azure >= 2 && viridian >= 1) stats.effectBreeze = true; // Determination (C C C) if (crimson >= 3) stats.effectDetermination = true; // Vitality (C C A) if (crimson >= 2 && azure >= 1) stats.effectHealthVampirism = true; // Eagerness (C C V) if (crimson >= 2 && viridian >= 1) stats.effectEagerness = true; // Bloom (V V V) if (viridian >= 3) stats.effectBloom = true; // Growth (V V A) if (viridian >= 2 && azure >= 1) stats.effectGrowth = true; // Rose (V V C) if (viridian >= 2 && crimson >= 1) { stats.effectRose = true; stats.thornDamageMult += 0.05f; } // The Darkening (3 Bright) if (bright >= 3) stats.effectDarkening = true; // Eclipse (2 Bright + 1 Dark) if (bright >= 1 && dark >= 1) stats.effectEclipse = true; // Angel Eye (Requires defining combo, placeholder logic) // if (bright >= 2 && azure >= 1) stats.effectAngelEye = true; } private float GetPct(bItem item, bItemAttributes attrName) { var attr = item.GetItemAttribute(attrName); if (attr != null) { return (float)attr.value / 100f; } return 0f; } } }