1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | using UnityEngine; using StatSystem; using Core; using CombatSystem; namespace CombatSystem { public static class DamageApplier { /// <summary> /// 주어진 공격자의 스탯 컨트롤러와 데미지 정보를 사용하여 대상에게 데미지를 적용 /// </summary> /// <param name="attackerStatController">공격자의 스탯 컨트롤러</param> /// <param name="damageable">데미지를 받을 대상</param> /// <param name="rawDamage">원본 데미지 정보</param> public static void ApplyDamage(StatController attackerStatController, IDamageable damageable, IEnhancedDamage rawDamage) { // 데미지 타입에 따른 데미지 계산 전략을 선택 var damageCalculationStrategy = SelectDamageStrategy(rawDamage.GetDamageType()); // 최종 데미지를 계산 int finalDamage = damageCalculationStrategy.CalculateDamage(attackerStatController, rawDamage); // 공격자의 크리티컬 확률을 가져옴 float shooterCriticalChance = attackerStatController.GetStatValue("CriticalHitChance"); // 공격 자체의 크리티컬 확률을 가져옴 float totalCriticalChance = rawDamage.GetCriticalHitChance() + shooterCriticalChance; // 크리티컬 히트 여부를 결정 (무작위 값을 기반으로 크리티컬 확률이 넘으면 true) bool isCriticalHit = Random.Range(0f, 100f) < totalCriticalChance; if (isCriticalHit) { // 공격자의 크리티컬 배율을 가져옴 float attackerCriticalMultiplier = attackerStatController.GetStatValue("CriticalHitMultiplier"); // 최종 크리티컬 배율 계산 (공격자의 크리티컬 배율 + 공격 자체의 크리티컬 배율) float totalCriticalMultiplier = (rawDamage.GetCriticalDamageMultiplier() + attackerCriticalMultiplier) / 100f; // 최종 데미지에 크리티컬 배율 적용 finalDamage = Mathf.RoundToInt(finalDamage * totalCriticalMultiplier); } // HealthModifier 객체를 생성하여 데미지 정보를 설정 HealthModifier damageInfo = new HealthModifier(); //FinalDamage 계산하는 부분은 Take 데미지와 반대여야함 damageInfo.SetMagnitude(-finalDamage); damageInfo.SetIsCriticalHit(rawDamage.GetIsCriticalHit()); damageInfo.SetInstigator(attackerStatController.gameObject); damageInfo.SetSource(rawDamage.GetSource()); // 대상에게 데미지를 적용 damageable.TakeDamage(damageInfo); } /// <summary> /// 주어진 대상의 스탯 컨트롤러와 데미지 정보를 사용하여 데미지를 계산하고 적용 /// </summary> /// <param name="targetStatController">데미지를 받을 대상의 스탯 컨트롤러</param> /// <param name="rawDamage">원본 데미지 정보</param> public static void TakeDamage(StatController targetStatController, IDamage rawDamage) { // 데미지 타입에 따른 방어 계산 전략을 선택 var defenseStrategy = SelectDefenseStrategy(rawDamage.GetDamageType()); // 최종 방어 후 데미지를 계산 int finalDamage = defenseStrategy.CalculateDefense(targetStatController, rawDamage); //Debug.Log("최종 데미지"+finalDamage); // HealthModifier 객체를 생성하여 데미지 정보를 설정 HealthModifier damageInfo = new HealthModifier(); damageInfo.SetMagnitude(finalDamage); damageInfo.SetIsCriticalHit(rawDamage.GetIsCriticalHit()); damageInfo.SetInstigator(rawDamage.GetInstigator()); damageInfo.SetSource(rawDamage.GetSource()); Stat healthStat = targetStatController.GetStat("Health"); // 대상의 체력에 데미지를 적용 //(targetStatController.GetStat("Health") as Attribute).ApplyModifier(damageInfo); // Health가 Attribute 또는 CalculatedAttribute인지 확인하고 데미지 적용 if (healthStat is Attribute healthAttribute) { //Debug.Log("스탯 컨트롤러에 적용"); healthAttribute.ApplyModifier(damageInfo); } else if (healthStat is CalculatedAttribute calculatedAttribute) { calculatedAttribute.ApplyModifier(damageInfo); } } /// <summary> /// 주어진 데미지 타입에 따른 방어 계산 전략을 선택 /// </summary> /// <param name="damageType">데미지 타입</param> /// <returns>방어 계산 전략</returns> public static IDefenseCalculationStrategy SelectDefenseStrategy(DamageType damageType) { switch (damageType) { case DamageType.PhysicalRanged: case DamageType.PhysicalMelee: return new PhysicalDefenseStrategy(); case DamageType.Magical: return new MagicalDefenseStrategy(); default: Debug.LogError($"Unexpected damage type: {damageType}"); return null; } } /// <summary> /// 주어진 데미지 타입에 따른 데미지 계산 전략을 선택 /// </summary> /// <param name="damageType">데미지 타입</param> /// <returns>데미지 계산 전략</returns> public static IDamageCalculationStrategy SelectDamageStrategy(DamageType damageType) { switch (damageType) { case DamageType.PhysicalRanged: return new PhysicalRangedDamageStrategy(); case DamageType.PhysicalMelee: return new PhysicalMeleeDamageStrategy(); case DamageType.Magical: return new MagicalDamageStrategy(); default: Debug.LogError($"Unexpected damage type: {damageType}"); return null; } } /// <summary> /// 주어진 크리티컬 히트 확률을 기반으로 크리티컬 히트 여부를 결정 /// </summary> /// <param name="statController">스탯 컨트롤러</param> /// <param name="attackCriticalHitChance">프로젝트 타격 확률</param> /// <returns>크리티컬 히트 여부</returns> private static bool GetIsCriticalHit(StatController statController, float attackCriticalHitChance) { // 공격자의 크리티컬 히트 확률을 가져옴 int entityCriticalHitChance = statController.GetStatValue("CriticalHitChance"); // 공격의 최종 크리티컬 히트 확률을 계산합니다. float finalCriticalHitChance = attackCriticalHitChance + entityCriticalHitChance; // 무작위 값을 기반으로 크리티컬 히트 여부를 결정합니다. return Random.Range(0f, 100f) < finalCriticalHitChance; } } } | cs |
뭐가 좋아진거임 ㅇㅅㅇ?
패턴 적용할줄 아니까 전체적으로 코드가 알기 쉬워짐
함수쓰면 될거를 쓸데없이 클래스로 만들어서 코드만 길어짐
근가