跳转到内容

内置属性实现参考

早期 WA1 的属性下拉内置了近百种预置类型(2026-08 删除,属性系统改为「自定义代码 + 属性库」)。 本文档从历史版本中提取全部旧实现,并按最新版 WA1 调整为可直接粘贴的自定义代码,供模块作者参考。 客户端:正式服(Midnight)与怀旧服都支持、共用一条代码路径。下面的代码按正式服的 API 面与 secret 规则书写——secret 消毒(SuperDPS.SN)在怀旧服是无副作用的空转,照写即可;但正式服独有的接口(如 C_AssistedCombat)在怀旧服取不到值,个别 C_Spell 结构体字段两端也可能不同,搬到怀旧服请先在游戏里验一次。

来源:早期 WA1 版本的属性表与插件查询函数库,2026-08-19 整理。

  1. 模块编辑器 → 属性卡片 → 属性下拉选「自定义代码」(或从属性库选现成条目)。
  2. 点「编辑」粘贴本文档的代码;参数列填逗号分隔的值(最多 3 段),代码里以 arg1/arg2/arg3 读取——纯数字段按数字传入,其余按字符串,空段为 nil。
  3. 代码的 return 值经条码带回传电脑端,与其他属性一致。

同一段代码可被多行属性复用(代码写 arg1,两行参数分别填 player / target)。

属性代码 vs 初始化代码(性能守则)

Section titled “属性代码 vs 初始化代码(性能守则)”
  • 属性代码是高频热路径:每 0.02 秒执行一次、每行属性各执行一次。里面只做读取与必要查询,不要放一次性工作——CreateFrame/RegisterEvent、建共享表、定义共享函数等,即使加了 if not ... 守卫,每帧也在白跑判断,漏写守卫更会每帧泄漏一个帧对象。
  • 一次性工作放模块的「初始化代码」(模块编辑器 → 初始化代码按钮):它在插件加载时执行一次,先于属性注册,与属性代码同环境(同 chunk,可用兼容层与 SuperDPS.* 接口),适合创建事件帧、初始化共享表、定义共享函数。本文档需要事件跟踪的条目(代码 1/6/12)与多行共用重逻辑的条目(代码 22)均已按「初始化代码 + 属性代码」两段给出。
  • 初始化代码保留 if not SuperDPS.XxxFrame 守卫是刻意的:插件重装/重载时初始化代码会再次执行,帧对象不可销毁,守卫防止重复创建与重复计数;这个判断只在加载时跑一次,无热路径成本。
  • 初始化代码抛错会中断整个插件启动(它不在属性那层 pcall 保护内),事件回调内注意 nil 守卫、逻辑要稳。

旧模块迁移:旧 .wa1 文件里属性行的 "p" 键是下表的「旧 Key」;载入新版后这些行会被归为自定义代码,但其值仍是旧「参数」而非代码,需按本文档补上代码、把旧值移入参数列。

  • 与插件同 chunk,可直接调 WoW API;GetSpellInfo/GetSpellCooldown/GetSpellCharges/UnitAura/UnitBuff/UnitDebuff 是已适配 C_Spell/C_UnitAuras 新接口的兼容层(旧多返回值签名)。
  • 保留接口:SuperDPS.GetUnitAura/GetUnitBuff/GetUnitDebuff(按名称或法术 ID 查光环,duration/expirationTime/count 已消毒)、SuperDPS.SN(v, "标记")(受保护值消毒,归 0)、SuperDPS.HekeliPrimary、SuperDPS.Prop(共享值表)。
  • 函数体内 UnitHealth/UnitHealthMax/UnitPower/UnitPowerMax 是原生 Raw 版本,战斗中可能返回受保护值。

Midnight 数值保护三规则(旧实现失效的主因)

