角色能力,存档

This commit is contained in:
2026-05-19 11:50:21 +08:00
parent d25f237e76
commit 2dcb7a961a
136 changed files with 36035 additions and 27551 deletions

View File

@@ -19,7 +19,15 @@ namespace BaseGames.Player.States
private float _invincibilityCooldownTimer;
private int _facingDir;
public bool CanDash => _cooldownTimer <= 0f;
/// <summary>本次离地后是否已消耗过一次空中冲刺。落地或下劈命中Pogo时重置。</summary>
private bool _airDashUsed;
public bool CanDash => _cooldownTimer <= 0f;
/// <summary>空中冲刺可用条件:冷却就绪 且 本次离地内尚未冲刺过。</summary>
public bool CanAirDash => _cooldownTimer <= 0f && !_airDashUsed;
/// <summary>重置空中冲刺次数(落地或 Pogo 时由 IdleState/RunState/DownAttackState 调用)。</summary>
public void ResetAirDash() => _airDashUsed = false;
/// <summary>
/// 无敌帧是否已冷却,即本次冲刺可以获得无敌。
@@ -44,11 +52,20 @@ namespace BaseGames.Player.States
_facingDir = Owner.FacingDirection;
_timer = Cfg.DashDuration;
// 空中冲刺:记录本次离地已使用冲刺(地面冲刺不消耗,仅空中限制一次)
if (!Move.IsGrounded)
_airDashUsed = true;
// 无敌帧:
// 条件 1已解锁 InvincibleDash
// 条件 2无敌冷却已就绪防止 spam 冲刺连序无敌)
// 窗口时长 = DashInvincibilityDuration < DashDuration冲刺后段无保护
if (Stats != null && Stats.HasAbility(AbilityType.InvincibleDash) && CanGrantInvincibility)
// 在设置冷却计时器前捕获,供后续动画选择使用
bool isInvincibleDash = Stats != null
&& Stats.HasAbility(AbilityType.InvincibleDash)
&& CanGrantInvincibility;
if (isInvincibleDash)
{
Stats.BeginInvincibility(Cfg.DashInvincibilityDuration);
_invincibilityCooldownTimer = Cfg.DashInvincibilityCooldown;
@@ -58,8 +75,11 @@ namespace BaseGames.Player.States
Move?.SetGravityScale(0f);
Move?.Dash(new Vector2(_facingDir, 0f), Cfg.DashSpeed);
// 播放冲刺动画
if (AnimCfg?.Dash != null) Anim?.Play(AnimCfg.Dash);
// 播放冲刺动画:无敌冲刺使用专属 Clip留空时回退到普通冲刺 Clip
var dashClip = (isInvincibleDash && AnimCfg?.DashInvincible != null)
? AnimCfg.DashInvincible
: AnimCfg?.Dash;
if (dashClip != null) Anim?.Play(dashClip);
}
public override void OnStateUpdate()
@@ -71,10 +91,19 @@ namespace BaseGames.Player.States
return;
}
// 撞墙立即终止冲刺(碰到实体墙立即中止,避免压墙卡住)
var wd = Owner.WallDetector;
if (wd != null && wd.IsTouchingWall && wd.WallDirection == _facingDir)
EndDash();
// 跳跃可取消冲刺:冲刺期间按跳跃立即中断并起跳。
// 空中冲刺时若有剩余空中跳跃次数,消耗一次并使用二段跳力度。
if (Buffer.ConsumeJump())
{
if (!Move.IsGrounded && Owner.AirJumpsLeft > 0)
{
Owner.UseAirJump();
Owner.GetState<JumpState>()?.SetDoubleJump(true);
}
Owner.TransitionTo(Owner.GetState<JumpState>());
return;
}
// 注:碰墙时不中止冲刺,完成完整冲刺时长(物理阻止位移,但计时继续)
}
public override void OnStateExit()
@@ -93,6 +122,8 @@ namespace BaseGames.Player.States
private void EndDash()
{
// 双轴速度归零,防止冲刺结束时角色带着 DashSpeed 冲出平台边缘后继续向前飞行。
Move?.ZeroVelocity();
if (Move != null && Move.IsGrounded)
Owner.TransitionTo(Owner.GetState<IdleState>());
else