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

87 lines
2.7 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.
## ShopManager — 商店管理(Autoload: ShopManager
## S2 范围:3 选 1 法术、金币扣减、刷新费用公式(P6-N23)
## 权威来源:development_plan.md S2、numerical_design.md §2.3
extends Node
signal shop_refreshed
signal shop_closed
const SLOT_COUNT: int = 3
const REROLL_BASE_COST: int = 20 # 第 1 次刷新费用
const REROLL_STEP: int = 10 # 每次递增价格
var current_slots: Array = [] # Array[SpellNode] null 表示已售出)
var reroll_count: int = 0 # 本波已刷新次数(WAVE_COMPLETE 后重置)
var _shop_seed: int = 0 # 随机种(ADR-A2 P-S2-07
var _rng: RandomNumberGenerator = RandomNumberGenerator.new()
func _ready() -> void:
EventBus.subscribe(EventID.WAVE_COMPLETE, _on_wave_complete)
func _on_wave_complete(_payload: Dictionary) -> void:
reroll_count = 0 # P6-N23:波次结算后重置刷新次数
func open_shop(seed_override: int = -1) -> void:
if seed_override >= 0:
_shop_seed = seed_override
else:
_shop_seed = randi()
_rng.seed = _shop_seed
_refresh_slots()
EventBus.emit(EventID.SHOP_OPENED, {"seed": _shop_seed})
func _refresh_slots() -> void:
# 纯数据驱动池:SpellRegistrydata/spells.json)中可购买(shop_cost>0)的法术
var pool: Array = SpellRegistry.get_all_ids().filter(func(id):
var s: SpellNode = SpellRegistry.get_spell(id)
return s != null and int(s.meta.get("shop_cost", 0)) > 0)
current_slots.clear()
for _i in SLOT_COUNT:
if pool.is_empty():
current_slots.append(null)
continue
var idx: int = _rng.randi_range(0, pool.size() - 1)
current_slots.append(SpellRegistry.get_spell(pool[idx]))
pool.remove_at(idx)
shop_refreshed.emit()
## 购买指定槽位的法术,返回购买的 SpellNode、失败返回 null
func buy_spell(slot_idx: int) -> SpellNode:
if slot_idx < 0 or slot_idx >= current_slots.size():
return null
var spell: SpellNode = current_slots[slot_idx]
if spell == null:
return null
var cost: int = int(spell.meta.get("shop_cost", 20))
if not PlayerStats.spend_gold(cost):
return null
current_slots[slot_idx] = null
shop_refreshed.emit()
return spell
## 刷新商店,返回 true 表示成功
func reroll() -> bool:
var cost: int = get_reroll_cost()
if not PlayerStats.spend_gold(cost):
return false
reroll_count += 1
_rng.seed = _shop_seed + reroll_count * 31337
_refresh_slots()
return true
## 刷新费用公式:base + step * reroll_countP6-N23
func get_reroll_cost() -> int:
return REROLL_BASE_COST + reroll_count * REROLL_STEP
func close_shop() -> void:
current_slots.clear()
shop_closed.emit()
func get_shop_seed() -> int:
return _shop_seed
func reset() -> void:
current_slots.clear()
reroll_count = 0
_shop_seed = 0