iter51-卡1

This commit is contained in:
DKChan committed 2026-11-04 05:08:31 +08:00
1 parent 61995733f7
commit 1cd6e2b1b0
21 files changed
+68 -93

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 B

After

Width:  |  Height:  |  Size: 123 B

+9 -22
View File
@@ -11,7 +11,6 @@ signal round_end_stopped(payload: Dictionary) ## 双发射源之停手路径
const PHASE_IDLE := "Idle"
const PHASE_ACTIVE := "Active"
const PHASE_WAITING := "Waiting"
const CHARGE_LAYER_CAP := 3 # 蓄力层上限(机制结构常量,非玩法表值——整备军备面)
# 相位轴:内部 enum + match,外部 phase getter 保持
# String 面(presentation_snapshot 与冒烟链的 "Idle"/"Active"/"Waiting" 对照契约)。
@@ -32,15 +31,10 @@ var rap: int:
var _last_round_end: Dictionary[String, String] = {} # {path_tag, continuation_hint}——排雷玩法 组包 round_end 的合法数据源
var _settlement_consumed := false # AC-14 门:notify_settlement_done 消费后才受理 round_start
var _pending_ap_delta := 0 # 下轮行动点修正排队(action 型 ±1 排队,轮开始兑现后清零)
# 蓄力流运行态:转蓄力=round_end grant_ap(mode:transfer) 订阅(finish_round_stop 定夺)、
# 深挖对价=dig_paid counter_spend 订阅(request_dig 施加面);charge_layers=蓄力层账本
var _charge_layers := 0
var charge_layers: int:
get: return _charge_layers
# 效果端口件(dig_paid/dig_stop/charge_full 发射面经端口路由宿主;组装期单点注入——
# 效果端口件(dig_paid/dig_stop 发射面经端口路由宿主;组装期单点注入——
# host _init bind_port;缺省 null=未绑零扰动,与原 _fx==null 守卫同语义)
var _port: EffectPort = null
var _last_stop_ap := 0 # 停手侧剩余 AP 记账(转存决策在 round_end 发射点——grant_ap(transfer) 订阅定夺)
var _last_stop_ap := 0 # 停手侧剩余 AP 记账(转存决策在 round_end 发射点)
# 效果端口件注入(host _init 组装期单点——先于 begin_battle 任何发射)
@@ -165,9 +159,9 @@ func _spend_and_arbitrate(action_kind: String, clears_map: bool) -> bool:
# 停手:剩余 AP 1:1 转存 RAP;行动经济 直发 stopped 路径 round_end(双发射源)。
# 转蓄力层〔上限 3〕替代 RAP 转存——「不动也是行动」;cleared 分支 AP 恒清零维持作废语义。
# cleared 分支 AP 恒清零维持作废语义。
# 本方法只记账——剩余 AP 存 _last_stop_ap 后清零,转存决策在 round_end 发射点
# finish_round_stop(grant_ap(mode:transfer) 订阅定夺)。
# finish_round_stop(转存率定夺)。
func request_stop() -> bool:
if _phase != Phase.ACTIVE:
_reject("phase")
@@ -193,18 +187,11 @@ func grant_reserve_ap(n: int) -> void:
_rap += maxi(0, n)
# 轮末停手转存决策(round_end 发射点调用——编排器授予段尾):transfer=true=剩余 AP 转蓄力层
# (上限 CHARGE_LAYER_CAP,整备军备面);false=按转存率转存 RAP(transfer_pct 百分比口径缺省 100=1:1;
# 储备罐 rap_transfer_mult magnitude 125=1.25:1,整数除法向下取整=每 4 AP 多转 1)。
# 非停手轮(cleared/耗尽)_last_stop_ap=0 两分支均零操作。转蓄后达上限的沿发 charge_full(R6 框架先行——现无订阅者)。
func finish_round_stop(transfer: bool, transfer_pct: int = 100) -> void:
if transfer:
var prev_layers := _charge_layers
_charge_layers = mini(CHARGE_LAYER_CAP, _charge_layers + _last_stop_ap)
if _port != null and _charge_layers >= CHARGE_LAYER_CAP and prev_layers < CHARGE_LAYER_CAP:
_port.emit("charge_full", {"layers": _charge_layers})
else:
_rap += _last_stop_ap * maxi(1, transfer_pct) / 100
# 轮末停手 RAP 转存(round_end 发射点调用——编排器授予段尾):按转存率转存 RAP
# (transfer_pct 百分比口径缺省 100=1:1;储备罐 rap_transfer_mult magnitude 125=1.25:1,
# 整数除法向下取整=每 4 AP 多转 1)。非停手轮(cleared/耗尽)_last_stop_ap=0 零操作。
func finish_round_stop(transfer_pct: int = 100) -> void:
_rap += _last_stop_ap * maxi(1, transfer_pct) / 100
_last_stop_ap = 0
+5 -9
View File
@@ -1,5 +1,5 @@
## 效果引擎宿主件(自 battle_orchestrator 收编 fx 族):事件发射面(fx_emit——18 发射点统一入口)、
## 补充事实判定(charge_layers 自答,余五事实转宿主)、主角 AC 三值累积与同步(本轮/本战累积器+
## 补充事实判定(biz_fact 闭面四键)、主角 AC 三值累积与同步(本轮/本战累积器+
## 基线快照)、bonus_delta 四轴累积(战末宿主 drain 汇入账本)、揭示待兑队列与兑付(含再入闸——
## 同步信号回环防二次缓冲二次兑付)、round/battle 桶计数器持有(桶随编排器生灭语义不变)、
## round_start 发射与施加、订阅重建、桶挂引用。生命周期=随编排器(编排器 _init 同建同灭,每战新建)。
@@ -34,7 +34,7 @@ var ac := {"base": -1, "round": 0, "battle": 0} # ac 束(base=主角 AC 基
var _fx_bonus_delta := {"atk": 0, "max_hp": 0, "armor_class": 0, "ap": 0} # 本战 bonus_delta 累积(战末宿主 bonus_delta_drain 读后清零)
var _fx_new_resource_types := {} # 本战已见资源类型集(地质学家 fact new_resource_type 判定——battle 域)
var reveal := {"queue": [], "busy": false} # reveal 束(queue=揭示效果待兑队列〔见血开窍/斩首学者/地质学家/跳格采掘共用——授予段末统一兑付,防轮 facts 迭代中追加重入〕;busy=兑付中标记——宿主 _on_cell_revealed 缓冲旁路判定,防二次缓冲二次兑付)
var facts_inject := {"dig_streak": 0, "rider_tier_bonus": 0, "rider_tier_crit": false} # 业务发射事实束(键集封闭——原 damage.inject 运行态束迁宿主:dig_streak=combat_segment 每轮写;rider 两键=begin_battle 每战复位;charge_layers 不在束内=活读 action_economy)
var facts_inject := {"dig_streak": 0, "rider_tier_bonus": 0, "rider_tier_crit": false} # 业务发射事实束(键集封闭——原 damage.inject 运行态束迁宿主:dig_streak=combat_segment 每轮写;rider 两键=begin_battle 每战复位)
func _init(bundle: Dictionary) -> void:
@@ -89,13 +89,11 @@ func counter_add(counter_id: String, value: int, set_form: bool) -> void:
EffectEngine.counter_add(counters_ctx, counter_id, value, set_form)
# 业务发射事实面(闭面五键——三 when 事实 {charge_layers 活读/dig_streak 轮内槽/hp_ratio 主角
# 业务发射事实面(闭面四键——三 when 事实 {dig_streak 轮内槽/hp_ratio 主角
# 血量比例算式逐字承 damage_controller 原式}∪ 两 rider 运行态读数 {facts_inject 现值};
# 其余事实一律 null——battle_index/round_index/seals_count/nest_count 禁进,扩面=行为变化)
func biz_fact(name: String) -> Variant:
match name:
"charge_layers":
return action_economy.charge_layers
"dig_streak":
return int(facts_inject["dig_streak"])
"hp_ratio":
@@ -216,11 +214,9 @@ func reveal_busy() -> bool:
return bool(reveal.busy)
# 补充事实面(fact 取值第二优先源——payload 未携带的运行态读数;charge_layers 本件自答
# 〔action_economy 直读〕,余五事实转宿主 facts_cb——宿主侧单点,未知事实回落 null)
# 补充事实面(fact 取值第二优先源——payload 未携带的运行态读数;
# 全部转宿主 facts_cb——宿主侧单点,未知事实回落 null)
func _fx_fact(fact: String) -> Variant:
if fact == "charge_layers":
return action_economy.charge_layers
return facts_cb.call(fact)
+1 -1
View File
@@ -110,7 +110,7 @@ func _book_negative_blast() -> void:
_rounds.mines_hits["total"] += 1
# 效果引擎宿主侧事实单点(fx_host facts_cb 注入——round_index/battle_index/seals_count/nest_count/hp_ratio 五事实;charge_layers 归 fx_host 自答;未知事实回落 null)
# 效果引擎宿主侧事实单点(fx_host facts_cb 注入——round_index/battle_index/seals_count/nest_count/hp_ratio 五事实;未知事实回落 null)
func _fx_host_fact(fact: String) -> Variant:
match fact:
"nest_count":
+4 -5
View File
@@ -268,8 +268,7 @@ func _hero_attack_ctx(t: Dictionary) -> Dictionary:
# 按序改写族四拍+掷点快照(armor_roll 发射点在此):第一拍矿工重锤命中交换(正负双修原生形态:
# 命中判定减成 trade_hit 点〔更易命中〕换攻击增伤 trade_atk%——高 AC 负期望/低 AC 正期望;
# 改写位先于掷点折扣读数)→ 第二拍专注免掷骰恒定折扣(方差买断成期望——稳定器人格;roll 记 0 归因)
# → 第三拍厚积薄发满层必中(spike ready 时 discount 恒全额、暴击面走倍乘不加掷;when charge_layers≥3
# 在 dispatch 判定——满层持续状态口径)→ 第四拍猎弱本能对轻甲敌折扣档改善 value 档
# → 第三拍满层必中(spike ready 时 discount 恒全额、暴击面走倍乘不加掷)→ 第四拍猎弱本能对轻甲敌折扣档改善 value 档
# (对冲 pierce 列 L1 −1 开局罚;改善 = 折扣表向全额方向移档,nat 最大面/已全额不重复)。
# clamp_check 同在此发射(唯一发射点——命中随返回值穿给 _ctx_clamp_delta)。
func _ctx_rewrites(t: Dictionary, target: Dictionary, armor: String, matchup: String) -> Dictionary:
@@ -335,7 +334,7 @@ func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
for h in ac_hits:
if String(h.get("kind", "")) == "modify_ticket" and int(h.get("trade_atk", 0)) > 0:
base_value *= 1.0 + float(int(h.trade_atk)) / 100.0
# 加法族:整备军备「每层下轮首段 +1」(层数×value 加算)——attack_bonus per charge_layers。
# 加法族:attack_bonus per 计数器层值(层数×value 加算)。
# value_counter 扩展〔疼痛记忆/弃图兑换/陷阱本能——rider 值=计数器账面,
# 值读于施加时点=命中序先行 rider 后清零行〕
for h in ac_hits:
@@ -349,7 +348,7 @@ func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
if String(h.get("kind", "")) == "counter_add":
var set_v = h.get("set", null)
_port.counter_add(String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null)
# 任意真族:厚积薄发满层 spike 倍乘(≥3 层——强制必中已在折扣拍承载)
# 任意真族:modify_ticket mode=spike 满层倍乘(强制必中已在折扣拍承载)
if ctx["spike_ready"]:
for h in ac_hits:
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "spike":
@@ -430,7 +429,7 @@ func _resolve_enemy_skill(t: Dictionary) -> void:
var hero: Dictionary[Variant, Variant] = units.hero_unit()
var roll := _enemy_roll(t)
var total: int = int(roll["total"])
# damage_taken 发射(kind=enemy_skill;铁壁整备减伤订阅面:shield 加法族合计 value×per(charge_layers),
# damage_taken 发射(kind=enemy_skill;shield 减伤订阅面:加法族合计 value×per 计数器层值,
# 稳健拓荒树规则同面(rebuild 合成订阅);减后过下限保底。damage_reduce〔背水 hp_ratio when〕/
# counter_add〔保险丝/石肤〕/ac_bonus〔石肤〕同面施加;hp_ratio fact 由 damage_taken 载荷携带)
var dt_res := _emit_hero_damage_taken(total, "enemy_skill", String(t.context.get("skill_id", "")), t.origin_cell, int(t.round_index))
+5 -5
View File
@@ -11,7 +11,7 @@ extends RefCounted
## 装板完成〔巢穴预告——每板恰一次,战斗板生成/重建发射点〕)
const EVENTS := ["dig_reveal", "dig_paid", "seal_hit", "mine_hit", "attack_commit", "clamp_check",
"armor_roll", "kill", "damage_taken", "enemy_hp_threshold", "round_start", "seal_settle",
"round_end", "reward_roll", "treasure_used", "charge_full", "dig_stop", "battle_won", "seal_missed",
"round_end", "reward_roll", "treasure_used", "dig_stop", "battle_won", "seal_missed",
"board_installed",
# 换图系双事件(refresh_request=玩家请求刷新〔省力周转 apply_discount 订阅面——折扣只改门槛
# 与扣费不改拒绝判据〕;board_refreshed=成功刷新事实〔换图系七件订阅主挂点——装新板后才发射〕)
@@ -56,7 +56,7 @@ const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open
## 当时有封印〔破封一击〕;ap_exhausted_last=上轮 AP 耗尽〔一滴不剩〕;hp_ratio=生命比例〔背水
## 06 前置条兑付〕;amount=单次伤害量〔保险丝〕;ap_left=停手剩余 AP〔弃图兑换〕)
const FACTS := ["matchup", "is_first_dig_of_battle", "terrain_kind", "target_armor_class",
"seals_count", "charge_layers", "nest_count", "round_index", "counter",
"seals_count", "nest_count", "round_index", "counter",
"new_resource_type", "is_edge_cell", "is_blank_zero", "dug_under_seal",
"ap_exhausted_last", "hp_ratio", "amount", "ap_left", "pct",
"battle_index"] # 关卡域战斗序(1 基,enc 携带;开局姿态组「每关首轮窗」条件面)
@@ -200,7 +200,7 @@ func _push_trigger(source: String, id: String, tr: Dictionary, row: Dictionary)
_triggers.append(t)
## 订阅查询面(发射点缺省行为仲裁用——如 round_end 无 transfer 订阅时走 RAP 转存)
## 订阅查询面(发射点缺省行为仲裁用——round_end 走 RAP 转存)
func has_effect_on(event: String, kind: String, mode: String = "") -> bool:
for tr in _triggers:
if String(tr.on) != event:
@@ -458,11 +458,11 @@ static func _vtr_from_refs(rid: String, tr: Dictionary, row: Dictionary, errs: A
## 组合规则(需求卡片 §3.4 六族——效果类型的必填属性,发射点施加面引用)
## 加法族(数值相加,可交换):add_ticket_rider、attack_bonus、grant_material、grant_ap(非 transfer)、
## 加法族(数值相加,可交换):add_ticket_rider、attack_bonus、grant_material、grant_ap、
## counter_add、shield——发射点逐条累加收集器。
## 乘法族(收集后一次施加,正负分桶):yield_mult、damage_mult。
## 任意真族(任一命中即生效):spawn_spell、spike。
## 按序改写族(收集→单点按声明序施加):modify_ticket 及一切改写窗口效果。
## 按序消耗族(按订阅序消耗共享资源,耗尽即止;可选 fallback):counter_spend。
## 即时执行族(每条命中各自执行一次,执行序=声明序):open_ticket、grant_ap(mode:transfer)、
## 即时执行族(每条命中各自执行一次,执行序=声明序):open_ticket、
## rewrite_board、apply_status——发射点逐条执行。
+2 -2
View File
@@ -1,7 +1,7 @@
## 效果端口件:战斗业务类(DamageController/ActionEconomy)唯一的效果发射出口——收事件与载荷、
## 交效果引擎结算、取回命中批。六 Callable 路由宿主(BattleFxHost.fx_emit_biz/counter_read/
## counter_add/biz_fact/enqueue_reveal/apply_ac_bonus),经组装期 bind_port 单点注入。
## 闭面红线:事实回调=biz_fact 闭面五键(charge_layers/dig_streak/hp_ratio/rider_tier_bonus/
## 闭面红线:事实回调=biz_fact 闭面四键(dig_streak/hp_ratio/rider_tier_bonus/
## rider_tier_crit),battle_index/round_index/seals_count/nest_count 禁进业务发射事实面。
## 单向接线:本件只持宿主注入的 Callable,禁持 BattleFxHost 对象引用(宿主 bundle 已持两业务类
## ——对象引用即成 host→damage→port→host 强引用环,两件均随每战新建=泄漏)。
@@ -50,7 +50,7 @@ func counter_add(counter_id: String, value: int, set_form: bool) -> void:
counter_add_cb.call(counter_id, value, set_form)
# 事实取值(闭面五键宿主侧单点——未绑→null)
# 事实取值(闭面四键宿主侧单点——未绑→null)
func fact(name: String) -> Variant:
if not fact_cb.is_valid():
return null
+1 -3
View File
@@ -1,7 +1,7 @@
class_name CombatSegment
extends RefCounted
# ③ 战斗段 Segment(P1-1 结算巨函数拆段;段边界=审计五段〔裁点③甲〕)。
# 职责:案C 闸复位 + 本轮扫雷事实推导(执拗 streak 取数面)+ 蓄力层注入 + 主角先手
# 职责:案C 闸复位 + 本轮扫雷事实推导(执拗 streak 取数面)+ 主角先手
# + 敌方行动兑现 + 地图伤害账殿后(补提交统一结账)。
# 调用序:主角先手 → 逐敌还手 → 地图伤害账殿后〔案C〕;hero hp=0 短路。
# 行发射/开单单点归宿主(oc)——案C 暂存闸归 RewardGrant(段持三引用直调,零转发壳)——
@@ -32,8 +32,6 @@ func run(ri: int) -> void:
elif evt.kind == "mine":
round_mine = true
oc.fx_host().facts_inject["dig_streak"] = 0 if round_mine else round_safe
# 蓄力层不再逐轮注入(效果端口件闭面——fact charge_layers 由宿主 biz_fact 活读 action_economy
# 现值:唯一写点=finish_round_stop 于上轮授予段尾,本轮授予段发射前无第二写点,活读等价)
_hero_strike(ri)
_enemy_actions(ri)
_board_deferred_settle(ri)
+2 -4
View File
@@ -259,8 +259,7 @@ func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionar
# round_end 发射+施加(每轮结算收口:熔火之躯反打单开立〔open_ticket 即时执行〕+积层清零〔counter_add
# set〕;整备转蓄力由 finish_round_stop 承载——停手侧 AP 已在 request_stop 记账,转存决策=grant_ap
# (mode:transfer) 订阅定夺,无订阅走 RAP 转存缺省)+施加面:grant_gp〔爆破会计/收盘——escrow 战斗域
# set〕;停手侧 AP 已在 request_stop 记账,finish_round_stop 按转存率转存 RAP)+施加面:grant_gp〔爆破会计/收盘——escrow 战斗域
# 缓冲,随 gp_dropped 上抛〕/grant_ap mode:queue〔封印回响——返 1 AP 下轮,queue_ap_delta 通道与轮始
# 加成同面〕+段界收口(转存率入参、清图奖励、揭示兑付、段界结账)
func _round_end_apply(ri: int) -> void:
@@ -278,8 +277,7 @@ func _round_end_apply(ri: int) -> void:
oc.action_economy.queue_ap_delta(int(h.get("value", 0)))
# 转存率入参(储备罐 rap_transfer_mult magnitude=目标转存率百分比 125=1.25:1;未装配=100 与 1:1 逐位一致)
var rap_pct: int = oc.attune_param_sum("rap_transfer_mult")
oc.action_economy.finish_round_stop(fx_host.engine.has_effect_on("round_end", "grant_ap", "transfer"),
rap_pct if rap_pct > 0 else 100)
oc.action_economy.finish_round_stop(rap_pct if rap_pct > 0 else 100)
if oc._facts.path == "cleared":
reward_grant.grant_clear_reward(ri, oc._facts.board_from_midround, oc.perfect_sweep_earned())
fx_host.flush_pending_reveals(ri) # 揭示效果兑付(授予段末统一掷格,防轮 facts 迭代重入)
+1 -1
View File
@@ -210,7 +210,7 @@ func _suites() -> Array:
{"path": "res://tests/unit/battle_settlement/roll_multiplier_test.gd", "expect": 0}, # 掷点与乘区宿主(敌攻击类型轴/护甲掷点行为面/乘区接线/伤害类型克制与标错/fresh 池攻击链——批 B 自 smoke_all 迁入)
{"path": "res://tests/unit/battle_settlement/seal_polarity_test.gd", "expect": 0}, # 封印与极性宿主(末点 AP 封印/封印不可逆四情况/清图奖励双份与弱形式/刷新 provenance 守卫/极性路由与封印溢价/负向字典/格面资源资格——批 B 自 smoke_all 迁入)
{"path": "res://tests/unit/battle_settlement/round_flow_skill_pool_test.gd", "expect": 0}, # 轮内流与技能池宿主(全战斗回放/轮内刷新与 V5 快照单源/遭遇区间骰/结算五段全序/技能池数据面·回放独立·EV 锚·死亡打断·校验拒绝/妨害附加/四桶计数——批 B 自 smoke_all 迁入)
{"path": "res://tests/unit/battle_settlement/refresh_feats_test.gd", "expect": 0}, # 换图系专长七件宿主(迭代 46 卡A——基座产 RAP 与折价同源/成功事实恰一次/全局受伤四路径恰一次/石层缓冲/崩壁延迟/蓄力层/坑道小憩/矿道红利 GP/七件数据与牌库/无专长基线;原经卡片申报走 02 关联档选跑,卡片退役后补登记由 02 全套件承接)
{"path": "res://tests/unit/battle_settlement/refresh_feats_test.gd", "expect": 0}, # 换图系专长七件宿主(迭代 46 卡A——基座产 RAP 与折价同源/成功事实恰一次/全局受伤四路径恰一次/石层缓冲/崩壁延迟/蓄力周转/坑道小憩/矿道红利 GP/七件数据与牌库/无专长基线;原经卡片申报走 02 关联档选跑,卡片退役后补登记由 02 全套件承接)
{"path": "res://tests/unit/battle_settlement/variant_placement_test.gd", "expect": 0}, # 变异布置宿主(战内布置段门控与数量公式/全局变异兜底回落与资源面偏斜——批 B 自 smoke_all 迁入)
{"path": "res://tests/unit/battle_settlement/skill_unlock_test.gd", "expect": 0}, # Boss 半血解锁技·容器机制(门谓词/闩不可逆/双面过滤/保底不逼锁定/零扰动)
{"path": "res://tests/unit/battle_settlement/extended_row_violation_test.gd", "expect": 1, "negative": true}, # 卡④ wr2-np 扩展行必载 effect_id 负路径(行协议运行期违约面首个负面套件——独立进程豁免错误扫描)
@@ -13,7 +13,7 @@ const ConfigDBScript := preload("res://core/config_db.gd")
const EffectEngineScript := preload("res://core/effect_engine.gd")
const TEST_SEED := 42 # 夹具种子(基建值非玩法数值——同种子两跑对比的隔离前提)
const LAYER_COUNTER := "swap_charge_layers" # 整备军备蓄力层计数器(feats.tres charge_rotation 行)
const LAYER_COUNTER := "swap_charge_layers" # 蓄力周转计数器(feats.tres swap_charge_layers 行)
var _db
@@ -54,7 +54,7 @@ func _hero_attack_value(rows: Array) -> int:
func _smoke_effect_port_wiring() -> void:
print("--- 效果端口:装配链单实例+真实发射路由 ---")
# 充能跑(整备军备在册——attack_commit 订阅行 attack_bonus per 蓄力层计数器)
# 充能跑(蓄力周转 charge_rotation 在册——attack_commit 订阅行 attack_bonus per 蓄力周转计数器)
var orch_c = _orch(TEST_SEED)
var rows_c: Array = []
orch_c.step_row.connect(func(row): rows_c.append(row))
@@ -64,7 +64,7 @@ func _smoke_effect_port_wiring() -> void:
var port_a = orch_c.action_economy._port
Kit.check("V1 端口在座(damage/action_economy 双绑)", port_d != null and port_a != null)
Kit.check("V1 端口单实例(两业务类持同一 EffectPort)", port_d == port_a)
# 蓄力层预置 3(调试注入两层·数据面粒度——计数器账面直写,与 refresh_feats_test V8 同法)
# 蓄力周转预置 3(调试注入两层·数据面粒度——计数器账面直写,与 refresh_feats_test V8 同法)
EffectEngineScript.counter_add(orch_c.fx_host().counters_ctx, LAYER_COUNTER, 3)
# 最小回合:停手即轮末结算(主角先手攻击在战斗段同步兑付——零 await 同步链)
orch_c.minesweeper.settle_batch([{"action": "stop"}])
@@ -80,7 +80,7 @@ func _smoke_effect_port_wiring() -> void:
orch_0.minesweeper.settle_batch([{"action": "stop"}])
var v_0 := _hero_attack_value(rows_0)
Kit.check("V1 对照跑攻击行在流", v_0 >= 0)
Kit.check("V1 delta 读数非零(蓄力层加算进入主角攻击基值)", v_c - v_0 >= 1)
Kit.check("V1 delta 读数非零(蓄力周转加算进入主角攻击基值)", v_c - v_0 >= 1)
# ---- V2 业务类零引擎直连(源码契约锚——theme_projection_test 源码锚惯例)----
@@ -100,7 +100,7 @@ func _test_biz_fact_face_closed() -> void:
print("--- 效果端口:业务发射事实面闭集 ---")
var orch = _orch(TEST_SEED)
Kit.check("V3 begin_battle 受理", orch.begin_battle(_enc([])))
# 合成行直改数据面(调试注入两层·数据面粒度):effect 段逐字抄现役铁壁 shield 表行(kind/value 零推表);
# 合成行直改数据面(调试注入两层·数据面粒度):effect 段逐字抄现役 shield 表行(kind/value 零推表);
# rebuild 走持有 id 过滤真实表行——合成行经直改表行进入装载域(订阅面换代为合成行独占,确定性)
var pos_id := "probe_shield_pos"
var neg_id := "probe_shield_neg"
@@ -127,3 +127,5 @@ func _test_biz_fact_face_closed() -> void:
ctrl.flush_submit(t_b)
var hp2 := int(ctrl.units.hero_unit().get("hp", 0))
Kit.check("V3 阴性对照:battle_index 不答——零减量(10→10,事实面未扩)", hp1 - hp2 == 10)
# 闭面收窄 V4(键退役验收——经 begin_battle 真实装配链取宿主应答;键在→返 0,键退役→null)
Kit.check("V4 闭面收窄:charge_layers 键退役——宿主事实应答 null", orch.fx_host().biz_fact("charge_layers") == null)
@@ -129,19 +129,19 @@ func _init() -> void:
ae6.queue_ap_delta(4 - int(db.run.action_economy.ap_per_round)) # 排队修正到测试口径 4 AP(notify_round_start 兑现)
ae6.notify_round_start()
ae6.request_stop()
ae6.finish_round_stop(false, 100)
ae6.finish_round_stop(100)
Kit.check_quiet(ae6.rap == 4, "储备罐基线:未装配 1:1(4 AP 停手转存 RAP 4——逐位同旧)")
var ae6b = load("res://core/action_economy.gd").new(db)
ae6b.queue_ap_delta(4 - int(db.run.action_economy.ap_per_round))
ae6b.notify_round_start()
ae6b.request_stop()
ae6b.finish_round_stop(false, 125)
ae6b.finish_round_stop(125)
Kit.check_quiet(ae6b.rap == 5, "储备罐正常:125% 转存(4 AP→RAP 5=1.25:1 整除口径;不碰 AP 上限)")
var ae6c = load("res://core/action_economy.gd").new(db)
ae6c.queue_ap_delta(3 - int(db.run.action_economy.ap_per_round))
ae6c.notify_round_start()
ae6c.request_stop()
ae6c.finish_round_stop(false, 125)
ae6c.finish_round_stop(125)
Kit.check_quiet(ae6c.rap == 3, "储备罐边界:3 AP→3(floor 3.75——不越参数面直改停手结算)")
# ⑦ 巢穴预告(装板后一次报数量——明细行经 step_row 信号收集)