iter53-卡2:改写族清退批: 四段零现役注册死分支摘除+词表收窄spike与trade双键+负域探针两枚+注释面退役名35处清零+玩家可见文案三处与sim死匹配
This commit is contained in:
1 parent
55f4de3ca4
commit
76a7067440
13 files changed
+89
-111
No files matched your search
@@ -79,7 +79,7 @@ func try_spend(action_kind: String) -> bool:
|
||||
|
||||
|
||||
# 排雷玩法 挖掘专用:chain_size = 连锁附加格数(不含首格);clears_map = 本次动作后全图安全格开完。
|
||||
# 深挖钻头付费开掘(dig_paid counter_spend 订阅施加面):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎
|
||||
# 付费开掘(dig_paid counter_spend 订阅施加面):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎
|
||||
# 计数器=授予段追加产出配额取数面);AP 不足全价时 fallback 降级只付基础 1 照常开格、不积计数
|
||||
# ——持有钻头永不锁死普通挖格(散件保底 B-2)。
|
||||
func request_dig(chain_size: int, clears_map: bool) -> bool:
|
||||
|
||||
@@ -255,7 +255,7 @@ func begin_battle(enc: Dictionary) -> bool:
|
||||
_begin_battle_fx_state(enc)
|
||||
_begin_battle_attune_params(enc)
|
||||
_begin_battle_preview_economy(enc)
|
||||
# 工兵晨令=round_start grant_ap(mode:queue) 订阅行承载(when round_index ≤ effective_rounds
|
||||
# 晨间 AP=round_start grant_ap(mode:queue) 订阅行承载(when round_index ≤ effective_rounds
|
||||
# value_from 定影);round_start 发射先于行动经济轮切换=树规则 queue 型当轮入队当轮兑现
|
||||
# (先手压制=首轮 AP+1 语义锚);计数器 round_start 重置点同点生效
|
||||
round_index = 1
|
||||
@@ -535,7 +535,7 @@ func _exit_distribution() -> void:
|
||||
if not _install_and_reset():
|
||||
_fatal("换图编排失败")
|
||||
return
|
||||
# 工兵晨令续队直调拆除(内容数据驱动扩展批 T4——round_start 订阅行承载,见 begin_battle 注)
|
||||
# 晨间 AP 续队直调拆除(内容数据驱动扩展批 T4——round_start 订阅行承载,见 begin_battle 注)
|
||||
action_economy.notify_settlement_done(mode)
|
||||
# round_start 发射先于行动经济轮切换(queue 型 grant_ap 当轮入队当轮兑现——与首轮同口径)
|
||||
round_index += 1
|
||||
|
||||
@@ -106,7 +106,7 @@ func _per_value(name: String, payload: Dictionary) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
# 巢穴控制数(fact nest_count 取数面——敌方名下 weaken 实例总数,猎巢人订阅面;
|
||||
# 巢穴控制数(fact nest_count 取数面——敌方名下 weaken 实例总数,nest_count 订阅消费面;
|
||||
# 个体化后削弱为累加行、每体各持一条——总数 = 被削弱个体数)
|
||||
func _nest_count() -> int:
|
||||
var n := 0
|
||||
@@ -135,7 +135,7 @@ func submit(t: Dictionary) -> int:
|
||||
# attack_commit 发射点(我方伤害单据开立入口;
|
||||
# 命中挂单据 context 随行——施加面在 _resolve_hero_attack 管线算术前逐族施加,开单时点=主角攻击
|
||||
# 单恒为段内首单(结账现场与开单现场一致)。载荷 atk/target/matchup + 挖掘 streak 事实
|
||||
# (执拗订阅面)+巢穴控制数〔猎巢人〕)
|
||||
# (开格 streak 订阅面)+巢穴控制数〔nest_count 订阅面〕)
|
||||
# spec 束必载键(缺载 assert——fail-fast):channel/base_value/target_rule/ri;
|
||||
# 可选键缺省=原形缺省:origin_cell=(-1,-1)/attack_type=""/rider=0/highlight=""/context={}。
|
||||
# 返回单据字典九栏目+requires/source_unit 逐字不变(契约 8)。
|
||||
@@ -247,9 +247,9 @@ func _resolve(t: Dictionary) -> void:
|
||||
|
||||
# 主角先手攻击:掷点 → 折扣/暴击 → 克制点数 → hero_offense×enemy_defense 池乘区 → 下限 → 交付
|
||||
# (attack_commit/clamp_check/armor_roll 订阅施加面:命中=开单入口随单
|
||||
# context 携带,按固定算序逐族施加——命中序=数据表声明序,确定性)。
|
||||
# context 携带,按固定算序逐族施加——命中序=数据表声明序,确定性;掷点折扣读数→克制点数两拍)。
|
||||
# 四步分段:命中面(_hero_attack_ctx,目标/护甲/
|
||||
# 掷点/按序改写族四拍/克制点数) → 基值装配(_hero_attack_base_value,加法族/计数器施加/倍乘) →
|
||||
# 掷点/掷点折扣读数/克制点数) → 基值装配(_hero_attack_base_value,加法族/计数器施加) →
|
||||
# 掷点兑现(_hero_attack_redeem,rolled/池乘/下限/rider/落地/击杀发射) → 交付(_hero_attack_deliver,
|
||||
# 状态施加/标签/明细行)。步骤间经 ctx/redemption 字典穿线——算序/取值固定(🔴 逐位一致契约)。
|
||||
func _resolve_hero_attack(t: Dictionary) -> void:
|
||||
@@ -261,7 +261,7 @@ func _resolve_hero_attack(t: Dictionary) -> void:
|
||||
_hero_attack_deliver(t, ctx, redemption)
|
||||
|
||||
|
||||
# 命中面(目标/护甲克制 matchup/armor_roll 发射→按序改写族四拍→克制点数读值+订阅改写;
|
||||
# 命中面(目标/护甲克制 matchup/armor_roll 发射→掷点折扣读数→克制点数读值+订阅改写;
|
||||
# 后两步各由 _ctx_rewrites/_ctx_clamp_delta 承载)。返回穿线 ctx(空=目标不可达)。
|
||||
# clamp_check 只在 _ctx_rewrites 内发射一次——_ctx_clamp_delta 消费同批命中(禁重复发射)。
|
||||
func _hero_attack_ctx(t: Dictionary) -> Dictionary:
|
||||
@@ -278,54 +278,25 @@ func _hero_attack_ctx(t: Dictionary) -> Dictionary:
|
||||
return {"target": target, "armor": armor, "atk_type": atk_type,
|
||||
"ac_hits": (t.context.get("fx_attack_hits", []) as Array), "ac_payload": ac_payload,
|
||||
"roll_read": rewrites["roll_read"], "threshold": rewrites["threshold"],
|
||||
"crit": rewrites["crit"], "discount": rewrites["discount"],
|
||||
"spike_ready": rewrites["spike_ready"], "cdelta": cdelta}
|
||||
"crit": rewrites["crit"], "discount": rewrites["discount"], "cdelta": cdelta}
|
||||
|
||||
|
||||
# 按序改写族四拍+掷点快照(armor_roll 发射点在此):第一拍矿工重锤命中交换(正负双修原生形态:
|
||||
# 命中判定减成 trade_hit 点〔更易命中〕换攻击增伤 trade_atk%——高 AC 负期望/低 AC 正期望;
|
||||
# 改写位先于掷点折扣读数)→ 第二拍专注免掷骰恒定折扣(方差买断成期望——稳定器人格;roll 记 0 归因)
|
||||
# → 第三拍满层必中(spike ready 时 discount 恒全额、暴击面走倍乘不加掷)→ 第四拍猎弱本能对轻甲敌折扣档改善 value 档
|
||||
# (对冲 pierce 列 L1 −1 开局罚;改善 = 折扣表向全额方向移档,nat 最大面/已全额不重复)。
|
||||
# clamp_check 同在此发射(唯一发射点——命中随返回值穿给 _ctx_clamp_delta)。
|
||||
# 掷点折扣读数+克制点数命中批(armor_roll 发射点在此):一拍护甲掷骰折扣读数(掷点对照
|
||||
# 防御阈值定折扣档——阈值=防御 AC+攻击加值,nat 面沿折扣表)→ 二拍 clamp_check 发射
|
||||
# (唯一发射点——命中随返回值穿给 _ctx_clamp_delta)。
|
||||
func _ctx_rewrites(t: Dictionary, target: Dictionary, armor: String, matchup: String) -> Dictionary:
|
||||
var ac_hits: Array[Variant] = (t.context.get("fx_attack_hits", []) as Array)
|
||||
var roll_read: Dictionary[Variant, Variant] = _armor_roll()
|
||||
var threshold: int = defender_ac(target) + int(db.combat.settlement.damage_roll.attack_bonus)
|
||||
# armor_roll 发射点(敌护甲掷骰判定;免掷恒折扣订阅面)
|
||||
var ar_hits := _fx_hits("armor_roll", {"target_ac": threshold, "roll": int(roll_read.roll)})
|
||||
var trade_hit := 0
|
||||
for h in ac_hits:
|
||||
if String(h.get("kind", "")) == "modify_ticket" and int(h.get("trade_hit", 0)) > 0:
|
||||
trade_hit += int(h.trade_hit)
|
||||
if trade_hit > 0:
|
||||
threshold = maxi(1, threshold - trade_hit)
|
||||
# armor_roll 发射点(敌护甲掷骰判定——事件在册、现役零订阅行,发射面保留)
|
||||
_fx_hits("armor_roll", {"target_ac": threshold, "roll": int(roll_read.roll)})
|
||||
var crit: bool = bool(roll_read.crit)
|
||||
var discount: int = _roll_discount(int(roll_read.roll), threshold)
|
||||
for h in ar_hits:
|
||||
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "armor_rewrite":
|
||||
discount = int(h.get("value", 0))
|
||||
crit = false
|
||||
roll_read["roll"] = 0
|
||||
var spike_ready := false
|
||||
for h in ac_hits:
|
||||
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "spike":
|
||||
spike_ready = true
|
||||
discount = 100
|
||||
var clamp_hits := _fx_hits("clamp_check", {"matchup": matchup})
|
||||
var shift := 0
|
||||
for h in clamp_hits:
|
||||
if String(h.get("kind", "")) != "modify_ticket":
|
||||
continue
|
||||
if String(h.get("mode", "")) == "discount_shift":
|
||||
shift += int(h.get("value", 0))
|
||||
if shift > 0 and armor == "light" and discount < 100:
|
||||
discount = _discount_shift_up(discount, shift)
|
||||
return {"roll_read": roll_read, "threshold": threshold, "crit": crit,
|
||||
"discount": discount, "spike_ready": spike_ready, "clamp_hits": clamp_hits}
|
||||
"discount": discount, "clamp_hits": clamp_hits}
|
||||
|
||||
|
||||
# 克制点数读值+订阅改写(魔网织者/湛蓝誓约/猎手刺剑 clamp_check modify delta——克制矩阵查表值
|
||||
# 克制点数读值+订阅改写(clamp_check 带模式行 modify delta——克制矩阵查表值
|
||||
# 后的直调;hero_attack 与 board_typed 两消费面同享)。命中批由 _ctx_rewrites 单次发射后传入。
|
||||
# 淬毒刃纹(行 triggers clamp_check
|
||||
# modify(mode:clamp_bonus) 订阅命中并入本处 delta 合计;mode 路由=主角攻击面专享,
|
||||
@@ -338,8 +309,8 @@ func _ctx_clamp_delta(atk_type: String, armor: String, clamp_hits: Array) -> int
|
||||
return cdelta
|
||||
|
||||
|
||||
# 基值装配(基值+单位标记加伤+矿工重锤增伤面+加法族(attack_bonus/
|
||||
# value_counter 层值)+计数器施加(attack_commit 用后清零行——命中序=声明序)+spike 倍乘。
|
||||
# 基值装配(基值+单位标记加伤+加法族(attack_bonus/
|
||||
# value_counter 层值)+计数器施加(attack_commit 用后清零行——命中序=声明序)。
|
||||
func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
|
||||
var ac_hits: Array[Variant] = ctx["ac_hits"]
|
||||
var ac_payload: Dictionary[Variant, Variant] = ctx["ac_payload"]
|
||||
@@ -347,10 +318,6 @@ func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
|
||||
# 单位标记加伤(处刑台 target_attack_bonus 挂单位字典 fx_atk_bonus 键;
|
||||
# 阈值沿发射点已写入,本处通用消费——对该敌伤害加算)
|
||||
base_value += float(int((ctx["target"] as Dictionary).get("fx_atk_bonus", 0)))
|
||||
# 按序改写族第五拍:矿工重锤增伤面(交换的正向侧)
|
||||
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
|
||||
# 加法族:attack_bonus per 计数器层值(层数×value 加算)。
|
||||
# value_counter 扩展〔疼痛记忆/弃图兑换/陷阱本能——rider 值=计数器账面,
|
||||
# 值读于施加时点=命中序先行 rider 后清零行〕
|
||||
@@ -365,11 +332,6 @@ 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)
|
||||
# 任意真族: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":
|
||||
base_value *= float(int(h.get("value", 1)))
|
||||
return base_value
|
||||
|
||||
|
||||
@@ -391,7 +353,7 @@ func _hero_attack_redeem(t: Dictionary, ctx: Dictionary, base_value: float) -> D
|
||||
var pooled: int = DamageMath.pool_damage(rolled, clamped_pool("hero_offense", StatusContainer.OWNER_HERO), clamped_pool("enemy_defense", StatusContainer.owner_key_for(target)))
|
||||
var landed: int = maxi(int(db.combat.settlement.damage_roll.damage_floor), pooled)
|
||||
# 加法族:英雄侧 rider(enemy_skill rider 对称位补齐口径)——后置必中附加,独立于掷点与乘区
|
||||
# (奥术余烬「普攻命中后恒定结算」语义);猎巢人巢控光环(per nest_count)/矿工的执拗开格加成
|
||||
# (普攻命中后恒定结算语义);巢控光环(per nest_count)/开格 streak 加成
|
||||
# (per dig_streak、cap 封顶)同通道合计;档一质变 rider+1 / 档二(crit 时)rider 乘暴击倍率。
|
||||
# rider 不改变下限语义(landed 含 rider 后不再过 floor)。
|
||||
var hero_rider := int(_fact_or("rider_tier_bonus") or 0) # or 0=未绑缺省与 int(null) 缺省同值(int() 构造拒 null——端口缺省 null 面的空值合并)
|
||||
@@ -421,7 +383,7 @@ func _kill_effects(t: Dictionary, target: Dictionary) -> void:
|
||||
_port.reveal_effect() # 斩首学者——击杀揭示 1 格(端口路由宿主入队,授予段末兑付)
|
||||
|
||||
|
||||
# 交付:即时执行族(碎甲震击打重甲附加「护甲裂解」——复用 off_guard,零新状态行;
|
||||
# 交付:即时执行族(重甲附加「护甲裂解」——复用 off_guard,零新状态行;
|
||||
# apply_effect 域闭/重复授予由状态容器自行守卫)/标签装配/明细行发射/兑现登记。
|
||||
func _hero_attack_deliver(t: Dictionary, ctx: Dictionary, redemption: Dictionary) -> void:
|
||||
var payload: Dictionary[Variant, Variant] = redemption["payload"]
|
||||
@@ -524,11 +486,11 @@ func _resolve_board_typed(t: Dictionary) -> void:
|
||||
var armor_b: String = String(target.get("armor_type", "light"))
|
||||
var atk_b: String = String(t.attack_type)
|
||||
# clamp_check 发射+施加(克制判定修正点棋盘面;与 hero_attack 同表同点:
|
||||
# modify delta 订阅改写合计进克制点数;discount_shift 档位面属主角攻击专享,本面不施加)
|
||||
# modify delta 订阅改写合计进克制点数;带模式行只施放于主角攻击面,本面不施加)
|
||||
var cdelta: int = _counter_delta(atk_b, armor_b)
|
||||
if atk_b != "":
|
||||
for h in _fx_hits("clamp_check", {"matchup": atk_b + "_vs_" + armor_b}):
|
||||
# 无模式 delta 才入棋盘窗(mode 路由:clamp_bonus=主角攻击面专享、discount_shift=折扣档面)
|
||||
# 无模式 delta 才入棋盘窗(mode 路由:带模式行=主角攻击面专享,棋盘窗只吃无模式 delta)
|
||||
if String(h.get("kind", "")) == "modify_ticket" and h.has("delta") and String(h.get("mode", "")) == "":
|
||||
cdelta += int(h.delta)
|
||||
var dealt: int = DamageMath.counter_component(int(t.base_value), cdelta, int(db.combat.settlement.damage_roll.damage_floor))
|
||||
@@ -619,15 +581,6 @@ func _counter_delta(attack_type: String, armor: String) -> int:
|
||||
return int(row.get(armor, 0))
|
||||
|
||||
|
||||
# 折扣档改善(猎弱本能——折扣表向全额方向移 value 档;查不到当前档 = 不动防御口径)
|
||||
func _discount_shift_up(discount: int, shift: int) -> int:
|
||||
var tbl: Array[Variant] = db.combat.settlement.damage_roll.roll_tier_discounts
|
||||
var idx := tbl.find(discount)
|
||||
if idx < 0:
|
||||
return discount
|
||||
return int(tbl[mini(tbl.size() - 1, idx + shift)])
|
||||
|
||||
|
||||
# 池内加算 → clamp [-100,+100](池间乘算归 DamageMath.pool_damage 调用侧);
|
||||
# 池按个体读(增益状态 v1.5):主角侧池传 OWNER_HERO,敌方侧池传被打者/施放者个体键——
|
||||
# 乘区只合计该个体名下实例(B 敌的削弱不进 A 敌的账)
|
||||
|
||||
@@ -27,7 +27,7 @@ const MINE_EVENTS := ["dig_reveal", "dig_paid", "seal_hit", "mine_hit", "seal_se
|
||||
## bias_rewards/preview。需求卡片标题计 23 系笔误,落码按行内容全收——commit 留痕)
|
||||
const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open_ticket",
|
||||
"attack_bonus", "yield_mult", "spawn_spell", "grant_material",
|
||||
"grant_ap", "grant_gp", "bias_wallet", "shield", "spike", "apply_status", "counter_add",
|
||||
"grant_ap", "grant_gp", "bias_wallet", "shield", "apply_status", "counter_add",
|
||||
"counter_spend", "reveal_tiles", "remove_mines", "refresh_pick",
|
||||
"bias_rewards", "preview",
|
||||
# 六型效果(奇物.md 基础件表 27 件声明清单):
|
||||
@@ -61,8 +61,8 @@ const FACTS := ["matchup", "is_first_dig_of_battle", "terrain_kind", "target_arm
|
||||
"ap_exhausted_last", "hp_ratio", "amount", "ap_left", "pct",
|
||||
"battle_index"] # 关卡域战斗序(1 基,enc 携带;开局姿态组「每关首轮窗」条件面)
|
||||
|
||||
## when 算子词汇(封闭——fact 查询面落法:mod_zero=计数器取模判满〔掘进蓄能〕、
|
||||
## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较〔深挖钻头配额〕、
|
||||
## when 算子词汇(封闭——fact 查询面落法:mod_zero=计数器取模判满、
|
||||
## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较(计数器配额面)、
|
||||
## ends_with=后缀匹配〔对某甲族的泛条件〕、mod_eq=取模余数判定〔双管镐每第 2 次——value=模数
|
||||
## ref=余数;dispatch 预评估口径〔when 于命中前读计数器现值〕下「每第 N 次」系用 ref=N-1 表达〕。
|
||||
## 均系映射表现状条件装进 fact 的查询面落法,白名单覆盖)
|
||||
@@ -79,7 +79,7 @@ const WHEN_KEYS := ["fact", "op", "value", "id", "ref", "value_from"]
|
||||
## axis=bonus_delta 加算区轴向)
|
||||
const DO_KEYS := ["kind", "value", "value_from", "delta", "delta_from", "mult", "mult_from",
|
||||
"cap", "cap_from", "cost_mult", "per", "divisor", "dtype", "mode", "channel", "counter_id",
|
||||
"set", "status_id", "label", "fallback", "target_kinds", "trade_atk", "trade_hit",
|
||||
"set", "status_id", "label", "fallback", "target_kinds",
|
||||
"value_event", "value_counter", "axis"]
|
||||
|
||||
## 主动件分发通道(不经事件订阅——刷新/显影/移除是玩家主动动作;use_treasure 按 kind 分发)
|
||||
@@ -154,7 +154,7 @@ func _push_tree_rule(rk: String, params: Dictionary[Variant, Variant]) -> void:
|
||||
"do": {"kind": "shield", "value": int(params["shield"])}}, {})
|
||||
"sense_sharp":
|
||||
# 锋=踩中危险格伤害减半·每关限次——mine_hit 挂点现成(damage_mult 收集→halve_pct,
|
||||
# 与惊巢反制同路径;伤害在结算战斗段末兑付,探索阶段零改动)
|
||||
# 与挖掘惩罚减半同路径;伤害在结算战斗段末兑付,探索阶段零改动)
|
||||
_push_trigger("tree", rk, {"on": "mine_hit",
|
||||
"when": [{"fact": "counter", "id": "lvl_tree_sense_sharp_used", "op": "lt", "value": int(params["cap_per_level"])}],
|
||||
"do": {"kind": "damage_mult", "value": int(params["halve_pct"])}}, {})
|
||||
@@ -449,7 +449,7 @@ static func _vtr_from_refs(rid: String, tr: Dictionary, row: Dictionary, errs: A
|
||||
## 加法族(数值相加,可交换):add_ticket_rider、attack_bonus、grant_material、grant_ap、
|
||||
## counter_add、shield——发射点逐条累加收集器。
|
||||
## 乘法族(收集后一次施加,正负分桶):yield_mult、damage_mult。
|
||||
## 任意真族(任一命中即生效):spawn_spell、spike。
|
||||
## 任意真族(任一命中即生效):spawn_spell。
|
||||
## 按序改写族(收集→单点按声明序施加):modify_ticket 及一切改写窗口效果。
|
||||
## 按序消耗族(按订阅序消耗共享资源,耗尽即止;可选 fallback):counter_spend。
|
||||
## 即时执行族(每条命中各自执行一次,执行序=声明序):open_ticket、
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
## 奖励授予件(自 battle_orchestrator 收编 grant 族):极性字典路由兑付(grant_routed——含封印溢价
|
||||
## 与惊巢反制减半)、三种行应用(flat 四分支/percent/gp)、伤害单据提交面(submit——案C 暂存闸承载)、
|
||||
## 与挖掘惩罚减半)、三种行应用(flat 四分支/percent/gp)、伤害单据提交面(submit——案C 暂存闸承载)、
|
||||
## 清图奖励与身份授予(完美封印第二份)、战斗内 GP 缓冲 escrow、秘宝使用四步编排(use_treasure——
|
||||
## 相位闸→校验→受理闸→逐 kind 应用→消耗)、揭示奖励兑付(reveal_redeem——fx_host flush 的兑付回调面)。
|
||||
## 生命周期=随编排器(编排器 _init 同建同灭,每战新建)。
|
||||
@@ -127,7 +127,7 @@ func use_treasure(handle: int, target: Vector2i) -> Dictionary:
|
||||
return {"ok": true, "item_id": v.item_id, "resolved": v.resolved, "record": rec}
|
||||
|
||||
|
||||
# 受理闸(treasure_used 发射+施加:counter_spend 订阅=掘进蓄能积点账本,积点不足拒绝零消耗。
|
||||
# 受理闸(treasure_used 发射+施加:counter_spend 订阅=付费积点账本,积点不足拒绝零消耗。
|
||||
# 零 item_id 特判;拒绝文案读装配集积点进度——宿主 attune 读投影)
|
||||
func _charge_gate(v: Dictionary, target: Vector2i) -> Dictionary:
|
||||
var tu_hits := fx_host.fx_emit("treasure_used", {"item_id": String(v.item_id), "target": target})
|
||||
@@ -180,13 +180,13 @@ func _safe_dig_open(v: Dictionary) -> Dictionary:
|
||||
return {}
|
||||
|
||||
|
||||
# 爆破工兵包兑付(中立移除危险格:未揭示/无封印/是雷过滤归排雷玩法;
|
||||
# 中立移除兑付(未揭示/无封印/是雷过滤归排雷玩法;
|
||||
# 邻接数字冻结零重算、清图分母零涉(危险格不入分母);空集拒绝零消耗——
|
||||
# consume 之前 return(拒绝面注记扩「③内零消耗分支」),拒绝 reason 可呈现)
|
||||
func _cell_removal_open(v: Dictionary) -> Dictionary:
|
||||
var blasted: Array[Variant] = fx_host.minesweeper.remove_mines_in(v.resolved)
|
||||
if blasted.is_empty():
|
||||
return {"ok": false, "reason": "爆破工兵包:3×3 区域内无可移除危险格(须未揭示且未封印)"}
|
||||
return {"ok": false, "reason": "中立移除:3×3 区域内无可移除危险格(须未揭示且未封印)"}
|
||||
return {}
|
||||
|
||||
|
||||
@@ -218,12 +218,12 @@ func grant_routed(snap: Dictionary, polarity: String, att: Dictionary) -> bool:
|
||||
row = row.duplicate()
|
||||
row["power"] = int(round(int(row.power) * prem_pct / 100.0))
|
||||
row["premium_pct"] = prem_pct
|
||||
# 惊巢反制(减半系数=mine_hit damage_mult 订阅命中〔行 value 50=减 50%,取整 ceil〕;
|
||||
# 挖掘惩罚减半(减半系数=mine_hit damage_mult 订阅命中〔行 value 50=减 50%,取整 ceil〕;
|
||||
# duplicate 隔离——减半不回写极性字典)
|
||||
if halve_pct > 0 and polarity == "negative" and source_class == "mine_hit":
|
||||
row = row.duplicate()
|
||||
var half: int = int(ceil(float(int(row.power)) * float(100 - halve_pct) / 100.0))
|
||||
emit_cb.call({"type": "effect", "source_class": source_class, "origin_cell": cell}, ri, "惊巢反制——危险格挖掘惩罚减半(%d→%d)" % [int(row.power), half], 0, {"effect_id": "nest_counter"})
|
||||
emit_cb.call({"type": "effect", "source_class": source_class, "origin_cell": cell}, ri, "挖掘惩罚减半(%d→%d)" % [int(row.power), half], 0, {"effect_id": "nest_halve"})
|
||||
row.power = half
|
||||
return _dispatch_row(row, att)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
## 掷格件:装配期格面资源摇号——池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影)。
|
||||
## 掷格件:装配期格面资源摇号——池行装配、区间行 roll、权重合成(订阅加权/board_skew 两路投影)。
|
||||
## 自 RewardEconomy 迁出掷格面(architecture v1.29 轴戊②);受理账面(grant/身份查询/快照/retire/
|
||||
## polarity_row)留守 RewardEconomy——衔接面=格→奖励身份映射批束(本件产出、受理件接收)。
|
||||
## 取号流声明:roll 每批恰开一 reward_roll 流(scope=每次 install 批不变),体序=normalize(行主序
|
||||
@@ -38,12 +38,12 @@ func _init(bundle: Dictionary) -> void:
|
||||
func roll(eligible: Array) -> Dictionary[Variant, Variant]:
|
||||
var list: Array[Dictionary] = _normalize_eligible(eligible)
|
||||
var stream: RandomNumberGenerator = rng.open_stream("reward_roll") # 恰一 scope 批(格批 + 清图批尾 + 区间行追加取号)
|
||||
# reward_roll 发射归 BattleFxHost(偏运硬币 bias_rewards 订阅命中合计经注入查询口取回);
|
||||
# reward_roll 发射归 BattleFxHost(bias_rewards 订阅命中合计经注入查询口取回);
|
||||
# 零命中/未接线=0=原行集零扰动
|
||||
var luck_bias := 0
|
||||
if luck_bias_query.is_valid():
|
||||
luck_bias = luck_bias_query.call(list.size())
|
||||
var cell_rows: Array[Variant] = _biased_cell_rows(luck_bias) # cell 池正向行 weight>0(偏运硬币装配时稀有正向 kinds 权重 +N——池结构零触碰)
|
||||
var cell_rows: Array[Variant] = _biased_cell_rows(luck_bias) # cell 池正向行 weight>0(订阅件装配时稀有正向 kinds 权重 +N——池结构零触碰)
|
||||
var clear_rows: Array[Variant] = _pool_rows("clear_default")
|
||||
# ① 身份批:每非封锁格恰一类型身份(雷安同池——同一行集同一权重分布)
|
||||
var draft := {}
|
||||
@@ -83,7 +83,7 @@ func _normalize_eligible(eligible: Array) -> Array[Dictionary]:
|
||||
return list
|
||||
|
||||
|
||||
# 偏运硬币权重投影(底稿 §3:只动池内权重、雷安仍同池同分布;luck_bias=0 逐位返回原行集——off 态零扰动)
|
||||
# 订阅加权权重投影(底稿 §3:只动池内权重、雷安仍同池同分布;luck_bias=0 逐位返回原行集——off 态零扰动)
|
||||
# 合成序:先经图级偏斜投影再叠件级加法——合成序锚=图级先、件级后
|
||||
#(环境事实先定型、玩家构筑叠其上;两投影均为池内权重面,雷安同池与取号次数零变化)
|
||||
func _biased_cell_rows(bias: int) -> Array:
|
||||
|
||||
@@ -124,8 +124,8 @@ func _reveal_safe(evt: Dictionary, snap: Dictionary, ri: int) -> void:
|
||||
|
||||
|
||||
# dig_reveal 施加面(序=计数器〔连击计数——乘区收集后执行=本格兑付用旧值〕→ 揭示入队〔地质学家/
|
||||
# 跳格采掘 reveal_tiles 订阅面,授予段末统一掷格兑付〕→ 追加产出〔深挖钻头 v2 双份制:grant_material
|
||||
# 命中=配额内追加第二份〕→ 奥术矢〔魔能共鸣——每战首次开安全格追加魔法矢;任意真族单次生效〕)
|
||||
# 跳格采掘 reveal_tiles 订阅面,授予段末统一掷格兑付〕→ 追加产出〔双份制:grant_material
|
||||
# 命中=配额内追加第二份〕→ 奥术矢(每战首次开安全格追加魔法矢;任意真族单次生效))
|
||||
func _reveal_safe_apply(dr_hits: Array, evt: Dictionary, ri: int) -> void:
|
||||
for h in dr_hits:
|
||||
if String(h.get("kind", "")) == "counter_add":
|
||||
@@ -163,7 +163,7 @@ func _reveal_mine(evt: Dictionary, snap: Dictionary, ri: int) -> void:
|
||||
reward_grant.grant_routed(reward_grant.feat_yield_adjust(snap, false, 0, 0), "negative", {"source_class": "mine_hit", "cell": evt.cell, "ri": ri, "halve_pct": int(applied["halve_pct"])})
|
||||
for h in mh_hits:
|
||||
if String(h.get("kind", "")) == "open_ticket" and String(h.get("channel", "")) == "reflect":
|
||||
var nct := damage.open_ticket(DamageController.KIND_BOARD_BLAST, "attune_nest_counter", "惊巢反制·反弹",
|
||||
var nct := damage.open_ticket(DamageController.KIND_BOARD_BLAST, "attune_nest_halve", "反弹伤害",
|
||||
{"channel": "board", "base_value": int(h.get("value", 0)), "target_rule": DamageController.TARGET_ALL_ALIVE,
|
||||
"ri": ri, "origin_cell": evt.cell})
|
||||
reward_grant.submit(nct, false)
|
||||
@@ -229,7 +229,7 @@ func _terrain_batch(ri: int) -> void:
|
||||
|
||||
# 封印判定批+战封印军规开单段(封印流:seal_judged 批后统一开单:轮末每面封印命中对最前存活敌
|
||||
# 结算 board_typed 必中伤害〔复用零新配方;「封印所在巢穴敌」简化为 default_target 最前存活敌——
|
||||
# 台账披露待追认〕;完美布防=本轮封印批全中(hit>0 且 miss==0)时封印伤 ×mult——全对推理奖励)。
|
||||
# 台账披露待追认〕;封印全中倍率=本轮 hit>0 且 miss==0 时封印伤 ×mult——全对推理奖励)。
|
||||
# 伤害单据案C 暂存战斗段末兑付。
|
||||
func _seal_batch(ri: int) -> void:
|
||||
for evt in facts.seals:
|
||||
@@ -237,7 +237,7 @@ func _seal_batch(ri: int) -> void:
|
||||
_seal_strike_batch(ri)
|
||||
|
||||
|
||||
# seal_settle 发射+施加(战封印 open_ticket + 完美布防 modify_ticket 改写窗口:封印伤基值×完美倍率后
|
||||
# seal_settle 发射+施加(战封印 open_ticket + 封印全中倍率 modify_ticket 改写窗口:封印伤基值×完美倍率后
|
||||
# 逐封印开单)
|
||||
func _seal_strike_batch(ri: int) -> void:
|
||||
var fs_hits := 0
|
||||
@@ -262,7 +262,7 @@ func _seal_strike_batch(ri: int) -> void:
|
||||
|
||||
|
||||
# 战封印军规基值决议(attack 通道 open_ticket 首命中取基值;seal_mult modify_ticket 连乘;
|
||||
# 完美布防=miss==0 且 hit>0 时基值×倍率。空旗集=空字典〔不开单合法态〕)
|
||||
# 封印全中倍率=miss==0 且 hit>0 时基值×倍率。空旗集=空字典〔不开单合法态〕)
|
||||
func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionary:
|
||||
var banner_hits: Array[Variant] = []
|
||||
for h in fs_fx:
|
||||
@@ -276,11 +276,11 @@ func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionar
|
||||
if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "seal_mult":
|
||||
seal_mult *= maxi(1, int(h.get("value", 1)))
|
||||
if fs_misses == 0 and fs_hits > 0 and seal_mult > 1:
|
||||
strike_value *= seal_mult # 完美布防:同轮全中封印伤倍增(全对推理奖励)
|
||||
strike_value *= seal_mult # 封印全中:同轮全中封印伤倍增(全对推理奖励)
|
||||
return {"value": strike_value}
|
||||
|
||||
|
||||
# round_end 发射+施加(每轮结算收口:熔火之躯反打单开立〔open_ticket 即时执行〕+积层清零〔counter_add
|
||||
# round_end 发射+施加(每轮结算收口:轮末反打单开立〔open_ticket 即时执行〕+积层清零〔counter_add
|
||||
# set〕;停手侧 AP 已在 request_stop 记账,finish_round_stop 按转存率转存 RAP)+施加面:grant_gp〔爆破会计/收盘——escrow 战斗域
|
||||
# 缓冲,随 gp_dropped 上抛〕/grant_ap mode:queue〔封印回响——返 1 AP 下轮,queue_ap_delta 通道与轮始
|
||||
# 加成同面〕+段界收口(转存率入参、清图奖励、揭示兑付、段界结账)
|
||||
@@ -348,7 +348,7 @@ func _judge_seal(evt: Dictionary, ri: int) -> void:
|
||||
|
||||
|
||||
# 封印命中(资格以危险格实例为键去重——排雷玩法 诚实重复上报的对侧;seal_hit 发射序:
|
||||
# 殉爆票据 → 施加面 → 雷区图谱额外兑付 → 基线正向兑付)
|
||||
# 标中雷反打票据 → 施加面 → 标中雷额外兑付 → 基线正向兑付)
|
||||
func _judge_seal_hit(evt: Dictionary, ri: int) -> void:
|
||||
var cell: Vector2i = evt.cell
|
||||
if facts.seal_consumed.has(cell):
|
||||
@@ -359,7 +359,7 @@ func _judge_seal_hit(evt: Dictionary, ri: int) -> void:
|
||||
"terrain_kind": minesweeper.harmful_adjacent(cell)})
|
||||
_seal_burst_tickets(fh_hits, cell, ri)
|
||||
_seal_hit_effects(fh_hits, cell, ri)
|
||||
# 雷区图谱(封印流——标中雷额外获得一份格面资源:封印开始产出对标开格;
|
||||
# 标中雷追加(封印流——标中雷额外获得一份格面资源:封印开始产出对标开格;
|
||||
# 复用 grant 单点,额外兑付走同一 grant_routed 正向路由)
|
||||
for h in fh_hits:
|
||||
if String(h.get("kind", "")) == "grant_material":
|
||||
@@ -370,7 +370,7 @@ func _judge_seal_hit(evt: Dictionary, ri: int) -> void:
|
||||
reward_grant.grant_routed(snap, "positive", {"source_class": "seal_hit", "cell": cell, "ri": ri, "highlight": "seal_hit"})
|
||||
|
||||
|
||||
# 标中殉爆票据(行 triggers open_ticket channel blast value_from magnitude——每标中一面封印全体存活敌
|
||||
# 标中雷反打票据(行 triggers open_ticket channel blast value_from magnitude——每标中一面封印全体存活敌
|
||||
# 吃 N 群伤,无类型走 blast 通道;封印爆裂〔专长〕同面消费)
|
||||
func _seal_burst_tickets(fh_hits: Array, cell: Vector2i, ri: int) -> void:
|
||||
for h in DamageController.hits_of(fh_hits, "open_ticket"):
|
||||
|
||||
@@ -17,7 +17,7 @@ const UNLOCK_COUNTER_KEYS := ["adventure_cleared", "boss_kill_count", "vision_us
|
||||
|
||||
const DIMENSIONS := ["info", "risk", "action", "plan", "counter"]
|
||||
# enum 九 kind 全部条件触发/机制修正类;mine_reveal/ap_grant 语义不变。
|
||||
# cell_removal = 爆破工兵包中立移除格;mine_hit_halve 系固定
|
||||
# cell_removal = 中立移除危险格通道;mine_hit_halve 系固定
|
||||
# 「减半」语义不消费 magnitude(反弹 N 由 reflect_damage 行 magnitude 承载)。
|
||||
# 主动件 kind 词族(reveal_tiles/preview/grant_ap/remove_mines/
|
||||
# refresh_pick——效果引擎 ACTIVE_KINDS 同名闭集);被动件不走 effect_kinds 词族
|
||||
@@ -119,7 +119,7 @@ func _validate_row_head(row: Dictionary, iid: String) -> Array[Variant]:
|
||||
|
||||
## 订阅形态域:triggers 事件订阅行判据与行级触发词表校验(被动件形态;与 effect_kinds 互斥校验
|
||||
## 面=passive 行(单形态——效果行为只走订阅);active_charged 行两形合法并存
|
||||
## (effect_kinds=主动分发通道 + triggers=受理闸订阅,掘进蓄能先例))
|
||||
## (effect_kinds=主动分发通道 + triggers=受理闸订阅,积点解锁先例))
|
||||
func _validate_row_triggers(row: Dictionary, iid: String) -> Array[Variant]:
|
||||
var errs: Array[Variant] = []
|
||||
if row.has("triggers"):
|
||||
|
||||
@@ -72,7 +72,7 @@ func _initialize() -> void:
|
||||
if attune_mode == "on":
|
||||
# 贪心画像:Slots=3(槽位判定源=树同调位节点点亮数,模拟画像=三节点
|
||||
# 全点亮常量);装配序 =
|
||||
# 表序 passive 优先至 Slots-1 + 首个 active(slots=3 → [淬毒刃纹, 标中殉爆, 掘进蓄能],
|
||||
# 表序 passive 优先至 Slots-1 + 首个 active(slots=3 → 表序头三件占满示例,
|
||||
# provisional 画像归调参);Y = 营地升级 Lv1 表值 1。autoplay 默认不刷——Y 仅注入容量,
|
||||
# 刷新消费归玩家策略面(钓鱼归玩家)。
|
||||
var slots: int = 3
|
||||
|
||||
@@ -411,14 +411,12 @@ static func _on_step_row(row: Dictionary, _runner, st: Dictionary, collect_rows:
|
||||
# 封印经济聚合(自结算流水聚合,零新随机源):
|
||||
# ⚠ 行侧判据考证实录:结算段对存续增益实例每轮复发行 effect 行且复用实例 source_class
|
||||
#(battle_orchestrator 状态列举行)——source_class=seal_hit 的行 ≠ 标中事件。事件行唯一判据
|
||||
# = 授予行专带 highlight="seal_hit"(实测 87 行 == 受理封印 87 动作,1:1 精确);
|
||||
# 雷区图谱追加分grant 无高光,以 display_name 后缀补捕(计入事件与合计——同封印第二份兑付)。
|
||||
# = 授予行专带 highlight="seal_hit"(实测 87 行 == 受理封印 87 动作,1:1 精确)。
|
||||
# 满层拒收行(reward_ineffective)零兑付不入。标空事件=归因行(type=seal_miss 每格恰一次);
|
||||
# 标空惩罚合计只入一次性兑付行(flat 直伤 damage/heal + gp_loss escrow 行)——sapped 授予行
|
||||
# 与其状态复发行行侧不可区分不入合计(登记注记,判读侧按事件数补算)。
|
||||
if row.source_class == "seal_hit" and row.type != "reward_ineffective":
|
||||
if String(row.get("highlight", "")) == "seal_hit" \
|
||||
or String(row.get("display_name", "")).contains("雷区图谱"):
|
||||
if String(row.get("highlight", "")) == "seal_hit":
|
||||
st.seal_hit += 1
|
||||
st.seal_hit_gain += int(row.value)
|
||||
if row.type == "seal_miss":
|
||||
|
||||
@@ -236,7 +236,7 @@ func _smoke_global_variant() -> void:
|
||||
Kit.check("生存族下调:heal 4→3 / defense 11→7(v=30 构造例)", wmap.get("heal_minor", -1) == 3 and wmap.get("ac_up", -1) == 7)
|
||||
Kit.check("进攻族上浮:attack 14→15 / blast 16→18 / pierce 8→9 / magic 8→9(v=30 构造例,等比上浮守恒)", wmap.get("attack_up", -1) == 15 and wmap.get("spark_aoe", -1) == 18 and wmap.get("pierce_strike", -1) == 9 and wmap.get("magic_bolt", -1) == 9)
|
||||
eco.roller.board_skew = 30
|
||||
var combo_rows: Array = eco.roller._biased_cell_rows(2) # 件级加算 2=偏运硬币行 value(reward_roll bias_rewards 命中面同值)
|
||||
var combo_rows: Array = eco.roller._biased_cell_rows(2) # 件级加算 2=订阅行 value(reward_roll bias_rewards 命中面同值)
|
||||
var cw := _rows_weight_map(combo_rows)
|
||||
Kit.check("合成序:图级偏斜先(乘法面)件级 luck_bias 后(加法 +2×四稀有类)——合计 77+8", eco.roller._pool_weight(combo_rows) == 77 + 4 * 2)
|
||||
Kit.check("合成序构造例:skew(heal 3)+2=5 / gp 2+2=4 / pierce 9+2=11 / magic 9+2=11(图级定型后玩家构筑叠加)", cw.get("heal_minor", -1) == 5 and cw.get("gp_coin", -1) == 4 and cw.get("pierce_strike", -1) == 11 and cw.get("magic_bolt", -1) == 11)
|
||||
|
||||
@@ -674,7 +674,7 @@ func _smoke_tree_rules() -> void:
|
||||
ctx_fz2.level_bucket = lvl_shared # 挂同一 level 桶引用(新形态跨战持久:无 export/seed,同字典即持久)
|
||||
Kit.check("锋:限次跨战持久(level 桶共享引用——替代旧副本搬运链)〔无状态化 V4〕",
|
||||
(fz2.dispatch(ctx_fz2, "mine_hit", {}, Callable()) as Array).is_empty())
|
||||
# 锋·惊巢反制效果行换代断言(迭代36 u13/wa12——_grant_routed 减半分支效果行=战斗日志
|
||||
# 锋·挖掘惩罚减半效果行换代断言(迭代36 u13/wa12——_grant_routed 减半分支效果行=战斗日志
|
||||
# step_row 真实生产面;display_name 玩家可见,禁字「挖雷」由此行清零钉住)
|
||||
var orch_nc = load("res://core/battle_orchestrator.gd").new(_db, _fresh_rng(777003))
|
||||
orch_nc.begin_battle({"level_index": 1, "node_depth": 0, "hero_hp": 40, "hero_atk": 8, "hero_max_hp": 40,
|
||||
@@ -687,17 +687,17 @@ func _smoke_tree_rules() -> void:
|
||||
# heal 负向行表值 power=6(极性字典行值——负向 power 走表值不走快照)→ halve 50% ceil=3
|
||||
orch_nc.reward_grant().grant_routed({"cell_type": "heal", "power": 10}, "negative",
|
||||
{"source_class": "mine_hit", "cell": Vector2i.ZERO, "ri": 0, "halve_pct": 50})
|
||||
# 受理判据=惊巢反制效果行落 step_row(halve 分支先于 dispatch 发行——flat 行 _apply_flat_row 分派
|
||||
# 受理判据=减半效果行落 step_row(halve 分支先于 dispatch 发行——flat 行 _apply_flat_row 分派
|
||||
# 恒返 false,返回值不承载受理语义;行发行即分支受理)
|
||||
var nc_hit := ""
|
||||
for r in nc_rows:
|
||||
if String((r as Dictionary).get("display_name", "")).contains("惊巢反制"):
|
||||
if String((r as Dictionary).get("display_name", "")).contains("挖掘惩罚减半"):
|
||||
nc_hit = String((r as Dictionary).get("display_name", ""))
|
||||
break
|
||||
Kit.check("锋:惊巢反制 mine_hit 减半分支受理(wa12 前提——halve_pct=50 效果行落 step_row)〔wa12〕",
|
||||
Kit.check("锋:挖掘惩罚减半 mine_hit 减半分支受理(wa12 前提——halve_pct=50 效果行落 step_row)〔wa12〕",
|
||||
nc_hit != "")
|
||||
Kit.check("惊巢反制效果行==「惊巢反制——危险格挖掘惩罚减半(6→3)」零「挖雷」(u13 换代)〔wa12〕",
|
||||
nc_hit == "惊巢反制——危险格挖掘惩罚减半(6→3)" and not nc_hit.contains("挖雷"))
|
||||
Kit.check("减半效果行==「挖掘惩罚减半(6→3)」零「挖雷」(u13 换代)〔wa12〕",
|
||||
nc_hit == "挖掘惩罚减半(6→3)" and not nc_hit.contains("挖雷"))
|
||||
# 守侧五场景(契约 12):编排 rig——begin_battle 携 sense_guard,授予段 _grant_seg._judge_seal 直注
|
||||
var orch = load("res://core/battle_orchestrator.gd").new(_db, _fresh_rng(777001))
|
||||
Kit.check("守侧 rig:战斗编排启动(tree_rules=sense_guard 携带)",
|
||||
|
||||
@@ -11,12 +11,33 @@ const Kit := preload("res://tests/unit/test_kit.gd")
|
||||
const SRC_DIR := "res://data/tables"
|
||||
const BAD_OVERFLOW_DIR := "user://effect_kind_fixture_overflow"
|
||||
const BAD_SEGMENTS_DIR := "user://effect_kind_fixture_segments"
|
||||
const BAD_SPIKE_DIR := "user://effect_kind_fixture_spike"
|
||||
const BAD_TRADEKEY_DIR := "user://effect_kind_fixture_tradekey"
|
||||
|
||||
# 注入探针:死通道 do.kind(甲案摘名两族——各一探针行)
|
||||
const PROBE_OVERFLOW := ' {\n "feat_id": "kind_overflow_probe",\n "display_name": "通道探针·溢出",\n "rarity": "common",\n "triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "overflow", "value": 50 } } ],\n "desc": "夹具探针——甲案退役词 overflow"\n},\n'
|
||||
const PROBE_SEGMENTS := ' {\n "feat_id": "kind_segments_probe",\n "display_name": "通道探针·连珠",\n "rarity": "common",\n "triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "attack_segments", "cap": 2, "divisor": 3, "value": 0 } } ],\n "desc": "夹具探针——甲案退役词 attack_segments"\n},\n'
|
||||
|
||||
|
||||
# 注入探针:改写族退役词(改写族清退批 T2)——spike kind 出域与 trade 键出域(各一探针行)
|
||||
const PROBE_SPIKE_MODE := ' {
|
||||
"feat_id": "kind_spike_probe",
|
||||
"display_name": "词表探针·甲",
|
||||
"rarity": "common",
|
||||
"triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "spike", "value": 2 } } ],
|
||||
"desc": "夹具探针——改写族退役 kind spike"
|
||||
},
|
||||
'
|
||||
const PROBE_TRADE_KEY := ' {
|
||||
"feat_id": "kind_tradekey_probe",
|
||||
"display_name": "键闭探针·乙",
|
||||
"rarity": "common",
|
||||
"triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "grant_ap", "trade_hit": 5, "value": 50 } } ],
|
||||
"desc": "夹具探针——改写族退役 do 键 trade_hit"
|
||||
},
|
||||
'
|
||||
|
||||
|
||||
func _inject(dir: String, probe: String) -> bool:
|
||||
var path := dir + "/feats.tres"
|
||||
var f := FileAccess.open(path, FileAccess.READ)
|
||||
@@ -65,5 +86,11 @@ func _init() -> void:
|
||||
if not _assert_rejected(BAD_SEGMENTS_DIR, PROBE_SEGMENTS, "effect_kind_retired_test/②attack_segments 出域"):
|
||||
quit(2)
|
||||
return
|
||||
print("[effect_kind_retired_test] 双探针均正确拒绝(甲案词表退役——死通道误写加载致命)〔架构整改 V3〕")
|
||||
if not _assert_rejected(BAD_SPIKE_DIR, PROBE_SPIKE_MODE, "effect_kind_retired_test/③词表闭面:kind=spike 出域拒绝"):
|
||||
quit(2)
|
||||
return
|
||||
if not _assert_rejected(BAD_TRADEKEY_DIR, PROBE_TRADE_KEY, "effect_kind_retired_test/④do 键闭面:trade_hit 出域拒绝"):
|
||||
quit(2)
|
||||
return
|
||||
print("[effect_kind_retired_test] 四探针均正确拒绝(甲案词表退役+改写族清退——退役词/键误写加载致命)〔架构整改 V3〕〔改写族清退 T2〕")
|
||||
quit(1)
|
||||
Reference in new issue
Block a user