多轮审查和修复
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using BaseGames.Core;
|
||||
using BaseGames.Core.Events;
|
||||
using BaseGames.Core.Save;
|
||||
|
||||
@@ -21,6 +23,7 @@ namespace BaseGames.Player
|
||||
[SerializeField] private IntEventChannelSO _onGeoChanged;
|
||||
[SerializeField] private AbilityTypeEventChannelSO _onAbilityUnlocked;
|
||||
[SerializeField] private VoidEventChannelSO _onPlayerDied;
|
||||
[SerializeField] private DifficultyChangedEventChannel _onDifficultyChanged;
|
||||
|
||||
// ── 运行时数值 ─────────────────────────────────────────────────────────
|
||||
public int CurrentHP { get; private set; }
|
||||
@@ -40,14 +43,24 @@ namespace BaseGames.Player
|
||||
private float _invincibleTimer;
|
||||
private float _spiritRegenTimer;
|
||||
private AbilityType _unlockedAbilities = AbilityType.None;
|
||||
private bool _isGodMode;
|
||||
private readonly CompositeDisposable _subs = new();
|
||||
|
||||
// ── 护符属性修改器 ─────────────────────────────────────────────────────────
|
||||
private readonly Dictionary<StatType, float> _flatModifiers = new();
|
||||
private readonly Dictionary<StatType, float> _percentModifiers = new();
|
||||
private float _animatorSpeedBonus = 0f;
|
||||
private int _soulCostReduction = 0;
|
||||
|
||||
/// <summary>动画速度倍率(AttackSpeedEffect 调节,初始 1.0)。</summary>
|
||||
public float AnimatorSpeedMultiplier => 1f + _animatorSpeedBonus;
|
||||
|
||||
/// <summary>法术灵力消耗减免(SoulSpellEffect 叠加)。</summary>
|
||||
public int SoulCostReduction => _soulCostReduction;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_config == null)
|
||||
{
|
||||
Debug.LogWarning("[PlayerStats] PlayerStatsSO not assigned.", this);
|
||||
return;
|
||||
}
|
||||
Debug.Assert(_config != null, "[PlayerStats] _config 未赋值,请在 Inspector 中指定 PlayerStatsSO。", this);
|
||||
MaxHP = _config.MaxHP;
|
||||
CurrentHP = MaxHP;
|
||||
MaxSoulPower = _config.MaxSoulPower;
|
||||
@@ -57,6 +70,21 @@ namespace BaseGames.Player
|
||||
CurrentGeo = _config.InitialGeo;
|
||||
}
|
||||
|
||||
private void OnEnable() => _onDifficultyChanged?.Subscribe(HandleDifficultyChanged).AddTo(_subs);
|
||||
private void OnDisable() => _subs.Clear();
|
||||
|
||||
private void HandleDifficultyChanged(DifficultyLevel _)
|
||||
{
|
||||
var scaler = ServiceLocator.GetOrDefault<IDifficultyService>()?.CurrentScaler;
|
||||
if (scaler == null) return;
|
||||
// 按比例缩放当前 HP(架构 19 §5:难度切换时保持 HP 比例)
|
||||
float hpRatio = MaxHP > 0 ? (float)CurrentHP / MaxHP : 1f;
|
||||
MaxHP = Mathf.Max(1, Mathf.RoundToInt(_config.MaxHP * scaler.PlayerMaxHPMultiplier));
|
||||
CurrentHP = Mathf.Clamp(Mathf.RoundToInt(MaxHP * hpRatio), IsAlive ? 1 : 0, MaxHP);
|
||||
_onMaxHPChanged?.Raise(MaxHP);
|
||||
_onHPChanged?.Raise(CurrentHP);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
float dt = Time.deltaTime;
|
||||
@@ -64,7 +92,7 @@ namespace BaseGames.Player
|
||||
if (_invincibleTimer > 0f)
|
||||
_invincibleTimer -= dt;
|
||||
|
||||
if (_config != null && _config.SpiritRegenRate > 0)
|
||||
if (_config.SpiritRegenRate > 0)
|
||||
{
|
||||
_spiritRegenTimer += dt;
|
||||
if (_spiritRegenTimer >= 1f)
|
||||
@@ -74,13 +102,62 @@ namespace BaseGames.Player
|
||||
}
|
||||
}
|
||||
}
|
||||
// ── 护符修改器 API ─────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>叠加属性修改器(护符效果装备时调用)。</summary>
|
||||
public void AddModifier(StatType stat, float flat, float percent)
|
||||
{
|
||||
_flatModifiers[stat] = _flatModifiers.GetValueOrDefault(stat) + flat;
|
||||
_percentModifiers[stat] = _percentModifiers.GetValueOrDefault(stat) + percent;
|
||||
if (stat == StatType.MaxHP) RecalcMaxHP();
|
||||
}
|
||||
|
||||
/// <summary>移除属性修改器(护符效果卸下时调用)。</summary>
|
||||
public void RemoveModifier(StatType stat, float flat, float percent)
|
||||
{
|
||||
_flatModifiers[stat] = _flatModifiers.GetValueOrDefault(stat) - flat;
|
||||
_percentModifiers[stat] = _percentModifiers.GetValueOrDefault(stat) - percent;
|
||||
if (stat == StatType.MaxHP) RecalcMaxHP();
|
||||
}
|
||||
|
||||
/// <summary>查询指定属性的固定加成(由 PlayerMovement、战斗等外部系统查询)。</summary>
|
||||
public float GetFlatModifier(StatType stat) => _flatModifiers.GetValueOrDefault(stat);
|
||||
|
||||
/// <summary>查询指定属性的百分比加成。</summary>
|
||||
public float GetPercentModifier(StatType stat) => _percentModifiers.GetValueOrDefault(stat);
|
||||
|
||||
/// <summary>加载动画速度加成(AttackSpeedEffect 装备时调用)。</summary>
|
||||
public void AddAnimatorSpeedBonus(float delta) => _animatorSpeedBonus += delta;
|
||||
|
||||
/// <summary>移除动画速度加成(AttackSpeedEffect 卸下时调用)。</summary>
|
||||
public void RemoveAnimatorSpeedBonus(float delta) => _animatorSpeedBonus -= delta;
|
||||
|
||||
/// <summary>增加灵力消耗减免(SoulSpellEffect 装备时调用)。</summary>
|
||||
public void AddSoulCostReduction(int amount) => _soulCostReduction += amount;
|
||||
|
||||
/// <summary>移除灵力消耗减免(SoulSpellEffect 卸下时调用)。</summary>
|
||||
public void RemoveSoulCostReduction(int amount) => _soulCostReduction = Mathf.Max(0, _soulCostReduction - amount);
|
||||
|
||||
private void RecalcMaxHP()
|
||||
{
|
||||
float flat = _flatModifiers.GetValueOrDefault(StatType.MaxHP);
|
||||
float percent = _percentModifiers.GetValueOrDefault(StatType.MaxHP);
|
||||
int newMax = Mathf.Max(1, Mathf.RoundToInt(_config.MaxHP * (1f + percent) + flat));
|
||||
SetMaxHP(newMax);
|
||||
}
|
||||
// ── HP ────────────────────────────────────────────────────────────────
|
||||
/// <summary>受到伤害时触发(已扣血,不包含无敌/死亡情况)。</summary>
|
||||
public event System.Action OnDamaged;
|
||||
|
||||
/// <summary>Debug:开启/关闭无敌模式(不计入无敌帧,永久生效直至关闭)。</summary>
|
||||
public void SetGodMode(bool v) { _isGodMode = v; }
|
||||
|
||||
public void TakeDamage(int amount)
|
||||
{
|
||||
if (IsInvincible || !IsAlive || amount <= 0) return;
|
||||
if (_isGodMode || IsInvincible || !IsAlive || amount <= 0) return;
|
||||
CurrentHP = Mathf.Max(0, CurrentHP - amount);
|
||||
_onHPChanged?.Raise(CurrentHP);
|
||||
OnDamaged?.Invoke();
|
||||
if (CurrentHP == 0)
|
||||
_onPlayerDied?.Raise();
|
||||
}
|
||||
@@ -119,6 +196,9 @@ namespace BaseGames.Player
|
||||
_onSoulPowerChanged?.Raise(CurrentSoulPower);
|
||||
}
|
||||
|
||||
/// <summary>AddSoul 是 AddSoulPower 的别名(架构 06_CombatModule §8 ParrySystem 使用此名称)。</summary>
|
||||
public void AddSoul(int amount) => AddSoulPower(amount);
|
||||
|
||||
public bool ConsumeSoulPower(int amount)
|
||||
{
|
||||
if (CurrentSoulPower < amount) return false;
|
||||
@@ -149,8 +229,7 @@ namespace BaseGames.Player
|
||||
if (CurrentSpringCharges <= 0) return false;
|
||||
CurrentSpringCharges--;
|
||||
_onSpringChargesChanged?.Raise(CurrentSpringCharges);
|
||||
if (_config != null)
|
||||
HealHP(_config.SpringHealAmount);
|
||||
HealHP(_config.SpringHealAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -163,7 +242,6 @@ namespace BaseGames.Player
|
||||
|
||||
public void AddKillPoints(int points = 1)
|
||||
{
|
||||
if (_config == null) return;
|
||||
SpringKillPoints += points;
|
||||
if (SpringKillPoints >= _config.SpringKillThreshold)
|
||||
{
|
||||
@@ -191,7 +269,7 @@ namespace BaseGames.Player
|
||||
// ── Invincibility ─────────────────────────────────────────────────────
|
||||
public void BeginInvincibility(float duration = -1f)
|
||||
{
|
||||
float d = duration >= 0f ? duration : (_config != null ? _config.InvincibilityDuration : 0.6f);
|
||||
float d = duration >= 0f ? duration : _config.InvincibilityDuration;
|
||||
_invincibleTimer = Mathf.Max(_invincibleTimer, d);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user