Files
spellforge/scripts/autoloads/player_stats.gd
T

118 lines
3.9 KiB
GDScript
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.
## PlayerStats — 玩家属性统计(Autoload: PlayerStats
## 权威来源:development_plan.md S2、numerical_design.md §1.2
extends Node
signal stats_changed
signal leveled_up(new_level: int)
# ── HP ───────────────────────────────────────────────
var hp: float = 100.0
var hp_max: float = 100.0
# ── 资源 ──────────────────────────────────────────────
var gold: int = 0
var xp: int = 0
# ── 等级 ──────────────────────────────────────────────
var level: int = 1
var xp_to_next: int = 10 # 升级所需 XP
# ── 战斗属性 ───────────────────────────────────────────
var cpu_limit: int = 5 # 控制 MAX_OPS = cpu_limit * 40
var armor: float = 0.0
var resistance: float = 0.0 # 0.0~1.0
# ── 魔力(MVP)─────────────────────────────────────────
var mana: float = 100.0
var mana_max: float = 100.0
var mana_regen: float = 5.0 # 每秒回复
func _ready() -> void:
EventBus.subscribe(EventID.PLAYER_DAMAGED, _on_player_damaged)
## 升级曲线:roundf(10 × 1.4^(level-1))P6-N16
## Level 1→2: 10 XP; Level 5→6: ≈ 54 XP
static func xp_for_level(lv: int) -> int:
return roundi(10.0 * pow(1.4, float(lv - 1)))
func gain_xp(amount: int) -> void:
xp += amount
while xp >= xp_to_next:
xp -= xp_to_next
level += 1
xp_to_next = xp_for_level(level)
leveled_up.emit(level)
EventBus.emit(EventID.LEVEL_UP, {"level": level})
stats_changed.emit()
func gain_gold(amount: int) -> void:
gold += amount
stats_changed.emit()
func spend_gold(amount: int) -> bool:
if gold < amount:
return false
gold -= amount
stats_changed.emit()
return true
func take_damage(amount: float) -> void:
hp = max(0.0, hp - amount * SettingsManager.player_dmg_taken_mult()) # 难度减伤(初学者×0.7
stats_changed.emit()
if hp <= 0.0:
EventBus.emit(EventID.PLAYER_DIED, {})
func heal(amount: float) -> void:
hp = min(hp_max, hp + amount)
stats_changed.emit()
func get_hp_percent() -> float:
return hp / max(hp_max, 0.001)
## 换杖时设定蓝池上限/回速,并把当前蓝夹到 [0, max]
func set_mana_pool(max_v: float, regen: float) -> void:
mana_max = max_v
mana_regen = regen
mana = clampf(mana, 0.0, mana_max)
stats_changed.emit()
## 花费魔力;够则扣除返回 true,否则不变返回 false
func spend_mana(cost: float) -> bool:
if mana < cost:
return false
mana -= cost
stats_changed.emit()
return true
## 每帧回蓝(PlayerManager 驱动)。不 emit stats_changed —— HUD 每帧直接读 mana
## 避免回蓝过程每帧发信号触发商店刷新。
func regen_mana(delta: float) -> void:
if mana >= mana_max:
return
mana = min(mana_max, mana + mana_regen * delta)
func _on_player_damaged(payload: Dictionary) -> void:
take_damage(float(payload.get("damage", 0.0)))
func reset_for_run() -> void:
hp = hp_max
mana = mana_max
gold = 0
xp = 0
level = 1
xp_to_next = xp_for_level(1)
stats_changed.emit()
func get_save_data() -> Dictionary:
return {"hp": hp, "hp_max": hp_max, "gold": gold, "xp": xp, "level": level, "cpu_limit": cpu_limit}
func load_save_data(data: Dictionary) -> void:
hp = float(data.get("hp", 100.0))
hp_max = float(data.get("hp_max", 100.0))
gold = int(data.get("gold", 0))
xp = int(data.get("xp", 0))
level = int(data.get("level", 1))
cpu_limit = int(data.get("cpu_limit", 5))
xp_to_next = xp_for_level(level)
stats_changed.emit()