Section titled “Midnight 数值保护三规则(旧实现失效的主因)”
  1. 直传/传参/真值判断可以:受保护值可直接 return(条带照常回传)、可 X or 0、if not X(非 boolean)。
  2. 比较与算术必先消毒:>、==、四则运算碰到受保护值立刻抛错,先过 SuperDPS.SN(v, "标记")(受保护归 0)。
  3. 例外:C_Spell.GetSpellCooldown() 的 isActive/isOnGCD 官方保证永不受保护,可安全做逻辑。

旧实现中大量 %255、×100、/100 缩放是旧「像素色块」单字节通道的遗留;新条码带支持完整数值,已一律去除——沿用旧模块阈值时注意单位换算(各条目有注记)。

图例:📦 = 新版属性库已有预置条目,直接用;✅ = 用下方编号代码;❌ = Midnight 下不可实现,已注明原因。


旧属性 旧 Key 旧实现 新版
战斗中 In Combat PropC4Ca SuperDPS.InCombatLockdown() 📦 预置「战斗中」
目标背后 Behind Target PropC4Cb getBehind()(UI_ERROR_MESSAGE 事件跟踪) ✅ 代码 1
公共冷却 Global CD PropC81E GCD()(61304 冷却 ×100,>255 归 0) 📦 预置「公共冷却」(单位改为秒)
WA 全局属性 PropC81F WaProp(name) 读 SuperDPS.Prop 📦 预置「全局属性」
Hekili 推荐 PropC82F 客户端专用通道(已删) 📦 预置「Hekili推荐」;另有零依赖的「内置推荐」

代码 1:目标背后(参数:无)。旧版靠插件主事件帧记录「必须在目标背后」报错;新版插件已不注册该事件,由模块自建事件帧,语义不变(报错后 0.6 秒内视为不在背后)。

放入初始化代码:

if not SuperDPS.BehindFrame then
SuperDPS.BehindAt = 0
local f = CreateFrame("Frame")
f:RegisterEvent("UI_ERROR_MESSAGE")
f:SetScript("OnEvent", function(_, _, _, msg)
if msg == SPELL_FAILED_NOT_BEHIND then
SuperDPS.BehindAt = GetTime()
end
end)
SuperDPS.BehindFrame = f
end

属性代码:

if GetTime() - SuperDPS.BehindAt > 0.6 then return 1 end
return 0

旧版公共冷却返回「厘秒」(剩余秒 ×100、超 255 归 0),预置「公共冷却」返回秒;沿用旧阈值除以 100 即可。

旧属性 旧 Key 旧实现 新版
自身血量百分比 PropEccb getHeal("player")(Health/Max×100) 📦 预置「生命百分比」(0~1 小数) 或 ✅ 代码 2
目标血量百分比 PropA87F getHeal("target") 同上,参数 target
宠物血量百分比 Prop1679 getHeal("pet") 同上,参数 pet
目标实际血量(千) PropE4Da getHeal2 = UnitHealth/1000 ✅ 代码 3(直传原值,除法会撞保护)
目标实际血量(万) PropE4Db getHeal3 = UnitHealth/10000 同代码 3

旧版 UnitHealth/UnitHealthMax 除法在 Midnight 战斗中直接抛错(受保护值不可运算)。

代码 2:血量百分比(0~100 旧刻度)(参数:player / target / pet)。经 SN 消毒后才能乘 100,战斗中若被保护按 0;若能接受 0~1 刻度,优先用预置「生命百分比」(直传,不受消毒降级影响):

local g = UnitGUID(arg1)
if not g then return 0 end
local v = SuperDPS.SN(UnitPercentHealthFromGUID(g), "healpct", arg1)
return v * 100

代码 3:实际血量(参数:target)。直接回传原值(受保护值也能上条带),千/万换算放到电脑端做:

