初次提交

This commit is contained in:
2026-07-20 10:56:52 +08:00
commit 7bcc0026e0
462 changed files with 50191 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
## 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