iter49-卡1:效果端口与掷格分件批(轴戊两件建件):EffectPort六Callable路由+RewardRoller掷格面迁出+两业务类零引擎直连+effect_port_test V1-V3
This commit is contained in:
1 parent
926b05a61c
commit
11beb4fc59
31 files changed
+697
-586
No files matched your search
@@ -41,19 +41,9 @@ var _outcomes := {} # ticket_id → "redeemed"/"zero"/"voided"(
|
||||
var _seq := 0 # 流水号
|
||||
var _halted := false # 主角倒下终止封印(死亡事件置位——flush 余单作废)
|
||||
var _hero_ac_override := -1 # 主角护甲等级合流入参(begin_battle 显式设定——-1 = 表值兜底,口径同战斗编排器)
|
||||
# 效果引擎(attack_commit/clamp_check/armor_roll/kill/damage_taken
|
||||
# 发射+施加面:dispatch 返回命中,本类按组合规则施加)
|
||||
var _fx: EffectEngine = null
|
||||
var _ctx: EffectContext = null
|
||||
# 战斗段运行态事实束(编排器每轮/每战注入——键集封闭,缺键读缺省即零扰动):
|
||||
# dig_streak/charge_layers——facts 取数面(attack_commit 载荷 dig_streak;猎巢人 per/整备
|
||||
# attack_bonus per/厚积薄发 when/铁壁 shield per 同读 charge_layers)——combat_segment 每轮写;
|
||||
# rider_tier_bonus/rider_tier_crit——流派档位两运行态(magic 档一 rider+1/档二 rider 可暴击)
|
||||
# ——begin_battle 每战写
|
||||
var inject := {"dig_streak": 0, "charge_layers": 0, "rider_tier_bonus": 0, "rider_tier_crit": false}
|
||||
# 效果引擎入站回调束(编排器 begin_battle 同点注入):reveal=揭示效果回调(kill 发射点 reveal_tiles
|
||||
# 订阅面,入队授予段末兑付)/ac=ac_bonus 回调(石肤 AC 累积单点同步)
|
||||
var fx_calls := {"reveal": Callable(), "ac": Callable()}
|
||||
# 效果端口件(组装期单点注入——host _init bind_port):发射/计数器/事实/揭示/AC 全经端口路由,
|
||||
# 缺省 null=未绑(与原 _fx==null 零扰动守卫同语义——单测直构不接端口的夹具零扰动照跑)
|
||||
var _port: EffectPort = null
|
||||
|
||||
|
||||
func _init(db_ref, rng_ref, units_ref, effects_ref) -> void:
|
||||
@@ -69,44 +59,33 @@ func set_hero_ac_override(v: int) -> void:
|
||||
_hero_ac_override = v
|
||||
|
||||
|
||||
# 效果引擎注入(战斗编排器 _init——事件发射面接线)
|
||||
func set_fx(fx: EffectEngine, ctx: EffectContext) -> void:
|
||||
_fx = fx
|
||||
_ctx = ctx
|
||||
# 效果端口件注入(host _init 组装期单点——先于 begin_battle 任何发射)
|
||||
func bind_port(port: EffectPort) -> void:
|
||||
_port = port
|
||||
|
||||
|
||||
# 事件发射薄面(发射+命中收集统一入口——订阅空=零循环零扰动;命中由各施加面按组合规则施加)
|
||||
# 事件发射薄面(发射+命中收集统一入口——订阅空=零循环零扰动;命中由各施加面按组合规则施加;
|
||||
# 路由经效果端口件,事实回调=biz_fact 闭面五键宿主侧)
|
||||
func _fx_hits(event: String, payload: Dictionary) -> Array:
|
||||
if _fx == null:
|
||||
if _port == null:
|
||||
return []
|
||||
return _fx.dispatch(_ctx, event, payload, _fx_fact)
|
||||
return _port.emit(event, payload)
|
||||
|
||||
|
||||
# 事件发射薄面(免施加观测位——enemy_hp_threshold 等现无订阅者的事件保留零扰动面)
|
||||
# 补充事实面(fact 取值第二优先源——payload 未携带的运行态读数:charge_layers 编排器每轮注入。
|
||||
# hp_ratio 补入〔背水 when 面,敌技 damage_taken 载荷不带血比例时回落〕;
|
||||
# fx_calls.reveal=揭示效果回调〔斩首学者 kill 订阅面——编排器注入,入队授予段末兑付〕)
|
||||
func _fx_fact(fact: String) -> Variant:
|
||||
match fact:
|
||||
"charge_layers":
|
||||
return int(inject["charge_layers"])
|
||||
"dig_streak":
|
||||
return int(inject["dig_streak"])
|
||||
"hp_ratio":
|
||||
var hu: Dictionary[Variant, Variant] = units.hero_unit()
|
||||
return int(round(100.0 * float(int(hu.get("hp", 0))) / float(maxi(1, int(hu.get("max_hp", 1)))))) # 百分比 int(when lte int 截断口径)
|
||||
return null
|
||||
# 未绑事实回落(缺省 null——int()/bool() 包裹后与原 inject 缺省值逐位同:int(null)=0/bool(null)=false)
|
||||
func _fact_or(name: String) -> Variant:
|
||||
return null if _port == null else _port.fact(name)
|
||||
|
||||
|
||||
# per 取数(per 字段解析——载荷同名字段优先,回落补充事实面;add_ticket_rider/attack_bonus/
|
||||
# per 取数(per 字段解析——载荷同名字段优先,回落端口事实面;add_ticket_rider/attack_bonus/
|
||||
# shield/open_ticket 的倍数承载:贡献值 = value × per 读数,cap 对乘积封顶)
|
||||
func _per_value(name: String, payload: Dictionary) -> int:
|
||||
if name == "":
|
||||
return 1
|
||||
if payload.has(name):
|
||||
return int(payload[name])
|
||||
if _fx_fact(name) != null:
|
||||
return int(_fx_fact(name))
|
||||
if _fact_or(name) != null:
|
||||
return int(_fact_or(name))
|
||||
return 0
|
||||
|
||||
|
||||
@@ -169,7 +148,7 @@ func open_ticket(kind: String, source_class: String, display: String, spec: Dict
|
||||
var ac_payload := {"atk": int(t.base_value),
|
||||
"target": String(tgt.get("display_name", "")) if tgt != null else "",
|
||||
"target_id": String(tgt.get("enemy_id", "")) if tgt != null else "",
|
||||
"matchup": matchup_o, "dig_streak": int(inject["dig_streak"]), "nest_count": _nest_count()}
|
||||
"matchup": matchup_o, "dig_streak": int(_fact_or("dig_streak") or 0), "nest_count": _nest_count()}
|
||||
t.context["fx_attack_hits"] = _fx_hits("attack_commit", ac_payload)
|
||||
t.context["fx_attack_payload"] = ac_payload
|
||||
return t
|
||||
@@ -361,13 +340,13 @@ func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float:
|
||||
if String(h.get("kind", "")) == "attack_bonus":
|
||||
var contrib := int(h.get("value", 0)) * _per_value(String(h.get("per", "")), ac_payload)
|
||||
if h.has("value_counter") and String(h.get("value_counter", "")) != "":
|
||||
contrib = EffectEngine.counter(_ctx, String(h.get("value_counter", "")))
|
||||
contrib = _port.counter_read(String(h.get("value_counter", "")))
|
||||
base_value += float(contrib)
|
||||
# 计数器施加(attack_commit 命中行内 counter_add〔用后清零行〕,命中序=声明序)
|
||||
# 计数器施加(attack_commit 命中行内 counter_add〔用后清零行〕,命中序=声明序;端口路由账面)
|
||||
for h in ac_hits:
|
||||
if String(h.get("kind", "")) == "counter_add":
|
||||
var set_v = h.get("set", null)
|
||||
EffectEngine.counter_add(_ctx, String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != 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 层——强制必中已在折扣拍承载)
|
||||
if ctx["spike_ready"]:
|
||||
for h in ac_hits:
|
||||
@@ -397,7 +376,7 @@ func _hero_attack_redeem(t: Dictionary, ctx: Dictionary, base_value: float) -> D
|
||||
# (奥术余烬「普攻命中后恒定结算」语义);猎巢人巢控光环(per nest_count)/矿工的执拗开格加成
|
||||
# (per dig_streak、cap 封顶)同通道合计;档一质变 rider+1 / 档二(crit 时)rider 乘暴击倍率。
|
||||
# rider 不改变下限语义(landed 含 rider 后不再过 floor)。
|
||||
var hero_rider := int(inject["rider_tier_bonus"])
|
||||
var hero_rider := int(_fact_or("rider_tier_bonus") or 0) # or 0=未绑缺省与 int(null) 缺省同值(int() 构造拒 null——端口缺省 null 面的空值合并)
|
||||
for h in ac_hits:
|
||||
if String(h.get("kind", "")) == "add_ticket_rider":
|
||||
var contrib := int(h.get("value", 0)) * _per_value(String(h.get("per", "")), ctx["ac_payload"])
|
||||
@@ -405,7 +384,7 @@ func _hero_attack_redeem(t: Dictionary, ctx: Dictionary, base_value: float) -> D
|
||||
contrib = mini(int(h.cap), contrib)
|
||||
hero_rider += contrib
|
||||
if hero_rider > 0:
|
||||
if bool(ctx["crit"]) and bool(inject["rider_tier_crit"]):
|
||||
if bool(ctx["crit"]) and bool(_fact_or("rider_tier_crit") or false):
|
||||
hero_rider = int(round(float(hero_rider) * float(db.combat.settlement.damage_roll.crit_multiplier)))
|
||||
landed += hero_rider
|
||||
payload["hero_rider"] = hero_rider
|
||||
@@ -421,9 +400,7 @@ func _hero_attack_redeem(t: Dictionary, ctx: Dictionary, base_value: float) -> D
|
||||
func _kill_overflow(t: Dictionary, target: Dictionary, landed: int) -> void:
|
||||
for h in _fx_hits("kill", {"target": String(target.display_name), "target_id": String(target.get("enemy_id", "")), "overflow": landed}):
|
||||
if String(h.get("kind", "")) == "reveal_tiles":
|
||||
var reveal_cb: Callable = fx_calls["reveal"]
|
||||
if reveal_cb.is_valid():
|
||||
reveal_cb.call() # 斩首学者——击杀揭示 1 格(编排器入队,授予段末兑付)
|
||||
_port.reveal_effect() # 斩首学者——击杀揭示 1 格(端口路由宿主入队,授予段末兑付)
|
||||
continue
|
||||
if String(h.get("kind", "")) != "overflow":
|
||||
continue
|
||||
@@ -468,7 +445,7 @@ func _resolve_enemy_skill(t: Dictionary) -> void:
|
||||
var total: int = int(roll["total"])
|
||||
# damage_taken 发射(kind=enemy_skill;铁壁整备减伤订阅面:shield 加法族合计 value×per(charge_layers),
|
||||
# 稳健拓荒树规则同面(rebuild 合成订阅);减后过下限保底。damage_reduce〔背水 hp_ratio when〕/
|
||||
# counter_add〔保险丝/石肤〕/ac_bonus〔石肤〕同面施加;hp_ratio fact 由 _fx_fact 补充事实面回落提供)
|
||||
# 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))
|
||||
total = int(dt_res["total"])
|
||||
units.apply_damage(hero, total)
|
||||
@@ -525,12 +502,10 @@ func _apply_hero_damage_effects(hits: Array, total: int) -> Dictionary:
|
||||
"damage_reduce":
|
||||
total = maxi(0, total - int(h.get("value", 0)))
|
||||
"ac_bonus":
|
||||
var ac_cb: Callable = fx_calls["ac"]
|
||||
if ac_cb.is_valid():
|
||||
ac_cb.call(h)
|
||||
_port.apply_ac(h)
|
||||
"counter_add":
|
||||
var set_v = h.get("set", null)
|
||||
EffectEngine.counter_add(_ctx, String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != 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)
|
||||
if shield > 0:
|
||||
total = maxi(int(db.combat.settlement.damage_roll.damage_floor), total - shield)
|
||||
return {"total": total, "shield": shield}
|
||||
|
||||
Reference in new issue
Block a user