Files
spellforge/scripts/domain/player_manager.gd
T
joywayerandClaude Opus 5 a3bb778715 feat(attr): 接线 MAX_OPS/移速/施法间隔;法杖 cpu_limit 以加成来源接入
MAX_OPS 由硬编码 40×5 改为读生效 cpu_limit——cores.json 里逐法杖配置的
3/5/6/8 自此生效,法杖间恢复运算力区分度。玩家基准取 0,故小木法杖仍为
5 → 200 步,现有平衡零改动。

法杖份额走 add_modifier 而非调用点相加:否则 hard(50) 只钳制玩家那一份,
法杖份额加在钳制之后可使总值越界。换杖时先 remove_modifiers_from("core")
再 add,防止累积。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 11:35:24 +08:00

126 lines
3.6 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.
## PlayerManager — 玩家管理 Autoload
## S0WASD 移动 + 位置查询
## S1:自动施法
## S4:停步蓄力 / 冲刺边沿检测(P6-N69、P6-N36
extends Node
const MOVE_THRESHOLD_NORM: float = 0.1
const CHARGE_TRIGGER_TIME: float = 1.5
var _position: Vector2 = Vector2.ZERO
var _velocity: Vector2 = Vector2.ZERO
var _player_node: Node2D = null
var _equipped_core: CoreDefinition = null
var _equipped_compiled: CompiledDeck = null
var _cast_timer: float = 0.0
var _cast_interval: float = 0.5
var _is_moving: bool = false
var _stationary_time: float = 0.0
var _charge_triggered: bool = false
var _last_dash_time: float = -999.0
var kill_count: int = 0
func _ready() -> void:
EventBus.subscribe(EventID.ENEMY_KILLED, _on_enemy_killed)
func _physics_process(delta: float) -> void:
PlayerStats.regen_mana(delta)
PlayerStats.mana_heat = maxf(0.0, PlayerStats.mana_heat - SettingsManager.mana_heat_decay() * delta)
_handle_movement(delta)
_handle_charge_state(delta)
_handle_auto_cast(delta)
func _handle_movement(delta: float) -> void:
var dir := Vector2(
Input.get_axis("ui_left", "ui_right"),
Input.get_axis("ui_up", "ui_down")
)
_is_moving = dir.length() > MOVE_THRESHOLD_NORM
if _is_moving:
dir = dir.normalized()
_velocity = dir * PlayerStats.move_speed
else:
_velocity = Vector2.ZERO
_position += _velocity * delta
if _player_node:
_player_node.global_position = _position
func _handle_charge_state(delta: float) -> void:
if Input.is_action_just_pressed("ui_accept"):
_last_dash_time = Time.get_ticks_msec() / 1000.0
EventBus.emit(EventID.DASH_TRIGGERED, {
"caster_id": 0,
"stationary_time": _stationary_time,
})
_stationary_time = 0.0
_charge_triggered = false
return
if _is_moving:
if _stationary_time > 0.0:
_stationary_time = 0.0
_charge_triggered = false
EventBus.emit(EventID.CHARGE_STATE_CHANGED, {"caster_id": 0, "progress": 0.0})
else:
_stationary_time += delta
if _stationary_time >= 0.3:
var prog: float = clampf(_stationary_time / CHARGE_TRIGGER_TIME, 0.0, 1.0)
EventBus.emit(EventID.CHARGE_STATE_CHANGED, {"caster_id": 0, "progress": prog})
if _stationary_time >= CHARGE_TRIGGER_TIME and not _charge_triggered:
_charge_triggered = true
EventBus.emit(EventID.CHARGE_FIRED, {"caster_id": 0})
func _handle_auto_cast(delta: float) -> void:
if _equipped_compiled == null or _equipped_compiled.is_empty():
return
_cast_timer -= delta
if _cast_timer <= 0.0:
_cast_timer = _cast_interval
SpellEvaluator.execute_compiled(_equipped_compiled, 0, _position)
func equip_wand(core: CoreDefinition, compiled: CompiledDeck) -> void:
_equipped_core = core
_equipped_compiled = compiled
_cast_interval = (core.cast_interval if core else 0.5) * PlayerStats.cast_delay_mod
_cast_timer = 0.0
if core:
PlayerStats.set_mana_pool(core.base_mana_max, core.base_mana_regen)
else:
PlayerStats.set_mana_pool(100.0, 5.0)
PlayerStats.mana_heat = 0.0
func get_position() -> Vector2:
return _position
func get_velocity() -> Vector2:
return _velocity
func get_stationary_time() -> float:
return _stationary_time
func is_charge_triggered() -> bool:
return _charge_triggered
func set_player_node(node: Node2D) -> void:
_player_node = node
if node:
_position = node.global_position
func _on_enemy_killed(_payload: Dictionary) -> void:
kill_count += 1
func reset() -> void:
_position = Vector2.ZERO
_velocity = Vector2.ZERO
_player_node = null
_equipped_compiled = null
_equipped_core = null
_cast_timer = 0.0
_is_moving = false
_stationary_time = 0.0
_charge_triggered = false
kill_count = 0