iter51-卡2
This commit is contained in:
1 parent
1cd6e2b1b0
commit
372b4fdc31
27 files changed
+1231
-356
No files matched your search
@@ -4,19 +4,38 @@ extends RefCounted
|
||||
# 职责:案C 闸复位 + 本轮扫雷事实推导(执拗 streak 取数面)+ 主角先手
|
||||
# + 敌方行动兑现 + 地图伤害账殿后(补提交统一结账)。
|
||||
# 调用序:主角先手 → 逐敌还手 → 地图伤害账殿后〔案C〕;hero hp=0 短路。
|
||||
# 行发射/开单单点归宿主(oc)——案C 暂存闸归 RewardGrant(段持三引用直调,零转发壳)——
|
||||
# 耦合边界(5.1 封装修复换代):引用束注入——构造收编排器组装的 20 键封闭束,本段断言 10 键
|
||||
# (facts/units/damage/status_effects/fx_host/minesweeper/db/emit_row_cb/fatal_cb/reward_grant)
|
||||
# 解包同名成员;行发射经 emit_row_cb 回宿主、fatal 经 fatal_cb 回宿主——对编排器零引用。
|
||||
# 本函数体为原编排器 _combat_segment 逐字搬运(🔴 零行为变更契约)。
|
||||
# run 编排骨架+三私有族(_hero_strike/_enemy_actions/_board_deferred_settle);段序逐字。
|
||||
|
||||
var oc: BattleOrchestrator # 宿主(类型标注=段内 := 推断前提;循环类名引用 Godot 4 全局类安全)
|
||||
var fx_host: BattleFxHost # 效果引擎宿主件(三引用构造——本轮无消费面,构造形与授予段同形)
|
||||
var reward_grant: RewardGrant # 奖励授予件(案C 暂存闸 defer 持有方)
|
||||
var facts: BattleFacts # 战斗事实件(轮缓冲 streak 取数面)
|
||||
var units: UnitContainer # 单位容器(目标解析/存活查询)
|
||||
var damage: DamageController # 伤害控制器(开单/提交面)
|
||||
var status_effects: StatusContainer # 状态容器(增益/妨害施加面)
|
||||
var fx_host: BattleFxHost # 效果引擎宿主件(facts_inject 写面)
|
||||
var minesweeper: MinesweeperRules # 排雷玩法(束形统一交付面——卡面 10 键分配)
|
||||
var db: ConfigDb
|
||||
var emit_row_cb: Callable # 宿主 _emit_row——行协议面单点(5 参 head 束形)
|
||||
var fatal_cb: Callable # 宿主 _fatal——battle_result 唯一写点留宿主
|
||||
var reward_grant: RewardGrant # 奖励授予件(案C 暂存闸 defer 持有方)
|
||||
|
||||
|
||||
func _init(host, fx_host_ref: BattleFxHost, reward_grant_ref: RewardGrant) -> void:
|
||||
oc = host
|
||||
fx_host = fx_host_ref
|
||||
reward_grant = reward_grant_ref
|
||||
func _init(bundle: Dictionary) -> void:
|
||||
for k in ["facts", "units", "damage", "status_effects", "fx_host", "minesweeper", "db",
|
||||
"emit_row_cb", "fatal_cb", "reward_grant"]:
|
||||
assert(bundle.has(k), "[战斗段] 引用束缺键: %s" % k)
|
||||
facts = bundle.facts
|
||||
units = bundle.units
|
||||
damage = bundle.damage
|
||||
status_effects = bundle.status_effects
|
||||
fx_host = bundle.fx_host
|
||||
minesweeper = bundle.minesweeper
|
||||
db = bundle.db
|
||||
emit_row_cb = bundle.emit_row_cb
|
||||
fatal_cb = bundle.fatal_cb
|
||||
reward_grant = bundle.reward_grant
|
||||
|
||||
|
||||
func run(ri: int) -> void:
|
||||
@@ -26,12 +45,12 @@ func run(ri: int) -> void:
|
||||
# 同一次 _settle 内,facts 已定。
|
||||
var round_safe := 0
|
||||
var round_mine := false
|
||||
for evt in oc._facts.reveals:
|
||||
for evt in facts.reveals:
|
||||
if evt.kind == "safe":
|
||||
round_safe += 1
|
||||
elif evt.kind == "mine":
|
||||
round_mine = true
|
||||
oc.fx_host().facts_inject["dig_streak"] = 0 if round_mine else round_safe
|
||||
fx_host.facts_inject["dig_streak"] = 0 if round_mine else round_safe
|
||||
_hero_strike(ri)
|
||||
_enemy_actions(ri)
|
||||
_board_deferred_settle(ri)
|
||||
@@ -46,26 +65,26 @@ func run(ri: int) -> void:
|
||||
# 护甲等级掷点:基础分量吃掷点判定(含暴击);棋盘来源伤害不掷不折;
|
||||
# 任何伤害落地 ≥ damage_floor(全局 max(1,·) 适用所有来源,下限在控制器管线单点收口)。
|
||||
func _hero_strike(ri: int) -> void:
|
||||
var hero_alive: bool = int(oc._enemy_system.hero_unit().get("hp", 0)) > 0
|
||||
var hero_target = oc._enemy_system.default_target()
|
||||
var hero_alive: bool = int(units.hero_unit().get("hp", 0)) > 0
|
||||
var hero_target = units.default_target()
|
||||
if hero_alive and hero_target != null:
|
||||
var ht := oc._damage.open_ticket(DamageController.KIND_HERO_ATTACK, "hero_attack", "主角攻击",
|
||||
{"channel": "combat", "base_value": oc._hero_atk(), "target_rule": DamageController.TARGET_FRONT_ALIVE,
|
||||
var ht := damage.open_ticket(DamageController.KIND_HERO_ATTACK, "hero_attack", "主角攻击",
|
||||
{"channel": "combat", "base_value": damage.hero_atk(), "target_rule": DamageController.TARGET_FRONT_ALIVE,
|
||||
"ri": ri, "origin_cell": Vector2i(-1, -1),
|
||||
"attack_type": String(oc._enemy_system.hero_unit().get("attack_type", "normal"))})
|
||||
oc._damage.submit(ht)
|
||||
"attack_type": String(units.hero_unit().get("attack_type", "normal"))})
|
||||
damage.submit(ht)
|
||||
|
||||
|
||||
# 敌方行动(敌人技能池批——本拍动作开轮已摇定,此处按技能行兑现;行序 = 生成序)。
|
||||
# 死亡即不动手:摇定后、兑现前死亡的敌不在存活序中——本拍技能作废,不 commit、不进冷却。
|
||||
func _enemy_actions(ri: int) -> void:
|
||||
for u in oc._enemy_system.query_alive("enemy"):
|
||||
if int(oc._enemy_system.hero_unit().hp) <= 0:
|
||||
for u in units.query_alive("enemy"):
|
||||
if int(units.hero_unit().hp) <= 0:
|
||||
break # hero hp=0 立即短路(死尸挨打行是归因噪音——用户拍板)
|
||||
var skill_id := oc._enemy_system.pending_action(u)
|
||||
var srow: Dictionary[Variant, Variant] = oc.db.combat.skill.row_by_id(skill_id)
|
||||
var skill_id := units.pending_action(u)
|
||||
var srow: Dictionary[Variant, Variant] = db.combat.skill.row_by_id(skill_id)
|
||||
if srow.is_empty():
|
||||
oc._fatal("敌实例待发动作悬空: %s" % skill_id)
|
||||
fatal_cb.call("敌实例待发动作悬空: %s" % skill_id)
|
||||
continue
|
||||
if String(srow.type) == "buff" or String(srow.type) == "debuff":
|
||||
# 增益/妨害技 = 0 伤害施放行:不掷不折;状态授予即数值兑现,技能冷却与增益持续两计时器分账。
|
||||
@@ -73,9 +92,9 @@ func _enemy_actions(ri: int) -> void:
|
||||
# 敌方增益技只强化施放者自己,不再全体受益);debuff → 主角(off_guard/sapped 同义主角侧)。
|
||||
var dur: int = int(srow.get("buff_duration", 1))
|
||||
var owner_key: String = StatusContainer.owner_key_for(u) if String(srow.type) == "buff" else StatusContainer.OWNER_HERO
|
||||
oc._status_effects.apply_effect(String(srow.buff_ref), owner_key, {"source_class": "enemy_action", "origin_cell": Vector2i(-1, -1), "round_index": ri}, dur)
|
||||
oc._emit_row({"type": "cast", "source_class": "enemy_action", "origin_cell": 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)
|
||||
status_effects.apply_effect(String(srow.buff_ref), owner_key, {"source_class": "enemy_action", "origin_cell": Vector2i(-1, -1), "round_index": ri}, dur)
|
||||
emit_row_cb.call({"type": "cast", "source_class": "enemy_action", "origin_cell": 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})
|
||||
units.commit_action(u)
|
||||
continue
|
||||
# 伤害技(含普攻——倍率恒 1)= 敌方伤害技单据:基线 = round(atk×倍率)、rider 预计算归开单侧
|
||||
# (表值算术零随机),掷点/克制查表(spec 束 attack_type = 敌方攻击类型——迭代 24 N3 轴开列前恒空串不查表)/
|
||||
@@ -84,27 +103,27 @@ func _enemy_actions(ri: int) -> void:
|
||||
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.combat.settlement.damage_roll.damage_floor), int(floor(float(u.atk) * float(srow.rider_mult))))
|
||||
var et := oc._damage.open_ticket(DamageController.KIND_ENEMY_SKILL, "enemy_action",
|
||||
rider = maxi(int(db.combat.settlement.damage_roll.damage_floor), int(floor(float(u.atk) * float(srow.rider_mult))))
|
||||
var et := damage.open_ticket(DamageController.KIND_ENEMY_SKILL, "enemy_action",
|
||||
"%s %s" % [u.display_name, String(srow.display_name)],
|
||||
{"channel": "combat", "base_value": baseline, "target_rule": DamageController.TARGET_HERO,
|
||||
"ri": ri, "origin_cell": Vector2i(-1, -1),
|
||||
"attack_type": String(u.get("attack_type", "normal")), "rider": rider})
|
||||
et["source_unit"] = u
|
||||
et["context"] = {"skill_id": skill_id, "baseline": baseline}
|
||||
oc._damage.submit(et)
|
||||
damage.submit(et)
|
||||
|
||||
|
||||
# 地图伤害兑付(案C:战斗段末——怪物还手后按授予段事件序补提交统一结账;
|
||||
# 主角死于怪物 → 地图账不兑,逐单留「未生效」行不作废静默——没生效也要留痕口径;
|
||||
# 补提交后若地图直伤反杀主角,控制器 _halted 作废余单——战斗已败,胜负归判定段)
|
||||
func _board_deferred_settle(ri: int) -> void:
|
||||
if int(oc._enemy_system.hero_unit().get("hp", 0)) <= 0:
|
||||
if int(units.hero_unit().get("hp", 0)) <= 0:
|
||||
for t in (reward_grant.defer["queue"] as Array):
|
||||
oc._emit_row({"type": "reward_ineffective", "source_class": String(t.get("source_class", "")), "origin_cell": t.get("origin_cell", Vector2i(-1, -1))}, ri,
|
||||
emit_row_cb.call({"type": "reward_ineffective", "source_class": String(t.get("source_class", "")), "origin_cell": t.get("origin_cell", Vector2i(-1, -1))}, ri,
|
||||
"%s 未生效(主角已倒下)" % String(t.get("display", "")), 0, {"forfeit": "hero_down"})
|
||||
else:
|
||||
for t in (reward_grant.defer["queue"] as Array):
|
||||
oc._damage.submit(t)
|
||||
damage.submit(t)
|
||||
(reward_grant.defer["queue"] as Array).clear()
|
||||
oc._damage.flush() # 战斗段界结账(B 模式——主角单+敌方单+地图单按开单序统一兑现;A 模式地图单补提交时即结)
|
||||
damage.flush() # 战斗段界结账(B 模式——主角单+敌方单+地图单按开单序统一兑现;A 模式地图单补提交时即结)
|
||||
Reference in new issue
Block a user