天网

天网

正在开发一个更智能的战斗AI,它将学习适应玩家的游戏风格。

我做了这个模组,和我的其他模组不同,这个模组我真的是费了很大功夫才最终让它跑起来。我整整尝试了两次才成功,第一次做出来之后,又经过好几天的努力,不得不推翻一切从头再来,现在终于能用了。

还不算完全完成,但已经能正常工作了。

据我所知,目前总共也就那么几个敌人AI模组,而它们普遍都变成了“攻击倒地队友”或者“攻击等级最低者”这种模式。说实话,这既无聊、又偷懒、还重复,根本算不上智能,最糟糕的是,这往往还会弄坏一堆有剧情脚本的战斗,让敌人的行为变得不合逻辑。

所以我想一步一步地解释这个模组是如何运作的:

  • 从一场战斗的开始到结束,会有一个持续运行的评估脉冲,它不停歇地检查每个敌人拥有的所有法术(顺便说一句,法术也包括普通攻击这类常规动作,因为在BG3内部,一切本质上都算作法术)。以下是它评估所有法术时会考虑的所有因素:

属性缓存 - isRanged, isMelee, isAoE, canTargetObjects, canTargetTerrain, ignoresVisionBlock, rangeMeters

派生属性 - isRanged, isMelee, isAoE, canTargetObjects, canTargetTerrain, ignoresVisionBlock, rangeMeters

多层分类引擎 - 将任何法术分类为:伤害、控制、辅助、自我增益、机动、召唤、变形、范围、单体:

第1层:游戏数据 — VerbalIntent + SpellType + SpellSchool + SpellFlags 第2层:名称模式识别 — 约120个伤害关键词,约50个控制关键词,约50个自我增益关键词,约15个机动关键词,约15个召唤关键词,约8个变形关键词

元素分类 - 根据法术名称识别:火焰/寒冷/闪电/毒素/力场/死灵/物理/其他

风格分类 — 根据法术名称识别:召唤/治疗/控制/专注/伤害

我做了所有这些,并在这里提及,是为了让你理解;因为从模组的标题你大概也能猜到,我想做一个真正理解法术实际作用的战斗AI,就像你(我假设正在阅读这段文字的是一个人类)在阅读法术和法术描述时能理解它们的用途一样,尤其是对于模组添加的、没有原版游戏参考依据的法术。(我稍后会再回到关于模组添加法术的话题上)

  • 与此同时,还有一个持续运行的环境感知模块:

  • 3D距离 — 欧几里得距离,带三级位置回退链(Ext.Entity → 备用实体 → Osi.GetPosition)

  • 水平距离 — 仅XZ平面(忽略高度),用于高地范围回退(无法直接控制位于玩家上方的敌人,因此在这种情况下会回退到原版AI,这在那些情况下似乎就足够了)

  • 视线 — 每个敌人实际能看到的东西。

  • 高地检测 — Y坐标差 > 1.5单位(约5英尺)

  • 地表检测 — 扫描危险地表:火焰、酸液、毒素、雷电、地狱火、蛛网、油 + 模组地表(因为我玩那些模组,还会检测血怒、灵质)

  • 障碍物检测 — 墙壁和门(需要扩展这个功能),并且专门扫描我的力场护盾,因为那是一个实际的物理力场。

  • 目标可达性 — 结合视线 + 距离与法术范围 + 针对远程法术的高地水平回退。

然后是角色情境评估:

  • 角色快照 — UUID、名称、等级、位置、职业、被动、状态、法术、关键威胁(潜行/游荡者侦测)
  • 玩家队伍分析 — 快照所有玩家角色
  • 战场情境 — 高地玩家、敌方聚集情况、玩家平均高度
  • 玩家威胁分析 — 专注状态、潜行多的队伍、低感知、近期控制法术、危险被动(游荡者/潜行/战士/圣骑士/至圣斩)
  • 敌方能力 — 基于属性的强度、法书中的跳跃/飞行、移动速度。
  • 友方/敌方数量 — 判定寡不敌众还是以多打少

