Files
gplan-2/game/core/status_container.gd
T
DKChan 32fdf957fd refactor(代码术语): 卡① flag→seal 全族换代+game/ 禁用词清扫(迭代 31 卡①)
标识符面:flag_*→seal_ 族(含 Godot 信号 flag_judged→seal_judged 与连接/回调同名、
FACTS 两键 flags_count→seals_count/dug_under_flag→dug_under_seal 全链、
.tres 键名与 schema .gd 同批同步);显式豁免零改动=size_flags_*(Godot 布局属性)+_fatal_flag。
中文面:金币→GP(金币袋→GP 袋)/插旗→封印/雷格→危险格/惩罚格→危险格/旗→封印·封印印记族,
game/ 内 *.gd/.tres/.md/.json 四类禁用词与 flag 双双零命中(V1/V4)。
守卫字面量不动(被检查的禁字不是使用):smoke_all V21 零「雷/旗」检查面、
ui_font_asset_test 字形集攻/雷/旗/封 保持原断言逻辑。
代拍板:板面单字槽 glyph「旗」→「封」(禁字纪律+单字位宽,消费面四处同名随动)。
素材换代(2026-10-18 用户裁案甲):assets/art/board/flag_seal.png→seal_mark.png(素材不入 git,
盘上改名+导入重刷),代码两处 res:// 字符串+COL_FLAG/CURSOR_FLAG 常量同步,
闸件四处随批(run_all_gates.sh/render_gate.sh/golden_baseline_refresh.sh/path_check.py)。
anchor.json 键名手改,重锚与改前改后 diff 随本卡收口(同裁案甲)。

基线读数(改前,主区 ed2dfaf6):冒烟 1151 检查 0 失败/单元 34 套全绿/探针 --click
存量红仅 screen_flow_probe(user:// 断点污染在册已知项)。
改后同批读数(本 worktree):冒烟 1151 检查 0 失败/探针 --click 同一存量红、其余全绿。
2026-10-19 02:52:38 +08:00

130 lines
5.0 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.
## VERTICAL SLICE - NOT FOR PRODUCTION
## 增益状态统一容器:三方效果同构实例、单一时限量纲(先兑付后衰减)、按行叠层与授予时快照抗热重载(垂直切片验证:增益减益逐行归因)。
## 零随机零信号——纯被动服务;授予唯一入口 apply_effect,满层拒绝零写入(拒收记未生效行归调用方)。
class_name StatusContainer
extends RefCounted
var db: ConfigDb
var _open := false
var _instances: Array[Dictionary] = [] # 插入序;元素 = {effect_id, layers, remaining, source_class, origin_cell, round_index, snap_m, snap_unit, snap_display}
func _init(db_ref: ConfigDb) -> void:
db = db_ref
func notify_battle_start() -> bool:
if _open:
push_warning("[增益状态] Active 下重复 notify_battle_start(EC11)")
return false
_open = true
_instances.clear()
return true
# 唯一授予入口(挖掘期零直写——战斗结算 结算编排期统一调用)。
# duration_override(敌人技能池批——增益技施放):技能行 buff_duration 覆盖状态行时长(-1 = 状态表值)。
# 施放是持续量的 owner(proposal §2.2 字段词汇表"buff_duration 增益持续回合数");其他授予路径传缺省。
func apply_effect(effect_id: String, source: Dictionary, duration_override: int = -1) -> bool:
if not _open:
push_warning("[增益状态] 域闭授予(EC1)")
return false
var row: Dictionary[Variant, Variant] = db.status_effect_row(effect_id)
if row.is_empty():
push_warning("[增益状态] 未知 effect_id(EC2): %s" % effect_id)
return false
var policy: String = row.stack_policy
var dur: int = int(row.duration_settlements) if duration_override < 1 else duration_override
var max_stack: int = int(row.max_stack)
# 授予时快照(抗表重载——EC9)
var snap_m: int = int(row.magnitude)
if source.has("magnitude_override"):
snap_m = int(source["magnitude_override"]) # 封印溢价贯穿(迭代14② T4——封印命中 percent 形态同乘快照;缺省路径零扰动)
var snap_unit: String = String(row.unit)
var snap_display: String = String(row.display_name)
match policy:
"independent":
_instances.append(_new_instance(effect_id, 1, dur, source, snap_m, snap_unit, snap_display))
return true
"refresh":
for inst in _instances:
if inst.effect_id == effect_id:
inst.remaining = dur # R ← D(取实例快照 D——同表值);L 不变;空刷新恒 true
return true
_instances.append(_new_instance(effect_id, 1, dur, source, snap_m, snap_unit, snap_display))
return true
"stack":
for inst in _instances:
if inst.effect_id == effect_id:
if inst.layers >= max_stack:
return false # 满层拒绝原子——容器零写入(拒收由战斗结算记"奖励未生效"行)
inst.layers += 1 # stack 授予不触碰 R(spec 决议)
return true
_instances.append(_new_instance(effect_id, 1, dur, source, snap_m, snap_unit, snap_display))
return true
push_warning("[增益状态] 未知 stack_policy")
return false
func _new_instance(effect_id: String, layers: int, dur: int, source: Dictionary, m: int, unit: String, display: String) -> Dictionary:
return {
"effect_id": effect_id,
"layers": layers,
"remaining": dur,
"source_class": String(source.get("source_class", "")),
"origin_cell": source.get("origin_cell", Vector2i(-1, -1)),
"round_index": int(source.get("round_index", 0)),
"snap_m": m,
"snap_unit": unit,
"snap_display": display,
}
# 只读投影(插入序稳定枚举;六归因字段 + display_name + 授予时快照)
func query_active(side: String) -> Array:
var out: Array[Dictionary] = []
for inst in _instances:
var row: Dictionary[Variant, Variant] = db.status_effect_row(inst.effect_id)
if row.is_empty():
continue
if String(row.target_side) != side:
continue
out.append({
"effect_id": inst.effect_id,
"layers": inst.layers,
"remaining_settlements": inst.remaining,
"source_class": inst.source_class,
"origin_cell": inst.origin_cell,
"round_index": inst.round_index,
"display_name": inst.snap_display,
"snap_magnitude": inst.snap_m,
"snap_unit": inst.snap_unit,
"effective_value": inst.layers * inst.snap_m, # L×m 加算(percent 越域不 clamp——收口归 战斗结算)
})
return out
# 轮末衰减:先兑付后衰减;每实例恰 −1;归 0 移除;返回移除数 k(恰一次执行由 战斗结算 编排信任承载)
func decay_round() -> int:
if not _open:
return 0 # EC13 域闭兜底读法——容器恒空,无独立分支不诊断
var k := 0
var survivors: Array[Dictionary] = []
for inst in _instances:
inst.remaining -= 1
if inst.remaining <= 0:
k += 1
else:
survivors.append(inst)
_instances = survivors
return k
func notify_battle_end() -> bool:
if not _open:
push_warning("[增益状态] BattleClosed 下重复 notify_battle_end(EC11)")
return false
_open = false
_instances.clear() # 全清不跨战斗
return true