using System; using System.Collections.Generic; using UnityEngine; using Colosseum.Abnormalities; namespace Colosseum.Skills { /// /// 젬의 주 역할 분류입니다. /// public enum SkillGemCategory { Common, Attack, Threat, Defense, Support, Control, Efficiency, } /// /// 젬 효과가 발동될 애니메이션 이벤트 인덱스와 효과 목록입니다. /// [Serializable] public class SkillGemTriggeredEffectEntry { [Tooltip("OnEffect(index)와 매칭되는 애니메이션 이벤트 인덱스")] [Min(0)] [SerializeField] private int triggerIndex = 0; [Tooltip("해당 인덱스에서 함께 실행할 추가 효과")] [SerializeField] private List effects = new(); public int TriggerIndex => triggerIndex; public IReadOnlyList Effects => effects; } /// /// 젬이 적중 대상에게 부여할 이상상태 목록입니다. /// [Serializable] public class SkillGemTriggeredAbnormalityEntry { [Tooltip("OnEffect(index)와 매칭되는 애니메이션 이벤트 인덱스")] [Min(0)] [SerializeField] private int triggerIndex = 0; [Tooltip("해당 인덱스에서 적중 대상에게 부여할 이상상태")] [SerializeField] private List abnormalities = new(); public int TriggerIndex => triggerIndex; public IReadOnlyList Abnormalities => abnormalities; } /// /// 스킬의 기반 효과 위에 추가 동작을 덧붙이는 젬 데이터입니다. /// [CreateAssetMenu(fileName = "NewSkillGem", menuName = "Colosseum/Skill Gem")] public class SkillGemData : ScriptableObject { [Header("기본 정보")] [SerializeField] private string gemName; [TextArea(2, 4)] [SerializeField] private string description; [SerializeField] private Sprite icon; [Tooltip("젬의 주 역할 분류")] [SerializeField] private SkillGemCategory category = SkillGemCategory.Common; [Header("장착 제약")] [Tooltip("장착 가능한 기반 스킬 분류입니다. None 또는 All이면 제한하지 않습니다.")] [SerializeField] private SkillBaseType allowedSkillTypes = SkillBaseType.All; [Tooltip("함께 장착할 수 없는 젬 분류")] [SerializeField] private SkillGemCategory[] incompatibleCategories = Array.Empty(); [Tooltip("함께 장착할 수 없는 특정 젬")] [SerializeField] private List incompatibleGems = new(); [Header("기본 수치 보정")] [Tooltip("장착 시 마나 비용 배율")] [Min(0f)] [SerializeField] private float manaCostMultiplier = 1f; [Tooltip("장착 시 쿨타임 배율")] [Min(0f)] [SerializeField] private float cooldownMultiplier = 1f; [Tooltip("장착 시 스킬 애니메이션 재생 속도 배율")] [Min(0.1f)] [SerializeField] private float castSpeedMultiplier = 1f; [Tooltip("장착 시 스킬이 만드는 피해량 배율")] [Min(0f)] [SerializeField] private float damageMultiplier = 1f; [Tooltip("장착 시 스킬이 만드는 회복량 배율")] [Min(0f)] [SerializeField] private float healMultiplier = 1f; [Tooltip("장착 시 스킬이 만드는 보호막량 배율")] [Min(0f)] [SerializeField] private float shieldMultiplier = 1f; [Tooltip("장착 시 스킬이 만드는 위협량 배율")] [Min(0f)] [SerializeField] private float threatMultiplier = 1f; [Tooltip("기반 스킬 시전을 몇 회 더 반복할지 정의합니다. 현재는 계산/표시용으로만 사용됩니다.")] [Min(0)] [SerializeField] private int additionalRepeatCount = 0; [Header("추가 효과")] [Tooltip("시전 시작 시 즉시 발동하는 추가 효과")] [SerializeField] private List castStartEffects = new(); [Tooltip("애니메이션 이벤트 인덱스별로 발동하는 추가 효과")] [SerializeField] private List triggeredEffects = new(); [Header("이상상태 부여")] [Tooltip("스킬 사용 시 자신에게 즉시 부여할 이상상태")] [SerializeField] private List selfAbnormalities = new(); [Tooltip("애니메이션 이벤트 인덱스별로 적중 대상에게 부여할 이상상태")] [SerializeField] private List onHitAbnormalities = new(); public string GemName => gemName; public string Description => description; public Sprite Icon => icon; public SkillGemCategory Category => category; public SkillBaseType AllowedSkillTypes => allowedSkillTypes; public float ManaCostMultiplier => manaCostMultiplier; public float CooldownMultiplier => cooldownMultiplier; public float CastSpeedMultiplier => castSpeedMultiplier; public float DamageMultiplier => damageMultiplier; public float HealMultiplier => healMultiplier; public float ShieldMultiplier => shieldMultiplier; public float ThreatMultiplier => threatMultiplier; public int AdditionalRepeatCount => additionalRepeatCount; public IReadOnlyList IncompatibleCategories => incompatibleCategories; public IReadOnlyList IncompatibleGems => incompatibleGems; public IReadOnlyList CastStartEffects => castStartEffects; public IReadOnlyList TriggeredEffects => triggeredEffects; public IReadOnlyList SelfAbnormalities => selfAbnormalities; public IReadOnlyList OnHitAbnormalities => onHitAbnormalities; /// /// 지정한 기반 스킬에 이 젬을 장착할 수 있는지 확인합니다. /// public bool CanAttachToSkill(SkillData skill) { if (skill == null) return false; if (allowedSkillTypes == SkillBaseType.None || allowedSkillTypes == SkillBaseType.All) return true; return (allowedSkillTypes & skill.BaseTypes) != 0; } /// /// 지정한 젬 분류와 상호 배타적인지 확인합니다. /// public bool IsCategoryIncompatible(SkillGemCategory otherCategory) { if (incompatibleCategories == null || incompatibleCategories.Length == 0) return false; for (int i = 0; i < incompatibleCategories.Length; i++) { if (incompatibleCategories[i] == otherCategory) return true; } return false; } /// /// 지정한 젬과 상호 배타적인지 확인합니다. /// public bool IsGemIncompatible(SkillGemData other) { if (other == null || incompatibleGems == null || incompatibleGems.Count == 0) return false; for (int i = 0; i < incompatibleGems.Count; i++) { if (incompatibleGems[i] == other) return true; } return false; } } }