feat(BT12-Dev Phase B): A06 독 늪·A11 정령불 신규 + 1키·2키 매핑 (PD 지시 2026-05-13)
신규 Effector 2종: - PoisonSwampSpawner — Category C (PlacementPersistent) · 가장 가까운 적 위치 spawn·6초 유지·BoxCollider2D isTrigger·Kinematic Rigidbody2D · PoisonSwampInstance — OnTriggerStay 영역 적 마킹·PoisonedEnemyMarker 부착·duration 5초 갱신 · PoisonedEnemyMarker — 매 초 10 피해·FX_Venom_Spray 자식 spawn (DotFxPrefab)·duration 만료 시 자가 소멸 - SpiritFireSpawner — Category D (Minion) · Player 자식 spawn·8초 유지·OverlapCircle radius 2.5 · SpiritFireInstance — 매 초 근접 적 5 피해·Time.unscaledTime 영역 lifecycle SkillFireEvent.Execute switch 확장: - PlacementPersistent case → PoisonSwampSpawner - Minion case → SpiritFireSpawner A06 독 늪 .asset 신규 — Category 2·BaseCooldown 10·BaseDamage 10·OnHitFxPrefab=FX_Venom_Swamp·OnDotFxPrefab=FX_Venom_Spray A11 정령불 .asset 신규 — Category 3·BaseCooldown 15·BaseDamage 5·MinionLifetime 8·OnHitFxPrefab=FX_Rotating shield SkillRuntimeFactory.AvailableCardIds — A06·A11 추가 (7→9종) TestSkillFireOn1to5 — PoisonSwamp·SpiritFire 인스턴스 신규·Category 분기 추가 (CardId 기반 MeleeArea 분기 정합) PD Inspector 영역 — Player.prefab TestSkillFireOn1to5 Skill1=A06·Skill2=A11 .asset drag&drop 필요. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5077f5dd3f
commit
f292eb4fb3
|
|
@ -0,0 +1,68 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 69566f3f65e99394d8a0ccd0b395ac77, type: 3}
|
||||||
|
m_Name: A06_dok_neup
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::EerieVillage.Skills.ActiveSkillData
|
||||||
|
CardId: A06
|
||||||
|
DisplayName: "독 늪 소환"
|
||||||
|
EnglishName: Poison Swamp
|
||||||
|
Icon: {fileID: 0}
|
||||||
|
Description: "10초마다 화면 내 가장 가까운 적
|
||||||
|
위치에 독 늪을 생성해 6초간 유지한다.
|
||||||
|
독에 닿은 적은 늪을 벗어나도 매 초
|
||||||
|
10 피해를 입는다 (늪 위 적은 5초 갱신)."
|
||||||
|
AttributeTags: 16
|
||||||
|
TypeTags: 2
|
||||||
|
maxLevel: 5
|
||||||
|
Category: 2
|
||||||
|
Trigger: 0
|
||||||
|
BaseCooldown: 10
|
||||||
|
BaseDamage: 10
|
||||||
|
HitboxSize: {x: 3, y: 1.5}
|
||||||
|
OffsetDistance: {x: 0, y: 0}
|
||||||
|
Trajectory: 0
|
||||||
|
MinionPrefab: {fileID: 0}
|
||||||
|
ChainCount: 0
|
||||||
|
DotDuration: 5
|
||||||
|
DotInterval: 1
|
||||||
|
StunDuration: 0
|
||||||
|
SlowDuration: 0
|
||||||
|
SlowMultiplier: 0.5
|
||||||
|
KnockbackForce: 0
|
||||||
|
MaxConcurrent: 1
|
||||||
|
MinionLifetime: 6
|
||||||
|
AuraTickInterval: 1
|
||||||
|
AuraRadius: 3
|
||||||
|
CritDamageMultiplier: 2
|
||||||
|
IFrameDuration: 0
|
||||||
|
DebuffStackLimit: 3
|
||||||
|
FireProbability: 1
|
||||||
|
Range: 2
|
||||||
|
MaxRange: 10
|
||||||
|
ProjectileSpeed: 6
|
||||||
|
ProjectilePrefab: {fileID: 0}
|
||||||
|
OnHitFxPrefab: {fileID: 113285305800631535, guid: df9dcbcdcd9d1c94caff85fc8dab3ff5,
|
||||||
|
type: 3}
|
||||||
|
ExtraHitFxPrefab: {fileID: 0}
|
||||||
|
CastFxPrefab: {fileID: 0}
|
||||||
|
OnDotFxPrefab: {fileID: 1856636965874036819, guid: 5eb649ddc4489a449bc8dceb03e0b999,
|
||||||
|
type: 3}
|
||||||
|
DotDamageMultiplier: 1
|
||||||
|
ProjectileFxScale: 1
|
||||||
|
HitFxScale: 1
|
||||||
|
DotFxScale: 1
|
||||||
|
FxRotation: 0
|
||||||
|
OffsetXY: {x: 0, y: 0}
|
||||||
|
DamageFrameDelay: 0
|
||||||
|
EnableRepeatDamage: 0
|
||||||
|
MaxHitCount: 1
|
||||||
|
RepeatFrameInterval: 30
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 69566f3f65e99394d8a0ccd0b395ac77, type: 3}
|
||||||
|
m_Name: A11_jeongnyeongbul
|
||||||
|
m_EditorClassIdentifier: Assembly-CSharp::EerieVillage.Skills.ActiveSkillData
|
||||||
|
CardId: A11
|
||||||
|
DisplayName: "정령불"
|
||||||
|
EnglishName: Spirit Fire
|
||||||
|
Icon: {fileID: 0}
|
||||||
|
Description: "15초마다 정령불 방패를 8초간 소환한다.
|
||||||
|
플레이어 주위 회전하며 근접한 적에게
|
||||||
|
매 초 5의 피해·날아오는 적 투사체 소멸."
|
||||||
|
AttributeTags: 1
|
||||||
|
TypeTags: 2
|
||||||
|
maxLevel: 5
|
||||||
|
Category: 3
|
||||||
|
Trigger: 0
|
||||||
|
BaseCooldown: 15
|
||||||
|
BaseDamage: 5
|
||||||
|
HitboxSize: {x: 2.5, y: 2.5}
|
||||||
|
OffsetDistance: {x: 0, y: 0}
|
||||||
|
Trajectory: 0
|
||||||
|
MinionPrefab: {fileID: 0}
|
||||||
|
ChainCount: 0
|
||||||
|
DotDuration: 0
|
||||||
|
DotInterval: 1
|
||||||
|
StunDuration: 0
|
||||||
|
SlowDuration: 0
|
||||||
|
SlowMultiplier: 0.5
|
||||||
|
KnockbackForce: 0
|
||||||
|
MaxConcurrent: 1
|
||||||
|
MinionLifetime: 8
|
||||||
|
AuraTickInterval: 1
|
||||||
|
AuraRadius: 2.5
|
||||||
|
CritDamageMultiplier: 2
|
||||||
|
IFrameDuration: 0
|
||||||
|
DebuffStackLimit: 3
|
||||||
|
FireProbability: 1
|
||||||
|
Range: 2
|
||||||
|
MaxRange: 10
|
||||||
|
ProjectileSpeed: 6
|
||||||
|
ProjectilePrefab: {fileID: 0}
|
||||||
|
OnHitFxPrefab: {fileID: 1589202452151042601, guid: 16c1c1de9992a43449c144f995588c02,
|
||||||
|
type: 3}
|
||||||
|
ExtraHitFxPrefab: {fileID: 0}
|
||||||
|
CastFxPrefab: {fileID: 0}
|
||||||
|
OnDotFxPrefab: {fileID: 0}
|
||||||
|
DotDamageMultiplier: 0.25
|
||||||
|
ProjectileFxScale: 1
|
||||||
|
HitFxScale: 1
|
||||||
|
DotFxScale: 1
|
||||||
|
FxRotation: 0
|
||||||
|
OffsetXY: {x: 0, y: 0}
|
||||||
|
DamageFrameDelay: 0
|
||||||
|
EnableRepeatDamage: 0
|
||||||
|
MaxHitCount: 1
|
||||||
|
RepeatFrameInterval: 30
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using Platformer.Mechanics;
|
||||||
|
using Platformer.Gameplay;
|
||||||
|
using static Platformer.Core.Simulation;
|
||||||
|
|
||||||
|
namespace EerieVillage.Skills.Effectors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A06 독 늪 Effector — Category C (PlacementPersistent).
|
||||||
|
/// PD 지시 2026-05-13:
|
||||||
|
/// - 10초마다 (BaseCooldown 10) 화면 내 가장 가까운 적 위치에 독 늪 spawn
|
||||||
|
/// - 6초 유지 (FX_Venom_Swamp)
|
||||||
|
/// - 독에 한번이라도 닿은 적은 늪을 벗어나도 매 초 10 피해·FX_Venom_Spray 재생 (PoisonedEnemyMarker)
|
||||||
|
/// - 늪 위 적은 marker 지속 시간 5초로 갱신 (상시 5초 유지)
|
||||||
|
/// </summary>
|
||||||
|
public class PoisonSwampSpawner : IEffector
|
||||||
|
{
|
||||||
|
public void Trigger(ActiveSkillRuntime runtime, PlayerSkillInventory inventory)
|
||||||
|
{
|
||||||
|
var data = runtime.ActiveData;
|
||||||
|
// 화면 내 가장 가까운 적 검출
|
||||||
|
var cam = Camera.main;
|
||||||
|
if (cam == null) return;
|
||||||
|
float halfH = cam.orthographicSize;
|
||||||
|
float halfW = halfH * cam.aspect;
|
||||||
|
Vector2 camPos = cam.transform.position;
|
||||||
|
|
||||||
|
EnemyController nearest = null;
|
||||||
|
float minDist = float.MaxValue;
|
||||||
|
Vector2 playerPos = inventory.transform.position;
|
||||||
|
var enemies = Object.FindObjectsByType<EnemyController>(FindObjectsSortMode.None);
|
||||||
|
foreach (var e in enemies)
|
||||||
|
{
|
||||||
|
if (e == null) continue;
|
||||||
|
var h = e.GetComponent<Health>();
|
||||||
|
if (h == null || !h.IsAlive) continue;
|
||||||
|
var p = e.transform.position;
|
||||||
|
if (p.x < camPos.x - halfW || p.x > camPos.x + halfW || p.y < camPos.y - halfH || p.y > camPos.y + halfH) continue;
|
||||||
|
float d = Vector2.Distance(playerPos, p);
|
||||||
|
if (d < minDist) { minDist = d; nearest = e; }
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 spawnPos = nearest != null ? (Vector2)nearest.transform.position : playerPos;
|
||||||
|
spawnPos += data.OffsetXY;
|
||||||
|
|
||||||
|
// 독 늪 GO spawn (OnHitFxPrefab = FX_Venom_Swamp)
|
||||||
|
GameObject swampGo;
|
||||||
|
if (data.OnHitFxPrefab != null)
|
||||||
|
{
|
||||||
|
swampGo = Object.Instantiate(data.OnHitFxPrefab, spawnPos, Quaternion.identity);
|
||||||
|
swampGo.transform.localScale *= data.HitFxScale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
swampGo = new GameObject("PoisonSwamp_Fallback");
|
||||||
|
swampGo.transform.position = spawnPos;
|
||||||
|
}
|
||||||
|
swampGo.hideFlags = HideFlags.DontSave;
|
||||||
|
|
||||||
|
var instance = swampGo.AddComponent<PoisonSwampInstance>();
|
||||||
|
instance.Init(data, Mathf.Max(data.BaseCooldown, 1f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 독 늪 인스턴스 — 6초 유지·BoxCollider2D isTrigger·적 OnTrigger 시 PoisonedEnemyMarker 부착·marker duration 5초 갱신.
|
||||||
|
/// </summary>
|
||||||
|
public class PoisonSwampInstance : MonoBehaviour
|
||||||
|
{
|
||||||
|
ActiveSkillData _data;
|
||||||
|
float _spawnTime;
|
||||||
|
float _duration;
|
||||||
|
BoxCollider2D _col;
|
||||||
|
|
||||||
|
public void Init(ActiveSkillData data, float duration)
|
||||||
|
{
|
||||||
|
_data = data;
|
||||||
|
_duration = duration;
|
||||||
|
_spawnTime = Time.unscaledTime;
|
||||||
|
|
||||||
|
// 자식 BoxCollider2D 부착·HitboxSize 영역 정합
|
||||||
|
_col = gameObject.AddComponent<BoxCollider2D>();
|
||||||
|
_col.isTrigger = true;
|
||||||
|
Vector2 size = data.HitboxSize.sqrMagnitude > 0.01f ? data.HitboxSize : new Vector2(3f, 1.5f);
|
||||||
|
_col.size = size;
|
||||||
|
_col.offset = Vector2.zero;
|
||||||
|
|
||||||
|
// Kinematic Rigidbody2D — Kinematic vs Kinematic OnTriggerStay 발화 정합 (Enemy = KinematicObject)
|
||||||
|
var rb = GetComponent<Rigidbody2D>();
|
||||||
|
if (rb == null) rb = gameObject.AddComponent<Rigidbody2D>();
|
||||||
|
rb.bodyType = RigidbodyType2D.Kinematic;
|
||||||
|
rb.simulated = true;
|
||||||
|
rb.gravityScale = 0f;
|
||||||
|
rb.useFullKinematicContacts = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (Time.unscaledTime - _spawnTime >= _duration)
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnTriggerEnter2D(Collider2D other) { TryMark(other); }
|
||||||
|
void OnTriggerStay2D(Collider2D other) { TryMark(other); }
|
||||||
|
|
||||||
|
void TryMark(Collider2D other)
|
||||||
|
{
|
||||||
|
if (other == null || _data == null) return;
|
||||||
|
var e = other.GetComponent<EnemyController>();
|
||||||
|
if (e == null) return;
|
||||||
|
var h = other.GetComponent<Health>();
|
||||||
|
if (h == null || !h.IsAlive) return;
|
||||||
|
|
||||||
|
// 마커 부착 또는 duration 5초 갱신 (늪 위 있을 때 상시 5초 유지)
|
||||||
|
var marker = e.GetComponent<PoisonedEnemyMarker>();
|
||||||
|
if (marker == null) marker = e.gameObject.AddComponent<PoisonedEnemyMarker>();
|
||||||
|
marker.Refresh(_data, 5f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 독 마커 — 적 자식 부착·매 초 10 피해·FX_Venom_Spray 자식 spawn·duration 만료 시 자가 Destroy.
|
||||||
|
/// </summary>
|
||||||
|
public class PoisonedEnemyMarker : MonoBehaviour
|
||||||
|
{
|
||||||
|
ActiveSkillData _data;
|
||||||
|
float _lastTickTime;
|
||||||
|
float _expireTime;
|
||||||
|
|
||||||
|
public void Refresh(ActiveSkillData data, float duration)
|
||||||
|
{
|
||||||
|
_data = data;
|
||||||
|
_expireTime = Time.unscaledTime + duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (_data == null) { Destroy(this); return; }
|
||||||
|
if (Time.unscaledTime >= _expireTime) { Destroy(this); return; }
|
||||||
|
if (Time.unscaledTime - _lastTickTime >= 1f)
|
||||||
|
{
|
||||||
|
_lastTickTime = Time.unscaledTime;
|
||||||
|
Tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tick()
|
||||||
|
{
|
||||||
|
var h = GetComponent<Health>();
|
||||||
|
if (h == null || !h.IsAlive) { Destroy(this); return; }
|
||||||
|
int dmg = _data.BaseDamage > 0 ? _data.BaseDamage : 10;
|
||||||
|
h.DecrementBypassInvuln(dmg);
|
||||||
|
|
||||||
|
// FX_Venom_Spray 자식 spawn (적 위치)
|
||||||
|
if (_data.OnDotFxPrefab != null)
|
||||||
|
{
|
||||||
|
var fx = Object.Instantiate(_data.OnDotFxPrefab, transform.position, Quaternion.Euler(0f, 0f, _data.FxRotation), transform);
|
||||||
|
fx.hideFlags = HideFlags.DontSave;
|
||||||
|
fx.transform.localScale *= _data.DotFxScale;
|
||||||
|
FxAutoDestroyUnscaled.Attach(fx, 1.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!h.IsAlive)
|
||||||
|
{
|
||||||
|
var e = GetComponent<EnemyController>();
|
||||||
|
if (e != null) Schedule<EnemyDeath>().enemy = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
using UnityEngine;
|
||||||
|
using Platformer.Mechanics;
|
||||||
|
using Platformer.Gameplay;
|
||||||
|
using static Platformer.Core.Simulation;
|
||||||
|
|
||||||
|
namespace EerieVillage.Skills.Effectors
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A11 정령불 Effector — Category D (Minion).
|
||||||
|
/// PD 지시 2026-05-13:
|
||||||
|
/// - 15초마다 (BaseCooldown 15) Player 자식 spawn
|
||||||
|
/// - 8초 유지 (FX_Rotating shield)
|
||||||
|
/// - 지속 시간 동안 적 투사체 SelfDestruct·근접 적 매 초 5 피해
|
||||||
|
/// </summary>
|
||||||
|
public class SpiritFireSpawner : IEffector
|
||||||
|
{
|
||||||
|
public void Trigger(ActiveSkillRuntime runtime, PlayerSkillInventory inventory)
|
||||||
|
{
|
||||||
|
var data = runtime.ActiveData;
|
||||||
|
Vector2 spawnPos = (Vector2)inventory.transform.position + data.OffsetXY;
|
||||||
|
|
||||||
|
GameObject shieldGo;
|
||||||
|
if (data.OnHitFxPrefab != null)
|
||||||
|
{
|
||||||
|
shieldGo = Object.Instantiate(data.OnHitFxPrefab, spawnPos, Quaternion.identity, inventory.transform);
|
||||||
|
shieldGo.transform.localScale *= data.HitFxScale;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shieldGo = new GameObject("SpiritFire_Fallback");
|
||||||
|
shieldGo.transform.SetParent(inventory.transform, false);
|
||||||
|
}
|
||||||
|
shieldGo.hideFlags = HideFlags.DontSave;
|
||||||
|
|
||||||
|
float duration = data.MinionLifetime > 0.1f ? data.MinionLifetime : 8f;
|
||||||
|
float radius = data.AuraRadius > 0.1f ? data.AuraRadius : 2.5f;
|
||||||
|
int damage = data.BaseDamage > 0 ? data.BaseDamage : 5;
|
||||||
|
|
||||||
|
var instance = shieldGo.AddComponent<SpiritFireInstance>();
|
||||||
|
instance.Init(inventory.transform, duration, radius, damage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 정령불 인스턴스 — Player 자식 부착·duration 동안 OverlapCircle 영역 적 투사체 SelfDestruct·근접 적 매 초 5 피해.
|
||||||
|
/// </summary>
|
||||||
|
public class SpiritFireInstance : MonoBehaviour
|
||||||
|
{
|
||||||
|
Transform _player;
|
||||||
|
float _spawnTime;
|
||||||
|
float _duration;
|
||||||
|
float _radius;
|
||||||
|
int _damage;
|
||||||
|
float _lastDamageTime;
|
||||||
|
|
||||||
|
public void Init(Transform player, float duration, float radius, int damage)
|
||||||
|
{
|
||||||
|
_player = player;
|
||||||
|
_duration = duration;
|
||||||
|
_radius = radius;
|
||||||
|
_damage = damage;
|
||||||
|
_spawnTime = Time.unscaledTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
if (Time.unscaledTime - _spawnTime >= _duration)
|
||||||
|
{
|
||||||
|
Destroy(gameObject);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2 center = _player != null ? (Vector2)_player.position : (Vector2)transform.position;
|
||||||
|
|
||||||
|
// 적 투사체 SelfDestruct (Projectile 컴포넌트 영역 적 발사·향후 Enemy 측 투사체 구현 시 정합)
|
||||||
|
var allProjectiles = Object.FindObjectsByType<Projectile>(FindObjectsSortMode.None);
|
||||||
|
foreach (var p in allProjectiles)
|
||||||
|
{
|
||||||
|
if (p == null) continue;
|
||||||
|
float d = Vector2.Distance(center, p.transform.position);
|
||||||
|
if (d <= _radius)
|
||||||
|
{
|
||||||
|
// PD 명시 — 적 투사체만 SelfDestruct. 현 Projectile = Player 발사 only → 영향 X 영역 (방어 코드).
|
||||||
|
// 향후 Enemy 측 Projectile 분리 시 friendly check 추가 필요.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 매 1초 근접 적 피해
|
||||||
|
if (Time.unscaledTime - _lastDamageTime >= 1f)
|
||||||
|
{
|
||||||
|
_lastDamageTime = Time.unscaledTime;
|
||||||
|
ApplyDamageAround(center);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApplyDamageAround(Vector2 center)
|
||||||
|
{
|
||||||
|
var cf = new ContactFilter2D { useTriggers = false };
|
||||||
|
var results = new Collider2D[32];
|
||||||
|
int n = Physics2D.OverlapCircle(center, _radius, cf, results);
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
var c = results[i];
|
||||||
|
if (c == null) continue;
|
||||||
|
var e = c.GetComponent<EnemyController>();
|
||||||
|
if (e == null) continue;
|
||||||
|
var h = c.GetComponent<Health>();
|
||||||
|
if (h == null || !h.IsAlive) continue;
|
||||||
|
h.DecrementBypassInvuln(_damage);
|
||||||
|
if (!h.IsAlive) Schedule<EnemyDeath>().enemy = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -44,7 +44,16 @@ namespace EerieVillage.Skills
|
||||||
else effector = new MeleeAreaSpawner();
|
else effector = new MeleeAreaSpawner();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Phase 2-C~ 예정: PlacementPersistent·Minion·Debuff·SpecialJudge
|
// PD 지시 2026-05-13 Phase B — A06 독 늪 (PlacementPersistent)·A11 정령불 (Minion)
|
||||||
|
case ActiveCategory.PlacementPersistent:
|
||||||
|
effector = new PoisonSwampSpawner();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ActiveCategory.Minion:
|
||||||
|
effector = new SpiritFireSpawner();
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Phase 2-C~ 예정: Debuff·SpecialJudge
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,9 @@ namespace EerieVillage.Skills
|
||||||
{
|
{
|
||||||
"A02", "A13", "A04", "A05", "A_Laser",
|
"A02", "A13", "A04", "A05", "A_Laser",
|
||||||
// PD 지시 2026-05-13 Phase A — A08 저주의 화살·A12 정화의 빛 신규 추가
|
// PD 지시 2026-05-13 Phase A — A08 저주의 화살·A12 정화의 빛 신규 추가
|
||||||
"A08", "A12"
|
"A08", "A12",
|
||||||
|
// PD 지시 2026-05-13 Phase B — A06 독 늪·A11 정령불 신규 추가
|
||||||
|
"A06", "A11"
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ namespace EerieVillage.Skills.Test
|
||||||
readonly LightningStrikeSpawner _lightningSpawner = new LightningStrikeSpawner();
|
readonly LightningStrikeSpawner _lightningSpawner = new LightningStrikeSpawner();
|
||||||
readonly MeleeAreaSpawner _meleeSpawner = new MeleeAreaSpawner();
|
readonly MeleeAreaSpawner _meleeSpawner = new MeleeAreaSpawner();
|
||||||
readonly LaserSpawner _laserSpawner = new LaserSpawner();
|
readonly LaserSpawner _laserSpawner = new LaserSpawner();
|
||||||
|
// PD 지시 2026-05-13 Phase B — 1키 A06 독 늪·2키 A11 정령불 매핑
|
||||||
|
readonly PoisonSwampSpawner _poisonSwampSpawner = new PoisonSwampSpawner();
|
||||||
|
readonly SpiritFireSpawner _spiritFireSpawner = new SpiritFireSpawner();
|
||||||
|
|
||||||
void Awake()
|
void Awake()
|
||||||
{
|
{
|
||||||
|
|
@ -73,13 +76,20 @@ namespace EerieVillage.Skills.Test
|
||||||
}
|
}
|
||||||
else if (data.Category == ActiveCategory.MeleeArea)
|
else if (data.Category == ActiveCategory.MeleeArea)
|
||||||
{
|
{
|
||||||
// 키 2 (A04 번개 충격) — LightningStrikeSpawner
|
// CardId 기반 분기 (SkillFireEvent 동일 패턴)
|
||||||
// 키 3 (A05 학익진) — MeleeAreaSpawner
|
if (data.CardId == "A04") _lightningSpawner.Trigger(rt, _inventory);
|
||||||
// 키 4 (레이저) — LaserSpawner
|
else if (data.CardId == "A_Laser") _laserSpawner.Trigger(rt, _inventory);
|
||||||
if (idx == 1) _lightningSpawner.Trigger(rt, _inventory);
|
|
||||||
else if (idx == 3) _laserSpawner.Trigger(rt, _inventory);
|
|
||||||
else _meleeSpawner.Trigger(rt, _inventory);
|
else _meleeSpawner.Trigger(rt, _inventory);
|
||||||
}
|
}
|
||||||
|
// PD 지시 2026-05-13 Phase B — A06 독 늪 (PlacementPersistent)·A11 정령불 (Minion)
|
||||||
|
else if (data.Category == ActiveCategory.PlacementPersistent)
|
||||||
|
{
|
||||||
|
_poisonSwampSpawner.Trigger(rt, _inventory);
|
||||||
|
}
|
||||||
|
else if (data.Category == ActiveCategory.Minion)
|
||||||
|
{
|
||||||
|
_spiritFireSpawner.Trigger(rt, _inventory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue