功能更新堆叠
This commit is contained in:
13
.cursor/mcp.json
Normal file
13
.cursor/mcp.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"CursorMCP对话插件": {
|
||||||
|
"command": "node",
|
||||||
|
"args": [
|
||||||
|
"c:\\Users\\rucky\\.cursor\\extensions\\local.xw-cursor-message-8.8.8\\dist\\mcp-server.mjs"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"MESSENGER_DATA_DIR": "C:\\Users\\rucky\\.moyu-message\\4ce20e1d7abb"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
.cursor/rules/mcp-messenger.mdc
Normal file
27
.cursor/rules/mcp-messenger.mdc
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
description: "自动调用 Messenger MCP 检查待发送消息"
|
||||||
|
globs: "**/*"
|
||||||
|
alwaysApply: true
|
||||||
|
---
|
||||||
|
|
||||||
|
# MCP 工具调用规则
|
||||||
|
|
||||||
|
1. 每轮对话回复**完整输出后**,最后一步必须调用 `check_messages`,适用于 Agent/Plan/Debug/Ask 所有模式,无一例外
|
||||||
|
2. `check_messages` 会持续等待直到用户发来新消息;收到后处理并回复,然后再次调用 `check_messages`,形成永续循环:回复 → check_messages → 收到消息 → 回复 → check_messages
|
||||||
|
3. 严禁在回合开始时或回复未完成时调用 `check_messages`;唯一豁免:用户明确要求结束对话
|
||||||
|
4. Plan 模式写完方案后、Debug 模式分析完问题后、Ask 模式回答完问题后,均不得直接结束对话,必须调用 `check_messages` 等待用户反馈
|
||||||
|
5. 需要用户做选择或确认时(选方案、选框架、确认操作等),必须调用 `ask_question`;严禁使用 Cursor 内置的 ask_user_question
|
||||||
|
6. `ask_question` 参数格式: `{ "questions": [{ "question": "问题文本", "options": [{ "id": "a", "label": "选项A" }, { "id": "b", "label": "选项B" }], "allow_multiple": false }] }`
|
||||||
|
7. 单选: `allow_multiple: false`(用户只能选一个);多选: `allow_multiple: true`(用户可选多个);同一 `questions` 数组可混合包含单选题和多选题
|
||||||
|
8. 用户在每道题中均可额外输入自定义补充文本(Other 输入框),无需为此添加额外选项
|
||||||
|
9. `ask_question` 收到用户回答后,处理完毕仍需调用 `check_messages` 继续监听
|
||||||
|
10. 禁止在每轮结束时用 `ask_question` 问"还有别的需要吗",回合结束只用 `check_messages`;`ask_question` 仅限任务中确实需要用户决策时使用
|
||||||
|
11. `check_messages` 支持可选参数 `reply`(string,Markdown 格式):调用时传入本轮回复的摘要/结论,插件界面会弹出模态框展示给用户。格式: `{ "reply": "## 结论\n修改完成..." }`
|
||||||
|
12. 当会话结束前,建议在调用 `check_messages` 时附带 `reply` 参数,将关键结论推送到插件界面;如果本轮无需特别总结,`reply` 可省略
|
||||||
|
13. 禁止调用subagent并发任务
|
||||||
|
14. 如果 `check_messages` 或 `ask_question` 因客户端取消、连接抖动或内部异常而意外返回/报错,且用户未明确要求结束对话,严禁把这类内部提示直接输出给用户,必须立刻再次调用对应工具继续等待
|
||||||
|
15. 执行多步任务时,每完成一个关键步骤后,必须调用 `send_progress` 推送进度摘要到远程控制台。格式: `{ "progress": "## 步骤1完成\n已修改xxx文件..." }`。`send_progress` 立即返回,不会等待消息,调用后继续执行下一步
|
||||||
|
16. `send_progress` 的 `progress` 参数应包含:已完成的操作、当前方案、下一步计划。使用简洁的 Markdown 格式
|
||||||
|
|
||||||
|
---
|
||||||
|
**回合结束(强制)**: 仅当回复**完整输出完毕后**,最后一步必须调用 CursorMCP对话插件 MCP 的 `check_messages` 工具(使用 CallMcpTool,server 为 CursorMCP对话插件 对应的 identifier,toolName 为 "check_messages",arguments 为 {})。严禁在回合开始或回复完成前调用。`ask_question` 仅用于任务中需要用户做选择时(如选框架、选方案)。
|
||||||
@@ -87,6 +87,8 @@ NP.Settings = {
|
|||||||
pvpEnemyNoClassColors = false,
|
pvpEnemyNoClassColors = false,
|
||||||
|
|
||||||
showQuestIcon = true,
|
showQuestIcon = true,
|
||||||
|
|
||||||
|
enableStacking = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
NP.Colors = {
|
NP.Colors = {
|
||||||
|
|||||||
@@ -670,6 +670,8 @@ local function BuildTab_Other(page)
|
|||||||
CreateCheckbox(page, "显示法力条", "showManaBar", L, y)
|
CreateCheckbox(page, "显示法力条", "showManaBar", L, y)
|
||||||
y = y - 26
|
y = y - 26
|
||||||
CreateCheckbox(page, "显示任务怪图标", "showQuestIcon", L, y, "在任务目标怪物的姓名板上显示\"!\"图标和进度 (配合pfQuest)")
|
CreateCheckbox(page, "显示任务怪图标", "showQuestIcon", L, y, "在任务目标怪物的姓名板上显示\"!\"图标和进度 (配合pfQuest)")
|
||||||
|
y = y - 26
|
||||||
|
CreateCheckbox(page, "堆叠姓名板", "enableStacking", L, y, "当多个姓名板重叠时,自动将它们上下分开排列。\n关闭时姓名板会自由重叠在3D位置上。")
|
||||||
|
|
||||||
y = y - 50
|
y = y - 50
|
||||||
|
|
||||||
|
|||||||
220
Plates.lua
220
Plates.lua
@@ -447,9 +447,10 @@ local function HandleNamePlate(frame)
|
|||||||
original.name = original.name or r3
|
original.name = original.name or r3
|
||||||
original.level = original.level or r4
|
original.level = original.level or r4
|
||||||
|
|
||||||
-- Shrink original frame to reduce game engine's anti-overlap stacking
|
-- Set parent to 1x1 to fully disable engine anti-overlap (ShaguPlates technique)
|
||||||
-- Original ~35px, lower = more overlap allowed, higher = more separation
|
-- Custom stacking in ResolveStacking() handles overlap instead
|
||||||
frame:SetHeight(14)
|
frame:SetHeight(1)
|
||||||
|
frame:SetWidth(1)
|
||||||
|
|
||||||
-- Create overlay
|
-- Create overlay
|
||||||
local np = CreateFrame("Button", plateName, frame)
|
local np = CreateFrame("Button", plateName, frame)
|
||||||
@@ -539,6 +540,14 @@ local function HandleNamePlate(frame)
|
|||||||
healthText:SetTextColor(1, 1, 1, 1)
|
healthText:SetTextColor(1, 1, 1, 1)
|
||||||
np.healthText = healthText
|
np.healthText = healthText
|
||||||
|
|
||||||
|
-- Threat percentage text
|
||||||
|
local threatPctText = health:CreateFontString(nil, "OVERLAY")
|
||||||
|
threatPctText:SetFont(NP.GetFont(), Settings.healthFontSize, NP.GetFontOutline())
|
||||||
|
threatPctText:SetPoint("CENTER", health, "CENTER", 0, 0)
|
||||||
|
threatPctText:SetTextColor(1, 1, 1, 1)
|
||||||
|
threatPctText:SetText("")
|
||||||
|
np.threatPctText = threatPctText
|
||||||
|
|
||||||
-- Name text
|
-- Name text
|
||||||
local name = np:CreateFontString(nil, "OVERLAY")
|
local name = np:CreateFontString(nil, "OVERLAY")
|
||||||
name:SetFont(NP.GetFont(), Settings.nameFontSize, NP.GetFontOutline())
|
name:SetFont(NP.GetFont(), Settings.nameFontSize, NP.GetFontOutline())
|
||||||
@@ -680,7 +689,8 @@ local function HandleNamePlate(frame)
|
|||||||
local oldOnShow = frame:GetScript("OnShow")
|
local oldOnShow = frame:GetScript("OnShow")
|
||||||
frame:SetScript("OnShow", function()
|
frame:SetScript("OnShow", function()
|
||||||
if oldOnShow then oldOnShow() end
|
if oldOnShow then oldOnShow() end
|
||||||
this:SetHeight(14)
|
this:SetHeight(1)
|
||||||
|
this:SetWidth(1)
|
||||||
local nameplate = this.nameplate
|
local nameplate = this.nameplate
|
||||||
if nameplate then
|
if nameplate then
|
||||||
Healthbar.ResetCache(nameplate)
|
Healthbar.ResetCache(nameplate)
|
||||||
@@ -692,6 +702,10 @@ local function HandleNamePlate(frame)
|
|||||||
nameplate._lastManaShowing = nil
|
nameplate._lastManaShowing = nil
|
||||||
nameplate._lastFriendly_resize = nil
|
nameplate._lastFriendly_resize = nil
|
||||||
nameplate._lastAlpha = nil
|
nameplate._lastAlpha = nil
|
||||||
|
nameplate._stackY = nil
|
||||||
|
nameplate._appliedOffY = nil
|
||||||
|
nameplate.healthBG:ClearAllPoints()
|
||||||
|
nameplate.healthBG:SetPoint("CENTER", nameplate, "CENTER", 0, Settings.nameplateYOffset or 0)
|
||||||
if nameplate._defaultStrata then
|
if nameplate._defaultStrata then
|
||||||
nameplate:SetFrameStrata(nameplate._defaultStrata)
|
nameplate:SetFrameStrata(nameplate._defaultStrata)
|
||||||
end
|
end
|
||||||
@@ -813,9 +827,10 @@ local function UpdateNamePlate(frame)
|
|||||||
local original = np.original
|
local original = np.original
|
||||||
if not original or not original.healthbar then return end
|
if not original or not original.healthbar then return end
|
||||||
|
|
||||||
-- Keep original frame small to reduce anti-overlap stacking jumps
|
-- Keep parent 1x1 to disable engine anti-overlap entirely
|
||||||
if frame:GetHeight() > 16 then
|
if frame:GetHeight() > 1 or frame:GetWidth() > 1 then
|
||||||
frame:SetHeight(14)
|
frame:SetHeight(1)
|
||||||
|
frame:SetWidth(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Continuously enforce hiding of original elements
|
-- Continuously enforce hiding of original elements
|
||||||
@@ -1024,17 +1039,21 @@ local function UpdateNamePlate(frame)
|
|||||||
if isHostile and not isTapped then
|
if isHostile and not isTapped then
|
||||||
local threatColor = nil
|
local threatColor = nil
|
||||||
local mobGUID = unitstr
|
local mobGUID = unitstr
|
||||||
|
local threatPctValue = nil
|
||||||
|
local threatPctRole = NP.playerRole or "DPS"
|
||||||
|
|
||||||
if NanamiPlates_Threat then
|
if NanamiPlates_Threat then
|
||||||
local hasData, playerHasAggro, otherName, otherPct = NanamiPlates_Threat.GetTWTankModeThreat(mobGUID, plateName)
|
local hasData, playerHasAggro, otherName, otherPct = NanamiPlates_Threat.GetTWTankModeThreat(mobGUID, plateName)
|
||||||
|
|
||||||
if hasData then
|
if hasData then
|
||||||
local role = NP.playerRole or "DPS"
|
local role = threatPctRole
|
||||||
if role == "TANK" then
|
if role == "TANK" then
|
||||||
if playerHasAggro then
|
if playerHasAggro then
|
||||||
threatColor = THREAT_COLORS.TANK.AGGRO
|
threatColor = THREAT_COLORS.TANK.AGGRO
|
||||||
|
threatPctValue = 100
|
||||||
elseif otherPct and otherPct > 70 then
|
elseif otherPct and otherPct > 70 then
|
||||||
threatColor = THREAT_COLORS.TANK.LOSING_AGGRO
|
threatColor = THREAT_COLORS.TANK.LOSING_AGGRO
|
||||||
|
threatPctValue = otherPct
|
||||||
elseif otherName and NP.TANK_CLASSES and NP.GetPlayerClassByName then
|
elseif otherName and NP.TANK_CLASSES and NP.GetPlayerClassByName then
|
||||||
local otherClass = NP.GetPlayerClassByName(otherName)
|
local otherClass = NP.GetPlayerClassByName(otherName)
|
||||||
if otherClass and NP.TANK_CLASSES[otherClass] then
|
if otherClass and NP.TANK_CLASSES[otherClass] then
|
||||||
@@ -1042,16 +1061,61 @@ local function UpdateNamePlate(frame)
|
|||||||
else
|
else
|
||||||
threatColor = THREAT_COLORS.TANK.NO_AGGRO
|
threatColor = THREAT_COLORS.TANK.NO_AGGRO
|
||||||
end
|
end
|
||||||
|
threatPctValue = otherPct or 0
|
||||||
else
|
else
|
||||||
threatColor = THREAT_COLORS.TANK.NO_AGGRO
|
threatColor = THREAT_COLORS.TANK.NO_AGGRO
|
||||||
|
threatPctValue = otherPct or 0
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if playerHasAggro then
|
if playerHasAggro then
|
||||||
threatColor = THREAT_COLORS.DPS.AGGRO
|
threatColor = THREAT_COLORS.DPS.AGGRO
|
||||||
|
threatPctValue = 100
|
||||||
elseif otherPct and otherPct > 70 then
|
elseif otherPct and otherPct > 70 then
|
||||||
threatColor = THREAT_COLORS.DPS.HIGH_THREAT
|
threatColor = THREAT_COLORS.DPS.HIGH_THREAT
|
||||||
|
threatPctValue = otherPct
|
||||||
else
|
else
|
||||||
threatColor = THREAT_COLORS.DPS.NO_AGGRO
|
threatColor = THREAT_COLORS.DPS.NO_AGGRO
|
||||||
|
threatPctValue = otherPct or 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not hasData and NanamiDPS and NanamiDPS.ThreatEngine then
|
||||||
|
local TE = NanamiDPS.ThreatEngine
|
||||||
|
if TE.inCombat and unitstr then
|
||||||
|
local data = TE:QueryUnitThreat(unitstr)
|
||||||
|
if not data and plateName then
|
||||||
|
local tk = TE.GetTargetKey and TE.GetTargetKey(unitstr)
|
||||||
|
if tk then
|
||||||
|
local t, isTk, pct = TE:QueryNameThreat(tk, UnitName("player"))
|
||||||
|
if t > 0 then
|
||||||
|
data = { pct = pct, isTanking = isTk, threat = t,
|
||||||
|
tankThreat = 0, secondPct = 0, secondName = nil }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if data then
|
||||||
|
local role = threatPctRole
|
||||||
|
if role == "TANK" then
|
||||||
|
if data.isTanking then
|
||||||
|
threatColor = THREAT_COLORS.TANK.AGGRO
|
||||||
|
threatPctValue = data.secondPct or 0
|
||||||
|
else
|
||||||
|
threatColor = THREAT_COLORS.TANK.NO_AGGRO
|
||||||
|
threatPctValue = data.pct or 0
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if data.isTanking then
|
||||||
|
threatColor = THREAT_COLORS.DPS.AGGRO
|
||||||
|
threatPctValue = 100
|
||||||
|
elseif data.pct and data.pct > 70 then
|
||||||
|
threatColor = THREAT_COLORS.DPS.HIGH_THREAT
|
||||||
|
threatPctValue = data.pct
|
||||||
|
else
|
||||||
|
threatColor = THREAT_COLORS.DPS.NO_AGGRO
|
||||||
|
threatPctValue = data.pct or 0
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1064,6 +1128,7 @@ local function UpdateNamePlate(frame)
|
|||||||
if data and data.start and data.duration then
|
if data and data.start and data.duration then
|
||||||
if data.start + data.duration > GetTime() then
|
if data.start + data.duration > GetTime() then
|
||||||
threatColor = THREAT_COLORS.STUN
|
threatColor = THREAT_COLORS.STUN
|
||||||
|
threatPctValue = nil
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1073,6 +1138,22 @@ local function UpdateNamePlate(frame)
|
|||||||
if threatColor then
|
if threatColor then
|
||||||
barR, barG, barB = threatColor[1], threatColor[2], threatColor[3]
|
barR, barG, barB = threatColor[1], threatColor[2], threatColor[3]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if np.threatPctText then
|
||||||
|
if threatPctValue and threatColor then
|
||||||
|
np.threatPctText:SetText(string.format("%.0f%%", threatPctValue))
|
||||||
|
np.threatPctText:SetTextColor(threatColor[1], threatColor[2], threatColor[3], 1)
|
||||||
|
np.threatPctText:Show()
|
||||||
|
else
|
||||||
|
np.threatPctText:SetText("")
|
||||||
|
np.threatPctText:Hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if np.threatPctText then
|
||||||
|
np.threatPctText:SetText("")
|
||||||
|
np.threatPctText:Hide()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
np.health:SetStatusBarColor(barR, barG, barB, 1)
|
np.health:SetStatusBarColor(barR, barG, barB, 1)
|
||||||
@@ -1286,6 +1367,126 @@ local function UpdateNamePlate(frame)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Nameplate vertical stacking resolution
|
||||||
|
-- Engine anti-overlap is fully disabled (parent set to 1x1 like ShaguPlates),
|
||||||
|
-- so we resolve overlaps ourselves with a stable algorithm.
|
||||||
|
local stackPool = {}
|
||||||
|
local stackN = 0
|
||||||
|
local STACK_SMOOTH = 0.15
|
||||||
|
|
||||||
|
local function ResolveStacking()
|
||||||
|
if not Settings.enableStacking then
|
||||||
|
-- Stacking disabled: decay any residual offsets from when it was enabled
|
||||||
|
for frame, np in pairs(registry) do
|
||||||
|
if np._stackY and np._stackY ~= 0 then
|
||||||
|
local new = np._stackY * (1 - STACK_SMOOTH * 3)
|
||||||
|
if new > -0.5 and new < 0.5 then new = 0 end
|
||||||
|
np._stackY = new
|
||||||
|
np._appliedOffY = (Settings.nameplateYOffset or 0) + new
|
||||||
|
np.healthBG:ClearAllPoints()
|
||||||
|
np.healthBG:SetPoint("CENTER", np, "CENTER", 0, np._appliedOffY)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
stackN = 0
|
||||||
|
for frame, np in pairs(registry) do
|
||||||
|
if frame:IsShown() and np:IsShown() then
|
||||||
|
local cx, cy = frame:GetCenter()
|
||||||
|
if cx and cy then
|
||||||
|
stackN = stackN + 1
|
||||||
|
if not stackPool[stackN] then stackPool[stackN] = {} end
|
||||||
|
local e = stackPool[stackN]
|
||||||
|
e.np = np
|
||||||
|
e.cx = cx
|
||||||
|
e.cy = cy
|
||||||
|
e.name = np.plateName or ""
|
||||||
|
e.stackTarget = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if stackN < 1 then return end
|
||||||
|
|
||||||
|
-- Single plate: decay any residual stacking offset
|
||||||
|
if stackN < 2 then
|
||||||
|
local np = stackPool[1].np
|
||||||
|
if np._stackY and np._stackY ~= 0 then
|
||||||
|
local new = np._stackY * (1 - STACK_SMOOTH * 3)
|
||||||
|
if new > -0.5 and new < 0.5 then new = 0 end
|
||||||
|
np._stackY = new
|
||||||
|
np._appliedOffY = (Settings.nameplateYOffset or 0) + new
|
||||||
|
np.healthBG:ClearAllPoints()
|
||||||
|
np.healthBG:SetPoint("CENTER", np, "CENTER", 0, np._appliedOffY)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Stable bubble sort: Y descending (higher on screen first), name as tiebreaker
|
||||||
|
for i = stackN, 2, -1 do
|
||||||
|
for j = 1, i - 1 do
|
||||||
|
local a = stackPool[j]
|
||||||
|
local b = stackPool[j + 1]
|
||||||
|
local ay = math_floor(a.cy)
|
||||||
|
local by = math_floor(b.cy)
|
||||||
|
if by > ay or (by == ay and b.name < a.name) then
|
||||||
|
stackPool[j] = b
|
||||||
|
stackPool[j + 1] = a
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Resolve vertical overlaps: push lower plates down when horizontally close
|
||||||
|
local minSep = (Settings.healthbarHeight or 12) + BORDER_PAD * 2
|
||||||
|
+ (Settings.nameFontSize or 9) + 6
|
||||||
|
local overlapW = (Settings.healthbarWidth or 120) * 0.8
|
||||||
|
|
||||||
|
for i = 1, stackN do
|
||||||
|
for j = i + 1, stackN do
|
||||||
|
local a = stackPool[i]
|
||||||
|
local b = stackPool[j]
|
||||||
|
local dx = a.cx - b.cx
|
||||||
|
if dx < 0 then dx = -dx end
|
||||||
|
if dx < overlapW then
|
||||||
|
local ya = a.cy + a.stackTarget
|
||||||
|
local yb = b.cy + b.stackTarget
|
||||||
|
local gap = ya - yb
|
||||||
|
if gap < minSep then
|
||||||
|
b.stackTarget = b.stackTarget - (minSep - gap)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apply stacking offsets with smooth convergence
|
||||||
|
for i = 1, stackN do
|
||||||
|
local e = stackPool[i]
|
||||||
|
local np = e.np
|
||||||
|
|
||||||
|
local curStack = np._stackY or 0
|
||||||
|
local tarStack = e.stackTarget
|
||||||
|
local d = tarStack - curStack
|
||||||
|
local newStack
|
||||||
|
if d > -0.5 and d < 0.5 then
|
||||||
|
newStack = tarStack
|
||||||
|
else
|
||||||
|
newStack = curStack + d * STACK_SMOOTH
|
||||||
|
end
|
||||||
|
if newStack > -0.3 and newStack < 0.3 then newStack = 0 end
|
||||||
|
np._stackY = newStack
|
||||||
|
|
||||||
|
local offY = (Settings.nameplateYOffset or 0) + newStack
|
||||||
|
|
||||||
|
local pY = np._appliedOffY or (Settings.nameplateYOffset or 0)
|
||||||
|
if (offY - pY) > 0.5 or (offY - pY) < -0.5 then
|
||||||
|
np._appliedOffY = offY
|
||||||
|
np.healthBG:ClearAllPoints()
|
||||||
|
np.healthBG:SetPoint("CENTER", np, "CENTER", 0, offY)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Main OnUpdate loop
|
-- Main OnUpdate loop
|
||||||
local scanThrottle = 0
|
local scanThrottle = 0
|
||||||
local SCAN_INTERVAL = 0.1
|
local SCAN_INTERVAL = 0.1
|
||||||
@@ -1312,6 +1513,9 @@ local function OnUpdate()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Resolve stacking overlaps and smooth position jitter
|
||||||
|
ResolveStacking()
|
||||||
|
|
||||||
-- Cleanup debuff timers
|
-- Cleanup debuff timers
|
||||||
if NanamiPlates_Auras then
|
if NanamiPlates_Auras then
|
||||||
NanamiPlates_Auras:CleanupTimers()
|
NanamiPlates_Auras:CleanupTimers()
|
||||||
|
|||||||
Reference in New Issue
Block a user