return UnitHealth(arg1)
旧属性 旧 Key 旧实现 新版
自身主能量 Prop8F14 getPower("player")(百分比) ✅ 代码 4(百分比,降级) 或 📦「能量」(直传)
自身能量(按类型) PropC9F0 UnitPower("player", 类型) 📦 预置「能量」/「连击点」,参数 player,类型
目标能量(按类型) Prop45C4 UnitPower("target", 类型) 同上,参数 target,类型
自身能量百分比 PropD3D9 getPowerById("player", 类型) ✅ 代码 4
目标能量百分比 Prop6512 getPowerById("target", 类型) ✅ 代码 4
目标距离 Prop45C5 getTargetRange()(多 API 逐级探测) ✅ 代码 5(降级) 或 📦「技能射程内」
目标可施法(视线) Prop45C6 UnitInLos2()(报错事件跟踪) ✅ 代码 6

能量类型对照(旧下拉提示):-2 HealthCost,0 法力,1 怒气,2 集中,3 能量,4 连击点,5 符文,6 符能,7 灵魂碎片,8 星能,9 神圣能量,11 漩涡值,12 真气,13 疯狂值,16 奥术充能,17 恶魔怒气,18 痛苦,不填 = 当前主资源。

代码 4:能量百分比(参数 1:单位,参数 2:类型可空)。战斗中双值被保护则按 0。新版属性库已有预置「能量百分比」📦:正式服有 UnitPowerPercent 就直传,没有才退回本段相除写法;建议尽量用直传版在电脑端判断:

local p = SuperDPS.SN(UnitPower(arg1, arg2), "powpct", arg1)
local m = SuperDPS.SN(UnitPowerMax(arg1, arg2), "powpct", arg1)
if m == 0 then return 0 end
return p / m * 100

代码 5:目标距离(参数:无;无目标/读不到返回 255,同旧语义)。UnitDistanceSquared 在 Midnight 对敌对单位可能受限,可用性以实测为准;按具体技能判射程请改用预置「技能射程内」:

if not UnitExists("target") then return 255 end
local ok, d2 = pcall(UnitDistanceSquared, "target")
if ok then
d2 = SuperDPS.SN(d2, "range")
if d2 > 0 then return math.sqrt(d2) end
end
return 255

代码 6:目标可施法(视线/超距冷却)(参数:无)。旧语义:目标存在且可见,且 1.5 秒内没对它报过「超出范围/视线阻挡」。

放入初始化代码(与代码 1 共用一个帧也可以——同一帧可注册多个事件、回调里分支处理,两段合并时只建一个帧):

if not SuperDPS.LosFrame then
SuperDPS.LosSeen = {}
local f = CreateFrame("Frame")
f:RegisterEvent("UI_ERROR_MESSAGE")
f:SetScript("OnEvent", function(_, _, _, msg)
if msg == ERR_OUT_OF_RANGE or msg == SPELL_FAILED_LINE_OF_SIGHT then
local g = UnitGUID("target")
if g then SuperDPS.LosSeen[g] = GetTime() end
end
end)
SuperDPS.LosFrame = f
end

属性代码:

local g = UnitGUID("target")
if not g or not UnitIsVisible("target") then return 0 end
local t = SuperDPS.LosSeen[g]
if not t or GetTime() - t >= 1.5 then return 1 end
return 0
旧属性 旧 Key 旧实现 新版
连击点 PropC20A GetComboPoints("player","target") 📦 预置「连击点」(UnitPower(unit,4))
DK 可用符文总数 PropC20B GetRune() ✅ 代码 7
DK 符文槽冷却 PropC20B2 GetRuneByType2(槽位) ✅ 代码 8
DK 鲜血符文 PropC20C GetRuneByType(1) ❌ 正式服自军团起无符文类型之分;怀旧服客户端仍有类型,但旧实现依赖暴雪符文框架内部字段,需自行改写验证
DK 冰霜符文 PropC20D GetRuneByType(3) ❌ 同上
DK 邪恶符文 PropC20E GetRuneByType(2) ❌ 同上
DK 死亡符文 PropC20F GetRuneByType(4) ❌ 同上
有召唤宠物 PropC20G hasPet()(HasPetUI) 📦 预置「有宠物」;需区分猎人宠物用 ✅ 代码 9

