ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PathOfBuilding Mod 语法完全指南:从 `mod()` 函数到 Extra Tags 的源码级解析

PathOfBuilding Mod 语法完全指南:从 `mod()` 函数到 Extra Tags 的源码级解析 PathOfBuilding Mod 语法完全指南从mod()函数到 Extra Tags 的源码级解析【免费下载链接】PathOfBuildingOffline build planner for Path of Exile.项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding本文基于 docs/modSyntax.md 展开系统讲解 Path of BuildingPoB中贯穿全代码库的 Mod 修饰符语法。该语法同时存在于物品、天赋树、珠宝、技能等多个数据源中理解它即可看懂、编写和调试 PoB 中的任何属性修饰。读完本文你将掌握mod()的七个参数、六大 ModType 的语义、位运算标志ModFlag / KeywordFlag的组合规则以及全部 Extra Tag 类型的参数用法并能结合源码定位具体实现。语法总览一段 Mod 的完整生命周期PoB 的核心工作是把游戏内的一条词缀文本翻译成内部可计算的修饰符结构。整个代码库中大量使用同一种 Mod 语法但绝大多数 Mod 集中在两个位置物品与通用修饰解析逻辑在 src/Modules/ModParser.lua技能数据映射表在 src/Data/SkillStatMap.lua。在 ModParser 中一个 Mod 的标准格式是mod(ModName, ModType, Value, source, modFlags, keywordFlags, extraTags)对应的函数声明位于 src/Modules/ModTools.lua#L20-L46即modLib.createMod。从源码的overload注解可以看到source、modFlags、keywordFlags三个参数会根据传入值的类型被自动识别第一个字符串参数被当作source后续的数字参数依次被当作flags和keywordFlags剩余参数全部并入 Extra Tags见 ModTools.lua#L33-L67 的实现。这意味着你完全可以省略其中的若干参数让 Lua 的类型判断替你填充。对于技能而言格式被简化了。makeSkillModsrc/Modules/Data.lua#L52-L67去掉了source参数因为在processModsrc/Modules/Data.lua#L68-L72中会自动以mod.source grantedEffect.modSource的方式从宝石数据补上来源。ModName全局索引键ModName是整个 Mod 的键用于在 PoB 内部引用这条 Mod。它的取值可以是任意字符串但实践中应当复用代码库中已有的名称例如Damage—— 伤害Life—— 生命PhysicalDamageGainAsLightning—— 物理伤害转化为闪电伤害编写新 Mod 前先搜索代码库中是否已存在你要用的名字避免重复造轮子。ModType六种计算语义ModType决定数值如何参与结算是 Mod 语法中最关键的部分类型语义说明BASE基础值与其他基础值相加如附加伤害、平坦生命、平坦闪避INC增/减加法叠加负值表示reduced减少MORE更多/更少乘法叠加负值表示less更少OVERRIDE覆盖忽略其他任何计算直接采用该值例如 Loreweave 的你的抗性为 78%FLAG条件开关值为true/false用于表达条件是否成立MAX/MIN取最大/最小多个来源同时存在时只取最高值或最低值生效MAX/MIN的典型例子是ImprovedMinionDamageAppliesToPlayer召唤物伤害的增/减按 X% 作用于你以及PoisonStackLimit无法对已叠加至少 X 层中毒的敌人施毒。有趣的是ModTools 的alias NumericModTypesModTools.lua#L23还额外列出了CHANCE、DUMMY等内部类型说明数值类型家族比文档列举的更广但对外作者通常只用上述几种核心语义。关于 FLAG 的便捷函数当你要使用FLAG类型时官方建议优先使用flag()函数它缩短代码并让意图更清晰。例如-- 写法一完整 mod() 调用 mod(ZealotsOath, FLAG, true, { type Condition, var UsingFlask }) -- 写法二flag() 便捷函数效果完全相同 flag(ZealotsOath, { type Condition, var UsingFlask })在技能映射表 SkillStatMap.lua 中flag()被大量使用例如flag(CannotMultiplePoison)、flag(BloodMagicReserved)、flag(Condition:NonPoisonedOnly)等。Value数值或 nilValue是 Mod 的原始数值。在技能映射表中这个值通常是nil因为实际数值会根据宝石等级从 gem 数据中动态提取。例如 SkillStatMap.lua#L491-L497 中的吸血类词缀全部写成mod(Damage, INC, nil, 0, 0, { type Condition, var LeechingLife })数值留空交给引擎在运行时计算。SourceMod 的来源Source记录这条 Mod 从何而来。绝大多数情况下它会由系统自动填充——来自天赋节点、宝石或物品。如果你确实需要手动指定它是一个字符串且可以使用特殊值Tree:[nodeId]这样在悬停时会在工具提示中显示天赋树的局部插图。ModFlags位运算标志能作用于什么ModFlags是位标志bitwise flags描述这条 Mod 可以作用于哪些对象。完整列表见 src/Data/Global.lua#L102-L133 中的ModFlag表其组织方式非常清晰伤害模式Attack(0x1)、Spell(0x2)、Hit(0x4)、Dot(0x8)、Cast(0x10)伤害来源Melee(0x100)、Area(0x200)、Projectile(0x400)、Ailment(0x800)武器类型Axe(0x10000)、Bow、Claw、Dagger、Mace、Staff、Sword、Wand、Unarmed、Fishing武器类别WeaponMelee、WeaponRanged、Weapon1H、Weapon2H及掩码WeaponMask(0x2FFF0000)。组合多个标志时使用bit.borModParser.lua 中直接别名成了bor。当多个 ModFlag 组合时要求全部匹配AND 逻辑如果只需要其中一个匹配应改用 Extra Tag 中的ModFlagOr。KeywordFlags关键字位标志与技能关键字匹配KeywordFlags与 ModFlag 类似但使用的是 Global.lua#L135-L171 中的KeywordFlag组通常基于宝石自身的技能关键字Aura、Curse、Warcry、Movement、Physical、Fire、Cold、Lightning、Chaos、Vaal、Bow、Trap、Mine、Totem、Minion、Attack、Spell、Hit、Brand、Poison、Bleed、Ignite 以及各类 DoT 标志。关键差异在于匹配逻辑相反组合多个 KeywordFlag 时只要其中一个匹配即可OR 逻辑如果需要全部匹配使用 Extra Tag 中的KeywordFlagAnd。实际上Global.lua 在源码层面还内置了KeywordFlag.MatchAll(0x40000000) 标志与MatchKeywordFlags缓存函数Global.lua#L189-L214配合两级数字缓存对高频比较做了性能优化——这印证了关键字匹配是 PoB 结算热路径上的重要操作。Extra Tags条件与高级行为Extra Tags 往往决定这条 Mod 在什么条件下才生效要不要按某个属性重复计算等。语法高度依赖第一个参数type数量不限可以多个同时叠加。部分参数如actor、neg可用于所有类型。以下是全部类型详解Condition —— 玩家条件要求玩家满足特定条件后 Mod 才生效例如 CritRecently、Shocked。var条件名称neg默认false布尔值取反条件。要设置条件本身请用Condition:[name]作为 FLAG Mod。例如mod(Damage, INC, 10, { type Condition, var LeechingLife })ActorCondition —— 敌人或召唤物条件作用于敌人或召唤物上的条件比 Condition 多了actor参数。var条件名称neg默认false布尔取反actor取值enemy或parent。parent用于给召唤物赋予基于玩家其控制者条件的 Mod。官方示例——当玩家拥有物理魔像时魔像获得伤害增幅mod(MinionModifier, LIST, { mod mod(Damage, INC, num, { type ActorCondition, actor parent, var HavePhysicalGolem }) }, { type SkillType, skillType SkillType.Golem })Multiplier —— 按变量成倍放大将 Mod 乘以某个变量通常来自充能球、尸体数等。var要乘的 Mod 名limitMod 能达到的最大值limitTotal默认false布尔值改变limit的行为使其在乘法之后再应用globalLimit即使多个来源叠加Mod 全局能达到的最大值适合最多不超过……的词缀globalLimitKey全局上限的字符串标识相同 key 的 Mod 无法突破 globalLimit。SkillStatMap.lua#L638 的示例mod(Damage, INC, nil, 0, 0, { type Multiplier, var EnduranceCharge })MultiplierThreshold —— 阈值型条件与条件类似但只有变量超过指定阈值后才生效。varMod 名threshold需要达到的数值。PerStat —— 按角色属性计算与 Multiplier 类似但乘的是角色属性力量、敏捷、智慧等而非任意计数。stat要乘的属性名div默认 1计算后除以该数并向下取整适合每 5 点力量这类词缀。示例SkillStatMap.lua#L644-L647mod(Damage, INC, nil, ModFlag.Attack, 0, { type PerStat, stat Armour, div 450 }) mod(Damage, INC, nil, ModFlag.Attack, 0, { type PerStat, stat Evasion, div 450 })StatThreshold —— 属性阈值与 MultiplierThreshold 类似但基于属性值。stat属性名threshold生效前需达到的数值。PercentStat —— 基于其他属性的百分比用于以某属性的百分比计算的 Mod如 Agnostic。stat属性名percent百分比数值。SkillType —— 按技能类型生效作用于所有指定类型的技能。skillTypeGlobal.lua 中的枚举值如SkillType.Golem。SkillName —— 按技能名生效与 SkillType 类似但指定技能名称通常用于附魔enchantments。skillName技能的英文名例如Decoy Totem。GlobalEffect —— 全局效果增益/诅咒主要用于即使不是主技能也能影响其他角色的 Buff 和 Curse。effectType取值Guard、Buff、Debuff、Aura、AuraDebuff、Curse分别作用于你 / 你 / 敌人 / 你召唤物 / 敌人 / 敌人effectName字符串标明全局效果来自哪里effectEnemyCond指定条件满足时 Mod 作用于敌人effectStackVar将该 Mod 乘以一个变量通常是另一个 ModmodCond当角色具有该条件时应用 Modunscalable布尔值决定该增益是否可被增益效果buff effect缩放。在processMod中凡是带GlobalEffect标签的 Mod 会被标记grantedEffect.hasGlobalEffect trueData.lua#L74-L79这决定了该技能是否需要在全局效果池中被追踪。DistanceRamp —— 距离渐变稀有类型用于随角色距离不同而行为变化的技能/效果。ramp不同距离对应的乘数列表。例如ramp {{35,0},{70,1}}表示 35 单位距离时无效果70 单位时达到满值中间线性过渡。ModFlagOr —— ModFlag 或匹配当只需要一个 ModFlag 匹配时使用。官方示例[with axes or swords] { flags ModFlag.Hit, tag { type ModFlagOr, modFlags bor(ModFlag.Axe, ModFlag.Sword) } }上例中要求必须有Hit但武器可以是斧或剑中的任意一个。modFlags像正常添加 ModFlag 一样使用bor。KeywordFlagAnd —— KeywordFlag 与匹配当需要全部 KeywordFlag 都匹配时使用。keywordFlags像正常添加 KeywordFlag 一样使用bor。从文本到结构ModParser 如何解析游戏词缀理解了内部结构后再回头看 ModParser 的前端解析逻辑会更有全局感。formListModParser.lua#L72-L158用一组正则把游戏原文词缀翻译成内部类型[^(%d)%% increased] INC, [^(%d)%% reduced] RED, [^(%d)%% more] MORE, [^(%d)%% less] LESS, [^([%%-][%d%.])%%?] BASE, [^you have ] FLAG, [is (%-?%d)%%? ] OVERRIDE,也就是说12% increased Damage 会先被识别为INC类再查表映射到Damage这个 ModName最终拼装成mod(Damage, INC, 12, ...)结构。解析入口modParser.parseModModParser.lua#L7000-L7019带有内存缓存并对无法识别的词缀形态进行去重统计便于开发者发现未知词缀。实战如何正确书写一条 Mod结合以上全部内容一条合格的 Mod 应当依次确认ModName先在代码库中检索是否已有同名 Mod优先复用ModType根据计算语义选择 BASE / INC / MORE / OVERRIDE / FLAG / MAX / MINValue固定数值直接填技能映射场景填nilSource通常省略交给系统需要手动指定时用字符串天赋节点用Tree:[nodeId]ModFlags用bor()组合全部匹配只需其一则改ModFlagOrKeywordFlags同样用bor()组合任一匹配需全部匹配则改KeywordFlagAndExtra Tags按需叠加type决定语义其余参数随类型而定。例如一条每 450 点护甲使攻击伤害提高 1%的 Mod 写作mod(Damage, INC, nil, ModFlag.Attack, 0, { type PerStat, stat Armour, div 450 })它同时展示了三个要点技能场景数值为nil、用ModFlag.Attack限定仅作用于攻击、用PerStat表达按护甲缩放。对照 src/Data/SkillStatMap.lua、src/Data/Global.lua 与 src/Modules/ModParser.lua 即可逐条验证每部分语义这套语法也是理解 PoB 全部数据文件物品、天赋、珠宝、技能的通用钥匙。【免费下载链接】PathOfBuildingOffline build planner for Path of Exile.项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表