按 code-conventions §1.4.1 第三轮定稿执行:core 22+schemas 18+presentation 根 14+views 28,全部头注 #→##、删日期/变更叙事/GDD 与架构反向链接/字段与域清单/机制描述,保留职责摘要+真实使用约束(防事故禁令/单一入口/信号契约每信号一行)。main.gd 31→5 行、save_manager 45→5 行、adventure_runner 37→5 行为最大单件。子代理分模块执行(波一 core+schemas、波二 presentation+views,并发≤2)。验收=tools/verify_comment_only_change.py 逐字节校验(82 文件头注区外逐行一致=零行为变更)+audit_file_headers 全绿;纯注释批免冒烟(先例 5843270)
24 lines
1.2 KiB
GDScript
24 lines
1.2 KiB
GDScript
## VERTICAL SLICE - NOT FOR PRODUCTION
|
|
## 敌人技能摇号器:可摇条目+随机子流 → skill_id,权重份额归一(垂直切片验证:敌方行动可归因)。
|
|
## 不碰血量/表/容器——过滤与冷却由调用方注入确定值;随机只消费传入子流,本类零自建随机源。
|
|
class_name SkillLottery
|
|
extends RefCounted
|
|
|
|
|
|
# 权重摇号(整数份额,行序累计走查——同份额前行优先,确定性);entries = [{skill_id, weight}](非空)
|
|
static func draw(entries: Array, stream: RandomNumberGenerator) -> String:
|
|
assert(not entries.is_empty(), "[技能摇号] 空可摇集合(普攻冷却恒 0 → 池恒非空——结构违例即致命)")
|
|
var total := 0
|
|
for e in entries:
|
|
var w: int = int(e.get("weight", 0))
|
|
assert(w > 0, "[技能摇号] 池条目权重须 > 0: %s" % str(e))
|
|
total += w
|
|
assert(total > 0, "[技能摇号] 可摇权重合计为 0")
|
|
var r: int = stream.randi_range(1, total)
|
|
var acc := 0
|
|
for e in entries:
|
|
acc += int(e.weight)
|
|
if r <= acc:
|
|
return String(e.skill_id)
|
|
return String(entries[entries.size() - 1].skill_id) # 数值防御分支(不可达——r ≤ total 恒有落点)
|