符文冷却在战斗中有受保护风险(官方预置因此未移植),以下实现已消毒,被保护时按 0:

代码 7:可用符文总数(参数:无):

local n = 0
for i = 1, 6 do
local _, _, ready = GetRuneCooldown(i)
if SuperDPS.SN(ready, "rune") == true then n = n + 1 end
end
return n

代码 8:符文槽冷却剩余(参数:1~6):

local start, duration = GetRuneCooldown(arg1)
start = SuperDPS.SN(start, "runecd")
duration = SuperDPS.SN(duration, "runecd")
if start == 0 or duration == 0 then return 0 end
local remain = start + duration - GetTime()
if remain > 0 then return remain end
return 0

代码 9:有召唤宠物(旧三态语义)(参数:无;2=猎人宠物,1=其他宠物,0=无):

local hasUI, isHunterPet = HasPetUI()
if hasUI and isHunterPet then return 2 end
if hasUI then return 1 end
return 0
旧属性 旧 Key 旧实现 新版
远程武器速度 PropC51C UnitRangedDamage("player")*100 ❌ 攻速家族在 Midnight 返回受保护值(同挥砍计时器死因)
技能冷却 PropAab3 GetSpellTime(id)(start+duration−now) 📦 预置「技能冷却」/「技能可用」(旧算法战斗中撞保护)
技能充能冷却 PropAab4 GetSpellTime2(id) ✅ 代码 10
技能施法时间 Prop9Bf3 SkillCastingTime(id)(实测并缓存) ✅ 代码 11
技能施放后经过时间 Prop9Bf4 getSpellCastTime(id)(事件跟踪) ✅ 代码 12
技能施放后经过时间(按目标) Prop9Bf5 getSpellCastTime2(id) ✅ 代码 12(注释切换)
DoT 跳伤计时(按目标) Prop9Bf6 getSpellCastDamage(CLEU 被封后已是 debuff 近似) 📦 预置「自施减益剩余」
技能充能层数 PropC74D GetSpellCharges(id) 📦 预置「技能充能」
技能可用次数 Prop70Ef GetSpellCount(id) ✅ 代码 13
物品数量 Prop6F49 GetItemCount(id) 📦 预置「物品数量」
团队增益人数 Prop1F0E getRaidBuffCount(id) ✅ 代码 14
团队增益人数(自施) Prop98F1 getRaidBuffCountByPlayer(id) ✅ 代码 14,参数加 ,1

代码 10:技能充能冷却剩余(参数:技能 ID):

local _, _, start, duration = GetSpellCharges(arg1)
start = SuperDPS.SN(start, "chargecd")
duration = SuperDPS.SN(duration, "chargecd")
if start == 0 or duration == 0 then return 0 end
local remain = start + duration - GetTime()
if remain > 0 then return remain end
return 0

代码 11:技能施法时间(参数:技能 ID;返回秒,旧版单位是毫秒/10 即厘秒 ×10,沿用旧阈值注意换算)。改用法术静态数据,不再实测缓存:

local info = C_Spell.GetSpellInfo(arg1)
if not info then return 0 end
return SuperDPS.SN(info.castTime, "casttime") / 1000

代码 12:技能施放后经过时间(参数:技能 ID;上限 120,从未施放返回 120,同旧语义)。旧版靠插件主事件帧,新版由模块自建;注意键从法术名改为法术 ID。

放入初始化代码:

if not SuperDPS.CastLogFrame then
SuperDPS.CastAt = {}
SuperDPS.CastAtTarget = {}
local f = CreateFrame("Frame")
f:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED")
f:SetScript("OnEvent", function(_, _, unit, _, spellID)
if unit == "player" and spellID then
SuperDPS.CastAt[spellID] = GetTime()
SuperDPS.CastAtTarget[spellID .. "_" .. (UnitGUID("target") or "")] = GetTime()
end
end)
SuperDPS.CastLogFrame = f
end

属性代码:

