Files
spellforge/scripts/autoloads/player_stats.gd
T
2026-07-20 10:56:52 +08:00

90 lines
2.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
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)
func _on_player_damaged(payload: Dictionary) -> void:
take_damage(float(payload.get("damage", 0.0)))
func reset_for_run() -> void:
hp = hp_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()