From b346fdebe8463a8b2ec6b49f4b98a6b895edfacb Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Tue, 31 Mar 2026 00:13:01 +0900 Subject: [PATCH] =?UTF-8?q?feat(balance):=20=EC=8A=A4=ED=82=AC=20=EB=B2=84?= =?UTF-8?q?=ED=94=84=20=EB=AA=A8=EB=94=94=ED=8C=8C=EC=9D=B4=EC=96=B4=203?= =?UTF-8?q?=EC=A2=85=20=EC=A0=84=ED=88=AC=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - defModifier: 몬스터 반격 시 방어력 배율 적용 (DEF × (1+defMod)) - criRateModifier: 플레이어 공격 시 크리티컬 확률 추가 - evasionModifier: 몬스터 반격 시 회피율 추가 - 기존 atkModifier 패턴과 동일하게 임시 적용 + HP/MP만 반영 --- lib/src/core/engine/combat_tick_service.dart | 40 ++++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/lib/src/core/engine/combat_tick_service.dart b/lib/src/core/engine/combat_tick_service.dart index 66b0357..280ca48 100644 --- a/lib/src/core/engine/combat_tick_service.dart +++ b/lib/src/core/engine/combat_tick_service.dart @@ -125,12 +125,22 @@ class CombatTickService { newEvents.addAll(potionResult.events); } + // 스킬 버프 모디파이어 조회 (전투 계산에 적용) + final buffMods = updatedSkillSystem.totalBuffModifiers; + // 플레이어 공격 체크 if (playerAccumulator >= playerStats.attackDelayMs) { + // 크리티컬 확률 버프 적용 + final buffedPlayerForAttack = buffMods.criMod != 0 + ? playerStats.copyWith( + criRate: (playerStats.criRate + buffMods.criMod).clamp(0.0, 1.0), + ) + : playerStats; + final attackProcessor = PlayerAttackProcessor(rng: rng); final attackResult = attackProcessor.processAttack( state: state, - playerStats: playerStats, + playerStats: buffedPlayerForAttack, monsterStats: monsterStats, updatedSkillSystem: updatedSkillSystem, activeDoTs: activeDoTs, @@ -145,7 +155,14 @@ class CombatTickService { healingMultiplier: healingMultiplier, ); - playerStats = attackResult.playerStats; + // 크리티컬 버프가 적용된 스탯에서 HP/MP만 원본에 반영 + final attackedPlayer = attackResult.playerStats; + playerStats = buffMods.criMod != 0 + ? playerStats.copyWith( + hpCurrent: attackedPlayer.hpCurrent, + mpCurrent: attackedPlayer.mpCurrent, + ) + : attackedPlayer; monsterStats = attackResult.monsterStats; updatedSkillSystem = attackResult.skillSystem; activeDoTs = attackResult.activeDoTs; @@ -161,8 +178,18 @@ class CombatTickService { // 몬스터가 살아있으면 반격 if (monsterStats.isAlive && monsterAccumulator >= monsterStats.attackDelayMs) { + // 방어력/회피율 버프 적용 + final buffedPlayerForDefense = (buffMods.defMod != 0 || + buffMods.evasionMod != 0) + ? playerStats.copyWith( + def: (playerStats.def * (1.0 + buffMods.defMod)).round(), + evasion: (playerStats.evasion + buffMods.evasionMod) + .clamp(0.0, 1.0), + ) + : playerStats; + final monsterAttackResult = _processMonsterAttack( - playerStats: playerStats, + playerStats: buffedPlayerForDefense, monsterStats: monsterStats, activeDebuffs: activeDebuffs, totalDamageTaken: totalDamageTaken, @@ -170,7 +197,12 @@ class CombatTickService { calculator: calculator, ); - playerStats = monsterAttackResult.playerStats; + // 버프 적용된 스탯에서 HP/MP만 원본에 반영 + final defendedPlayer = monsterAttackResult.playerStats; + playerStats = playerStats.copyWith( + hpCurrent: defendedPlayer.hpCurrent, + mpCurrent: defendedPlayer.mpCurrent, + ); totalDamageTaken = monsterAttackResult.totalDamageTaken; newEvents.addAll(monsterAttackResult.events); monsterAccumulator -= monsterStats.attackDelayMs;