P1-1 结算巨函数拆段(裁点③甲 审计五段): - game/core/settlement/ 五段类: GrantSegment(授予段体+旗判随段迁入+counter_add 五位/ grant_material 三位分支单点化)/AuraSegment/CombatSegment(原 _combat_segment 体)/ DecaySegment/VerdictSegment(返回裁定,终局早退语义留宿主) - 编排器 1725→1325 行退为段序编排+行发射/开单原语单点;_judge_flag/_combat_segment 旧实现同批删除;smoke 白盒 rig 随段迁址(orch._grant_seg._judge_flag) 姊妹病灶(同批): - damage_controller _resolve_hero_attack 148 行拆四步: _hero_attack_ctx(命中面/按序改写 族四拍)→_hero_attack_base_value(加法族/计数器施加/倍乘)→_hero_attack_redeem(掷点/池乘/ rider/落地/击杀)→_hero_attack_deliver(状态/交付行);ctx/redemption 字典穿线算序逐字保留 验收: - V4 settle_segments_test 16 断言进 run_all(25→26 套) - 逐位一致对拍三变体全同(RUNSUM+JSONL 双面零漂移);冒烟 1077/0+run_all 26 套 +probe click+render golden 0.00%
102 lines
7.7 KiB
GDScript
102 lines
7.7 KiB
GDScript
class_name CombatSegment
|
||
extends RefCounted
|
||
# ③ 战斗段 Segment(迭代 27 T2——P1-1 结算巨函数拆段;段边界=审计五段〔裁点③甲〕)。
|
||
# 职责:案C 闸复位 + 本轮扫雷事实推导(执拗 streak/连珠矢段数)+ 蓄力层注入 + 主角先手
|
||
# (含连珠矢分段开单)+ 敌方行动兑现 + 地图伤害账殿后(补提交统一结账)。
|
||
# 调用序:主角先手 → 逐敌还手 → 地图伤害账殿后〔案C 2026-10-06 用户裁〕;hero hp=0 短路。
|
||
# 行发射/开单/兑付原语仍归宿主编排器(oc)——本函数体为原编排器 _combat_segment 逐字搬运
|
||
# (🔴 零行为变更契约)。
|
||
|
||
var oc: BattleOrchestrator # 宿主(类型标注=段内 := 推断前提;循环类名引用 Godot 4 全局类安全) 宿主
|
||
|
||
|
||
func _init(host) -> void:
|
||
oc = host
|
||
|
||
|
||
func run(ri: int) -> void:
|
||
oc._defer_board_damage = false # 案C 闸复位——战斗段起开单即入队(主角/敌方/补提交的地图单按开单序统一结账)
|
||
# 本轮扫雷事实推导(迭代 12 T4——执拗 streak/连珠矢段数共用取数面):本轮 safe 事件数=
|
||
# streak;踩雷即清零(mine_hit 监听同口——执拗「踩雷清零」承载)。攻击在战斗段=授予段后
|
||
# 同一次 _settle 内,facts 已定。
|
||
var round_safe := 0
|
||
var round_mine := false
|
||
for evt in oc._facts_reveals:
|
||
if evt.kind == "safe":
|
||
round_safe += 1
|
||
elif evt.kind == "mine":
|
||
round_mine = true
|
||
oc._damage.dig_streak = 0 if round_mine else round_safe
|
||
# 蓄力层注入(内容数据驱动扩展批 T3——整备军备「每层下轮首段 +1」/厚积薄发满层 spike/铁壁整备
|
||
# 减伤——三件 fact charge_layers 同读 action_economy;battle 域每轮刷新)
|
||
oc._damage.charge_layers = oc.action_economy.charge_layers
|
||
# ⓪ 主角先手攻击(基础攻击恒存在——2026-09-11 用户裁决;先于敌方行动。案C 后授予段不再产出伤害,
|
||
# 主角进入战斗段时恒存活——先手必兑,除非场上无敌)。
|
||
# 单分量伤害构成(2026-09-19 充能退役批·用户拍板):主角攻击 = 唯一基础分量(atk,吃掷点含暴击;
|
||
# 类型 = 主角 attack_type 表值——2026-09-18 营地扩展前置批:量与类型抽象分离;查甲效矩阵对应行取克制修正)。
|
||
# 原"基础 + 穿刺/魔法充能三分量"模型随充能系统整体退役——克制策略归冒险前配置(营地换型 / 未来冒险前参数面),
|
||
# 局内不再有挖掘攒弹药的第二伤害供给。attack_up 增益经 hero_offense 池乘攻击合计(见池乘区注记)。
|
||
# 护甲等级掷点批(2026-09-16):基础分量吃掷点判定(含暴击);棋盘来源伤害不掷不折;
|
||
# 任何伤害落地 ≥ damage_floor(全局 max(1,·)——2026-09-20 用户拍板扩全来源,下限在控制器管线单点收口)。
|
||
var hero_alive: bool = int(oc._enemy_system.hero_unit().get("hp", 0)) > 0
|
||
var hero_target = oc._enemy_system.default_target()
|
||
if hero_alive and hero_target != null:
|
||
var ht := oc._damage.open_ticket(DamageController.KIND_HERO_ATTACK, "hero_attack", "主角攻击", "combat", oc._hero_atk, \
|
||
DamageController.TARGET_FRONT_ALIVE, ri, Vector2i(-1, -1), String(oc._enemy_system.hero_unit().get("attack_type", "normal")))
|
||
oc._damage.submit(ht)
|
||
# 连珠矢(内容数据驱动扩展批 T3——attack_commit 订阅施加面:开格节奏变攻击段数,本轮每开
|
||
# ~3 安全格 +1 段穿刺附加(上限 cap;段值 provisional 固定值不乘 atk——台账披露)。施加位
|
||
# 紧随主角攻击单开立=迁移前开单位(先于敌方行动单入队——flush 兑现序逐位一致)
|
||
for h in oc._hits_of(ht.context.get("fx_attack_hits", []) as Array, "attack_segments"):
|
||
var segments := mini(int(h.get("cap", 2)), oc._damage.dig_streak / maxi(1, int(h.get("divisor", 3))))
|
||
for s in segments:
|
||
# 迭代 20 T9——source_class 中性名(旧件名 feat_chain_arrows 随连珠矢退役;attack_segments 兑付通道保留泛用面)
|
||
var ct := oc._damage.open_ticket(DamageController.KIND_BOARD_TYPED, "fx_streak_segments",
|
||
"连击分段", "board", int(h.get("value", 0)), DamageController.TARGET_FRONT_ALIVE, ri,
|
||
oc.minesweeper.hero_pos(), "pierce")
|
||
oc._damage.submit(ct)
|
||
# 敌方行动(敌人技能池批——本拍动作开轮已摇定,此处按技能行兑现;行序 = 生成序)。
|
||
# 死亡即不动手:摇定后、兑现前死亡的敌不在存活序中——本拍技能作废,不 commit、不进冷却。
|
||
for u in oc._enemy_system.query_alive("enemy"):
|
||
if int(oc._enemy_system.hero_unit().hp) <= 0:
|
||
break # hero hp=0 立即短路(死尸挨打行是归因噪音——用户拍板)
|
||
var skill_id := oc._enemy_system.pending_action(u)
|
||
var srow: Dictionary = oc.db.skill_row(skill_id)
|
||
if srow.is_empty():
|
||
oc._fatal("敌实例待发动作悬空: %s" % skill_id)
|
||
continue
|
||
if String(srow.type) == "buff" or String(srow.type) == "debuff":
|
||
# 增益/妨害技(新效应词汇批 2026-09-19)= 0 伤害施放行:不掷不折;状态授予即数值兑现,技能冷却与增益持续两计时器分账。
|
||
# (原"本轮喂的伏击逢施放拍不兑现"读怪奖励随伏击退役一并作废——2026-09-20 八型批)
|
||
# 落点由状态行 target_side 路由(buff → 敌方侧 / debuff → 主角侧——容器零改动,proposal-status-vocabulary §1)。
|
||
var dur: int = int(srow.get("buff_duration", 1))
|
||
oc._status_effects.apply_effect(String(srow.buff_ref), {"source_class": "enemy_action", "origin_cell": Vector2i(-1, -1), "round_index": ri}, dur)
|
||
oc._emit_row("cast", "enemy_action", Vector2i(-1, -1), ri, "%s 施放 %s" % [u.display_name, String(srow.display_name)], 0, {"skill_id": skill_id, "effect_id": String(srow.buff_ref), "duration": dur})
|
||
oc._enemy_system.commit_action(u)
|
||
continue
|
||
# 伤害技(含普攻——倍率恒 1)= 敌方伤害技单据:基线 = round(atk×倍率)、rider 预计算归开单侧
|
||
# (表值算术零随机),掷点/克制查表(第 9 参 = 敌方 attack_type——迭代 24 N3 轴开列前恒空串不查表)/
|
||
# hero_defense×enemy_output 池乘区/下限/rider 后置/commit 全归控制器管线(兑现序 = 开单序;
|
||
# 来源敌已死在兑现时作废——死亡即不动手)。
|
||
var baseline: int = int(round(float(u.atk) * float(srow.get("damage_mult", 1.0))))
|
||
var rider := 0
|
||
if srow.has("rider_mult"):
|
||
rider = maxi(int(oc.db.settlement.damage_floor), int(floor(float(u.atk) * float(srow.rider_mult))))
|
||
var et := oc._damage.open_ticket(DamageController.KIND_ENEMY_SKILL, "enemy_action", "%s %s" % [u.display_name, String(srow.display_name)], "combat", \
|
||
baseline, DamageController.TARGET_HERO, ri, Vector2i(-1, -1), String(u.get("attack_type", "normal")), rider)
|
||
et["source_unit"] = u
|
||
et["context"] = {"skill_id": skill_id, "baseline": baseline}
|
||
oc._damage.submit(et)
|
||
# 地图伤害兑付(案C 2026-10-06 用户裁——战斗段末:怪物还手后按授予段事件序补提交统一结账;
|
||
# 主角死于怪物 → 地图账不兑,逐单留「未生效」行不作废静默——没生效也要留痕口径;
|
||
# 补提交后若地图直伤反杀主角,控制器 _halted 作废余单——战斗已败,胜负归判定段)
|
||
if int(oc._enemy_system.hero_unit().get("hp", 0)) <= 0:
|
||
for t in oc._deferred_board:
|
||
oc._emit_row("reward_ineffective", String(t.get("source_class", "")), t.get("origin_cell", Vector2i(-1, -1)), ri,
|
||
"%s 未生效(主角已倒下)" % String(t.get("display", "")), 0, {"forfeit": "hero_down"}, "")
|
||
else:
|
||
for t in oc._deferred_board:
|
||
oc._damage.submit(t)
|
||
oc._deferred_board.clear()
|
||
oc._damage.flush() # 战斗段界结账(B 模式——主角单+敌方单+地图单按开单序统一兑现;A 模式地图单补提交时即结)
|