Files
zeling_v2/Assets/_Game/Scripts/Combat/LethalTrap.cs
2026-05-17 07:56:12 +08:00

106 lines
4.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BaseGames.Core.Events;
using UnityEngine;
namespace BaseGames.Combat
{
/// <summary>
/// 致命陷阱(地刺、深渊等)——触碰即造成伤害、可无视无敌帧的固定危险区域:
///
/// ① 玩家 HurtBox 触碰时,通过 HurtBox.ReceiveDamage() 造成一次伤害
/// 并携带 IgnoreIFrame 标记(无视翻滚/受击无敌帧,保证陷阱的绝对威胁性)。
/// ② 若伤害导致玩家死亡 → PlayerController.TakeDamage 已 Raise EVT_PlayerDied
/// 走完整死亡流程(死亡动画 → 重载场景)。
/// ③ 若玩家存活 → 本组件 Raise EVT_PlayerDied强制返回最近检查点
/// 同样触发 DeathRespawnService无死亡演出只是重新加载
///
/// 可下劈Pogo
/// - 将 _canPogo = true并在地刺顶部添加子 GameObject
/// · 挂 HurtBox 组件EnemyHurtBox 层)
/// · 父链上无 IDamageable → ReceiveDamage 无副作用HP 不扣除)
/// · 玩家下劈 HitBox 命中该 HurtBox → HitBox.OnHitConfirmed →
/// WeaponHitBoxInstance.OnDownHitConfirmed → DownAttackState.OnDownHitConfirmed
/// → Move.Jump() 完成弹跳,无需额外代码。
/// - _canPogo = false 则不添加顶部 HurtBox下劈时玩家仍受地刺伤害。
/// </summary>
[RequireComponent(typeof(Collider2D))]
public class LethalTrap : MonoBehaviour
{
[Header("伤害")]
[Tooltip("每次触碰造成的伤害量(建议设为 1确保任意陷阱触碰即扟一格血量")]
[SerializeField] private int _damage = 1;
[Header("检测")]
[Tooltip("勾选 PlayerHurtBox 层")]
[SerializeField] private LayerMask _playerLayers;
[Header("事件")]
[Tooltip("EVT_PlayerDied — 触发后由 DeathRespawnService 接管回到检查点")]
[SerializeField] private VoidEventChannelSO _onPlayerDied;
[Header("设计")]
[Tooltip("true = 顶部有 HurtBox 子节点可下劈弹跳(需手动添加 Pogo Surface 子节点)")]
[SerializeField] private bool _canPogo = true;
private bool _triggered;
private void Awake()
{
var col = GetComponent<Collider2D>();
if (!col.isTrigger)
{
col.isTrigger = true;
Debug.LogWarning($"[LethalTrap] {name}: Collider2D.isTrigger 已自动设为 true。", this);
}
}
private void OnEnable() => _triggered = false;
private void OnTriggerEnter2D(Collider2D other)
{
if (_triggered) return;
if ((_playerLayers.value & (1 << other.gameObject.layer)) == 0) return;
_triggered = true;
// ── 1. 通过 HurtBox 流水线造成伤害(含防御计算,携带 IgnoreIFrame────────
bool playerDiedFromDamage = false;
if (_damage > 0)
{
var hurtBox = other.GetComponent<HurtBox>();
if (hurtBox != null)
{
var info = new DamageInfo.Builder()
.SetRaw(_damage)
.SetFlags(DamageFlags.IgnoreIFrame) // 无视无敌帧(翻滚/受击)
.SetSourceId("lethal_trap")
.Build();
hurtBox.ReceiveDamage(info);
// 检测伤害后玩家存活状态:
// 若已死亡PlayerController.TakeDamage 已在同帧内 Raise EVT_PlayerDied
// 若存活,需由本组件 Raise 使其回到检查点。
var damageable = other.transform.root.GetComponentInParent<IDamageable>();
playerDiedFromDamage = damageable != null && !damageable.IsAlive;
}
}
// ── 2. 若玩家存活(或无 HurtBox / damage=0强制触发检查点回溯 ───────────
if (!playerDiedFromDamage)
_onPlayerDied?.Raise();
}
#if UNITY_EDITOR
[UnityEngine.ContextMenu("打印 Pogo 提示")]
private void PrintPogoInfo()
{
Debug.Log(
_canPogo
? $"[LethalTrap] {name}: _canPogo=true。请在顶部添加子 GO + HurtBox(EnemyHurtBox 层) + Collider2D(isTrigger=true),父链上无 IDamageable。"
: $"[LethalTrap] {name}: _canPogo=false无下劈弹跳。",
this);
}
#endif
}
}