修复猎人野兽训练展示技能所需训练点数错误问题

修复拾取问题
修复其他已知问题
修复自动下马问题以及带来的猎人守护自动关闭问题
彻底修复拾取界面问题
修复目标框架的施法条监控
修复其他已知问题
调整dps插件对仇恨的估算方式
优化dps插件
修复远程攻击条问题
This commit is contained in:
rucky
2026-03-25 00:56:49 +08:00
parent c0f1ecc713
commit c7dd0f4848
9 changed files with 393 additions and 266 deletions

264
Chat.lua
View File

@@ -374,12 +374,23 @@ function SFrames:RefreshClassColorCache()
PersistClassCache()
end
SFrames._classMissCache = {}
SFrames._classMissCacheTime = 0
function SFrames:GetClassHexForName(name)
if not name or name == "" then return nil end
local cache = self.PlayerClassColorCache
if cache[name] then return cache[name] end
if self._classMissCache[name] then return nil end
self:RefreshClassColorCache()
return cache[name]
if cache[name] then return cache[name] end
self._classMissCache[name] = true
local now = GetTime()
if now - self._classMissCacheTime > 30 then
self._classMissCacheTime = now
self._classMissCache = {}
end
return nil
end
function SFrames:GetLevelForName(name)
@@ -730,27 +741,24 @@ end
local function ParseHardcoreDeathMessage(text)
if type(text) ~= "string" or text == "" then return nil end
if not string.find(text, "硬核") and not string.find(text, "死亡") then
local lower = string.lower(text)
if not string.find(lower, "hc news") and not string.find(lower, "has fallen")
and not string.find(lower, "died") and not string.find(lower, "slain") then
return nil
end
end
local clean = string.gsub(text, "|c%x%x%x%x%x%x%x%x", "")
clean = string.gsub(clean, "|r", "")
-- Check for Hardcore death signatures
if string.find(string.lower(clean), "hc news") or string.find(clean, "硬核") or string.find(clean, "死亡") or string.find(string.lower(clean), "has fallen") or string.find(string.lower(clean), "died") or string.find(string.lower(clean), "slain") then
-- Turtle English "Level 14"
local _, _, lvlStr = string.find(clean, "Level%s+(%d+)")
if lvlStr then return tonumber(lvlStr) end
-- Chinese "14级"
local _, _, lvlStr2 = string.find(clean, "(%d+)%s*级")
if lvlStr2 then return tonumber(lvlStr2) end
-- Fallback
local _, _, lvlStr3 = string.find(clean, "Level:%s+(%d+)")
if lvlStr3 then return tonumber(lvlStr3) end
-- If it matches death signatures but no level is found, return 1 as a baseline to trigger the filter.
if string.find(string.lower(clean), "hc news") or (string.find(clean, "硬核") and (string.find(clean, "死亡") or string.find(clean, "has fallen"))) then
return 1
end
local _, _, lvlStr = string.find(clean, "Level%s+(%d+)")
if lvlStr then return tonumber(lvlStr) end
local _, _, lvlStr2 = string.find(clean, "(%d+)%s*级")
if lvlStr2 then return tonumber(lvlStr2) end
local _, _, lvlStr3 = string.find(clean, "Level:%s+(%d+)")
if lvlStr3 then return tonumber(lvlStr3) end
local lower = string.lower(clean)
if string.find(lower, "hc news") or (string.find(clean, "硬核") and (string.find(clean, "死亡") or string.find(lower, "has fallen"))) then
return 1
end
return nil
end
@@ -1527,6 +1535,8 @@ local function EnsureDB()
if type(db.editBoxPosition) ~= "string" then db.editBoxPosition = DEFAULTS.editBoxPosition end
if type(db.editBoxX) ~= "number" then db.editBoxX = DEFAULTS.editBoxX end
if type(db.editBoxY) ~= "number" then db.editBoxY = DEFAULTS.editBoxY end
if db.translateEnabled == nil then db.translateEnabled = true end
if db.chatMonitorEnabled == nil then db.chatMonitorEnabled = true end
if type(db.layoutVersion) ~= "number" then db.layoutVersion = 1 end
if db.layoutVersion < 2 then
db.topPadding = DEFAULTS.topPadding
@@ -3137,6 +3147,7 @@ function SFrames.Chat:ToggleConfigFrame()
end
local CONFIG_PAGE_ORDER = {
{ key = "general", label = "通用", title = "通用设置", desc = "翻译引擎和聊天消息监控的总开关。", icon = "settings" },
{ key = "window", label = "窗口", title = "聊天窗口", desc = "尺寸、缩放、边框和输入框位置。", icon = "settings" },
{ key = "tabs", label = "标签", title = "标签管理", desc = "切换、重命名、新建和删除聊天标签。", icon = "chat" },
{ key = "filters", label = "过滤", title = "消息过滤", desc = "为当前标签设置消息类型和频道接收规则。", icon = "settings" },
@@ -3442,6 +3453,57 @@ function SFrames.Chat:EnsureConfigFrame()
return page
end
local generalPage = CreatePage("general")
do
local engineSection = CreateCfgSection(generalPage, "翻译引擎", 0, 0, 584, 120, fontPath)
AddControl(CreateCfgCheck(engineSection, "启用 AI 翻译引擎", 16, -30,
function() return EnsureDB().translateEnabled ~= false end,
function(checked)
EnsureDB().translateEnabled = (checked == true)
end,
function()
SFrames.Chat:RefreshConfigFrame()
end
))
local transDesc = engineSection:CreateFontString(nil, "OVERLAY")
transDesc:SetFont(fontPath, 10, "OUTLINE")
transDesc:SetPoint("TOPLEFT", engineSection, "TOPLEFT", 38, -50)
transDesc:SetWidth(520)
transDesc:SetJustifyH("LEFT")
transDesc:SetText("关闭后将完全停止调用 STranslateAPI 翻译接口,所有标签的自动翻译均不生效。")
transDesc:SetTextColor(0.7, 0.7, 0.74)
local monitorSection = CreateCfgSection(generalPage, "聊天消息监控", 0, -136, 584, 160, fontPath)
AddControl(CreateCfgCheck(monitorSection, "启用聊天消息监控与收集", 16, -30,
function() return EnsureDB().chatMonitorEnabled ~= false end,
function(checked)
EnsureDB().chatMonitorEnabled = (checked == true)
end,
function()
SFrames.Chat:RefreshConfigFrame()
end
))
local monDesc = monitorSection:CreateFontString(nil, "OVERLAY")
monDesc:SetFont(fontPath, 10, "OUTLINE")
monDesc:SetPoint("TOPLEFT", monitorSection, "TOPLEFT", 38, -50)
monDesc:SetWidth(520)
monDesc:SetJustifyH("LEFT")
monDesc:SetText("启用后将拦截聊天消息,提供消息历史缓存、右键复制 [+] 标记、频道翻译触发等功能。\n关闭后消息将原样通过,不做任何处理(翻译、复制等功能不可用)。")
monDesc:SetTextColor(0.7, 0.7, 0.74)
local reloadHint = monitorSection:CreateFontString(nil, "OVERLAY")
reloadHint:SetFont(fontPath, 10, "OUTLINE")
reloadHint:SetPoint("TOPLEFT", monitorSection, "TOPLEFT", 38, -86)
reloadHint:SetWidth(520)
reloadHint:SetJustifyH("LEFT")
reloadHint:SetText("提示:更改监控开关后建议 /reload 以确保完全生效。")
reloadHint:SetTextColor(0.9, 0.75, 0.5)
end
local windowPage = CreatePage("window")
do
local appearance = CreateCfgSection(windowPage, "窗口外观", 0, 0, 584, 274, fontPath)
@@ -6562,26 +6624,42 @@ function SFrames.Chat:Initialize()
end
end
-- Helper: save a message to the persistent cache ring buffer
local _persistWriteIdx = table.getn(db.messageCache)
local function PersistMessage(msgID, text, r, g, b, frameIndex)
local cache = EnsureDB().messageCache
if not cache then
EnsureDB().messageCache = {}
cache = EnsureDB().messageCache
end
table.insert(cache, {
id = msgID,
text = text,
r = r,
g = g,
b = b,
frame = frameIndex or 1,
time = date("%H:%M:%S"),
})
-- Trim to MAX_CACHE
while table.getn(cache) > MAX_CACHE do
table.remove(cache, 1)
_persistWriteIdx = _persistWriteIdx + 1
if _persistWriteIdx > MAX_CACHE then
_persistWriteIdx = 1
end
local entry = cache[_persistWriteIdx]
if entry then
entry.id = msgID
entry.text = text
entry.r = r
entry.g = g
entry.b = b
entry.frame = frameIndex or 1
entry.time = date("%H:%M:%S")
else
cache[_persistWriteIdx] = {
id = msgID,
text = text,
r = r,
g = g,
b = b,
frame = frameIndex or 1,
time = date("%H:%M:%S"),
}
end
end
local _cfTabCache = {}
for i = 1, 7 do
_cfTabCache[_G["ChatFrame" .. i]] = i
end
for i = 1, 7 do
@@ -6594,13 +6672,28 @@ function SFrames.Chat:Initialize()
origAddMessage(self, text, r, g, b, alpha, holdTime)
return
end
if string.sub(text, 1, 10) ~= "|Hsfchat:" and string.sub(text, 1, 12) ~= "|cff888888|H" then
if EnsureDB().chatMonitorEnabled == false then
origAddMessage(self, text, r, g, b, alpha, holdTime)
return
end
local b1 = string.byte(text, 1)
if b1 == 124 then
local b2 = string.byte(text, 2)
if b2 == 72 and string.find(text, "^|Hsfchat:") then
origAddMessage(self, text, r, g, b, alpha, holdTime)
return
end
if b2 == 99 and string.find(text, "^|cff888888|H") then
origAddMessage(self, text, r, g, b, alpha, holdTime)
return
end
end
do
local db = EnsureDB()
-- Universal catch for Turtle WoW custom chat channels like [硬核]
local chanName = GetChannelNameFromChatLine(text)
if chanName and IsIgnoredChannelByDefault(chanName) then
-- Global HC kill switch override check
if db.hcGlobalDisable then
local lowerChan = string.lower(chanName)
if string.find(lowerChan, "hc") or string.find(chanName, "硬核") or string.find(lowerChan, "hardcore") then
@@ -6608,46 +6701,32 @@ function SFrames.Chat:Initialize()
end
end
local frameName = self:GetName()
local matchedTabIdx = nil
if type(frameName) == "string" and string.find(frameName, "^ChatFrame%d+$") then
matchedTabIdx = SFrames.Chat:GetTabIndexForChatFrame(self)
if not matchedTabIdx then
local _, _, frameNumStr = string.find(frameName, "^ChatFrame(%d+)$")
local frameNum = tonumber(frameNumStr)
if frameNum then
local db = EnsureDB()
if frameNum <= table.getn(db.tabs) then
matchedTabIdx = frameNum
end
end
end
local matchedTabIdx = _cfTabCache[self]
or SFrames.Chat:GetTabIndexForChatFrame(self)
if not matchedTabIdx then
return
end
if matchedTabIdx then
local tab = EnsureDB().tabs[matchedTabIdx]
if tab then
if not SFrames.Chat:GetTabChannelFilter(matchedTabIdx, chanName) then
return
local tabs = db.tabs
local tab = tabs and tabs[matchedTabIdx]
if tab then
if not SFrames.Chat:GetTabChannelFilter(matchedTabIdx, chanName) then
return
end
local shouldTranslate = SFrames.Chat:GetTabChannelTranslateFilter(matchedTabIdx, chanName)
if shouldTranslate then
local cleanText = CleanTextForTranslation(text)
cleanText = string.gsub(cleanText, "^%[.-%]%s*", "")
local _, _, senderName = string.find(cleanText, "^%[([^%]]+)%]:%s*")
if senderName then
cleanText = string.gsub(cleanText, "^%[[^%]]+%]:%s*", "")
end
-- If it passed channel filter, allow translation for these bypassed channels
local shouldTranslate = SFrames.Chat:GetTabChannelTranslateFilter(matchedTabIdx, chanName)
if shouldTranslate then
local cleanText = CleanTextForTranslation(text)
-- Remove the channel prefix from translation text to be clean
cleanText = string.gsub(cleanText, "^%[.-%]%s*", "")
-- It might also have [PlayerName]:
local _, _, senderName = string.find(cleanText, "^%[([^%]]+)%]:%s*")
if senderName then
cleanText = string.gsub(cleanText, "^%[[^%]]+%]:%s*", "")
end
if cleanText ~= "" then
local tabId = tab.id
SFrames.Chat:RequestAutoTranslation(cleanText, function(result)
if result and result ~= "" then
SFrames.Chat:AppendAutoTranslatedLine(tabId, "channel", chanName, cleanText, result, senderName)
end
end)
end
if cleanText ~= "" then
local tabId = tab.id
SFrames.Chat:RequestAutoTranslation(cleanText, function(result)
if result and result ~= "" then
SFrames.Chat:AppendAutoTranslatedLine(tabId, "channel", chanName, cleanText, result, senderName)
end
end)
end
end
else
@@ -6655,7 +6734,6 @@ function SFrames.Chat:Initialize()
end
end
-- Hardcore Death Event Overrides
if db.hcDeathDisable or (db.hcDeathLevelMin and db.hcDeathLevelMin > 1) then
local deathLvl = ParseHardcoreDeathMessage(text)
if deathLvl then
@@ -6667,47 +6745,13 @@ function SFrames.Chat:Initialize()
SFrames.Chat.MessageIndex = SFrames.Chat.MessageIndex + 1
local msgID = SFrames.Chat.MessageIndex
-- Store in runtime lookup
SFrames.Chat.MessageHistory[msgID] = text
-- Persist to SavedVariables
local frameIdx = nil
for fi = 1, 7 do
if self == _G["ChatFrame" .. fi] then
frameIdx = fi
break
end
end
PersistMessage(msgID, text, r, g, b, frameIdx)
PersistMessage(msgID, text, r, g, b, _cfTabCache[self])
-- Apply class color to player names in message
local coloredText = ColorPlayerNamesInText(text)
-- Insert the clickable button [+] at the beginning
local modifiedText = "|cff888888|Hsfchat:" .. msgID .. "|h[+]|h|r " .. coloredText
origAddMessage(self, modifiedText, r, g, b, alpha, holdTime)
-- Legacy auto-translate disabled; handled by per-tab routing above.
if false then
if self == ChatFrame1 and not string.find(text, "%[翻译%]") then
if string.find(text, "%[.-硬核.-%]") or string.find(string.lower(text), "%[.-hc.-%]") or string.find(string.lower(text), "%[.-hardcore.-%]") then
local cleanText = string.gsub(text, "|c%x%x%x%x%x%x%x%x", "")
cleanText = string.gsub(cleanText, "|r", "")
cleanText = string.gsub(cleanText, "|H.-|h(.-)|h", "%1")
if _G.STranslateAPI and _G.STranslateAPI.IsReady and _G.STranslateAPI.IsReady() then
_G.STranslateAPI.Translate(cleanText, "auto", "zh", function(result, err, meta)
if result then
DEFAULT_CHAT_FRAME:AddMessage("|cff00ffff[翻译] |cffffff00" .. tostring(result) .. "|r")
end
end, "Nanami-UI")
elseif _G.STranslate and _G.STranslate.SendIO then
_G.STranslate:SendIO(cleanText, "IN", "auto", "zh")
end
end
end
end
else
origAddMessage(self, text, r, g, b, alpha, holdTime)
end
end
end