local t = SuperDPS.CastAt[arg1]
-- 「按目标」版:改用下一行(同一技能对不同目标分别计时)
-- local t = SuperDPS.CastAtTarget[arg1 .. "_" .. (UnitGUID("target") or "")]
if not t then return 120 end
return math.min(GetTime() - t, 120)

代码 13:技能可用次数(参数:技能 ID;如灭杀标记类「还能施放几次」):

return C_Spell.GetSpellCastCount and C_Spell.GetSpellCastCount(arg1) or 0

代码 14:团队增益人数(参数 1:光环 ID 或名称,参数 2:填 1 只统计自己施放的):

local n = 0
for i = 1, 40 do
local u = "raid" .. i
if UnitExists(u) and not UnitIsDeadOrGhost(u) and UnitIsPlayer(u) then
local name, _, _, _, _, _, source = SuperDPS.GetUnitBuff(u, arg1)
if name and (not arg2 or source == "player") then n = n + 1 end
end
end
return n

旧版这一族共 31 个属性,全部是「单位 × 增益/减益 × 剩余时间/层数 × 是否限自施」的组合;新版用 4 段通用代码 + 参数覆盖全部组合。单位填 player/pet/target/focus,光环填法术 ID(推荐,免语言差异)或名称。

旧属性(按组) 旧 Key 新版
自身/宠物增益剩余 Prop6Ea9 / Prop3417 📦 预置「增益剩余」,参数 player,ID / pet,ID
自身增益层数 PropC16A 📦 预置「增益层数」
自身增益剩余/层数(自施) Prop6364 / Prop182B ✅ 代码 15/16,参数加 ,1
自身减益剩余/层数 PropE369 / Prop1C38 📦「减益剩余」/「减益层数」,参数 player,ID
目标增益剩余/层数(±自施) Prop19Ca / PropA5Bf / PropA577 / PropD67D ✅ 代码 15/16,单位 target
焦点增益剩余/层数(±自施) Prop19Ca1 / PropA5Bf1 / PropA5771 / PropD67D1 ✅ 代码 15/16,单位 focus
目标减益剩余/层数(±自施) PropD645 / Prop3416 / PropA1D0 / Prop17E6 📦「减益剩余」「减益层数」「自施减益剩余」或 ✅ 代码 17
焦点减益剩余/层数(±自施) PropD6451 / Prop34161 / PropA1D01 / Prop17E61 同上,单位 focus
增益图标剩余/层数(±自施) Prop3C59 / PropB6D7 / Prop3769 / Prop1Ff1(自身)
Prop8E29 / Prop4E73 / Prop02E7 / Prop33E7(目标)
✅ 代码 18(增益+减益全表搜索)

代码 15:增益剩余时间(通用)(参数:单位,光环[,1限自施])。保留旧语义:永久增益与刚到期返回 1,不存在返回 0——预置「增益剩余」对永久增益返回 0,逻辑依赖此差异的旧模块用本版:

local name, _, _, _, _, expire, source = SuperDPS.GetUnitBuff(arg1, arg2)
if not name or (arg3 and source ~= "player") then return 0 end
expire = SuperDPS.SN(expire, "bufftime", arg1)
local remain = expire - GetTime()
if remain < 0 then return 1 end
return remain

代码 16:增益层数(通用)(参数:单位,光环[,1限自施]):

local name, _, count, _, _, _, source = SuperDPS.GetUnitBuff(arg1, arg2)
if not name or (arg3 and source ~= "player") then return 0 end
return count or 0

代码 17:减益剩余/层数(通用)(参数:单位,光环[,1限自施])。减益无「到期→1」钳制(历史行为,与增益版刻意不同):

local name, _, count, _, _, expire, source = SuperDPS.GetUnitDebuff(arg1, arg2)
if not name or (arg3 and source ~= "player") then return 0 end
expire = SuperDPS.SN(expire, "debufftime", arg1)
if expire == 0 then return 0 end
return expire - GetTime()
-- 层数版:删掉上面三行,改为 return count or 0

