跳转到内容

决策脚本与运行环境

脚本用 Lua 编写,是模块的决策核心。新建模块不带任何脚本,需要你自己写:在编辑器里双击一行 Lua 打开编辑器,给它起个名字并写入代码。

脚本每次触发就从头完整跑一遍,不要在脚本里写死循环。「循环」来自外层:只要你按住启动键(按键模式)或开着开关(开关模式),程序就按 APM 节奏每轮调用一次你的脚本。所以脚本只需写「这一刻该做什么」的判断,为真就发一次宏、为假就什么都不做,下一轮再来。

函数 用途
Prop(name) 读某个属性的当前值(数字)。名字必须与属性表里的一致,否则本轮脚本报错中断。
Macro(slotOrName) 按序号或名称调用宏。返回是否提交发键;未就绪、同步不完整或帧失效返回 false,并不代表施法结果。
Cast(name) 兼容原宏名称调用,也能解析已同步的动态名称;返回 nil。新代码推荐使用 Macro(序号或名称),可读取是否已提交发键。
Select(index) 选择目标,等价 Cast("SelectTarget"..index):1=自己、2-5=小队 1-4、6-45=团队 1-40。
CoolDown(name, ms) 节流闸门:距上次调用满 ms 毫秒才返回 true 并重置。用来限制某个动作的触发频率。
SetTimeOut(name, ms)
GetTimeOut(name)
设置 / 查询一个定时点:ms 毫秒后到期,GetTimeOut 返回是否已到期。
Sleep(ms) 阻塞等待若干毫秒(会卡住执行线程,一般用 CoolDown 代替)。
PressKey(code, [ms]) 直接向游戏发送一个虚拟键码,可选按住时长。

此外可使用 Lua 标准库(math / string / table 等)。

下面是一段示例脚本(需你按自己的属性名与宏名改写)。它每轮判断一次,用 CoolDown 避免每 tick 都触发:

-- 目标可攻击才输出
if Prop("目标可攻击") == 1 then
-- 血量低于 50% 且距上次补盾满 1.5 秒,补一次
if Prop("生命百分比") < 0.5 and CoolDown("补盾", 1500) then
Cast("治疗术")
-- 连击点满 5,放终结技
elseif Prop("连击点") >= 5 then
Cast("终结技")
else
Cast("主输出")
end
end

Prop("生命百分比") 是预置属性、返回 0~1 的小数;Prop("连击点") 返回原始点数。Cast 里的名字要与你宏表中的宏名对应。

写好并命名脚本后,在主设置里把一个启动键(鼠标侧键或指定键盘键)绑定到这个脚本名。之后按住启动键(按键模式)或按一下(开关模式),程序就会按 APM 节奏反复执行它。

每个自定义属性的代码会被包成一个无参函数,与游戏端插件同处一个 Lua 作用域。生成后的形态如下(首行重新遮蔽了几个战斗数值函数,让你能拿到未处理的原始值;次行是参数注入):

SuperDPS.CustomFunc["属性名"] = function()
local UnitHealth, UnitHealthMax, UnitPower, UnitPowerMax =
SuperDPS.RawUnitHealth, SuperDPS.RawUnitHealthMax,
SuperDPS.RawUnitPower, SuperDPS.RawUnitPowerMax
local arg1, arg2, arg3 = "player", nil, nil -- 由「参数」列注入
-- 你的代码从这里开始,必须 return 一个值
return UnitHealth(arg1)
end

代码必须 return 一个值(数字或布尔)。布尔会以 1 / 0 回传;返回 nil 或运行出错都按 0 处理,且同一错误只在聊天框提示一次。因为与插件同作用域,你可以直接调用下面这些兼容层函数。

GetSpellInfo(spell) GetSpellCooldown(spell) GetSpellCharges(id)
UnitAura(unit,i,filter) UnitBuff(unit,i) UnitDebuff(unit,i)
issecret(v) -- 判断是否为受保护值
接口 用途
SuperDPS.GetUnitBuff(unit, aura)
SuperDPS.GetUnitDebuff(unit, aura)
SuperDPS.GetUnitAura(unit, aura, filter)
查询光环。aura 可用法术 ID 或名称。返回 15 个值:name, icon, count, dispelType, duration, expirationTime, source, ...。其中 count / duration / expirationTime 已做消毒处理。Buff/Debuff 无 filter 参数。
SuperDPS.SN(v, "标记") 消毒器:把受保护值或 nil 归 0,让它能参与比较/运算。需要计算前先经它处理。
SuperDPS.RawUnitHealth 等 4 个 Raw 原始(未归零)的血量/能量函数。自定义代码里 UnitHealth 等名字已被指向它们。
SuperDPS.HekeliPrimary Hekili 当前首个推荐技能的 ID(字段,非函数);未装 Hekili 时为 0。
SuperDPS.IsMidnight / SuperDPS.CleuAvailable
SuperDPS.IsClassic()
契约存根,取值恒定、不随客户端变化:前两个是布尔字段(分别恒 true / false),IsClassic() 是函数、恒返回 false。正式服与怀旧服共用同一套代码,所以这三个不能用来判断客户端——要区分请直接探测接口是否存在,例如 if C_AssistedCombat then。

正式服把部分战斗数值设为受保护值。判断一律以 issecret(v) 为准——注意 print() 能正常显示受保护值,「肉眼看到数字」不代表能运算。对受保护值的规则:

允许 禁止
直接 return、传参、字符串拼接、string.format / tostring、以及对非布尔值做 X or 0 / if not X 的真值判断 算术、比较(> == 等)、对布尔做真值判断、取长度、作表的键、索引访问、当函数调用

据此归纳出三档姿势:

  • 直传档:只需把值取回、不做运算。直接 return 即可,例如 return UnitHealth(arg1)。
  • 消毒档:需要比较或计算时,先经 SuperDPS.SN(v, "标记") 归零再算。
  • 只有确认不是受保护值时才进行比较、运算或索引。推荐技能 ID 也建议先用 SuperDPS.SN 处理,并检查类型与范围。