Files
gplan-2/game/core/skill_lottery.gd
T

29 lines
1.7 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VERTICAL SLICE - NOT FOR PRODUCTION
# Validation Question: 玩家能否无指导在一场完整战斗中经历「开战→挖掘规划→轮末结算逐行兑现→胜/负」并逐行归因(P2)
# Date: 2026-09-16
# 敌人系统·技能摇号器(proposal-skill-pool D9 封装纪律):独立服务类——输入 实例池可摇条目 + 随机子流,
# 输出 skill_id。权重份额归一:中签率 = 该技能权重 ÷ 可摇权重合计(排除谁,谁的份额按比例摊给其余技能)。
# 不碰血量、不碰表、不碰容器——过滤与冷却状态由调用方(战斗结算换算层)注入确定值。
# 零随机纪律:随机消费只在子流参数(behavior_roll 派生流),本类无自建随机源。
# 实现 GDD:design/gdd/systems/战斗循环/敌人系统.md(registry 追溯锚,命名规范见 CLAUDE.md)
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 恒有落点)