代码 18:光环图标剩余(增益+减益全表搜索)(参数:单位,光环[,1限自施])。旧「图标」族不区分增益/减益、按名称或 ID 全搜——对应新版不带过滤器的 GetUnitAura:

local name, _, count, _, _, expire, source = SuperDPS.GetUnitAura(arg1, arg2)
if not name or (arg3 and source ~= "player") then return 0 end
expire = SuperDPS.SN(expire, "auratime", arg1)
local remain = expire - GetTime()
if remain < 0 then return 1 end
return remain
-- 层数版:删掉上面四行,改为 return count or 0
旧属性 旧 Key 旧实现 新版
姓名板自施减益数 Prop17E7 getNamePlateDebuffCountByPlayer(id) ✅ 代码 19
姓名板距离内数量 Prop17E8 getNamePlateRangeCount(码数) ✅ 代码 20(距离 API 有风险) 或 📦「敌对目标数」(不限距)

姓名板单位受游戏内「敌对姓名板」显示开关(默认 V 键)与显示距离限制。

代码 19:身上有我 DoT 的姓名板数量(参数:减益 ID;AOE 补 DoT 判断):

local n = 0
for i = 1, 40 do
local u = "nameplate" .. i
if UnitExists(u) then
local name, _, _, _, _, _, source = SuperDPS.GetUnitDebuff(u, arg1)
if name and source == "player" then n = n + 1 end
end
end
return n

代码 20:指定码数内姓名板数量(参数:码数,如 8)。依赖 UnitDistanceSquared,Midnight 对敌对单位可用性以实测为准,读不到的单位不计入:

local n = 0
local r2 = arg1 * arg1
for i = 1, 40 do
local u = "nameplate" .. i
if UnitExists(u) then
local ok, d2 = pcall(UnitDistanceSquared, u)
if ok then
d2 = SuperDPS.SN(d2, "nprange")
if d2 > 0 and d2 <= r2 then n = n + 1 end
end
end
end
return n
旧属性 旧 Key 旧实现 新版
目标施法代码 PropF717 CastingInfo("target")(ID%255) 📦 预置「目标施法」(完整 ID,不再 %255)
焦点施法代码 PropF718 CastingInfo("focus") 同上,参数 focus
自身施法代码 Prop6C83 CastingInfo("player") 同上,参数 player
自身施法进度 Prop7F39 CastingTime("player")((end−now)/100) 📦 预置「施法剩余」(单位秒),参数 player
目标施法进度 Prop7F38 CastingTime("target") 同上,参数 target

旧「施法代码」把法术 ID 对 255 取模(单字节通道限制),旧模块里按取模值写的判断需换成完整法术 ID;旧「施法进度」单位是 0.1 秒(毫秒/100),预置版是秒。

旧属性 旧 Key 旧实现 新版
目标在技能射程内 PropD9D4 IsSpellInRange(id) 📦 预置「技能射程内」
队友驱散类型检查 Prop67C6 GetDeBuffType(类型) ✅ 代码 21
最低血量队友编号 Prop642E getDamagePlayer() ✅ 代码 22
最低血量队友掉血比例 PropF457 getDamagePlayerHealth() ✅ 代码 22(返回值切换)
最低血量队友编号(有增益) PropC0C7 getDamagePlayerBuff(id) ✅ 代码 22,模式 hasBuff
最低血量掉血比例(有增益) Prop2838 getDamagePlayerHealthBuff(id) 同上
最低血量队友编号(无增益) Prop9A11 getDamagePlayerNoBuff(id) ✅ 代码 22,模式 noBuff
最低血量掉血比例(无增益) PropD82C getDamagePlayerHealthNoBuff(id) 同上
最低血量队友编号(无减益) PropA684 getDamagePlayerNoDeBuff(id) ✅ 代码 22,模式 noDebuff
最低血量掉血比例(无减益) PropB53B getDamagePlayerHealthNoDeBuff(id) 同上

