feat: 무기 특성(WeaponTrait) 시스템 및 보조손 장착 구현

- WeaponTrait enum 추가 (Melee/TwoHanded/Defense/Magic/Ranged)

- SkillData에 allowedWeaponTraits 필드 및 MatchesWeaponTrait() 검증 메서드 추가

- WeaponEquipment에 보조손(오프핸드) 슬롯 지원 (장착/해제/스탯 보너스/네트워크 동기화)

- EquippedWeaponTraits 프로퍼티로 메인+보조 무기 특성 합산 제공

- PlayerSkillInput 4곳(OnSkillInput/RPC/CanUseSkill/DebugExecute)에 무기 trait 제약 검증 추가

- SkillSlotUI에 무기 불호환 시 회색 표시(weaponIncompatibleColor) 지원

- 기존 검 에셋에 weaponTrait=Melee 설정
This commit is contained in:
2026-04-01 21:13:05 +09:00
parent 2ec7216b6d
commit 3663692b9d
6 changed files with 319 additions and 2 deletions

View File

@@ -307,6 +307,13 @@ namespace Colosseum.Player
return;
}
// 무기 trait 제약 검증
if (weaponEquipment != null && !skill.MatchesWeaponTrait(weaponEquipment.EquippedWeaponTraits))
{
Debug.Log($"무기 조건 불충족: {skill.SkillName}");
return;
}
// 마나 비용 체크 (무기 배율 적용)
float actualManaCost = GetActualManaCost(loadoutEntry);
if (networkController != null && networkController.Mana < actualManaCost)
@@ -352,6 +359,10 @@ namespace Colosseum.Player
if (skillController.IsExecutingSkill || skillController.IsOnCooldown(skill))
return;
// 무기 trait 제약 검증
if (weaponEquipment != null && !skill.MatchesWeaponTrait(weaponEquipment.EquippedWeaponTraits))
return;
// 마나 비용 체크 (무기 배율 적용)
float actualManaCost = GetActualManaCost(loadoutEntry);
if (networkController != null && networkController.Mana < actualManaCost)
@@ -578,6 +589,10 @@ namespace Colosseum.Player
if (actionState != null && !actionState.CanStartSkill(skill))
return false;
// 무기 trait 제약 검증
if (weaponEquipment != null && !skill.MatchesWeaponTrait(weaponEquipment.EquippedWeaponTraits))
return false;
return !skillController.IsOnCooldown(skill) && !skillController.IsExecutingSkill;
}
@@ -627,6 +642,13 @@ namespace Colosseum.Player
return false;
}
// 무기 trait 제약 검증
if (weaponEquipment != null && !skill.MatchesWeaponTrait(weaponEquipment.EquippedWeaponTraits))
{
Debug.LogWarning($"[Debug] DebugExecuteSkillAsServer 실패: 무기 조건 불충족");
return false;
}
if (skillController == null || skillController.IsExecutingSkill || skillController.IsOnCooldown(skill))
{
string reason = skillController == null ? "skillController=null" :