然后它会记录你在游戏中经历的每一场战斗并从中学习(战斗日志存储在 AppData\Local\Larian Studios\Baldur's Gate 3\Script Extender\Skynet),将玩家档案保存到 player_profile.json

  • 跨战斗追踪 — 保存到 Skynet/player_profile.json
  • 法术频率 — 玩家最常使用的法术
  • 元素偏好 — 玩家最喜欢的伤害类型
  • 风格追踪 — 近战/远程/召唤/施法/治疗/控制的倾向
  • 主导元素/风格 — 根据使用次数自动检测
  • 反制推荐引擎 — 将玩家风格映射到反制策略:
    • 玩家近战 → 控制(控住他们)
    • 玩家远程 → 激进(拉近距离)
    • 玩家召唤 → 范围伤害(清理召唤物)
    • 玩家施法 → 控制(打断专注)
    • 玩家治疗 → 激进(爆发伤害)
    • 玩家控制 → 激进(在控制技放出前施压)
  • 置信度门控 — 需要 ≥2场战斗 + ≥3次某类别动作;完整反制需0.5置信度,部分反制需0.3
  • 元素切换 — 如果玩家对敌方的专精元素有抗性/免疫,则避开该元素
  • 档案更新 在战斗结束时 + 战斗中每3轮更新一次

然后它会对敌人可用的法术进行评分:

  • 基础伤害、范围伤害潜力、单体伤害
  • 控制 vs 正在专注的玩家、反刷控制、控制 vs 群体
  • 自我增益(视情况:拉近距离时+4,否则-10)
  • 机动性(存在危险/障碍物:+8,已经绕开:-8,地形开阔:-5)
  • 召唤、变形加成
  • 协同加成(征服/光环 + 控制,圣骑士 + 至圣斩,法师 + 伤害)
  • 潜行反制(对潜行多的队伍 +9,使用看破/真实/致盲类法术)
  • 打断专注(对专注中的玩家 +5)
  • 高地惩罚(对高地上的玩家 +3)
  • 范围聚集加成(玩家聚集时 +6)
  • 重复规避(本场战斗每次先前使用 -3)
  • 混合偏向(伤害+控制法术 +2)
  • 无可达目标惩罚(-25)
  • 可达目标加成(+5),范围匹配加成(+4)
  • 范围聚集加成(范围内每多一个玩家 +5)
  • 近战距离过远惩罚(-15),远程距离合适加成(+4)
  • 危险区域惩罚/加成(近战在危险区域:-12,远程在危险区域:+6)
  • 障碍物评分(力场/巫术箭 vs 力场护盾:+12,火焰/力场 vs 墙壁:+5)
  • 基于玩家档案的反制加成

其目标选择方面,威胁检测比单纯的“最佳目标 vs 最近目标”更彻底:

  • 最佳目标选择器 — 根据距离 + 范围聚集 + 可达性为每个玩家评分;近战强烈偏好近距离目标,远程对此不太敏感
  • 最近玩家查找器 — 通过3D距离返回最近的存活玩家

有时候,当Skynet将控制权交还给原版游戏AI时,它仍会根据自身的判断向原版AI推荐行为原型(总共推荐19条潜在路径):

  • 紧急低生命值 → 治疗或防御
  • 队友需要治疗 → 治疗者
  • 寡不敌众 → 召唤/控制/防御
  • 有召唤物 → 召唤者
  • 力场护盾激活 → 激进/控制/防御
  • 地表阻挡 → 防御
  • 潜行玩家 → 范围伤害/控制/激进
  • 低地 → 防御
  • 高地 → 防御(远程 + 伤害)
  • 聚集玩家 → 范围伤害
  • 玩家在专注 → 控制
  • 元素专精(火焰+寒冷+寒冷/闪电+近身/力场+力场护盾)
  • 基于档案的反制
  • 一般控制
  • 以多打少 + 近身 → 激进
  • 高伤害 → 激进/防御
  • 近战多 + 近身 → 激进
  • 默认 → 防御

但我想澄清的是,在大多数战斗的大多数时候,Skynet都处于控制状态,它会持续压制原版游戏AI,所以一切(包括敌人移动或重新站位)都由Skynet处理。

对于移动,它会考虑:

  • 危险感知移动 — 扫描路径上的火焰/酸液/毒素等危险地表;通过扩展环形搜索(8个方向,最远6米半径)找到安全的替代路线
  • 路径危险扫描 — 沿移动路径按间隔采样点,检查每个点是否有危险
  • 安全位置查找 — 从目标位置进行扩展环形搜索
  • 部分移动 — 如果不存在完全安全的完整路径,则在危险区域前尽可能安全地移动
  • 免费重新定位 — 当法术距离仅差一点超出水平范围或近战范围时,使用不消耗动作的移动来接近3-4米
  • 机动法术分类 — 冲刺/奔跑/传送/飞行/迷雾/位移/加速视为机动;跳跃/腾跃视为跳跃(因边缘bug而排除)

所以不再会有敌人穿过火海来攻击玩家的情况了。

边界情况和安全措施

我为Skynet考虑了一些边界情况,让它不去处理或做好防范,具体如下:

  • UUID解析 — 多方法解析(这是为了将来某些重要NPC因Skynet控制而出错时准备的)
  • 重复法术规避 — 本场战斗每次先前使用 -3
  • 可见目标检查 — 如果敌人对任何玩家都没有视线,则交还给基础AI(原版AI处理隐藏/隐形队员已经足够好了)
  • 绝望回退 — 如果没有任何法术够得着任何玩家且没有机动能力,则不顾可达性对所有法术进行评分(恐慌模式!!)
  • 友方/敌方分析 — 寡不敌众触发防御/召唤;以多打少触发激进

兼容性

我目前为BG3安装了1241个模组,有些来自Nexus,有些来自Mod.IO,有些来自其他地方,还有一些是我为本地微调自己做的。但真正厉害的并不是它与所有东西都兼容,不。

真正厉害的是,我终于让通过Absolute Laboratory运作的Cahoot Config在我的模组配置里正常工作了,这全是因为Skynet。

像往常一样,我总在我做的所有模组中提及,它们主要是为我自己制作的,整个过程中最无私的部分就是我决定分享它们,但这次我决定分享这个模组,更多是出于自私(稍后会详述)。

你知道,我玩游戏时喜欢高难度、地狱般的、合理挑战的玩法。BG3并不是那么难,尤其是与原版(试着玩无存档无重载的EET+SCS)相比。所以在做这个模组之前,我尝试玩Cahoot Config,下载了Cahoot在依赖包中提到的每一个依赖,但我游戏会卡到无法玩的程度,有时还会毫无理由地崩溃,而且如果我在Absolute Laboratory完全加载配置后尝试加载另一个存档,它也会崩溃。

所以我放弃那些模组(AL、Cahoot、UNSO等),做了Skynet。在做Skynet时,我尝试为我拥有的每个法术模组中的每个法术制作自己的CX配置,但即使有Skynet,也没达到我期望的效果,而且在尝试让某些特定NPC配合Skynet和那个CX配置变得更聪明时,游戏会崩溃。

然后我给Skynet添加了一个安全功能,即使某个NPC身上挂载了90多个法术(是的,我的配置就这样),也会把它们削减到18个法术。这就是我之前提到的关于敌人及其携带法术的安全功能。

这仍然没能解决我和CX及我的配置之间的问题,但后来我毫无理由地决定再试一次Cahoot,看看会发生什么,结果它竟然出奇地流畅运行了,而且带有Cahoot带来的所有加成,以及敌人法术的额外变体。

战斗真正变成了我享受的挑战,因为Skynet掌控着一切。

所以总而言之,Skynet应该与你拥有的任何模组兼容,只要不是敌人AI模组(Skynet应该会让那些变得多余),不过无论如何还是把它放在加载顺序的最后吧。

未来计划

我确实说过发布这个模组更多是自私而非无私,那么这里就说下核心原因吧。我希望Skynet能成为尽可能强大的AI系统,用于我自己的游戏体验,但我显然无法测试每一种玩法,因为我有自己的风格,而且我知道Skynet会适应并反制我的行为,但我希望其他人也来玩玩看,看是否有人以某种方式玩,而它无法反制。

如果你确实发现Skynet做了什么蠢事,请在帖子区提出来,这样我就可以调整AI以将之纳入考虑,并从涉及这些玩法的风格中学习并加以反制。

除此之外,我确实希望进一步发展Skynet,让它考虑某些其他模组,比如Grit and GloryAdditional Spell Interactions,以及我自己的模组Damage DestructionConsequential Wildshape。此外,如果你有希望AI考虑的其他增加战斗深度的模组,请告诉我。

(在遥远的未来,我也会想让这个模组考虑Brawl,但这要等到很久以后,因为我还想制作自己的Brawl分支版本,因为Tinybike已经没有在开发那个模组了)

依赖

  • Script Extender
  • MCM Menu

建议搭配安装的模组

Damage Destruction

Consequential Wildshape

Grit and Glory

Additional Spell Interactions

Absolute Laboratory + Cahoot Config

Codex of Might & Magic(以后肯定会让Skynet考虑这个)

An Actual Invulnurable Globe

Countdown to Ceremorphosis FIXED