编号约定(与旧版一致,用于电脑端按编号选宏目标):1=自己,25=party14,645=raid140;单人只算自己,小队算自己+party,团队只算 raid 单位。

代码 21:队友驱散类型检查(参数:Curse/Disease/Magic/Poison;返回首个中招队友编号,无人中招返回 0):

local function hit(unit)
if UnitIsDeadOrGhost(unit) or not UnitIsPlayer(unit) then return false end
for j = 1, 40 do
local name, _, _, dispelType = UnitDebuff(unit, j)
if not name then return false end
if dispelType == arg1 then return true end
end
return false
end
if UnitPlayerOrPetInRaid("player") then
for i = 1, 40 do
local u = "raid" .. i
if UnitExists(u) and hit(u) then return i + 5 end
end
elseif UnitPlayerOrPetInParty("player") then
if hit("player") then return 1 end
for i = 1, 4 do
local u = "party" .. i
if UnitExists(u) and hit(u) then return i + 1 end
end
elseif hit("player") then
return 1
end
return 0

代码 22:最低血量队友(全家族统一)(参数 1:模式,空/hasBuff/noBuff/noDebuff;参数 2:光环 ID,模式为空可不填)。8 个旧属性共用同一扫描逻辑,按「初始化代码定义共享函数 + 属性行薄调用」组织,多行同用零重复。Midnight 重要提示:血量百分比经消毒,战斗中被保护的成员按满血跳过,激烈战斗中此族可能整体降级——官方预置刻意未移植,治疗模块谨慎依赖。旧版还叠加了视线过滤(报错事件),需要的话按代码 6 的 LosSeen 自行加一段。另一处语义微调:旧版掉血基准为 -1(全员满血也会选中首个合格成员),本版基准为 0(无人掉血返回 0)。

放入初始化代码:

-- 最低血量队友扫描,供多行属性共用。返回: 编号, 掉血百分比(0~100)
function SuperDPS.ScanLowHp(mode, aura)
local best, bestDamage = 0, 0
local function consider(idx, unit)
if not UnitExists(unit) or UnitIsDeadOrGhost(unit) or not UnitIsPlayer(unit) then return end
if mode == "hasBuff" or mode == "noBuff" then
local name = SuperDPS.GetUnitBuff(unit, aura)
if (mode == "hasBuff") ~= (name ~= nil) then return end
elseif mode == "noDebuff" then
if SuperDPS.GetUnitDebuff(unit, aura) then return end
end
local g = UnitGUID(unit)
if not g then return end
local hp = SuperDPS.SN(UnitPercentHealthFromGUID(g), "lowhp", unit)
if hp == 0 then return end -- 死亡/读不到/受保护 → 跳过
local damage = (1 - hp) * 100
if damage > bestDamage then best, bestDamage = idx, damage end
end
if UnitPlayerOrPetInRaid("player") then
for i = 1, 40 do consider(i + 5, "raid" .. i) end
else
consider(1, "player")
if UnitPlayerOrPetInParty("player") then
for i = 1, 4 do consider(i + 1, "party" .. i) end
end
end
return best, bestDamage
end

属性代码(「编号」版):

local idx = SuperDPS.ScanLowHp(arg1, arg2)
return idx

属性代码(「掉血比例」版):

local _, damage = SuperDPS.ScanLowHp(arg1, arg2)
return damage
旧属性 旧 Key 旧实现 新版
主手武器 CD Prop9F61 getSwingTimer("main") ❌ UnitAttackSpeed 在 Midnight 返回受保护值,挥砍计时无法实现(实测,整个子系统因此删除)
主手武器 CD(正值) Prop9F62 getSwingTimer2("main") ❌ 同上
副手武器 CD Prop72B3 getSwingTimer("off") ❌ 同上
远程武器 CD Prop072B getSwingTimer("ranged") ❌ 同上
主手临时附魔 ID Prop66F0 GetWeaponEnchantInfoMain()(%255) ✅ 代码 23
副手临时附魔 ID Prop093F GetWeaponEnchantInfoOff() ✅ 代码 23

