ThreeKingdomsSlingshot/Assets/Scripts/Runtime/ActionResolver.cs

480 lines
21 KiB
C#
Raw Normal View History

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TKS
{
/// <summary>슬링샷 한 번의 결과 요약.</summary>
public class ActionOutcome
{
public bool BonusMove; // 보병: 최종 목표점 명중 → 추가 이동
public bool Returned; // 기병: 최종 목표점 명중 → 제자리 복귀
public bool Overwatch; // 창병: 최종 목표점 명중 → 대기(견제)
public bool Crit; // 궁병: 최종 목표점 명중 → 크리티컬
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
public bool MovedOnly; // 행동 유닛 자신은 공격하지 않음(이동 · 밀어내기만)
public int DamageDealt;
public int CounterTaken;
public List<Unit> Attacked = new List<Unit>();
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
/// <summary>충돌로 밀려난 유닛(아군·적군 · PD 2026-11-04 #1080).</summary>
public List<Unit> Pushed = new List<Unit>();
/// <summary>밀린 아군이 적과 닿아 얻은 공격 등 부가 설명(HUD 문구).</summary>
public List<string> Notes = new List<string>();
/// <summary>실제로 지나간 경로(시작 포함). 창병 견제 판정용.</summary>
public List<Vector2> Path = new List<Vector2>();
}
/// <summary>
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
/// 슬링샷 벡터(시작점 → 목표점)를 병종 규칙대로 이동·공격으로 해석한다 (PD 2026-11-04 #1080 충돌 규칙).
/// ① 보병: 경로 위 첫 유닛(아군·적군)에 부딪히면 알까기처럼 그 유닛을 남은 힘만큼 밀어내고 자신은 멈춤 · 적이면 공격(반격 받음) · 목표점 명중 시 추가 이동 1회
/// ② 기병: 유닛을 무시하고 관통 · 경로 위 적은 모두 피해(옆으로 밀림) · 아군은 지나칠 거리가 안 나오면 그 아군 직전에 멈춤 · 목표점 명중 시 제자리 복귀
/// ③ 창병: 첫 유닛에 부딪히면 튕기지 않고 남은 거리만큼 밀며 함께 전진 · 적이면 피해(반격 받음) · 아군이면 밀기만 · 목표점 명중 시 대기(견제)
/// ④ 궁병: 사거리 = 슬링샷 최대 거리 · 조준 방향 사거리 안의 적은 제자리에서 사격 · 사거리 밖 ~ ×(1+비율) 안이면 들어올 만큼만 다가가 사격 ·
/// 더 멀면 목표점까지 이동 · 반격 없음 · 목표점 명중 시 크리티컬 · 근접 전투는 피해 50 % · 피격 +50 %(Combat.Damage)
/// ⑤ 밀린 아군(행동 유닛과 같은 진영)이 상대 유닛과 닿으면 그 자리에서 공격 1회(조작마다 · 자기 행동은 소모하지 않음)
/// </summary>
public class ActionResolver
{
readonly BalanceConfig cfg;
readonly BattleManager battle;
readonly System.Random rng;
public ActionResolver(BalanceConfig cfg, BattleManager battle, System.Random rng)
{
this.cfg = cfg;
this.battle = battle;
this.rng = rng;
}
public IEnumerator Resolve(Unit u, Vector2 target, bool moveOnly, ActionOutcome o)
{
Vector2 origin = u.Position;
Vector2 delta = target - origin;
float dist = delta.magnitude;
o.Path.Add(origin);
if (dist < 0.001f || !u.IsAlive) yield break;
Vector2 dir = delta / dist;
switch (u.Type)
{
case UnitType.Infantry:
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
yield return InfantryRoutine(u, origin, dir, dist, target, moveOnly, o);
break;
case UnitType.Spear:
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
yield return SpearRoutine(u, origin, dir, dist, target, moveOnly, o);
break;
case UnitType.Cavalry:
yield return CavalryRoutine(u, origin, dir, dist, target, moveOnly, o);
break;
case UnitType.Archer:
yield return ArcherRoutine(u, origin, dir, dist, target, moveOnly, o);
break;
}
}
// ---------- 미리보기(드라이런) ----------
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
/// <summary>조작 중 표시용: 이 슬링샷으로 행동 유닛이 직접 공격하게 될 적 목록(밀린 아군의 공격은 예측하지 않음).</summary>
public List<Unit> PredictTargets(Unit u, Vector2 target, bool moveOnly)
{
var result = new List<Unit>();
if (moveOnly) return result;
Vector2 origin = u.Position;
Vector2 delta = target - origin;
float dist = delta.magnitude;
if (dist < 0.001f) return result;
Vector2 dir = delta / dist;
float hitDist;
switch (u.Type)
{
case UnitType.Infantry:
case UnitType.Spear:
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
var first = FirstUnitBeforeWall(u, origin, dir, dist, out hitDist);
if (first != null && first.Faction != u.Faction) result.Add(first);
break;
}
case UnitType.Cavalry:
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
float travel = Combat.FreeTravel(u, origin, dir, dist, false, false);
travel = StopBeforeUnclearedAllies(u, origin, dir, travel);
var dists = new List<float>();
result.AddRange(Combat.EnemiesOnPath(u, origin, dir, travel, dists));
break;
}
case UnitType.Archer:
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
var first = Combat.FirstEnemyOnPath(u, origin, dir, u.AttackRange + u.ArcherMoveAllow, out hitDist);
if (first != null) result.Add(first);
break;
}
}
return result;
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
// ---------- 공통 질의 ----------
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
/// <summary>경로 위 첫 유닛. 벽이 그보다 먼저 있으면 null.</summary>
Unit FirstUnitBeforeWall(Unit u, Vector2 origin, Vector2 dir, float dist, out float hitDist)
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
Unit first = Combat.FirstUnitOnPath(u, origin, dir, dist, out hitDist);
if (first == null) return null;
float wall = Combat.FreeTravel(u, origin, dir, dist, false, false);
if (hitDist > wall + Combat.Epsilon)
{
hitDist = 0f;
return null;
}
return first;
}
// ---------- 보병: 알까기 충돌 ----------
IEnumerator InfantryRoutine(Unit u, Vector2 origin, Vector2 dir, float dist, Vector2 target, bool moveOnly, ActionOutcome o)
{
if (moveOnly)
{
yield return MoveFree(u, origin, dir, dist, o);
yield break;
}
float hitDist;
Unit first = FirstUnitBeforeWall(u, origin, dir, dist, out hitDist);
if (first == null)
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
yield return MoveFree(u, origin, dir, dist, o);
yield break;
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
Vector2 contact = origin + dir * hitDist;
yield return Move(u, contact, o); // 부딪힌 지점에서 멈춤
float remaining = Mathf.Max(0f, dist - hitDist);
bool enemy = first.Faction != u.Faction;
bool isFinal = enemy && Combat.EnemyAtPoint(u, target, cfg.finalHitTolerance) == first;
if (enemy)
{
yield return Attack(u, first, false, false, o, true);
if (!u.IsAlive) yield break;
}
else
{
o.MovedOnly = true;
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
}
if (first.IsAlive)
{
// 알까기: 접촉 방향(행동 유닛 중심 → 부딪힌 유닛 중심)으로 남은 힘만큼 밀어낸다
Vector2 n = first.Position - contact;
n = n.sqrMagnitude > 1e-6f ? n.normalized : dir;
yield return Push(first, n, remaining * cfg.collisionPushRatio, u, o);
if (!enemy) yield return PushedAllyAttack(first, o);
}
if (isFinal && u.IsAlive) o.BonusMove = true;
}
// ---------- 창병: 밀며 함께 전진 ----------
IEnumerator SpearRoutine(Unit u, Vector2 origin, Vector2 dir, float dist, Vector2 target, bool moveOnly, ActionOutcome o)
{
if (moveOnly)
{
yield return MoveFree(u, origin, dir, dist, o);
yield break;
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
float hitDist;
Unit first = FirstUnitBeforeWall(u, origin, dir, dist, out hitDist);
if (first == null)
{
yield return MoveFree(u, origin, dir, dist, o);
yield break;
}
Vector2 contact = origin + dir * hitDist;
yield return Move(u, contact, o);
float remaining = Mathf.Max(0f, dist - hitDist);
bool enemy = first.Faction != u.Faction;
bool isFinal = enemy && Combat.EnemyAtPoint(u, target, cfg.finalHitTolerance) == first;
if (enemy)
{
yield return Attack(u, first, false, false, o, true);
if (!u.IsAlive) yield break;
}
else
{
o.MovedOnly = true;
}
if (first.IsAlive && remaining > 0.01f)
{
// 튕기지 않고 앞 유닛을 밀며 함께 전진 · 앞 유닛이 다른 유닛·벽에 막히면 둘 다 멈춤 · 접촉 간격 유지
float travel = Combat.FreeTravel(first, first.Position, dir, remaining, true, true, u);
if (travel > 0.01f)
{
Vector2 firstEnd = first.Position + dir * travel;
Vector2 spearEnd = contact + dir * travel;
Fx.Run(Fx.MoveAlong(first.transform, first.Position, firstEnd, cfg.moveSpeed, null));
yield return Fx.MoveAlong(u.transform, contact, spearEnd, cfg.moveSpeed, null);
first.Position = firstEnd;
u.Position = spearEnd;
o.Path.Add(spearEnd);
battle.NotifyChanged();
}
o.Pushed.Add(first);
if (!enemy) yield return PushedAllyAttack(first, o);
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
if (isFinal && u.IsAlive)
{
u.SetOverwatch(true);
o.Overwatch = true;
}
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
// ---------- 기병: 관통 ----------
IEnumerator CavalryRoutine(Unit u, Vector2 origin, Vector2 dir, float dist, Vector2 target, bool moveOnly, ActionOutcome o)
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
float travel = Combat.FreeTravel(u, origin, dir, dist, false, false); // 유닛은 무시 · 벽만
travel = StopBeforeUnclearedAllies(u, origin, dir, travel); // 지나칠 수 없는 아군 직전에서 멈춤
var dists = new List<float>();
var enemies = moveOnly ? new List<Unit>() : Combat.EnemiesOnPath(u, origin, dir, travel, dists);
Unit finalHit = moveOnly ? null : Combat.EnemyAtPoint(u, target, cfg.finalHitTolerance);
bool willReturn = finalHit != null && enemies.Contains(finalHit);
Vector2 end = origin + dir * travel;
if (!willReturn) end = BackOffFromEnemies(u, origin, dir, travel);
if (enemies.Count == 0)
{
yield return Move(u, end, o);
o.MovedOnly = true;
yield break;
}
if (u.View != null) u.View.PlayAttack();
int idx = 0;
var hit = new List<Unit>();
yield return Fx.MoveAlong(u.transform, origin, end, cfg.moveSpeed, travelled =>
{
while (idx < enemies.Count && travelled >= dists[idx] - 0.01f)
{
PierceHit(u, enemies[idx], dir, o);
hit.Add(enemies[idx]);
idx++;
}
});
u.Position = end;
o.Path.Add(end);
for (; idx < enemies.Count; idx++)
{
if (dists[idx] <= travel + 0.01f)
{
PierceHit(u, enemies[idx], dir, o);
hit.Add(enemies[idx]);
}
}
yield return Fx.Wait(0.15f);
// 살아남은 근접 적의 반격
foreach (var e in hit)
{
if (!u.IsAlive) break;
if (!e.IsAlive || !UnitTypeInfo.IsMelee(e.Type)) continue;
int c = Combat.CounterDamage(cfg, e, u, rng);
u.TakeDamage(c);
o.CounterTaken += c;
Fx.Popup(u.Position, c.ToString(), new Color(1f, 0.45f, 0.45f));
battle.NotifyChanged();
yield return Fx.Wait(0.12f);
}
if (willReturn && u.IsAlive)
{
yield return Fx.Wait(0.1f);
yield return Move(u, origin, o);
o.Returned = true;
}
}
void PierceHit(Unit cav, Unit e, Vector2 dir, ActionOutcome o)
{
if (!e.IsAlive) return;
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
int dmg = Combat.Damage(cfg, cav, e, false, rng, true);
e.TakeDamage(dmg);
o.Attacked.Add(e);
o.DamageDealt += dmg;
Fx.Popup(e.Position, dmg.ToString(), Color.white);
// 옆으로 밀어내기
Vector2 side = new Vector2(-dir.y, dir.x);
float sign = Vector2.Dot(e.Position - cav.Position, side) >= 0f ? 1f : -1f;
if (e.IsAlive)
{
Vector2 to = battle.Board.ClampInside(e.Position + side * sign * cfg.cavalryKnockback, e.Radius);
Fx.Run(Fx.MoveAlong(e.transform, e.Position, to, cfg.moveSpeed * 0.6f, null));
}
battle.NotifyChanged();
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
/// <summary>아군은 관통(통과)하되 travel 안에 완전히 지나칠 수 없는 아군이 있으면 그 아군 직전까지로 줄인다.</summary>
float StopBeforeUnclearedAllies(Unit u, Vector2 origin, Vector2 dir, float travel)
{
float t = travel;
var allies = battle.AliveUnits(u.Faction);
for (int pass = 0; pass < 4; pass++)
{
float before = t;
foreach (var a in allies)
{
if (a == u) continue;
Vector2 rel = a.Position - origin;
float along = Vector2.Dot(rel, dir);
float lat = Mathf.Abs(rel.x * dir.y - rel.y * dir.x);
float sum = u.Radius + a.Radius;
if (lat >= sum || along + sum <= 0f) continue; // 경로와 겹치지 않음 · 뒤쪽
float half = Mathf.Sqrt(sum * sum - lat * lat);
float touch = along - half;
float clear = along + half;
if (t >= clear || t <= touch) continue; // 완전히 지나침 · 닿기 전에 멈춤
t = Mathf.Min(t, Mathf.Max(0f, touch - Combat.Epsilon));
}
if (Mathf.Approximately(before, t)) break;
}
return t;
}
/// <summary>종착점이 적과 겹치면 경로를 되짚어 겹치지 않는 지점까지 물러선다.</summary>
Vector2 BackOffFromEnemies(Unit u, Vector2 origin, Vector2 dir, float travel)
{
float t = travel;
for (int i = 0; i < 40 && t > 0f; i++)
{
Vector2 p = origin + dir * t;
bool overlap = false;
foreach (var e in battle.AliveUnits(u.Faction == Faction.Player ? Faction.Enemy : Faction.Player))
{
if (Vector2.Distance(p, e.Position) < u.Radius + e.Radius - 0.01f)
{
overlap = true;
break;
}
}
if (!overlap) return p;
t -= 0.1f;
}
return origin;
}
// ---------- 궁병 ----------
IEnumerator ArcherRoutine(Unit u, Vector2 origin, Vector2 dir, float dist, Vector2 target, bool moveOnly, ActionOutcome o)
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
// 조준 방향으로 사거리 + 접근 허용 거리 안의 첫 적. hitDist = 그 적 가장자리에 닿기까지의 이동 거리(= 가장자리 간격).
float hitDist = 0f;
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
Unit first = moveOnly ? null : Combat.FirstEnemyOnPath(u, origin, dir, u.AttackRange + u.ArcherMoveAllow, out hitDist);
if (first == null)
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
// 공격 가능 범위에 적이 없으면 목표점까지 이동 (PD 2026-11-04 2차 지시)
yield return MoveFree(u, origin, dir, dist, o);
yield break;
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
// 사거리 안이면 제자리 · 밖이면 가장자리가 사거리에 들어올 만큼만 다가간다(접근 허용 거리 상한)
float need = Mathf.Clamp(hitDist - u.AttackRange, 0f, u.ArcherMoveAllow);
float freeMove = need > 0.01f ? Combat.FreeTravel(u, origin, dir, need, true) : 0f;
if (freeMove > 0.01f) yield return Move(u, origin + dir * freeMove, o);
if (hitDist - freeMove <= u.AttackRange + 0.05f)
{
bool crit = Combat.EnemyAtPoint(u, target, cfg.finalHitTolerance) == first;
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
yield return Attack(u, first, true, crit, o, true);
}
else
{
o.MovedOnly = true; // 아군·벽에 막혀 사거리에 못 들어감
}
}
// ---------- 공통 ----------
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
IEnumerator MoveFree(Unit u, Vector2 origin, Vector2 dir, float dist, ActionOutcome o)
{
float free = Combat.FreeTravel(u, origin, dir, dist, true, true);
yield return Move(u, origin + dir * free, o);
o.MovedOnly = true;
}
IEnumerator Move(Unit u, Vector2 to, ActionOutcome o)
{
yield return Fx.MoveAlong(u.transform, u.Position, to, cfg.moveSpeed, null);
u.Position = to;
o.Path.Add(to);
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
/// <summary>부딪힌 유닛을 n 방향으로 force 만큼 밀어낸다(다른 유닛·벽에 닿으면 멈춤). 밀어 주는 유닛(pusher)은 막는 것으로 보지 않는다.</summary>
IEnumerator Push(Unit target, Vector2 n, float force, Unit pusher, ActionOutcome o)
{
if (target == null || !target.IsAlive || force < 0.01f) yield break;
float slide = Combat.FreeTravel(target, target.Position, n, force, true, true, pusher);
if (slide > 0.01f)
{
Vector2 end = battle.Board.ClampInside(target.Position + n * slide, target.Radius);
yield return Fx.MoveAlong(target.transform, target.Position, end, cfg.moveSpeed, null);
target.Position = end;
}
o.Pushed.Add(target);
battle.NotifyChanged();
}
/// <summary>규칙 ⑤: 밀린 아군이 상대 유닛과 닿아 있으면 그 자리에서 공격 1회(근접 · 자기 행동 소모 없음).</summary>
IEnumerator PushedAllyAttack(Unit ally, ActionOutcome o)
{
if (ally == null || !ally.IsAlive) yield break;
Unit foe = Combat.TouchingOpponent(ally);
if (foe == null) yield break;
yield return Fx.Wait(0.1f);
yield return Attack(ally, foe, false, false, o, false);
}
/// <summary>공격 1회. byActor = 행동 유닛의 공격(결과 요약에 집계) · false = 밀린 아군의 공격(Notes 에 기록).</summary>
IEnumerator Attack(Unit a, Unit d, bool ranged, bool crit, ActionOutcome o, bool byActor)
{
if (a.View != null) a.View.PlayAttack();
if (ranged) yield return Fx.Arrow(a.Position, d.Position);
else yield return Fx.Lunge(a, d.Position);
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
int dmg = Combat.Damage(cfg, a, d, crit, rng, !ranged);
d.TakeDamage(dmg);
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
if (byActor)
{
o.Attacked.Add(d);
o.DamageDealt += dmg;
o.Crit |= crit;
}
Fx.Popup(d.Position, crit ? dmg + "!" : dmg.ToString(), crit ? new Color(1f, 0.7f, 0.2f) : Color.white);
battle.NotifyChanged();
yield return Fx.Wait(0.2f);
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
int counter = 0;
if (!ranged && d.IsAlive && a.IsAlive)
{
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
counter = Combat.CounterDamage(cfg, d, a, rng);
if (d.View != null) d.View.PlayAttack();
yield return Fx.Lunge(d, a.Position);
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
a.TakeDamage(counter);
if (byActor) o.CounterTaken += counter;
Fx.Popup(a.Position, counter.ToString(), new Color(1f, 0.45f, 0.45f));
battle.NotifyChanged();
yield return Fx.Wait(0.2f);
}
전투 로직 #1080 — 알까기 충돌(보병) · 관통·아군 직전 정지(기병) · 밀며 함께 전진(창병) · 밀린 아군 공격 기회 · 궁병 제자리 사격(사거리 = 슬링샷)+접근 20 % · 궁수 근접 피해 50 %/피격 +50 % · 원화 1차·2차 반영(전장 배경 + 황건적 5 + 동탁군 4) · 테스트 22/22 - ActionResolver 전면 재작성: InfantryRoutine(접촉점 정지 · Push 접촉 방향 × collisionPushRatio · 적이면 공격+반격 뒤 밀림) · SpearRoutine(앞 유닛과 같은 속도로 함께 전진 · 접촉 간격 유지) · CavalryRoutine(벽만 막음 · StopBeforeUnclearedAllies) · ArcherRoutine(AttackRange = 슬링 · ArcherMoveAllow = 슬링 × archerRangeRatio) · PushedAllyAttack(규칙 ⑤ · ActionOutcome.Pushed/Notes) - Combat: Damage(melee) 궁병 근접 배율(근접 유닛 상대만) · FirstUnitOnPath · TouchingOpponent · FreeTravel ignore - BalanceConfig/Defaults: archerMeleeDealtRatio 0.5 · archerMeleeTakenRatio 1.5 · collisionPushRatio 1 · boardArt battlefield_01 (자산 재시드) - Board: Resources/Board/<boardArt> 원화 배경(격자·진영 띠 생략) · UnitArtImporter Board 규칙 · GameBootstrap - Resources/Units: hgj_infantry·spear·cavalry·archer·boss_zhangjiao · dz_infantry·spear·cavalry·archer (원화 세션 납품 정지 그림 · rig_frames_export static) · Resources/Board/battlefield_01.png - BattleManager Describe 「밀어냄 · 밀린 B → 적 공격」 · BattleHUD 궁병 줄 · 테스트 22종(신규·개정 7 + 원화 확인) · CLAUDE.md · README Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 06:56:02 +00:00
if (!byActor)
{
o.Notes.Add("밀린 " + a.DisplayName + " → " + d.DisplayName + " 공격 " + dmg + (counter > 0 ? " · 반격 " + counter : ""));
}
}
}
}