merge master(d3fa887 技能池④+⑤提灯)入分支:07清单⑭双登冲突解(技能池⑭保留+秘宝目检改⑮);四文件auto-merge带旧词族零带入(全查仅存档键合法例外)
This commit is contained in:
commit
a9a2e25a0a
17 files changed
+342
-28
No files matched your search
@@ -916,6 +916,15 @@ func _grant_clear_identity(snap: Dictionary, ri: int, suffix: String) -> bool:
|
||||
func _roll_round_actions() -> void:
|
||||
var pity_m: int = int(db.skill.pity_threshold)
|
||||
for u in _enemy_system.query_alive("enemy"):
|
||||
# Boss 半血解锁闩(迭代14④ T4——开轮摇号前逐敌检查;一次过门单向闩;解锁出一次归因明细行
|
||||
# 「XX 解锁了 YY」带 skill_unlock 高光键〔type=highlight 既有行型零新增〕,呈现层弹一次性
|
||||
# 技能名提示〔轻量 toast 非演出——D8 呈现面〕。门=确定性谓词,机制面零随机,摇号随机
|
||||
# 消费仍在 behavior_roll 既有流——同种子逐位复现不破坏)
|
||||
for sid in _enemy_system.check_skill_unlocks(u):
|
||||
var srow_u: Dictionary = db.skill_row(sid)
|
||||
_emit_row("highlight", "enemy_action", Vector2i(-1, -1), round_index,
|
||||
"%s 解锁了 %s" % [String(u.display_name), String(srow_u.get("display_name", sid))],
|
||||
0, {"skill_id": sid}, "skill_unlock")
|
||||
var entries: Array = _enemy_system.rollable_skills(u)
|
||||
if _enemy_system.basic_streak(u) >= pity_m:
|
||||
var specials: Array = _enemy_system.special_skills(u)
|
||||
|
||||
@@ -72,11 +72,17 @@ func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_override:
|
||||
# 实例池快照(proposal §2.2:开战把模板快照一份,冷却全零——与"生成拿到当时的表值快照"同一条快照纪律)
|
||||
var pool_snap: Array[Dictionary] = []
|
||||
for entry in row.get("pool", []):
|
||||
pool_snap.append({
|
||||
var snap_entry := {
|
||||
"skill_id": String(entry.get("skill_id", "")),
|
||||
"weight": int(entry.get("weight", 0)),
|
||||
"cooldown_left": 0,
|
||||
})
|
||||
}
|
||||
# Boss 半血解锁技(迭代14④ T3——unlock_hp_pct 随池模板快照进实例池;缺省无字段=无门槛;
|
||||
# unlocked=单向闩标记,初始锁定)
|
||||
if entry.has("unlock_hp_pct"):
|
||||
snap_entry["unlock_hp_pct"] = int(entry.get("unlock_hp_pct", 0))
|
||||
snap_entry["unlocked"] = false
|
||||
pool_snap.append(snap_entry)
|
||||
_enemies.append({
|
||||
"handle_id": i,
|
||||
"enemy_id": String(row.enemy_id),
|
||||
@@ -113,32 +119,60 @@ func query_alive(side: String) -> Array:
|
||||
|
||||
# ---- 实例池状态机(敌人技能池批——全部确定性状态,随机在 战斗结算换算层)----
|
||||
|
||||
# 池条目锁定判定(迭代14④ Boss 半血解锁——带 unlock_hp_pct 且未过闩 = 锁定:双面过滤不进
|
||||
# 可摇集合与保底特殊技集合;解锁后即可摇,冷却初值 0)
|
||||
func _entry_locked(e: Dictionary) -> bool:
|
||||
return e.has("unlock_hp_pct") and not bool(e.get("unlocked", false))
|
||||
|
||||
|
||||
# 可摇集合:冷却已尽的池条目投影 [{skill_id, weight}]。普通攻击冷却恒 0 → 恒非空(空池不可能的结构前提,
|
||||
# 加载校验"每池恰一行普攻"兜底)。hero/失效句柄拒绝。
|
||||
# 加载校验"每池恰一行普攻"兜底)。hero/失效句柄拒绝。锁定条目(半血未解锁)双面过滤不入。
|
||||
func rollable_skills(u: Dictionary) -> Array:
|
||||
if u.is_empty() or _despawned or u.get("is_hero", false):
|
||||
_diag("rollable_skills 失效句柄")
|
||||
return []
|
||||
var out: Array[Dictionary] = []
|
||||
for e in u.pool:
|
||||
if _entry_locked(e):
|
||||
continue
|
||||
if int(e.cooldown_left) <= 0:
|
||||
out.append({"skill_id": String(e.skill_id), "weight": int(e.weight)})
|
||||
return out
|
||||
|
||||
|
||||
# 特殊技集合(保底专用——proposal §2.1:必出特殊技、特殊技内按权重、不受冷却限制):type ≠ 普攻的全部池条目。
|
||||
# 锁定条目(半血未解锁)双面过滤——保底不得逼出未解锁技(迭代14④ T3)。
|
||||
func special_skills(u: Dictionary) -> Array:
|
||||
if u.is_empty() or _despawned or u.get("is_hero", false):
|
||||
_diag("special_skills 失效句柄")
|
||||
return []
|
||||
var out: Array[Dictionary] = []
|
||||
for e in u.pool:
|
||||
if _entry_locked(e):
|
||||
continue
|
||||
var srow: Dictionary = db.skill_row(String(e.skill_id))
|
||||
if not srow.is_empty() and String(srow.type) != "basic":
|
||||
out.append({"skill_id": String(e.skill_id), "weight": int(e.weight)})
|
||||
return out
|
||||
|
||||
|
||||
# 半血解锁闩检查(迭代14④ T3——开轮摇号前逐敌检查;hp ≤ round(max_hp × unlock_hp_pct/100) →
|
||||
# 一次过门、单向闩〔实例标记,不解锁回退〕。门=确定性谓词零随机;返回本拍新解锁的 skill_id 列表
|
||||
# 供编排层出归因行〔每技恰一次——闩已置位不再返回〕)
|
||||
func check_skill_unlocks(u: Dictionary) -> Array:
|
||||
var out: Array = []
|
||||
if u.is_empty() or _despawned or u.get("is_hero", false) or not bool(u.get("alive", false)):
|
||||
return out
|
||||
for e in u.pool:
|
||||
if not e.has("unlock_hp_pct") or bool(e.get("unlocked", false)):
|
||||
continue
|
||||
var threshold: int = int(round(float(int(u.max_hp)) * float(int(e.unlock_hp_pct)) / 100.0))
|
||||
if int(u.hp) <= threshold:
|
||||
e["unlocked"] = true # 单向闩(不解锁回退——治疗抬血不解锁)
|
||||
out.append(String(e.skill_id))
|
||||
return out
|
||||
|
||||
|
||||
# 摇定结果写入(战斗结算换算层调用——确定值;roll_seq 递增 = 单敌第几拍诊断标签,不参与派生)
|
||||
func set_pending_action(u: Dictionary, skill_id: String) -> void:
|
||||
if u.is_empty() or _despawned or u.get("is_hero", false):
|
||||
|
||||
Reference in new issue
Block a user