代码 23:武器临时附魔 ID(参数:4 主手 / 8 副手;完整 ID,不再 %255,旧模块按取模值写的判断需换成完整附魔 ID):

local id = select(arg1, GetWeaponEnchantInfo())
return id or 0
旧属性 旧 Key 旧实现 新版
按钮高亮检测 Prop44F6 checkButtonOverlay(按钮) ✅ 代码 24
UI 可见检查 Prop44F7 UiCheck(框体) ✅ 代码 25
当前地图 ID Prop44F8 MapId()(%255) ✅ 代码 26
团队总掉血比例 Prop03Af getAllHealth()(平均掉血%) ✅ 代码 27(同代码 22 的降级提示)
法术强度 Prop0311 GetSpellPower(除数) ✅ 代码 28

代码 24:按钮高亮检测(参数:ActionButton1~ActionButton12)。旧版查 overlay 字段;新版客户端的技能高亮框架字段已改名,两者都查:

local b = _G[arg1]
if b and (b.overlay or b.SpellActivationAlert) then return 1 end
return 0

代码 25:UI 可见检查(参数:框体全局名,如 PVPFrame):

local f = _G[arg1]
if f and f.IsVisible and f:IsVisible() then return 1 end
return 0

代码 26:当前地图 ID(参数:无;完整 ID,不再 %255):

return C_Map.GetBestMapForUnit("player") or 0

代码 27:团队平均掉血百分比(参数:无;0~100):

local total, n = 0, 0
local function acc(unit)
if not UnitExists(unit) or UnitIsDeadOrGhost(unit) then return end
local g = UnitGUID(unit)
if not g then return end
local hp = SuperDPS.SN(UnitPercentHealthFromGUID(g), "allhp", unit)
if hp == 0 then return end
total = total + (1 - hp)
n = n + 1
end
if UnitPlayerOrPetInRaid("player") then
for i = 1, 40 do acc("raid" .. i) end
else
acc("player")
if UnitPlayerOrPetInParty("player") then
for i = 1, 4 do acc("party" .. i) end
end
end
if n == 0 then return 0 end
return total / n * 100

代码 28:法术强度(参数:除数,旧版用它把大数值压进单字节通道,新版可填 1 取原值)。属性数值在战斗中可能受保护,消毒后按 0:

local v = SuperDPS.SN(GetSpellBonusDamage(7), "spellpower")
return v / (arg1 or 1)

旧属性 原因
挥砍计时器全家族(主手/副手/远程 CD、远程武器速度) UnitAttackSpeed/UnitRangedDamage 在 Midnight 返回受保护值,比较即抛错(实测 2026-08,旧插件的挥砍子系统因此整体删除)
DK 分类型符文(鲜血/冰霜/邪恶/死亡) 正式服自军团版本起符文无类型之分,只在怀旧服有意义;旧实现还依赖暴雪符文框架内部字段 _G["Rune"..i].rune.runeType(非公开 API,版本间易失效),要用需自行改写并在目标客户端验证
基于 CLEU 的 DoT 跳伤计时 战斗记录事件对插件硬性封锁(旧版后期已退化为 debuff 存在性近似,直接用预置「自施减益剩余」)

降级可用清单(战斗中可能读不到,按 0 处理)

Section titled “降级可用清单(战斗中可能读不到,按 0 处理)”
  • 百分比类(代码 2/4/22/27):除法/比较必须消毒,被保护的值归 0;
  • 符文类(代码 7/8):冷却值有受保护风险;
  • 距离类(代码 5/20):UnitDistanceSquared 对敌对单位可用性以实测为准;
  • 法术强度(代码 28)。

触发降级时游戏内聊天框会提示一次「被客户端保护,已按 0 处理」,明细 /dump SuperDPS.SecretSeen。