From afd74e167e8f879e496ad47b0bf18d7f2c47a7c1 Mon Sep 17 00:00:00 2001 From: pepopo978 Date: Thu, 26 Feb 2026 12:56:02 -0800 Subject: [PATCH] add new malediction option, refactor more stuff --- Cursive.toc | 8 +++---- Localization.lua | 2 ++ commands.lua | 56 ++++++++++++------------------------------------ curses.lua | 28 +++++++++++++----------- settings.lua | 2 ++ ui.lua | 18 ++-------------- 6 files changed, 39 insertions(+), 75 deletions(-) diff --git a/Cursive.toc b/Cursive.toc index 71d6bbc..41e5042 100644 --- a/Cursive.toc +++ b/Cursive.toc @@ -1,9 +1,9 @@ ## Interface: 11200 -## Title: [|CFF33AAFFSUPERWOW|R] Cursive 2.6.6 -## Title-zhCN: [|CFF33AAFFSUPERWOW|R] Cursive 2.6.6 +## Title: Cursive 3.0.0 +## Title-zhCN: Cursive 3.0.0 ## Author: Pepopo -## Notes: Uses SuperWoW GUIDs to show units in combat and track curses -## Notes-zhCN: 使用SuperWoW的GUID功能来显示战斗中的单位并监视诅咒等 +## Notes: Uses GUIDs to show units in combat and track curses +## Notes-zhCN: 使用的GUID功能来显示战斗中的单位并监视诅咒等 ## Version: 1.4.0 ## SavedVariablesPerCharacter: CursiveDB ## X-Embeds: Ace2, FuBarPlugin-2.0, CompostLib, DewDropLib, TabletLib diff --git a/Localization.lua b/Localization.lua index 5b87b7f..038e266 100644 --- a/Localization.lua +++ b/Localization.lua @@ -13,6 +13,7 @@ L:RegisterTranslations("enUS", function() ["Filter targets by name. Can be a partial match. If no match is found, the command will do nothing."] = true, ["Ignore targets with the specified spell id already on them. Useful for ignoring targets that already have a shared debuff."] = true, ["Ignore targets with the specified spell texture already on them. Useful for ignoring targets that already have a shared debuff."] = true, + ["For Warlocks with the Malediction talent: when checking if Curse of Recklessness, Curse of the Elements, or Curse of Shadow is already on a target, check for Curse of Agony instead. Default is 1 (enabled). Set malediction=0 to disable and check for the original curse."] = true, ["Time threshold at which to allow refreshing a curse. Default is 0 seconds."] = true, ["Always prioritize current target when choosing target for multicurse. Does not affect 'curse' command."] = true, ["Ignore the current target when choosing target for multicurse. Does not affect 'curse' command."] = true, @@ -221,6 +222,7 @@ L:RegisterTranslations("zhCN", function() ["Filter targets by name. Can be a partial match. If no match is found, the command will do nothing."] = "通过名称过滤目标。可以是部分匹配。如果没有找到匹配项,命令将不执行.", ["Ignore targets with the specified spell id already on them. Useful for ignoring targets that already have a shared debuff."] = "忽略已经在目标身上的指定法术ID。对于忽略已经有共享debuff的目标很有用.", ["Ignore targets with the specified spell texture already on them. Useful for ignoring targets that already have a shared debuff."] = "忽略已经在目标身上的指定法术纹理。对于忽略已经有共享debuff的目标很有用.", + ["For Warlocks with the Malediction talent: when checking if Curse of Recklessness, Curse of the Elements, or Curse of Shadow is already on a target, check for Curse of Agony instead. Default is 1 (enabled). Set malediction=0 to disable and check for the original curse."] = "对于拥有诅咒天赋的术士:检查鲁莽诅咒、元素诅咒或暗影诅咒是否已在目标身上时,改为检查痛苦诅咒。默认为1(启用)。设置malediction=0可禁用并检查原始诅咒。", ["Time threshold at which to allow refreshing a curse. Default is 0 seconds."] = "允许刷新诅咒的时间阈值。默认是0秒.例如:refreshtime=2", ["Always prioritize current target when choosing target for multicurse. Does not affect 'curse' command."] = "选择多重诅咒目标时总是优先当前目标。不影响‘诅咒’命令。", ["Ignore the current target when choosing target for multicurse. Does not affect 'curse' command."] = "选择多重诅咒目标时忽略当前目标。不影响‘诅咒’命令。", diff --git a/commands.lua b/commands.lua index edd2151..7458623 100644 --- a/commands.lua +++ b/commands.lua @@ -16,6 +16,7 @@ local commandOptions = { name = L["Filter targets by name. Can be a partial match. If no match is found, the command will do nothing."], ignorespellid = L["Ignore targets with the specified spell id already on them. Useful for ignoring targets that already have a shared debuff."], ignorespelltexture = L["Ignore targets with the specified spell texture already on them. Useful for ignoring targets that already have a shared debuff."], + malediction = L["For Warlocks with the Malediction talent: when checking if Curse of Recklessness, Curse of the Elements, or Curse of Shadow is already on a target, check for Curse of Agony instead. Default is 1 (enabled). Set malediction=0 to disable and check for the original curse."], } local commands = { @@ -77,6 +78,11 @@ local function parseOptions(optionsStr) if texture then options["ignorespelltexture"] = texture end + elseif option == "malediction" then + local _, _, maledictionVal = string.find(optionsStr, "malediction=(%d)") + if maledictionVal then + options["malediction"] = tonumber(maledictionVal) + end elseif string.find(optionsStr, option) then options[option] = true end @@ -241,32 +247,12 @@ local crowdControlledSpellIds = { } local function isMobCrowdControlled(guid) - -- check if mob is CC'ed - - -- check debuffs - for i = 1, 16 do - local _, _, _, spellId = UnitDebuff(guid, i) - if spellId then - if crowdControlledSpellIds[spellId] then - return true - end - else - break + local auras = GetUnitField(guid, "aura") + for i, spellId in pairs(auras) do + if crowdControlledSpellIds[spellId] then + return true end end - - -- check buffs - for i = 1, 32 do - local _, _, spellId = UnitBuff(guid, i) - if spellId then - if crowdControlledSpellIds[spellId] then - return true - end - else - break - end - end - return false end @@ -283,26 +269,12 @@ local function GetSquarePrioRaidTargetIndex(guid) end local function hasSpellId(guid, ignoreSpellId) - for i = 1, 16 do - local texture, stacks, spellSchool, spellId = UnitDebuff(guid, i); - if not spellId then - break - end + local auras = GetUnitField(guid, "aura") + for i, spellId in pairs(auras) do if spellId == ignoreSpellId then return true end end - - for i = 1, 32 do - local texture, stacks, spellId = UnitBuff(guid, i); - if not spellId then - break - end - if spellId == ignoreSpellId then - return true - end - end - return false end @@ -401,7 +373,7 @@ local function pickTarget(selectedPriority, lowercaseSpellNameNoRank, checkRange end if passedRangeCheck then -- check if the target has the curse - if not Cursive.curses:HasCurse(lowercaseSpellNameNoRank, guid, refreshTime) and not isMobCrowdControlled(guid) then + if not Cursive.curses:HasCurse(lowercaseSpellNameNoRank, guid, refreshTime, options["malediction"]) and not isMobCrowdControlled(guid) then local mobHp = UnitHealth(guid) if not minHp or mobHp >= minHp then local primaryValue = -1 @@ -512,7 +484,7 @@ function Cursive:Curse(spellName, targetedGuid, options) -- remove (Rank x) from spellName if it exists local lowercaseSpellNameNoRank = Cursive.utils.GetLowercaseSpellNameNoRank(spellName) - if targetedGuid and not Cursive.curses:HasCurse(lowercaseSpellNameNoRank, targetedGuid, options["refreshtime"]) and not isMobCrowdControlled(targetedGuid) then + if targetedGuid and not Cursive.curses:HasCurse(lowercaseSpellNameNoRank, targetedGuid, options["refreshtime"], options["malediction"]) and not isMobCrowdControlled(targetedGuid) then castSpellWithOptions(string.lower(spellName), lowercaseSpellNameNoRank, targetedGuid, options) return true elseif options["warnings"] then diff --git a/curses.lua b/curses.lua index 932ed1e..ed63a77 100644 --- a/curses.lua +++ b/curses.lua @@ -534,29 +534,31 @@ function curses:GetCurseData(spellName, guid) return nil end -function curses:HasCurse(lowercaseSpellNameNoRank, targetGuid, minRemaining) +function curses:HasCurse(lowercaseSpellNameNoRank, targetGuid, minRemaining, malediction) if not minRemaining then minRemaining = 0 -- default to 0 end + if malediction == nil then + malediction = 1 -- default to enabled + end + -- handle faerie fire special case if curses.isDruid and string.find(lowercaseSpellNameNoRank, L["faerie fire"]) then -- remove (feral) or (bear) from spell name lowercaseSpellNameNoRank = L["faerie fire"] end - -- handle malediction for warlocks - if curses.isWarlock and - lowercaseSpellNameNoRank == L["curse of recklessness"] or - lowercaseSpellNameNoRank == L["curse of the elements"] or - lowercaseSpellNameNoRank == L["curse of shadow"] then - -- check if they have malediction - local _, _, _, _, malediction = GetTalentInfo(1, 17) - - if malediction > 0 then - lowercaseSpellNameNoRank = L["curse of agony"] -- check for curse of agony instead - end - end + -- handle malediction for warlocks + if curses.isWarlock and malediction ~= 0 and ( + lowercaseSpellNameNoRank == L["curse of recklessness"] or + lowercaseSpellNameNoRank == L["curse of the elements"] or + lowercaseSpellNameNoRank == L["curse of shadow"]) then + local _, _, _, _, hasMalediction = GetTalentInfo(1, 17) + if hasMalediction > 0 then + lowercaseSpellNameNoRank = L["curse of agony"] + end + end if curses.guids[targetGuid] and curses.guids[targetGuid][lowercaseSpellNameNoRank] then local remaining = Cursive.curses:TimeRemaining(curses.guids[targetGuid][lowercaseSpellNameNoRank]) diff --git a/settings.lua b/settings.lua index 7027608..5147a01 100644 --- a/settings.lua +++ b/settings.lua @@ -20,6 +20,8 @@ Cursive:RegisterDefaults("profile", { showhealthbar = true, showunitname = true, + malediction = true, + shareddebuffs = { faeriefire = false, }, diff --git a/ui.lua b/ui.lua index 12ffc35..016509f 100644 --- a/ui.lua +++ b/ui.lua @@ -509,26 +509,12 @@ local function GetBarCords(row, col) end local function hasAnySpellId(guid, spellIds) - for i = 1, 16 do - local texture, stacks, spellSchool, spellId = UnitDebuff(guid, i); - if not spellId then - break - end + local auras = GetUnitField(guid, "aura") + for i, spellId in pairs(auras) do if spellIds[spellId] then return spellId end end - - for i = 1, 32 do - local texture, stacks, spellId = UnitBuff(guid, i); - if not spellId then - break - end - if spellIds[spellId] then - return spellId - end - end - return nil end