feat(BT12-Dev-Clone 완료): A10 분신 스킬 α·β·γ·δ 4단계 SOT 정합
EerieVillage local commit 171506e (18 파일·PD Editor GitAutoSync 자동 push 대기): - 신규 4 (CloneInstance·CloneEffector·A10_bunsin.asset·CloneSkillTests + .meta) - 수정 10 (PlayerSkillInventory·ActiveSkillRuntime·SkillFireEvent·SkillRuntimeFactory·6 Effector) BT 레포 변경: - 설계 v1 §A10 신설 (1063~1586 라인·512+) + 잔존 5 위치 PD 결정 정합 (1423·1427·1431·1524·1572) - 이펙트 SOT v1 §3 A10 (BaseCooldown 25·MinionLifetime 12·PD 결정 4건 주석) + §4 변경 이력 2행 - 개발팀_PD_지시_로그 BT12-Dev-Clone 완료 표기 (commit hash 반영) - 대화로그 EerieVillage 2026-05-15 신설 (BT12-Dev-Clone 4단계 + PD 결정 엔트리) PD 명세 5 + PD 결정 4 정합: - facing 반대 1유닛·alpha 0.5·OnPlayerSkillFired hook 0.5초 지연·damage 50% - BaseCooldown 25·MinionLifetime 12 자동 소멸·facing 고정·무적 Collider 미부착 - Lv 업 분신 수 X·지속시간+데미지 비율(%)↑ (balance 후속) 매니페스트 자동 archive 4종: BT11_Plan_60skills·BT12_C48-50_CSV_DevDelegation·BT12_PD결정3건_집행·BT12_Dev_Clone_A10 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a265d2a9bf
commit
72ee04a1c4
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,129 @@
|
|||
# EerieVillage 대화로그 — 2026-05-15
|
||||
|
||||
## [BT12-Dev-Clone 1단계 완료] 개발팀장 Opus 직접 설계 (A10 분신 스킬)
|
||||
|
||||
**시간**: 2026-05-15 16:56
|
||||
**주체**: 개발팀장 (`dev-team-lead`)
|
||||
**Task ID**: PM 매니페스트 `BT12_Dev_Clone_A10_2026-05-15_2200` (4 target_files)
|
||||
**C49 표준 프로세스 시범**: 1단계 (개발팀장 Opus 설계) → 2단계 (클라이언트팀 Sonnet 구현) → 3단계 (개발팀장 Opus 검증)
|
||||
|
||||
### 결정·근거·영향 (C32 의무 3요소)
|
||||
|
||||
**결정**: A10 분신 스킬 구조 = (나) `CloneInstance` 단일 MonoBehaviour + Player Inventory hook + 0.5초 지연 큐 + `IsCloneFireActive` 분기.
|
||||
|
||||
**근거**:
|
||||
1. PD 명세 5항목 (위치 facing 반대 1유닛·반투명 alpha 0.5·동일 스킬·50% 반감·0.5초 딜레이) 전수 충족
|
||||
2. v0.4 CSV A10 행 "분신 1기·동일 패턴 모방·공격력 비율 감소·무적" 정합
|
||||
3. C11 자원 효율 — MonoBehaviour 1기·Singleton (별도 Inventory mirror 부재)
|
||||
4. C11 코드 직관성 — "Player Fire 0.5초 뒤 분신 위치에서 동일 Effector + 50% damage" 단 1줄 멘탈 모델
|
||||
5. 옵션 (가) 별도 GameObject + Inventory mirror = 코드 중복 (장착·Lv·각성 2중 동기화 부담) → 기각
|
||||
6. 옵션 (다) Player+Clone 2회 동시 발동 = PD 명세 5번 "0.5초 뒤" 직접 위반 → 기각
|
||||
|
||||
**영향**:
|
||||
- 기존 시스템 영향 최소 — `PlayerSkillInventory`에 4필드 + 1이벤트 추가, `ActiveSkillRuntime.Fire()` 1줄, `CalculateEffectiveDamage()` 1줄, `SkillFireEvent.Execute` Minion case CardId 분기, `SkillRuntimeFactory.AvailableCardIds` "A10" 추가
|
||||
- 6개 Effector (Projectile·MeleeArea·LightningStrike·Laser·PoisonSwamp·SpiritFire) 영역 `IsCloneFireActive` 분기 일관 추가 (spawn 위치·facing) — 약 18줄
|
||||
- BT12-Dev-Vis 진행 13 스킬 정상 동작 보장 (분신 hook이 Player 발동 영향 X — `IsCloneFireActive == false` 조건)
|
||||
- Lv 업·각성 영향 X (분신 자체 Lv 업 X — Player Lv 업 시 분신 발동 damage 자동 갱신)
|
||||
|
||||
### 기각안 5건 (C32 의무 — 결정 엔트리 기각안 필드)
|
||||
|
||||
1. **별도 GameObject + 자체 `PlayerSkillInventory` mirror** — 코드 중복·동기화 부담
|
||||
2. **Effector 한 번 호출 시 Player+Clone 2회 발동 (분신 = sprite만)** — PD 명세 0.5초 딜레이 위반
|
||||
3. **`PlayerSkillInventory.transform.position` swap (1 frame)** — Camera·HUD·다른 컴포넌트 transform 참조 부작용 위험
|
||||
4. **분신 lifetime 8초 (A11 동등)** — v0.4 CSV "분신 1기" + "긴 주기" 의미 무너짐
|
||||
5. **분신 facing이 Player와 독립 (적 방향 자체 추적)** — "동일 패턴 모방" v0.4 CSV 정합 X·분신 = 독립 actor 의미 회귀
|
||||
|
||||
### 산출물
|
||||
|
||||
- `프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md` §A10 신설 (16 sub-section)
|
||||
- `프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md` §3 A10 추가 + §4 변경 이력 갱신
|
||||
- `공유/PD_지시_트래킹/개발팀_PD_지시_로그.md` BT12-Dev-Clone 행 1단계 완료 표기
|
||||
|
||||
### PD 결정 안건 (3단계 검증 시 보고)
|
||||
|
||||
1. **BaseCooldown 30** PM 추정 — balance-designer 후속 확정 영역
|
||||
2. **facing 변경 시 분신 위치 처리** — spawn 시점 고정 vs Player 추종 (PM 1차: Player 자식 부착 + spawn facing 고정)
|
||||
3. **분신 무적 spec** — collider 미부착 / 적이 분신 위 올라타거나 적 투사체 통과 영역 Play 검증
|
||||
4. **Lv 업 (분신 수 증가 등) 1차 미반영** — 후속 PD 결정 안건
|
||||
|
||||
### 2단계 작업 단위 분해 (Sonnet Task 위임 예정)
|
||||
|
||||
**파일 13종**:
|
||||
|
||||
| # | 파일 | 작업 |
|
||||
|---|------|------|
|
||||
| 1 | `Assets/Scripts/Skills/Effectors/CloneInstance.cs` | 신규 — MonoBehaviour + 0.5초 지연 큐 |
|
||||
| 2 | `Assets/Scripts/Skills/Effectors/CloneEffector.cs` | 신규 — IEffector 구현 |
|
||||
| 3 | `Assets/Scripts/Skills/Runtime/PlayerSkillInventory.cs` | 수정 — 4필드 + OnPlayerSkillFired 이벤트 |
|
||||
| 4 | `Assets/Scripts/Skills/Runtime/ActiveSkillRuntime.cs` | 수정 — Fire() + CalculateEffectiveDamage() |
|
||||
| 5 | `Assets/Scripts/Skills/Events/SkillFireEvent.cs` | 수정 — Minion CardId 분기 + Cleanup reset |
|
||||
| 6 | `Assets/Scripts/Skills/Runtime/SkillRuntimeFactory.cs` | 수정 — AvailableCardIds "A10" 추가 |
|
||||
| 7~12 | 6개 Effector | 수정 — IsCloneFireActive 분기 일관 추가 |
|
||||
| 13 | `Assets/Resources/Skills/Active/A10_bunsin.asset` | 신규 — A11 동등 패턴 + A10 고유 필드 |
|
||||
| 14 | `Assets/Tests/Editor/CloneSkillTests.cs` | 신규 — EditMode 7건 |
|
||||
|
||||
---
|
||||
|
||||
## [BT12-Dev-Clone PD 결정 4건 반영 2026-05-15]
|
||||
|
||||
**시각**: 2026-05-15 (1단계 결과 보고 후 PD 응답)
|
||||
**주체**: PM 직접 SOT 갱신 (C48 시범 — Task 회피)
|
||||
**영역**: BT12-Dev-Clone 1단계 설계 핵심 영역 변경
|
||||
**유형**: PD 결정 채택 + SOT 4종 갱신
|
||||
|
||||
### PD 결정 4건
|
||||
|
||||
| # | PD 명세 | PM 1차 안 | PD 결정 |
|
||||
|---|---------|----------|---------|
|
||||
| 1 | BaseCooldown | 30초 | **25초** |
|
||||
| 2 | lifetime | 영구 1기 (재발동 시 대체) | **12초 자동 소멸 + Singleton 1기** |
|
||||
| 3 | facing | 고정 (PM 1차) | **고정 확정** |
|
||||
| 4 | 무적 | Collider 미부착 (PM 1차) | **Collider 미부착 확정** |
|
||||
| 5 | Lv 업 | 분신 수 X · 1차 미반영 | **분신 수 X · 추후 지속시간↑ + 플레이어 참조 데미지 비율(%)↑** (balance-designer 후속) |
|
||||
|
||||
### 핵심 변경 — lifetime 12초 자동 소멸
|
||||
|
||||
PM 1차 영구 1기 (Singleton·재발동 시 대체) → PD 결정 **12초 지속 + Singleton 1기**. spawn 시점 `unscaledTime + 12초` 후 자동 destroy. 12초 내 재발동 시 기존 destroy + 새 spawn (Singleton 패턴). BaseCooldown 25초 < lifetime 12초 → 분신 활성 중 재발동 시 자동 갱신.
|
||||
|
||||
### SOT 반영 완료 (PM 직접 Edit)
|
||||
|
||||
| 파일 | 영역 | 변경 |
|
||||
|------|------|------|
|
||||
| `프로젝트/EerieVillage/개발/spec/스킬_시스템_설계_v1.md` | §A10-1 | lifetime 12초·BaseCooldown 25·Lv 업 메커니즘 명시 |
|
||||
| `프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md` | §3 A10 | BaseCooldown 25·MinionLifetime 12·PD 결정 4건 주석 |
|
||||
| `프로젝트/EerieVillage/개발/spec/스킬_이펙트_확정_v1.md` | §4 변경 이력 | PD 결정 4건 행 추가 |
|
||||
| `공유/PD_지시_트래킹/개발팀_PD_지시_로그.md` | BT12-Dev-Clone 사후 조치 | PD 결정 4건 표기 |
|
||||
| `공유/대화로그/EerieVillage/2026-05-15.md` | 본 엔트리 | PD 결정 엔트리 |
|
||||
|
||||
### 2단계 진행 결정
|
||||
|
||||
PM 권고 (b) 4분할 채택 (PD 명시 옵션 결정 X·PM 권고 default 적용). α 분할 진행 대기:
|
||||
- **α**: `CloneInstance.cs`·`CloneEffector.cs` 신규 2 파일 (코어 컴포넌트)
|
||||
- **β**: `PlayerSkillInventory`·`ActiveSkillRuntime`·`SkillFireEvent`·`SkillRuntimeFactory` 수정 4
|
||||
- **γ**: 6 Effector `IsCloneFireActive` 분기 일관 추가
|
||||
- **δ**: `A10_bunsin.asset` 신규 (BaseCooldown 25·MinionLifetime 12·PD 결정 반영) + `CloneSkillTests.cs` EditMode 7건
|
||||
|
||||
### 잔존 정리 영역 (commit 직전 일괄)
|
||||
|
||||
설계 v1 §A10 1421·1429·1522·1523·1570 라인 영역 BaseCooldown 30 잔존 표기 → 25 정정. 본 응답 핵심 SOT (§A10-1·§3 A10) 우선 반영·세부 표 영역 후속 일괄 정정 (commit 직전).
|
||||
|
||||
### 결정·근거·영향
|
||||
|
||||
**결정**: PD 결정 4건 즉시 SOT 반영. 2단계 (b) 4분할 진행 채택.
|
||||
|
||||
**근거**: PD 2026-05-15 직접 결정 (= C1).
|
||||
|
||||
**영향**:
|
||||
- lifetime 12초 변경 = 1단계 설계 핵심 영역 변경. CloneInstance Update에 lifetime 타이머 추가 의무 (α 단계 구현 영역)
|
||||
- Lv 업 메커니즘 명시 = balance-designer 후속 수치 안건 명확화 (지속시간 Lv별 증가량·데미지 비율 Lv별 증가량)
|
||||
- BaseCooldown 25 < lifetime 12 → 분신 활성 중 재발동 시 갱신 가능 (25초 마다 분신 재spawn)
|
||||
|
||||
### 관련 규칙
|
||||
|
||||
- C1 (PD 결정 = 승인) · C5 · C22 (PD 도입 용어 보존 — "지속시간"·"분신 수"·"플레이어 참조 데미지 비율(%)") · C25 · C32 · C34-11
|
||||
- C43 호칭 라우팅 (개발팀 직접 수령)
|
||||
- **C48 시범** (PM 직접 SOT Edit·Task 회피)
|
||||
- **C49 1단계 완료** (개발팀장 설계)·2단계 Sonnet/PM 진행 대기
|
||||
- **C50** (1단계 25K + 2단계 60~80K 4분할 + 3단계 15~20K = 본 BT12-Dev-Clone 총량 100~125K)
|
||||
|
||||
---
|
||||
|
|
@ -1034,6 +1034,7 @@ Phase 2는 **PM이 별도 Task로 클라이언트팀 Sonnet에 위임**하는
|
|||
| 일시 | 변경 | 사유 | 기안 |
|
||||
|------|------|------|------|
|
||||
| 2026-04-24 | v1.0 Phase 1 설계 — 아키텍처 4계층·인터페이스 4+4종·데이터 흐름·자동 발동 사이클·각성 조건 매니저·카테고리 매핑 6+5+4·BT7-Dev 통합 영역 | BT12-Dev PD 직접 지시 "스킬 시스템 설계 진행" + C49 1단계 시범 적용 | 개발팀장 |
|
||||
| 2026-05-15 | §A10 분신 스킬 상세 설계 신설 — PD 명세 5항목 (위치·반투명·동일 스킬·50% 반감·0.5초 딜레이) + 구조 결정 (CloneInstance 단일 + 0.5초 지연 큐) + 신규/수정 파일 13종 분해 + 기각안 5건 + EditMode 7건 + 3단계 검증 항목 7종 | BT12-Dev-Clone PD 직접 지시 + C49 1단계 시범 (개발팀장 Opus 설계 → 클라이언트팀 Sonnet 구현 → 개발팀장 검증) | 개발팀장 |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -1059,6 +1060,519 @@ Phase 2는 **PM이 별도 Task로 클라이언트팀 Sonnet에 위임**하는
|
|||
|
||||
---
|
||||
|
||||
## §A10. 분신 스킬 상세 설계 (BT12-Dev-Clone 2026-05-15)
|
||||
|
||||
> **PD 직접 지시 (2026-05-15)** 원문:
|
||||
> > "1. 이번에는 분신 스킬을 구현해줘.
|
||||
> > 2. 이 스킬을 사용하면 플레이어의 x좌표 1 뒤쪽에 반투명한 형태의 플레이어의 분신이 생성되어서 플레이와 동일한 스킬을 사용해야 해. (단, 분신의 공격은 플레이어의 공격력의 50% 반감되어야하고, 플레이어보다 0.5초 뒤 사용해야 해. (공격 시작 딜레이))"
|
||||
>
|
||||
> **C49 표준 프로세스 시범 — 1단계 (개발팀장 Opus 설계)**.
|
||||
|
||||
### A10-1. PD 명세 5항목 확정
|
||||
|
||||
| # | 항목 | PD 명세 (원문 인용) |
|
||||
|---|------|---------|
|
||||
| 1 | 위치 | "**플레이어의 x좌표 1 뒤쪽**" — facing 반대 방향 1유닛 (예: facing=오른쪽 → 분신 x = player.x - 1) |
|
||||
| 2 | 외형 | "**반투명한 형태의 플레이어의 분신**" — Player sprite 복제 + alpha 0.5 (개발팀장 재량) |
|
||||
| 3 | 동작 | "**플레이와 동일한 스킬을 사용**" — Player 장착 액티브 발동 시 분신도 동일 카드 발동 |
|
||||
| 4 | 공격력 | "**분신의 공격은 플레이어의 공격력의 50% 반감**" — damage * 0.5 |
|
||||
| 5 | 타이밍 | "**플레이어보다 0.5초 뒤 사용** (공격 시작 딜레이)" — Player Fire 시점 + 0.5초 지연 큐 |
|
||||
|
||||
**기획 SOT v0.4 CSV A10 행 정합** (인용):
|
||||
> `A10,액티브,분신,D. 소환,긴 주기로 분신 1기를 생성한다. 플레이어 공격 패턴을 동일하게 모방해 자동 공격 (분신은 무적이나 공격력은 플레이어보다 비율 감소),추가 공격 기회`
|
||||
|
||||
PD 본 발화에 없는 v0.4 CSV 명세 합리적 기본값 (PM 1차 안 채택):
|
||||
- **분신 lifetime**: **12초 자동 소멸 + Singleton 1기 유지** (PD 2026-05-15 직접 결정) — spawn 시점 unscaledTime + 12초 후 자동 destroy. 12초 내 재발동 시 기존 분신 destroy + 새 분신 spawn (Singleton 패턴·BaseCooldown 25초 정합)
|
||||
- **BaseCooldown**: **25초** (PD 2026-05-15 직접 결정 — PM 1차 30초 → PD 조정 25초)
|
||||
- **분신 무적**: 유지 — v0.4 명시 + PD 2026-05-15 직접 결정 "무적으로 진행 (Collider 미부착)". 적 투사체·벽·player·enemy 모두 통과
|
||||
- **collision**: wall·player·enemy 모두 무충돌 (반투명·무적 정합) — 시각 GameObject 전용
|
||||
- **Lv 업 메커니즘** (PD 2026-05-15 직접 결정): **분신 수 증가 X** (1기 고정). 추후 **지속시간 ↑ + 플레이어 참조 데미지 비율(%) ↑** (PassiveSkill Lv 업 시 분신 lifetime·damage multiplier 증가 명세 — balance-designer 후속 수치 확정)
|
||||
|
||||
### A10-2. 구조 결정 — 3개 옵션 검토
|
||||
|
||||
| 옵션 | 설명 | 장단점 |
|
||||
|------|------|-------|
|
||||
| (가) | `CloneController` 별도 GameObject + 자체 `PlayerSkillInventory` mirror | (장) 분신 = 독립 actor·테스트 격리 (단) 코드 중복 — 인벤토리·Lv·각성·이벤트 구독 2중 동기화 부담 |
|
||||
| **(나) ✅** | **`CloneInstance` 단일 MonoBehaviour + Player Inventory hook** — Player Fire 시 0.5초 지연 큐 enqueue → 분신 위치 anchor로 동일 Effector 재호출 + damage 50% 반감 | (장) Effector 코드 재활용·인벤토리 단일 SOT 유지·동기화 부담 0 (단) Effector가 inventory 컨텍스트 분기 필요 — `PlayerStats` 50% 반감 처리 |
|
||||
| (다) | Effector 한 번 호출 시 Player+Clone 2회 발동 (분신 = sprite만) | (장) 최소 구현 (단) "0.5초 뒤" PD 명세 위반 — 즉시 2회 발동은 spec 어긋남 |
|
||||
|
||||
**채택 = (나)**. 근거:
|
||||
1. **PD 명세 5번 (0.5초 딜레이) 충족**: (다) 즉시 발동은 spec 위반
|
||||
2. **PD 명세 3번 (동일 스킬)**: Effector 재활용으로 13종 카드 무차별 지원
|
||||
3. **C11 자원 효율**: 별도 Inventory mirror 부재 — 메모리·GC 부담 최소
|
||||
4. **C11 코드 직관성**: 분신 = "Player Fire 0.5초 뒤 분신 위치에서 동일 Effector 호출 + 50% damage" 단 1줄 멘탈 모델
|
||||
|
||||
### A10-3. 신규 컴포넌트 — `CloneInstance` MonoBehaviour
|
||||
|
||||
**파일**: `Assets/Scripts/Skills/Effectors/CloneInstance.cs` (신규)
|
||||
|
||||
**계약**:
|
||||
|
||||
```csharp
|
||||
namespace EerieVillage.Skills.Effectors
|
||||
{
|
||||
/// <summary>
|
||||
/// A10 분신 인스턴스. Player 자식 부착 X (독립 GameObject — Player 이동 시 위치 미동조·고정 위치 1기).
|
||||
/// PD 명세 (2026-05-15):
|
||||
/// - Player x좌표 1 뒤쪽 spawn (facing 반대 방향 1유닛)
|
||||
/// - 반투명 sprite (alpha 0.5)
|
||||
/// - Player 발동 시 0.5초 뒤 동일 Effector 발동
|
||||
/// - damage 50% 반감
|
||||
/// - 무적·무충돌 (collider 미부착)
|
||||
/// </summary>
|
||||
public class CloneInstance : MonoBehaviour
|
||||
{
|
||||
// 정적 Singleton — 분신 1기 유지 (재발동 시 기존 destroy)
|
||||
private static CloneInstance _current;
|
||||
|
||||
private PlayerSkillInventory _playerInventory;
|
||||
private float _spawnFacingX; // spawn 시점 Player facing.x (분신 facing 고정)
|
||||
|
||||
// 지연 큐: (발동 시각, Runtime, Inventory 컨텍스트)
|
||||
private readonly Queue<PendingFire> _pendingQueue = new Queue<PendingFire>();
|
||||
|
||||
private struct PendingFire
|
||||
{
|
||||
public float TriggerTime; // unscaledTime + 0.5초
|
||||
public ActiveSkillRuntime Runtime;
|
||||
}
|
||||
|
||||
public static void SpawnOrReplace(PlayerSkillInventory playerInventory, ActiveSkillData cloneData) { /* §A10-4 */ }
|
||||
|
||||
public void EnqueuePlayerFire(ActiveSkillRuntime runtime) { /* §A10-5 */ }
|
||||
|
||||
void Update() { /* §A10-5 — 큐 dequeue + Effector 재호출 */ }
|
||||
|
||||
void OnDestroy() { /* Player Inventory unsubscribe + _current 정리 */ }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### A10-4. 분신 spawn 로직 (CloneEffector)
|
||||
|
||||
**파일**: `Assets/Scripts/Skills/Effectors/CloneEffector.cs` (신규)
|
||||
|
||||
```csharp
|
||||
namespace EerieVillage.Skills.Effectors
|
||||
{
|
||||
/// <summary>
|
||||
/// A10 분신 Effector — Category D (Minion) 카테고리에서 CardId == "A10" 분기.
|
||||
/// SkillFireEvent.Execute 영역 Minion case 분기:
|
||||
/// if (data.CardId == "A10") effector = new CloneEffector();
|
||||
/// else effector = new SpiritFireSpawner(); (기존 A11)
|
||||
/// </summary>
|
||||
public class CloneEffector : IEffector
|
||||
{
|
||||
public void Trigger(ActiveSkillRuntime runtime, PlayerSkillInventory inventory)
|
||||
{
|
||||
// 분신 spawn 또는 교체 (Singleton)
|
||||
CloneInstance.SpawnOrReplace(inventory, runtime.ActiveData);
|
||||
// 분신 자체는 "발동"이 아닌 "생성" — 발동은 Player Fire 시 분신 인스턴스가 hook
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**`CloneInstance.SpawnOrReplace` 동작**:
|
||||
|
||||
```csharp
|
||||
public static void SpawnOrReplace(PlayerSkillInventory playerInventory, ActiveSkillData cloneData)
|
||||
{
|
||||
// 1. 기존 분신 destroy (1기 유지)
|
||||
if (_current != null) { Destroy(_current.gameObject); _current = null; }
|
||||
|
||||
// 2. Player 위치·facing 취득
|
||||
var pc = playerInventory.GetComponent<PlayerController>();
|
||||
Vector2 facing = pc != null ? pc.Facing : Vector2.right;
|
||||
float signX = facing.x < 0f ? -1f : 1f;
|
||||
Vector2 playerPos = playerInventory.transform.position;
|
||||
|
||||
// 3. PD 명세 — facing 반대 1유닛 (예: facing=오른쪽 → -1유닛)
|
||||
Vector2 spawnPos = playerPos + new Vector2(-signX * 1f, 0f);
|
||||
|
||||
// 4. Player sprite clone — SpriteRenderer 복제 + alpha 0.5
|
||||
var go = new GameObject("Clone_A10");
|
||||
go.hideFlags = HideFlags.DontSave;
|
||||
go.transform.position = spawnPos;
|
||||
|
||||
var playerSr = playerInventory.GetComponentInChildren<SpriteRenderer>();
|
||||
if (playerSr != null)
|
||||
{
|
||||
var sr = go.AddComponent<SpriteRenderer>();
|
||||
sr.sprite = playerSr.sprite;
|
||||
sr.flipX = playerSr.flipX; // Player와 동일 방향 시각 (PD 명세 "분신" 외형)
|
||||
sr.sortingOrder = playerSr.sortingOrder - 1; // Player 뒤쪽
|
||||
Color c = playerSr.color;
|
||||
c.a = 0.5f; // 반투명
|
||||
sr.color = c;
|
||||
}
|
||||
|
||||
// 5. CloneInstance 컴포넌트 부착 + Player Inventory hook 구독
|
||||
var instance = go.AddComponent<CloneInstance>();
|
||||
instance._playerInventory = playerInventory;
|
||||
instance._spawnFacingX = signX;
|
||||
_current = instance;
|
||||
|
||||
// 6. Player Fire 이벤트 구독 — 새 hook 신설 필요 (§A10-6)
|
||||
playerInventory.OnPlayerSkillFired += instance.EnqueuePlayerFire;
|
||||
}
|
||||
```
|
||||
|
||||
### A10-5. Player Fire hook + 0.5초 지연 큐
|
||||
|
||||
**PlayerSkillInventory 신규 이벤트 (`§A10-6` 확장)**:
|
||||
|
||||
```csharp
|
||||
// PlayerSkillInventory.cs 신설 영역
|
||||
public event System.Action<ActiveSkillRuntime> OnPlayerSkillFired;
|
||||
|
||||
// ActiveSkillRuntime.Fire() 영역에 hook 추가:
|
||||
// - Fire() 호출 시 Simulation.Schedule<SkillFireEvent> 발동 직후
|
||||
// - inventory.OnPlayerSkillFired?.Invoke(this) 호출
|
||||
// 이렇게 함으로써 분신이 자체적으로 Player Fire 시점을 감지 → 0.5초 지연 큐 enqueue
|
||||
```
|
||||
|
||||
**CloneInstance Update + enqueue 로직**:
|
||||
|
||||
```csharp
|
||||
public void EnqueuePlayerFire(ActiveSkillRuntime runtime)
|
||||
{
|
||||
// A10 분신 자체 발동 = 무한 재귀 방지 (분신은 분신을 발동하지 않음)
|
||||
if (runtime.ActiveData.CardId == "A10") return;
|
||||
|
||||
_pendingQueue.Enqueue(new PendingFire {
|
||||
TriggerTime = Time.unscaledTime + 0.5f, // PD 명세 0.5초 딜레이
|
||||
Runtime = runtime
|
||||
});
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
while (_pendingQueue.Count > 0 && _pendingQueue.Peek().TriggerTime <= Time.unscaledTime)
|
||||
{
|
||||
var pending = _pendingQueue.Dequeue();
|
||||
FireAtClonePosition(pending.Runtime);
|
||||
}
|
||||
}
|
||||
|
||||
private void FireAtClonePosition(ActiveSkillRuntime runtime)
|
||||
{
|
||||
var data = runtime.ActiveData;
|
||||
if (data == null) return;
|
||||
|
||||
// 분신 위치 anchor로 Effector 재호출
|
||||
// 핵심 패턴: PlayerStats.CloneDamageMultiplier (또는 _isCloneFire 플래그) 분기로 damage 50% 반감
|
||||
// 옵션 A — _playerInventory.Stats 임시 백업·multiplier 0.5 적용·Effector 호출·복구
|
||||
// 옵션 B — CloneInventoryWrapper 별도 객체 (Stats 사본·DamageMultiplier *= 0.5) — 채택
|
||||
|
||||
var cloneCtx = CloneFireContext.Create(_playerInventory, transform.position, _spawnFacingX);
|
||||
IEffector effector = ResolveEffector(data);
|
||||
if (effector != null) effector.Trigger(runtime, cloneCtx.WrappedInventory);
|
||||
}
|
||||
```
|
||||
|
||||
**`CloneFireContext`** (신규 헬퍼 — 별도 inventory 어댑터):
|
||||
|
||||
```csharp
|
||||
internal static class CloneFireContext
|
||||
{
|
||||
// PlayerSkillInventory 직접 수정 없이 분신 발동 컨텍스트 분리
|
||||
// 옵션 1 — PlayerSkillInventory.IsCloneFireContext 플래그 (간단)
|
||||
// 옵션 2 — 별도 wrapper (코드 직관성 ↑)
|
||||
// 채택 = 1 — Effector 변경 최소 (PlayerSkillInventory 1 필드 추가만)
|
||||
}
|
||||
```
|
||||
|
||||
**최종 채택 = 옵션 1** (PlayerSkillInventory 플래그):
|
||||
|
||||
```csharp
|
||||
// PlayerSkillInventory.cs 신설 필드
|
||||
internal bool IsCloneFireActive = false;
|
||||
internal Vector2 CloneFireOrigin = Vector2.zero;
|
||||
internal float CloneFireFacingX = 1f;
|
||||
internal const float CLONE_DAMAGE_MULTIPLIER = 0.5f;
|
||||
```
|
||||
|
||||
각 Effector에서 `inventory.IsCloneFireActive` 분기:
|
||||
- spawn 위치 = `inventory.CloneFireOrigin` (분신 위치) 사용
|
||||
- facing = `Vector2(inventory.CloneFireFacingX, 0)` 사용
|
||||
- damage = 기존 계산 결과 * `CLONE_DAMAGE_MULTIPLIER` (0.5)
|
||||
|
||||
`ActiveSkillRuntime.CalculateEffectiveDamage()` 영역에 단 1줄 추가:
|
||||
|
||||
```csharp
|
||||
public int CalculateEffectiveDamage()
|
||||
{
|
||||
// ... 기존 ...
|
||||
float effective = ActiveData.BaseDamage * stats.DamageMultiplier * StackLevelFactor(StackLevel) * attrMult;
|
||||
if (_inventory != null && _inventory.IsCloneFireActive) effective *= PlayerSkillInventory.CLONE_DAMAGE_MULTIPLIER;
|
||||
return Mathf.RoundToInt(effective);
|
||||
}
|
||||
```
|
||||
|
||||
위치·facing 분기는 Effector 진입점 (ProjectileSpawner·MeleeAreaSpawner·LightningStrikeSpawner·LaserSpawner·PoisonSwampSpawner·SpiritFireSpawner) 영역 `inventory.transform.position` 대신:
|
||||
|
||||
```csharp
|
||||
Vector2 anchorPos = inventory.IsCloneFireActive ? inventory.CloneFireOrigin : (Vector2)inventory.transform.position;
|
||||
Vector2 facing = ...; if (inventory.IsCloneFireActive) facing = new Vector2(inventory.CloneFireFacingX, 0);
|
||||
```
|
||||
|
||||
`CloneInstance.FireAtClonePosition`:
|
||||
|
||||
```csharp
|
||||
private void FireAtClonePosition(ActiveSkillRuntime runtime)
|
||||
{
|
||||
var inv = _playerInventory;
|
||||
inv.IsCloneFireActive = true;
|
||||
inv.CloneFireOrigin = transform.position;
|
||||
inv.CloneFireFacingX = _spawnFacingX;
|
||||
try
|
||||
{
|
||||
// SkillFireEvent.Execute 영역 그대로 재호출
|
||||
var ev = Simulation.Schedule<SkillFireEvent>();
|
||||
ev.Runtime = runtime;
|
||||
ev.Inventory = inv;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Schedule 즉시 처리 X — 1 frame 후 reset (또는 SkillFireEvent.Execute 마지막에 reset)
|
||||
// 채택: SkillFireEvent.Cleanup 영역 IsCloneFireActive=false 일관 reset
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**reset 시점 결정 안건** (3단계 검증 영역):
|
||||
- (가) SkillFireEvent.Cleanup 영역 reset — Simulation 일관 시점·자동
|
||||
- (나) 다음 frame Coroutine — race 회피 (다른 Player Fire 영역 영향 차단)
|
||||
- 채택 = (가) — Simulation.Event Cleanup 영역 일관 reset
|
||||
|
||||
### A10-6. ActiveSkillRuntime.Fire() 영역 OnPlayerSkillFired 발화
|
||||
|
||||
기존 코드:
|
||||
```csharp
|
||||
public void Fire()
|
||||
{
|
||||
if (ActiveData.Category == ActiveCategory.SpecialJudge) { /* 확률 판정 */ }
|
||||
var ev = Simulation.Schedule<SkillFireEvent>();
|
||||
ev.Runtime = this;
|
||||
ev.Inventory = _inventory;
|
||||
}
|
||||
```
|
||||
|
||||
확장 1줄 추가:
|
||||
```csharp
|
||||
public void Fire()
|
||||
{
|
||||
if (ActiveData.Category == ActiveCategory.SpecialJudge) { /* 확률 판정 */ }
|
||||
var ev = Simulation.Schedule<SkillFireEvent>();
|
||||
ev.Runtime = this;
|
||||
ev.Inventory = _inventory;
|
||||
|
||||
// BT12-Dev-Clone 2026-05-15 — A10 분신 hook
|
||||
if (_inventory != null && !_inventory.IsCloneFireActive)
|
||||
_inventory.OnPlayerSkillFired?.Invoke(this);
|
||||
}
|
||||
```
|
||||
|
||||
**`IsCloneFireActive` 분기**가 중요 — 분신 발동도 OnPlayerSkillFired 호출 시 무한 재귀. Clone 컨텍스트에서는 발화하지 않음.
|
||||
|
||||
### A10-7. SkillFireEvent.Execute 영역 Minion case + CardId 분기
|
||||
|
||||
기존:
|
||||
```csharp
|
||||
case ActiveCategory.Minion:
|
||||
effector = new SpiritFireSpawner();
|
||||
break;
|
||||
```
|
||||
|
||||
수정:
|
||||
```csharp
|
||||
case ActiveCategory.Minion:
|
||||
if (data.CardId == "A10") effector = new CloneEffector();
|
||||
else effector = new SpiritFireSpawner();
|
||||
break;
|
||||
```
|
||||
|
||||
**Cleanup 영역 추가** (분신 발동 reset):
|
||||
```csharp
|
||||
internal override void Cleanup()
|
||||
{
|
||||
if (Inventory != null) Inventory.IsCloneFireActive = false;
|
||||
Runtime = null;
|
||||
Inventory = null;
|
||||
}
|
||||
```
|
||||
|
||||
### A10-8. A10 ActiveSkillData `.asset` 핵심 필드
|
||||
|
||||
**파일**: `Assets/Resources/Skills/Active/A10_bunsin.asset` (신규)
|
||||
|
||||
A11_jeongnyeongbul.asset 동등 패턴 + A10 고유 필드:
|
||||
|
||||
| 필드 | 값 | 근거 |
|
||||
|------|---|------|
|
||||
| CardId | "A10" | v0.4 CSV |
|
||||
| DisplayName | "분신" | v0.4 CSV |
|
||||
| EnglishName | "Clone" | 일관성 |
|
||||
| Description | "긴 주기로 분신 1기를 생성한다. 플레이어 공격 패턴을 동일하게 모방해 자동 공격..." | v0.4 CSV 인용 |
|
||||
| AttributeTags | 0 (None) | 분신 자체 속성 X — Effector 발동 시 카드별 속성 |
|
||||
| TypeTags | 0 (None) | 동일 |
|
||||
| maxLevel | 5 | 표준 |
|
||||
| Category | 3 (Minion) | v0.4 CSV "D. 소환" |
|
||||
| Trigger | 0 (OnTime) | 표준 |
|
||||
| BaseCooldown | **25** | **PD 결정 2026-05-15** (PM 1차 30 → PD 조정 25). balance-designer 후속 Lv별 증가량 확정 |
|
||||
| BaseDamage | 0 | 분신 자체 damage X — Effector 재호출 시 Player damage * 0.5 |
|
||||
| HitboxSize | (0,0) | 분신 자체 판정 X |
|
||||
| OffsetDistance | (0,0) | 분신 자체 spawn offset = facing 반대 1유닛 (코드 하드코딩 — PD 명세 정합) |
|
||||
| MinionLifetime | **12** | **PD 결정 2026-05-15** — 12초 자동 소멸 + Singleton 1기 (BaseCooldown 25 < lifetime 12 영역 활성 중 재발동 시 25초마다 갱신). Lv 업 시 추후 증가 (balance-designer 후속) |
|
||||
| OnHitFxPrefab | null | 분신 sprite는 코드 spawn (Player sprite 복제) |
|
||||
| 기타 | 기본값 | - |
|
||||
|
||||
**PD 결정 완료 (2026-05-15)**: BaseCooldown 25·MinionLifetime 12·facing 고정·무적 Collider 미부착·Lv 업 시 분신 수 X (지속시간+데미지 비율(%)↑·balance-designer 후속 수치).
|
||||
|
||||
### A10-9. SkillRuntimeFactory.AvailableCardIds 추가
|
||||
|
||||
```csharp
|
||||
static readonly HashSet<string> AvailableCardIds = new HashSet<string>
|
||||
{
|
||||
"A02", "A13", "A04", "A05", "A_Laser",
|
||||
"A08", "A12",
|
||||
"A06", "A11",
|
||||
"A10" // BT12-Dev-Clone 2026-05-15 신규
|
||||
};
|
||||
```
|
||||
|
||||
### A10-10. 무적·무충돌 처리
|
||||
|
||||
PD 명세 "분신은 무적" + 본 PM 합리적 기본값 "wall·player·enemy 모두 무충돌":
|
||||
|
||||
| 요소 | 처리 |
|
||||
|------|------|
|
||||
| Collider2D | **미부착** — 무충돌 자동 (Trigger·Wall·Enemy 판정 모두 비활성) |
|
||||
| Rigidbody2D | **미부착** — 물리 영향 X (중력·관성 모두 무관) |
|
||||
| Health 컴포넌트 | **미부착** — 적 투사체 Decrement 호출 X — Health 검색 대상 외 |
|
||||
| SpriteRenderer | **부착** — 시각 전용 (sortingOrder Player 뒤쪽) |
|
||||
|
||||
**PD 검증 권고**: Play 시 분신 위에 적이 올라타거나 적 투사체 통과 — 무영향 검증.
|
||||
|
||||
### A10-11. 분신 위치 동작 — 고정 vs Player 동조
|
||||
|
||||
**옵션 A — 고정 위치** (Player 이동 시 분신 그대로):
|
||||
- spawn 시점 Player 위치 - 1유닛 = 분신 고정 위치
|
||||
- Player가 이동해도 분신은 그 자리 유지 → 분신 발동도 분신 위치에서 발동
|
||||
- VS류 게임 분신 표준 동작 (Vampire Survivors Pummarola 등)
|
||||
|
||||
**옵션 B — Player 동조** (Player 자식 부착):
|
||||
- 분신이 항상 Player x-1 위치 추종
|
||||
- "분신" 의미와 정합도 ↑ ("분신"은 분신·복제·따라다님)
|
||||
|
||||
**채택 = B (Player 자식 부착)** — 근거:
|
||||
1. PD 명세 "**플레이어의 x좌표 1 뒤쪽**" — 현재형 표현 = Player 이동 시 분신도 동조 자연
|
||||
2. v0.4 CSV "**플레이어 공격 패턴을 동일하게 모방**" — 분신이 Player 따라다니며 모방 = 자연
|
||||
3. 분신 1기 + Player 영구 동조 = 시각적 일관성
|
||||
|
||||
**구현**: `go.transform.SetParent(playerInventory.transform, true);` + spawn 시 `localPosition = (-signX * 1f, 0, 0)`
|
||||
|
||||
**facing 변경 시**: Player facing 변경 시 분신의 "x 1 뒤쪽" 의미가 바뀜 (오른쪽→왼쪽 변경 시 분신은 원래 -1 → 새로운 -1 = Player 오른쪽 +1). **PD 명세 모호 영역** — 3단계 검증 시 PD 결정 안건.
|
||||
|
||||
**PM 1차 채택**: spawn 시점 facing 고정. Player facing 변경되어도 분신 위치 (spawn 시점 기준 -1유닛) 유지. 분신의 facing은 Player flipX 동조 (시각 일관성).
|
||||
|
||||
### A10-12. 변경 영향 — 기존 코드 수정 영역
|
||||
|
||||
| 파일 | 변경 |
|
||||
|------|------|
|
||||
| `Assets/Scripts/Skills/Effectors/CloneInstance.cs` | **신규** |
|
||||
| `Assets/Scripts/Skills/Effectors/CloneEffector.cs` | **신규** |
|
||||
| `Assets/Scripts/Skills/Runtime/PlayerSkillInventory.cs` | `IsCloneFireActive·CloneFireOrigin·CloneFireFacingX·CLONE_DAMAGE_MULTIPLIER` 4필드 + `OnPlayerSkillFired` 이벤트 신설 |
|
||||
| `Assets/Scripts/Skills/Runtime/ActiveSkillRuntime.cs` | `Fire()` 영역 OnPlayerSkillFired 발화 1줄 + `CalculateEffectiveDamage()` 영역 50% 반감 1줄 |
|
||||
| `Assets/Scripts/Skills/Events/SkillFireEvent.cs` | Minion case 영역 CardId 분기 + Cleanup 영역 IsCloneFireActive reset |
|
||||
| `Assets/Scripts/Skills/Runtime/SkillRuntimeFactory.cs` | AvailableCardIds 영역 "A10" 추가 |
|
||||
| `Assets/Scripts/Skills/Effectors/{ProjectileSpawner,MeleeAreaSpawner,LightningStrikeSpawner,LaserSpawner,PoisonSwampSpawner,SpiritFireSpawner}.cs` | **선택** — `IsCloneFireActive` 분기로 spawn 위치·facing 분신 origin 사용 |
|
||||
| `Assets/Resources/Skills/Active/A10_bunsin.asset` | **신규** |
|
||||
|
||||
**Effector 변경 최소화 옵션**: 모든 Effector에 `if (inventory.IsCloneFireActive) playerPos = inventory.CloneFireOrigin` 일관 적용. 6개 Effector × 약 3줄 = 18줄.
|
||||
|
||||
**대안 = 매우 최소화 (옵션 ε)**: 분신 발동 시 PlayerSkillInventory.transform.position을 1 frame 동안 분신 위치로 swap. Effector 변경 0줄. 그러나 부작용 가능성 (다른 컴포넌트 transform 참조). **기각** — 부작용 위험.
|
||||
|
||||
**채택**: 6개 Effector 일관 분기 — 명시성·안정성 우선.
|
||||
|
||||
### A10-13. 기각안
|
||||
|
||||
#### A10-13-1. 분신 별도 GameObject + 자체 PlayerSkillInventory mirror — 기각
|
||||
|
||||
**기각 근거** (§A10-2 옵션 (가)):
|
||||
- 코드 중복 (인벤토리·Lv·각성·이벤트 구독 2중 동기화)
|
||||
- C11 자원 효율 위반 — MonoBehaviour 2중 부담
|
||||
- **채택안**: (나) — CloneInstance 단일 + Player Inventory hook + 0.5초 지연 큐
|
||||
|
||||
#### A10-13-2. Effector 한 번 호출 시 Player+Clone 2회 발동 (분신 = sprite만) — 기각
|
||||
|
||||
**기각 근거** (§A10-2 옵션 (다)):
|
||||
- PD 명세 5번 "**플레이어보다 0.5초 뒤**" 직접 위반 — 즉시 2회 발동은 spec 어긋남
|
||||
- **채택안**: (나) — 0.5초 지연 큐 + 분신 위치 재호출
|
||||
|
||||
#### A10-13-3. PlayerSkillInventory.transform.position swap — 기각
|
||||
|
||||
**기각 근거** (§A10-12 옵션 ε):
|
||||
- 1 frame 부작용 가능성 — Camera·HUD·다른 컴포넌트 transform 참조 영향
|
||||
- **채택안**: Effector 6개 일관 IsCloneFireActive 분기 (18줄)
|
||||
|
||||
#### A10-13-4. 분신 lifetime 8초 (A11 동등) — 기각
|
||||
|
||||
**기각 근거** (§A10-1 합리적 기본값):
|
||||
- v0.4 CSV "분신 1기" + "긴 주기" — 잠시 spawn 후 사라지면 "긴 주기로 1기 생성" 의미가 무너짐
|
||||
- **PD 결정 채택안 (2026-05-15)**: **12초 자동 소멸 + Singleton 1기 + BaseCooldown 25초**. 12초 내 재발동 시 기존 destroy + 새 spawn (Singleton). BaseCooldown 25 < lifetime 12 영역 활성 중 재발동 시 25초마다 갱신
|
||||
- **Lv 업 메커니즘** (PD 결정 2026-05-15): 분신 수 증가 X·추후 **지속시간 ↑ + 플레이어 참조 데미지 비율(%) ↑** (balance-designer 후속 Lv별 수치 확정)
|
||||
|
||||
#### A10-13-5. 분신 facing이 Player와 독립 (분신 발동 시 적 방향) — 기각
|
||||
|
||||
**기각 근거** (§A10-1 PD 명세):
|
||||
- "**플레이어 공격 패턴을 동일하게 모방**" v0.4 CSV — Player와 동일 facing이 자연
|
||||
- 분신이 적 방향 자체 추적 시 분신 = 독립 actor 의미 → §A10-2 (가) 옵션 회귀
|
||||
- **채택안**: Player facing 동조 (분신은 Player flipX와 동조)
|
||||
|
||||
### A10-14. EditMode 테스트 신설 (3단계 검증 영역)
|
||||
|
||||
`Assets/Tests/Editor/CloneSkillTests.cs` 신설:
|
||||
|
||||
1. **CloneSpawnPosition_FacingRight_X_Minus1** — Player facing=오른쪽 시 분신 x = player.x - 1 검증
|
||||
2. **CloneSpawnPosition_FacingLeft_X_Plus1** — Player facing=왼쪽 시 분신 x = player.x + 1 검증
|
||||
3. **CloneSpriteAlpha_Is_0_5** — 분신 SpriteRenderer.color.a == 0.5f
|
||||
4. **CloneDamageMultiplier_50_Percent** — Player damage 10 → Clone damage 5 검증
|
||||
5. **CloneFireDelay_0_5_Seconds** — Player Fire 시 분신 발동 시각 = Player Fire 시각 + 0.5초 (unscaledTime 기반)
|
||||
6. **CloneSingleton_RespawnReplaces** — A10 재발동 시 기존 분신 destroy + 새 분신 spawn (단 1기)
|
||||
7. **CloneNoRecursion_A10_FireSkipped** — 분신 자체가 A10 발동 시도 X (무한 재귀 차단)
|
||||
|
||||
### A10-15. 2단계 클라이언트팀 위임 작업 단위 분해
|
||||
|
||||
**Sonnet Task 단일 위임** (C48 3자문 통과·영역 전문성·Unity C# 구현 = Sonnet 적정):
|
||||
|
||||
| # | 작업 | 파일 |
|
||||
|---|------|------|
|
||||
| 1 | `CloneInstance.cs` 신규 — MonoBehaviour + 0.5초 지연 큐 + SpawnOrReplace 정적 메서드 + Update dequeue + OnDestroy unsubscribe | 신규 |
|
||||
| 2 | `CloneEffector.cs` 신규 — IEffector 구현 + CloneInstance.SpawnOrReplace 호출 | 신규 |
|
||||
| 3 | `PlayerSkillInventory.cs` 확장 — IsCloneFireActive·CloneFireOrigin·CloneFireFacingX·CLONE_DAMAGE_MULTIPLIER 4필드 + OnPlayerSkillFired 이벤트 신설 | 수정 |
|
||||
| 4 | `ActiveSkillRuntime.cs` 확장 — Fire() 영역 OnPlayerSkillFired 발화 + CalculateEffectiveDamage() 영역 50% 반감 분기 | 수정 |
|
||||
| 5 | `SkillFireEvent.cs` 수정 — Minion case 영역 CardId 분기 + Cleanup 영역 IsCloneFireActive reset | 수정 |
|
||||
| 6 | `SkillRuntimeFactory.cs` 수정 — AvailableCardIds 영역 "A10" 추가 | 수정 |
|
||||
| 7 | 6개 Effector 영역 IsCloneFireActive 분기 일관 추가 (spawn 위치·facing) | 수정 |
|
||||
| 8 | `A10_bunsin.asset` 신규 — A11 동등 패턴 + A10 고유 필드 | 신규 |
|
||||
| 9 | EditMode 테스트 7건 신설 | 신규 |
|
||||
|
||||
**예상 작업량**: 신규 4 파일 + 수정 9 파일 + .asset 1 + 테스트 1. 단일 Sonnet Task 범위.
|
||||
|
||||
### A10-16. 3단계 개발팀장 검증 항목 (사전 명시)
|
||||
|
||||
1. **PD 명세 5항목 전수 정합** — 위치 (facing 반대 1유닛)·외형 (alpha 0.5)·동작 (동일 스킬)·공격력 (50% 반감)·타이밍 (0.5초 딜레이)
|
||||
2. **v0.4 CSV A10 행 정합** — 분신 1기·영구 유지·동일 패턴 모방·공격력 비율 감소·무적
|
||||
3. **기존 시스템 충돌 없음** — Player Fire 정상 (분신 hook이 Player 발동 영향 X)·다른 카드 정상·BT12-Dev-Vis 13 스킬 정상
|
||||
4. **C11 정합** — 자원 효율 (CloneInstance 1기·MonoBehaviour 부담 최소)·코드 직관성 (3계층 hook 명시)·범용성 (Effector 6종 무차별 지원)
|
||||
5. **EditMode 7건 + 기존 테스트 전부 green**
|
||||
6. **SOT 갱신** — 스킬 이펙트 확정 SOT v1 §3 A10 추가 + §4 변경 이력 추가
|
||||
7. **PD 결정 정합 검증 (2026-05-15)** — BaseCooldown 25·MinionLifetime 12·facing 고정·무적 Collider 미부착·Lv 업 메커니즘 (분신 수 X·지속시간+데미지 비율↑) 전수 코드 정합 확증
|
||||
|
||||
---
|
||||
|
||||
## §14. 참조 문서
|
||||
|
||||
- **기획 SOT**:
|
||||
|
|
|
|||
|
|
@ -139,6 +139,31 @@ HitFxScale=0.5 FxRotation=0 OffsetXY=(0,0)
|
|||
DamageFrameDelay=0 EnableRepeatDamage=0 MaxHitCount=1 RepeatFrameInterval=30
|
||||
```
|
||||
|
||||
### A10 분신 (Clone·Category 3 Summon·CloneEffector·BT12-Dev-Clone 2026-05-15·PD 결정 stamp 2026-05-15)
|
||||
```
|
||||
BaseCooldown=25 BaseDamage=0 HitboxSize=(0, 0) OffsetDistance=(0, 0)
|
||||
Trajectory=0 MinionLifetime=12 (12초 지속·Singleton 1기·PD 직접 결정 2026-05-15)
|
||||
AttributeTags=0 TypeTags=0
|
||||
ProjectilePrefab=null OnHitFxPrefab=null ExtraHitFxPrefab=null CastFxPrefab=null
|
||||
OnDotFxPrefab=null
|
||||
DotDuration=0 DotInterval=0.5
|
||||
HitFxScale=1 FxRotation=0 OffsetXY=(0,0)
|
||||
DamageFrameDelay=0 EnableRepeatDamage=0 MaxHitCount=1 RepeatFrameInterval=30
|
||||
# PD 명세 5항목 (코드 하드코딩 영역·.asset 영역 변경 불요):
|
||||
# - spawn 위치: facing 반대 1유닛 (CloneInstance.SpawnOrReplace·facing 고정)
|
||||
# - sprite alpha: 0.5
|
||||
# - 동일 스킬 사용: OnPlayerSkillFired hook (PlayerSkillInventory)
|
||||
# - damage 50% 반감: ActiveSkillRuntime.CalculateEffectiveDamage + IsCloneFireActive 분기
|
||||
# - 0.5초 딜레이: CloneInstance._pendingQueue (unscaledTime 기반)
|
||||
# PD 2026-05-15 직접 결정 4건:
|
||||
# - BaseCooldown 25초 (PM 1차 30초 → PD 조정 25초)
|
||||
# - MinionLifetime 12초 (영구 1기 → 12초 자동 소멸·Singleton 유지)
|
||||
# - facing 고정 (spawn 시점 facing 고정·Player 이동 시 분신 위치·방향 불변)
|
||||
# - 무적 = Collider 미부착 (적 투사체·벽·player·enemy 모두 통과)
|
||||
# - Lv 업 시 분신 수 증가 X · 추후 지속시간↑+플레이어 참조 데미지 비율(%)↑ (balance-designer 후속 수치 확정)
|
||||
# BaseDamage 0 = 분신 자체 damage X (Effector 재호출 시 Player damage * 0.5)
|
||||
```
|
||||
|
||||
### A_Laser 용염 레이저 (Dragonfire Laser·Category 1 MeleeArea·LaserSpawner)
|
||||
```
|
||||
BaseCooldown=3 BaseDamage=5 HitboxSize=(10, 1.2) OffsetDistance=(-0.4, -0.1)
|
||||
|
|
@ -155,6 +180,8 @@ DamageFrameDelay=10 EnableRepeatDamage=1 MaxHitCount=7 RepeatFrameInterval=10
|
|||
|---|---|---|
|
||||
| 2026-05-14 | 본 SOT 신설 (확정 stamp) | `1a1de0c` |
|
||||
| 2026-05-14 | A06·A11 박스 시각화 추가 (PoisonSwampHitbox_Debug·SpiritFireHitbox_Debug) · A11 OverlapBox 전환 (HitboxSize 사용) · A11 DotInterval 기반 피해 간격 · A11 소멸 0.5초 전 페이드 (alpha 1→0·scale 1→0.5) — PD 발화 정합 | (본 commit) |
|
||||
| 2026-05-15 | **§3 A10 분신 (Clone) 신설** — Category 3 Summon · CloneEffector + CloneInstance + PlayerSkillInventory.OnPlayerSkillFired hook + 0.5초 지연 큐 + IsCloneFireActive 분기 (damage 50% 반감) · spawn 위치 facing 반대 1유닛 · sprite alpha 0.5 · BaseCooldown 30 PM 1차 추정. BT12-Dev-Clone PD 명세 5항목 정합 + C49 1단계 (개발팀장 Opus 설계) 시범 | (후속 EerieVillage commit) |
|
||||
| 2026-05-15 | **§3 A10 PD 결정 4건 반영** — BaseCooldown 30→25·MinionLifetime 0(영구)→12초 자동 소멸·facing 고정·무적 Collider 미부착·Lv 업 시 분신 수 X·지속시간+데미지 비율(%) ↑ (balance 후속). BT12-Dev-Clone PD 직접 결정 2026-05-15 | (후속 EerieVillage commit) |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue