卡①T9(核心数据面结构收敛批): 散条组——K5 action_economy(删_next_round_mode死存储+_ap_exhausted_last派生合并(ap_exhausted_last_round改_last_round_end.path_tag派生读,同源同刻等值)+last_round_end属性→方法,消费方minesweeper_rules:495改址)/reward_economy roll_board规范化域提取(_normalize_eligible开流前零RNG)+_skewed_cell_rows两域(_skew_families分族+_apply_skew权重装配,守恒assert随段迁移)/minesweeper_rules _do_dig拆_reveal_chain(cell_revealed发射序即链序整体随段搬迁)/K6′ unit_container spawn签名束化(10→1 req Dictionary,束键封闭词表缺省逐字)+体内拆_spawn_hero_unit/_spawn_rowset/_row_instance_counts+调用点24处9文件改束形(orchestrator+测试8,断言标签字面量零触碰);gdstyle 92→83键NEW=0
This commit is contained in:
1 parent
2bd2625194
commit
070a5340b3
13 files changed
+136
-88
No files matched your search
@@ -30,10 +30,7 @@ var _rap := 0
|
||||
var rap: int:
|
||||
get: return _rap
|
||||
var _last_round_end: Dictionary[String, String] = {} # {path_tag, continuation_hint}——排雷玩法 组包 round_end 的合法数据源
|
||||
var last_round_end: Dictionary[Variant, Variant]:
|
||||
get: return _last_round_end
|
||||
var _settlement_consumed := false # AC-14 门:notify_settlement_done 消费后才受理 round_start
|
||||
var _next_round_mode := "" # 调试观测量(同板续轮 / 换新图)
|
||||
var _pending_ap_delta := 0 # 下轮行动点修正排队(action 型 ±1 排队,轮开始兑现后清零)
|
||||
# 蓄力流运行态:转蓄力=round_end grant_ap(mode:transfer) 订阅(finish_round_stop 定夺)、
|
||||
# 深挖对价=dig_paid counter_spend 订阅(request_dig 施加面);charge_layers=蓄力层账本
|
||||
@@ -44,7 +41,6 @@ var charge_layers: int:
|
||||
var _fx: EffectEngine = null
|
||||
var _ctx: EffectContext = null
|
||||
var _last_stop_ap := 0 # 停手侧剩余 AP 记账(转存决策在 round_end 发射点——grant_ap(transfer) 订阅定夺)
|
||||
var _ap_exhausted_last := false # 上轮 AP 耗尽封印(一滴不剩 round_start when 面)
|
||||
|
||||
|
||||
func set_fx(fx: EffectEngine, ctx: EffectContext) -> void:
|
||||
@@ -216,7 +212,6 @@ func notify_settlement_done(next_round_mode: String) -> bool:
|
||||
_reject("phase")
|
||||
return false
|
||||
_settlement_consumed = true
|
||||
_next_round_mode = next_round_mode
|
||||
return true
|
||||
|
||||
|
||||
@@ -272,13 +267,19 @@ func _finish_round(path_tag: String, continuation_hint: String) -> void:
|
||||
assert(path_tag != "ap_exhausted" or _ap == 0, "耗尽轮剩余行动点恒为 0(实现层断言兜底)")
|
||||
assert(path_tag != "cleared" or _ap == 0, "清图轮剩余行动点当场清零(不进储备池)")
|
||||
_last_round_end = {"path_tag": path_tag, "continuation_hint": continuation_hint}
|
||||
_ap_exhausted_last = path_tag == "ap_exhausted" # 一滴不剩 when 面(轮始发射读数)
|
||||
_phase = Phase.WAITING
|
||||
|
||||
|
||||
# 上轮 AP 是否耗尽(round_start 发射 payload 读数面;轮始兑现后保持到本轮末)
|
||||
# 上轮组包读数({path_tag, continuation_hint}——排雷玩法 组包 round_end 的合法数据源;
|
||||
# 属性→方法 K5 换形,消费方 minesweeper_rules 单点改址)
|
||||
func last_round_end() -> Dictionary[String, String]:
|
||||
return _last_round_end
|
||||
|
||||
|
||||
# 上轮 AP 是否耗尽(round_start 发射 payload 读数面;轮始兑现后保持到本轮末)——
|
||||
# 派生读(同源同刻:_last_round_end 组包点即派生原点,K5 派生合并——存储成员退役)
|
||||
func ap_exhausted_last_round() -> bool:
|
||||
return _ap_exhausted_last
|
||||
return _last_round_end.get("path_tag", "") == "ap_exhausted"
|
||||
|
||||
|
||||
func _reject(source: String) -> void:
|
||||
|
||||
@@ -302,9 +302,7 @@ func _begin_battle_accept(enc: Dictionary) -> bool:
|
||||
return false
|
||||
# E4 收口:加成经 encounter 显式携带(hero_atk/hero_max_hp;缺省 = 表值——冒烟/工具直呼路径)
|
||||
_hero_atk = int(enc.get("hero_atk", int(db.combat.hero.atk)))
|
||||
if not _enemy_system.spawn(int(enc.level_index), int(enc.node_depth), int(enc.hero_hp), dice[0],
|
||||
_hero_atk, int(enc.get("hero_max_hp", -1)), dice[1],
|
||||
String(enc.get("attack_type", "")), String(enc.get("armor_type", "")), String(enc.get("node_type", "battle"))): # 两根类型轴(空串=锻造配置默认值回退,行为连续)+行类维(battle/boss)
|
||||
if not _enemy_system.spawn({"level_index": int(enc.level_index), "node_depth": int(enc.node_depth), "hero_hp": int(enc.hero_hp), "unit_count_overrides": dice[0], "hero_atk_override": _hero_atk, "hero_max_hp_override": int(enc.get("hero_max_hp", -1)), "enemy_atk_overrides": dice[1], "hero_attack_type": String(enc.get("attack_type", "")), "hero_armor_type": String(enc.get("armor_type", "")), "row_kind": String(enc.get("node_type", "battle"))}): # 两根类型轴(空串=锻造配置默认值回退,行为连续)+行类维(battle/boss)
|
||||
_fatal("敌人系统 spawn 被拒")
|
||||
return false
|
||||
return true
|
||||
|
||||
@@ -304,15 +304,22 @@ func _do_dig(c: Vector2i) -> Dictionary:
|
||||
if was_sealed:
|
||||
_seals.erase(c)
|
||||
var reveal_order: Array[Variant] = _chain_reveal_order(c, eff_seals)
|
||||
_reveal_chain(c, reveal_order, was_sealed)
|
||||
if action_economy.phase != action_economy.PHASE_ACTIVE:
|
||||
_emit_round_end_seals_and_payload()
|
||||
return _outcome(true, "executed", "", "")
|
||||
|
||||
|
||||
## 连锁揭示域:首格+连锁新格揭示(BFS 规范序——cell_revealed 发射序即链序,整体随段搬迁)。
|
||||
## 格面资源资格:chain/dig 恒 true——安全格与危险格一视同仁(危险格亦携带,
|
||||
## 负向兑付归 战斗结算 极性路由);initial(封锁格)恒 false。资源本体与极性不在本系统。
|
||||
## dug_under_seal = 首格带封印直挖标记(战斗结算 情况④兑付改判消费;连锁格恒 false——连锁不越封印)
|
||||
func _reveal_chain(c: Vector2i, reveal_order: Array, was_sealed: bool) -> void:
|
||||
for rc in reveal_order:
|
||||
if _revealed.has(rc):
|
||||
continue # 闭包可穿过已开区——已开格零事件(cell_revealed × |O′ ∖ O|)
|
||||
var is_mine := _board.is_mine(rc)
|
||||
var channel := "dig" if rc == c else "chain"
|
||||
# 格面资源资格:chain/dig 恒 true——安全格与危险格一视同仁(危险格亦携带,
|
||||
# 负向兑付归 战斗结算 极性路由);initial(封锁格)恒 false。资源本体与极性不在本系统。
|
||||
# dug_under_seal = 首格带封印直挖标记(战斗结算 情况④兑付改判消费;连锁格恒 false——连锁不越封印)
|
||||
if is_mine:
|
||||
if _board.is_mine(rc):
|
||||
_revealed[rc] = {"kind": "mine", "digit": -1}
|
||||
cell_revealed.emit({
|
||||
"cell": rc, "kind": "mine", "digit": -1,
|
||||
@@ -326,9 +333,6 @@ func _do_dig(c: Vector2i) -> Dictionary:
|
||||
"variant_ids": _board.variant_ids(rc), "channel": channel, "resource": true,
|
||||
"dug_under_seal": was_sealed and rc == c,
|
||||
})
|
||||
if action_economy.phase != action_economy.PHASE_ACTIVE:
|
||||
_emit_round_end_seals_and_payload()
|
||||
return _outcome(true, "executed", "", "")
|
||||
|
||||
|
||||
func _board_face_dig(c: Vector2i) -> String:
|
||||
@@ -492,7 +496,7 @@ func _emit_seals_batch() -> void:
|
||||
|
||||
func _emit_round_end_seals_and_payload() -> void:
|
||||
_emit_seals_batch()
|
||||
var payload: Dictionary[Variant, Variant] = action_economy.last_round_end # 逐字段取自 行动经济(读取权 = 接口契约)
|
||||
var payload: Dictionary[Variant, Variant] = action_economy.last_round_end() # 逐字段取自 行动经济(读取权 = 接口契约;属性→方法 K5)
|
||||
round_end_board.emit({"path_tag": payload.get("path_tag", ""), "continuation_hint": payload.get("continuation_hint", "")})
|
||||
|
||||
|
||||
|
||||
+36
-20
@@ -40,18 +40,8 @@ func roll_board(eligible: Array) -> bool:
|
||||
if eligible.is_empty():
|
||||
_fatal("roll_board 空资格清单(E1 兜底 fail-fast——排雷玩法 不变式④前置)")
|
||||
return false
|
||||
# 行主序规范化 + 去重(排序责任不外推给 战斗结算;排序键单点 BoardData.row_major_key)
|
||||
var seen := {}
|
||||
var list: Array[Dictionary] = []
|
||||
for e in eligible:
|
||||
var c: Vector2i = e.cell
|
||||
if seen.has(c):
|
||||
push_warning("[地图战斗资源] 资格清单重复格已去重: %s" % str(c))
|
||||
continue
|
||||
seen[c] = true
|
||||
list.append({"cell": c})
|
||||
list.sort_custom(func(a, b): return BoardData.row_major_key(a.cell) < BoardData.row_major_key(b.cell))
|
||||
_eligible = list
|
||||
_eligible = _normalize_eligible(eligible)
|
||||
var list: Array[Dictionary] = _eligible
|
||||
_granted.clear() # 新批重置映射受理面(旧图快照消亡)
|
||||
_power_roll.clear()
|
||||
_clear_power = -1
|
||||
@@ -85,6 +75,21 @@ func roll_board(eligible: Array) -> bool:
|
||||
return true
|
||||
|
||||
|
||||
## 资格清单规范化域(开流前——零 RNG):行主序 + 去重(排序责任不外推给 战斗结算;排序键单点 BoardData.row_major_key)
|
||||
func _normalize_eligible(eligible: Array) -> Array[Dictionary]:
|
||||
var seen := {}
|
||||
var list: Array[Dictionary] = []
|
||||
for e in eligible:
|
||||
var c: Vector2i = e.cell
|
||||
if seen.has(c):
|
||||
push_warning("[地图战斗资源] 资格清单重复格已去重: %s" % str(c))
|
||||
continue
|
||||
seen[c] = true
|
||||
list.append({"cell": c})
|
||||
list.sort_custom(func(a, b): return BoardData.row_major_key(a.cell) < BoardData.row_major_key(b.cell))
|
||||
return list
|
||||
|
||||
|
||||
# ---- 查询面(Ready 只读;未开格恒可查——秘宝 桥接结构前提)----
|
||||
|
||||
# 相位只读出口(诊断观测面——unrolled/ready/retired;消费方禁直读 _phase 下划线字段)
|
||||
@@ -217,6 +222,20 @@ func _skewed_cell_rows() -> Array:
|
||||
if board_skew <= 0:
|
||||
return _rollable_rows()
|
||||
var base: Array[Variant] = _rollable_rows()
|
||||
var families := _skew_families(base)
|
||||
if families["down"].is_empty() or families["up"].is_empty():
|
||||
return base # 结构缺族 = 无偏斜作用面(保守直通——池结构变更须走表加载校验另批)
|
||||
# 下调总量 = round_half_up(Σ生存×v/100);逐行精确份额 w×v/100 最大余数取整(行序平局)
|
||||
var drops := _largest_remainder_split(families["down"], board_skew, 100, (2 * _pool_weight(families["down"]) * board_skew + 100) / 200)
|
||||
# 上浮总量 = 下调总量(守恒),逐行精确份额 drop×w/Σ进攻 最大余数取整
|
||||
var gains := _largest_remainder_split(families["up"], drops_total(drops), _pool_weight(families["up"]), drops_total(drops))
|
||||
var out := _apply_skew(base, families["down"], families["up"], drops, gains)
|
||||
assert(_pool_weight(out) == _pool_weight(base), "图级偏斜守恒破(偏斜后合计须等于原池)")
|
||||
return out
|
||||
|
||||
|
||||
## 分族域:生存下调族与进攻上浮族行集拆分(池结构不变式零触碰)
|
||||
func _skew_families(base: Array) -> Dictionary:
|
||||
var down: Array[Variant] = []
|
||||
var up: Array[Variant] = []
|
||||
for row in base:
|
||||
@@ -225,13 +244,11 @@ func _skewed_cell_rows() -> Array:
|
||||
down.append(row)
|
||||
elif SKEW_UP_KINDS.has(k):
|
||||
up.append(row)
|
||||
if down.is_empty() or up.is_empty():
|
||||
return base # 结构缺族 = 无偏斜作用面(保守直通——池结构变更须走表加载校验另批)
|
||||
var v := board_skew
|
||||
# 下调总量 = round_half_up(Σ生存×v/100);逐行精确份额 w×v/100 最大余数取整(行序平局)
|
||||
var drops := _largest_remainder_split(down, v, 100, (2 * _pool_weight(down) * v + 100) / 200)
|
||||
# 上浮总量 = 下调总量(守恒),逐行精确份额 drop×w/Σ进攻 最大余数取整
|
||||
var gains := _largest_remainder_split(up, drops_total(drops), _pool_weight(up), drops_total(drops))
|
||||
return {"down": down, "up": up}
|
||||
|
||||
|
||||
## 权重装配域:逐行精确份额增减(下调族扣 drops、上浮族加 gains——守恒 assert 随段迁移)
|
||||
func _apply_skew(base: Array, down: Array, up: Array, drops: Array, gains: Array) -> Array:
|
||||
var di := 0
|
||||
var ui := 0
|
||||
var out: Array[Variant] = []
|
||||
@@ -248,7 +265,6 @@ func _skewed_cell_rows() -> Array:
|
||||
var skewed: Dictionary[Variant, Variant] = row.duplicate()
|
||||
skewed["weight"] = w
|
||||
out.append(skewed)
|
||||
assert(_pool_weight(out) == _pool_weight(base), "图级偏斜守恒破(偏斜后合计须等于原池)")
|
||||
return out
|
||||
|
||||
|
||||
|
||||
+54
-25
@@ -33,42 +33,58 @@ func _init(db_ref: ConfigDb) -> void:
|
||||
# (下标=行集行序,长度短于行集时缺省 -1 = 该行行值路径;空数组 = 全行定值)。
|
||||
# 逐行实例化、生成序 = 文件行序(行序即契约,敌人系统 v0.15);行集实例总数(各行传入数量求和)
|
||||
# ≤ ENEMY_ROWSET_INSTANCE_MAX 守卫 fail-fast。
|
||||
func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_overrides: Array = [],
|
||||
atk_override: int = -1, max_hp_override: int = -1, enemy_atk_overrides: Array = [],
|
||||
hero_attack_type: String = "", hero_armor_type: String = "", row_kind: String = "battle") -> bool:
|
||||
# spawn 引用束(K6′ 签名束化——10 形参收单 Dictionary 束):束键封闭词表——
|
||||
# 必载 level_index/node_depth/hero_hp;可选 unit_count_overrides=[]/enemy_atk_overrides=[]/
|
||||
# hero_atk_override=-1/hero_max_hp_override=-1/hero_attack_type=""/hero_armor_type=""/
|
||||
# row_kind="battle"(缺省语义与现行形参缺省逐字同值)。
|
||||
# enemy_atk_override:遭遇骰同流的 spawn 期整战持久 roll 结果
|
||||
# (-1 = 表值定值路径;≥0 = 行值替换后再乘关卡 atk_mult)。敌人系统 零随机纪律保持。
|
||||
# 行集受理:unit_count_overrides / enemy_atk_overrides 为**逐行数组**
|
||||
# (下标=行集行序,长度短于行集时缺省 -1 = 该行行值路径;空数组 = 全行定值)。
|
||||
# 逐行实例化、生成序 = 文件行序(行序即契约,敌人系统 v0.15);行集实例总数(各行传入数量求和)
|
||||
# ≤ ENEMY_ROWSET_INSTANCE_MAX 守卫 fail-fast。
|
||||
func spawn(req: Dictionary) -> bool:
|
||||
if _spawned:
|
||||
push_warning("[敌人系统] Alive 相位重复 spawn(相位守卫)")
|
||||
return false
|
||||
# 行集数组口径(resolver 按 (L,band) 带寻址返回全部行、文件序)
|
||||
var rowset: Array[Variant] = db.combat.enemy.resolve_rowset(level_index, node_depth, row_kind)
|
||||
var rowset: Array[Variant] = db.combat.enemy.resolve_rowset(int(req.level_index), int(req.node_depth), String(req.get("row_kind", "battle")))
|
||||
if rowset.is_empty():
|
||||
push_error("[敌人系统] 遭遇行解析失败/越域 (%d,%d,%s)" % [level_index, node_depth, row_kind])
|
||||
push_error("[敌人系统] 遭遇行解析失败/越域 (%s,%s,%s)" % [str(req.get("level_index")), str(req.get("node_depth")), String(req.get("row_kind", "battle"))])
|
||||
assert(false, "遭遇行悬空(R1 前置守卫)")
|
||||
return false
|
||||
if not _spawn_hero_unit(int(req.hero_hp), int(req.get("hero_atk_override", -1)), int(req.get("hero_max_hp_override", -1)), String(req.get("hero_attack_type", "")), String(req.get("hero_armor_type", ""))):
|
||||
return false
|
||||
var mod: Dictionary[Variant, Variant] = db.run.difficulty.resolve_modifiers(int(req.level_index), int(req.node_depth))
|
||||
if not _spawn_rowset(rowset, req.get("unit_count_overrides", []), req.get("enemy_atk_overrides", []), float(mod.get("hp_mult", 1.0)), float(mod.get("atk_mult", 1.0))):
|
||||
return false
|
||||
_spawned = true
|
||||
_despawned = false
|
||||
return true
|
||||
|
||||
|
||||
## 英雄单位构建域:生效上限与类型轴快照(读注入值,空串回退锻造工坊配置默认值 normal/light)。
|
||||
## max_hp = 生效上限(非入参 hero_hp)——跨战斗携带 HP 时上限不得压扁
|
||||
## (恢复点/治疗包的满血守卫与治疗上限随之失效)
|
||||
func _spawn_hero_unit(hero_hp: int, atk_override: int, max_hp_override: int, hero_attack_type: String, hero_armor_type: String) -> bool:
|
||||
var eff_atk: int = atk_override if atk_override >= 1 else int(db.combat.hero.atk)
|
||||
var eff_max_hp: int = max_hp_override if max_hp_override >= 1 else int(db.combat.hero.max_hp)
|
||||
if hero_hp > eff_max_hp or hero_hp <= 0:
|
||||
push_warning("[敌人系统] hero_hp 入参越界(EC16): %d" % hero_hp)
|
||||
return false
|
||||
# max_hp = 生效上限(非入参 hero_hp)——跨战斗携带 HP 时上限不得压扁
|
||||
# (恢复点/治疗包的满血守卫与治疗上限随之失效)
|
||||
_hero = {"hp": hero_hp, "max_hp": eff_max_hp, "atk": eff_atk, "is_hero": true, "alive": true, "display_name": String(db.combat.hero.display_name), "enemy_id": "hero", "armor_type": hero_armor_type if hero_armor_type != "" else db.crossrun.forge.default_armor_type, "attack_type": hero_attack_type if hero_attack_type != "" else db.crossrun.forge.default_attack_type} # 护甲/攻击类型轴快照(读注入值,空串回退锻造工坊配置默认值 normal/light;甲效矩阵消费面)
|
||||
_enemies.clear() # 难度曲线与Boss DifficultyTable 修饰:施加于行值、行值快照之前——MVP 空表 = 恒 1.0 无行为(AC-10);混编行集内全部敌种同乘((L,D) 精确匹配一次取值——F9 同乘不改变异,敌人系统 v0.15)
|
||||
var mod: Dictionary[Variant, Variant] = db.run.difficulty.resolve_modifiers(level_index, node_depth)
|
||||
var hp_mult: float = float(mod.get("hp_mult", 1.0))
|
||||
var atk_mult: float = float(mod.get("atk_mult", 1.0))
|
||||
# 逐行数量定值(敌人系统 零随机纪律——骰定在 战斗结算 遭遇骰层按行完成,本层收确定值;
|
||||
# 行 i 数量 = overrides[i](≥1 时)否则该行 unit_count 行值)
|
||||
var per_row_counts: Array[int] = []
|
||||
_hero = {"hp": hero_hp, "max_hp": eff_max_hp, "atk": eff_atk, "is_hero": true, "alive": true, "display_name": String(db.combat.hero.display_name), "enemy_id": "hero", "armor_type": hero_armor_type if hero_armor_type != "" else db.crossrun.forge.default_armor_type, "attack_type": hero_attack_type if hero_attack_type != "" else db.crossrun.forge.default_attack_type} # 护甲/攻击类型轴快照(甲效矩阵消费面)
|
||||
return true
|
||||
|
||||
|
||||
## 行集实例化域(难度曲线修饰施加于行值、行值快照之前——MVP 空表 = 恒 1.0 无行为〔AC-10〕;
|
||||
## 混编行集内全部敌种同乘——(L,D) 精确匹配一次取值,F9 同乘不改变异,敌人系统 v0.15)
|
||||
func _spawn_rowset(rowset: Array, unit_count_overrides: Array, enemy_atk_overrides: Array, hp_mult: float, atk_mult: float) -> bool:
|
||||
_enemies.clear()
|
||||
var per_row_counts := _row_instance_counts(rowset, unit_count_overrides)
|
||||
if per_row_counts.is_empty():
|
||||
return false
|
||||
var total_instances := 0
|
||||
for row_i in range(rowset.size()):
|
||||
var row_i_dict: Dictionary[Variant, Variant] = rowset[row_i]
|
||||
var ovr: int = int(unit_count_overrides[row_i]) if row_i < unit_count_overrides.size() else -1
|
||||
var count: int = ovr if ovr >= 1 else int(row_i_dict.unit_count)
|
||||
if count < EnemyTable.UNIT_COUNT_MIN or count > EnemyTable.UNIT_COUNT_MAX:
|
||||
push_warning("[敌人系统] 行 %d 实例化数量越域(单种数域 [%d,%d]): %d" % [row_i, EnemyTable.UNIT_COUNT_MIN, EnemyTable.UNIT_COUNT_MAX, count])
|
||||
return false
|
||||
per_row_counts.append(count)
|
||||
for count in per_row_counts:
|
||||
total_instances += count
|
||||
# 行集实例总数守卫(行集构成纪律③——各行骰后数量求和 ≤4;骰后值加载期不可判,此处 fail-fast)
|
||||
if total_instances > EnemyTable.ROWSET_INSTANCE_MAX:
|
||||
@@ -99,11 +115,24 @@ func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_overrides
|
||||
"is_hero": false,
|
||||
})
|
||||
handle += 1
|
||||
_spawned = true
|
||||
_despawned = false
|
||||
return true
|
||||
|
||||
|
||||
## 逐行数量定值(敌人系统 零随机纪律——骰定在 战斗结算 遭遇骰层按行完成,本层收确定值;
|
||||
## 行 i 数量 = overrides[i](≥1 时)否则该行 unit_count 行值)。越域行 = 空数组(受理拒绝信号)
|
||||
func _row_instance_counts(rowset: Array, unit_count_overrides: Array) -> Array[int]:
|
||||
var per_row_counts: Array[int] = []
|
||||
for row_i in range(rowset.size()):
|
||||
var row_i_dict: Dictionary[Variant, Variant] = rowset[row_i]
|
||||
var ovr: int = int(unit_count_overrides[row_i]) if row_i < unit_count_overrides.size() else -1
|
||||
var count: int = ovr if ovr >= 1 else int(row_i_dict.unit_count)
|
||||
if count < EnemyTable.UNIT_COUNT_MIN or count > EnemyTable.UNIT_COUNT_MAX:
|
||||
push_warning("[敌人系统] 行 %d 实例化数量越域(单种数域 [%d,%d]): %d" % [row_i, EnemyTable.UNIT_COUNT_MIN, EnemyTable.UNIT_COUNT_MAX, count])
|
||||
return []
|
||||
per_row_counts.append(count)
|
||||
return per_row_counts
|
||||
|
||||
|
||||
# 实例池快照(proposal §2.2:开战把模板快照一份,冷却全零——与"生成拿到当时的表值快照"同一条
|
||||
# 快照纪律。触发条件:技能行 trigger 是字段权威——快照随读;带 latch 行写单向闩标记
|
||||
# trigger_latched 初始锁定;缺省无 trigger=无条件技)
|
||||
|
||||
Reference in new issue
Block a user