英雄升级技能生成机制
随机数取值
上古纪元技能使用的随机数生成是C# 标准库的 System.Random,是伪随机,通过确定的算法 + 初始种子值(大概率就是随机地图的生成随机种子),计算出来的一系列看似随机的数字。
至于种子是什么其实并不重要,正常玩的时候人脑不可能去模拟计算这个生成,只需要知道这个算法是线性同余生成器,根据公式由上一个种子生成下一个种子。所以我们只需要知道有哪些行为使用了 System.Random,会导致随机数有变化,也就是 S/L 之后哪些行为会使出现的技能池出现变化。有且不止如下:
- 战斗时的伤害值计算;
- 起魔法行会时送的随机魔法的计算;
- 招募新英雄后,酒馆英雄池刷新;
- 另一个英雄升级时英雄技能选择的计算;
- 新一周随机周种类;宝物商店刷新;
技能池分类
相关机制代码:传送门,以下总结的底稿是把源代码文件直接扔给AI总结而成。
游戏内置多层级技能池,按以下优先级排列:
- 特殊技能池(specialSkillsChances):稀有技能,特定条件下出现;
- 默认技能池(defaultSkillsChances):当前等级可学习的常规技能;
- 保留技能池(reserveSkillsChances):保底技能,防止无技能可选;
- 伪技能池(pseudoSkillsChances):增加英雄的主要属性,确保选项不空缺;
- 已开放技能池(openedSkillsChances):英雄已学习但未满级的技能;
特殊技能池
定义文件在Core.zip/heroes_skills\skills_by_level_tables\下:
- 在英雄等级为 4 的倍数时,技能池为四个魔法系的主技能能,权重比例等同于其默认权重;
- 在英雄等级为 5 的倍数时,技能池为种族技能和魔武专属技能,权重均为 100;
- 在英雄等级为 20 级时,技能池为四系魔法、种族技能和魔武专属技能,四系魔法为双倍权重,种族技能和专属技能为 100 权重;
某些英雄会在 2/4/6 级时,对初始自带技能中不是种族技能的那个有 500/1000 的权重变化。定义文件在Core.zip/heroes_skills\skills_by_level_replace_tables\下:
注:该文件配置的权重只影响英雄已学技能在升级时权重,将其改为其它未学技能并不会影响该技能在出新技能时的权重;而且本身英雄第二初始技能的升级就比较容易,所以实际上影响很小。
相关英雄列表
- ============ 圣殿 ============
- 尊贵的艾欧丝 — Aeos the Exalted
- 快乐的伊莱亚斯 — Merry Elias
- 无拘者莉亚 — Lia the Untethered One
- ============ 墓园 ============
- 布沃克 — Bulwark
- 麦格 — Mag
- 影纺者乌娜 — Shadespinner Oona
- ============ 裂渊 ============
- 黑角 — Blackhorn
- 苍白玛塔斯塔拉 — Matastala the White
- 沃卡 — Walkha
- 变形怪乌尔戈 — Changeling Urgo
- 叛徒格雷列克 — Grellekh the Betrayer
- 冰后赫尔嘉特 — Icequeen Hel'Ghat
- ============ 森林 ============
- 戈雷尔·矛头 — Gorel Spearhead
- 奥克塔维亚 — Octavia
- 瓦塔娜 — Vatawna
- 苏莉 — Sullie
- 吟游诗人 — The Minstrel
- ============ 虫巢 ============
- 妮耶芙 — Niev
- 塔维 — Tavi
- 金舌 — Goldentongue
- 战斗公爵阿比戈尔 — Abigor, Duke of Battle
- 希尔 — Xirr
- 卡瑞瑟斯 — Khariseth
- ============ 地牢 ============
- 瑞亚 — Rhea
- 灰白格利尔德 — Gleard the Grey
- 伟大的扎克伦 — Zakron the Great
- 光芒洛克托尔 — Sunny Rauktol
- 洛多斯 — Lodos
默认技能池和保留技能池
定义文件在Core.zip/heroes_skills\skills_by_level_tables\下:
数值即为英雄职业页面列出的数据。默认技能池和保留技能池其实列表和数值是完全一样的。在竞技场模式中,非战斗的技能会被移除:
- skill_mastery — Wisdom — 智能 — 智慧术;
- skill_mastery — Intelligence — 智能 — 通智术;
- skill_enlightenment — Insight — 洞察 — 启迪术;
- skill_diplomacy — Diplomacy — 外交 — 外交术;
- skill_logistic — Logistics — 后勤 — 后勤术;
- skill_scouting — Scouting — 侦察 — 侦察术;
- skill_economy — Economy — 经济 — 理财术;
- skill_siege — Siegecraft — 围攻 — 攻城术;
- skill_trainer — Recruitment — 招募 — 募兵术;
伪技能池
定义文件在Core.zip/heroes_skills\skills_by_level_tables\下:
随机增加 1/2/3 点英雄的一项主要属性,对应的权重分别是 50000/500/5;
状态评估
在每次升级时,系统会实时评估英雄的以下状态指标:
- 技能数量状态:当前已学习技能总数(最大为 8 个);判断是否达到技能上限,影响新技能的获取优先级;
- 技能等级状态:未满级技能数量(nonMasterSkillsCount);是否所有技能都已达到最大等级(haveAllSkillsMaxLevel)
- 技能类型分析:新技能(英雄尚未学习);可升级技能(已学习但未满级);伪技能(特殊占位技能);
- 动态权重调整:系统通过精细的权重管理确保技能生成的合理性;
- 排除机制:已学习的技能会从各技能池中暂时移除;
- 优先级覆盖:特殊英雄可以覆盖默认权重配置;基于英雄职业和特性定制化技能出现概率;
详细生成流程
阶段一:预处理与初始化
配置加载:系统首先根据英雄的职业类型(configSid)和技能变体(skillsRollVariant)加载对应的权重配置文件。特殊英雄可能拥有独特的替换配置(replaceSet),这会改变默认的技能出现概率。
状态检测:
- 检测是否为完全刷新(_refreshAll)还是部分刷新
- 验证现有技能选项的有效性
- 初始化三个槽位的刷新标记
阶段二:槽位顺序处理
系统采用非顺序处理策略,按 1→3→2 的顺序生成技能,避免选项间的冲突,确保逻辑合理性。
第一槽位生成逻辑:
- 情景一:技能栏未满(少于 8 个技能),优先获取新技能,按默认池→保留池→伪技能池的顺序选择;
- 情景二:技能栏已满且至少有3个未满级技能,专注现有技能升级,从已开放技能池中选择可升级技能;
- 情景三:其他情况,选择伪技能作为保底,确保始终有可选内容;
第三槽位生成逻辑:
- 情景一:存在未满级技能,优先升级现有技能
- 情景二:全技能满级但技能栏未满,获取新技能
- 情景三:技能已满且全满级,选择伪技能
第二槽位生成逻辑:
- 情景一:技能栏未满,优先尝试特殊技能池(提供稀有选择),备选策略 — 50%概率新技能 / 50%概率升级;
- 情景二:技能栏已满且有≥2个未满级技能,专注升级;
- 情景三:其他情况,伪技能保底
阶段三:权重随机算法
系统的随机选择采用经典的权重累加算法,这种算法确保了高权重技能有更高出现概率,即使低概率技能也有机会出现,分布符合数学期望,避免极端情况。
public string Roll(Random _random) {
int totalWeight = 0;
foreach (var skill in skillPool) {
totalWeight += skill.Weight; // 计算总权重
}
int randomValue = _random.Next(0, totalWeight);
int currentWeight = 0;
// 反向遍历确保权重分布正确
for (int i = skillPool.Count - 1; i >= 0; i--) {
currentWeight += skillPool[i].Weight;
if (currentWeight > randomValue) {
return skillPool[i].SkillId;
}
}
}
其它机制
- 技能有效性验证:每个技能在放入槽位前都需通过严格的有效性检查;验证标准包括技能是否已被英雄学习、技能当前等级与最大等级关系、槽位特定的功能要求、英雄整体技能结构平衡性;
- 动态排除机制:已选技能会从后续选择中实时排除 — NullifyChanceForSkill(skillPool, selectedSkillId);