diff --git a/Cursive.toc b/Cursive.toc index cf4b5d2..bac56a1 100644 --- a/Cursive.toc +++ b/Cursive.toc @@ -28,6 +28,7 @@ global.lua utils.lua settings.lua core.lua +spells\shared_debuffs.lua spells\druid.lua spells\hunter.lua spells\mage.lua diff --git a/Localization.lua b/Localization.lua index eb92470..df21c9e 100644 --- a/Localization.lua +++ b/Localization.lua @@ -30,6 +30,7 @@ L:RegisterTranslations("enUS", function() ["Same as HIGHEST_HP_RAID_MARK but with INVERSE_RAID_MARK mark prio."] = true, ["|cffffcc00Cursive:|cffffaaaa Couldn't find a target to curse."] = true, ["curse_duration_format"] = ".*over ([%d.]+) sec.", + ["Shared Debuffs"] = true, -- curses ["(.+) fades from (.+)"] = true, @@ -99,7 +100,7 @@ L:RegisterTranslations("enUS", function() ["Ignored Mobs List (Enter to save)"] = true, ["Comma separated list of strings to ignore if found in the unit name"] = true, ["Shared Faerie Fire"] = true, - ["This will show other player's Faerie Fires as well as your own"] = true, + ["This will show other player's Faerie Fires and avoid trying to cast Faerie Fire on those mobs"] = true, -- spells ["Rank"] = true, @@ -230,6 +231,7 @@ L:RegisterTranslations("zhCN", function() -- 虫群:敌人被飞虫围绕,攻击命中率降低2%,在18秒内受到总计99点自然伤害。 -- 月火术:灼烧敌人,对其造成40到48点伤害,并在18秒内造成额外的120点奥术伤害。 ["curse_duration_format"] = "(%d+%.?%d*)秒", + ["Shared Debuffs"] = "共享debuff", -- curses ["(.+) fades from (.+)"] = "(.+)效果从(.+)身上消失", @@ -294,6 +296,8 @@ L:RegisterTranslations("zhCN", function() ["Not ignored"] = "不被忽略", ["Ignored Mobs List (Enter to save)"] = "忽略的怪物列表(回车保存)", ["Comma separated list of strings to ignore if found in the unit name"] = "如果在单位名称中找到,则忽略的字符串列表,用半角逗号分隔", + ["Shared Faerie Fire"] = "共享精灵之火", + ["This will show other player's Faerie Fires and avoid trying to cast Faerie Fire on those mobs"] = "这将显示其他玩家的精灵之火,并避免尝试在这些怪物上施放精灵之火", -- spells ["Rank"] = "等级", diff --git a/curses.lua b/curses.lua index e7172ba..1ea9474 100644 --- a/curses.lua +++ b/curses.lua @@ -26,7 +26,14 @@ local curses = { pendingCast = {}, resistSoundGuids = {}, expiringSoundGuids = {}, - requestedExpiringSoundGuids = {} -- guid added on spellcast, moved to expiringSoundGuids once rendered by ui + requestedExpiringSoundGuids = {}, -- guid added on spellcast, moved to expiringSoundGuids once rendered by ui + + sharedDebuffs = { + faeriefire = {}, + }, + sharedDebuffGuids = { + faeriefire = {}, -- used for scanning for shared debuffs like faerie fire + }, -- used for scanning for shared debuffs like faerie fire } -- combat events for curses @@ -46,25 +53,38 @@ function curses:LoadCurses() curses.trackedCurseNamesToTextures = {} curses.trackedCurseNameRanksToSpellSlots = {} + curses.isWarlock = playerClassName == "WARLOCK" + curses.isPriest = playerClassName == "PRIEST" + curses.isMage = playerClassName == "MAGE" + curses.isDruid = playerClassName == "DRUID" + curses.isHunter = playerClassName == "HUNTER" + curses.isRogue = playerClassName == "ROGUE" + curses.isShaman = playerClassName == "SHAMAN" + curses.isWarrior = playerClassName == "WARRIOR" + + -- curses to track - if playerClassName == "WARLOCK" then + if curses.isWarlock then curses.trackedCurseIds = getWarlockSpells() - elseif playerClassName == "PRIEST" then + elseif curses.isPriest then curses.trackedCurseIds = getPriestSpells() - elseif playerClassName == "MAGE" then + elseif curses.isMage then curses.trackedCurseIds = getMageSpells() - elseif playerClassName == "DRUID" then + elseif curses.isDruid then curses.trackedCurseIds = getDruidSpells() - elseif playerClassName == "HUNTER" then + elseif curses.isHunter then curses.trackedCurseIds = getHunterSpells() - elseif playerClassName == "ROGUE" then + elseif curses.isRogue then curses.trackedCurseIds = getRogueSpells() - elseif playerClassName == "SHAMAN" then + elseif curses.isShaman then curses.trackedCurseIds = getShamanSpells() - elseif playerClassName == "WARRIOR" then + elseif curses.isWarrior then curses.trackedCurseIds = getWarriorSpells() end + -- load shared debuffs + curses.sharedDebuffs = getSharedDebuffs() + -- go through spell slots and local i = 1 while true do @@ -165,35 +185,17 @@ Cursive:RegisterEvent("SPELLCAST_CHANNEL_STOP", StopChanneling); Cursive:RegisterEvent("SPELLCAST_INTERRUPTED", StopChanneling); Cursive:RegisterEvent("SPELLCAST_FAILED", StopChanneling); - -local FaerieFire = { - [770] = true, --r1 - [778] = true, --r2 - [9749] = true, --r3 - [9907] = true, --r4 - - [16855] = true, --bear r1 - [17387] = true, --bear r2 - [17388] = true, --bear r3 - [17389] = true, --bear r4 - - [16857] = true, --cat r1 - [17390] = true, --cat r2 - [17391] = true, --cat r3 - [17392] = true, --cat r4 -} - Cursive:RegisterEvent("UNIT_CASTEVENT", function(casterGuid, targetGuid, event, spellID, castDuration) -- immolate will fire both start and cast if event == "CAST" then local _, guid = UnitExists("player") if casterGuid ~= guid then - if Cursive.db.profile.sharedFaerieFire and FaerieFire[spellID] then - lastGuid = targetGuid - Cursive:ScheduleEvent("addCurse" .. targetGuid .. curses.trackedCurseIds[spellID].name, curses.ApplyCurse, 0.2, self, spellID, targetGuid, GetTime()) - else - return + -- check for faeriefire + if Cursive.db.profile.shareddebuffs.faeriefire and curses.sharedDebuffs.faeriefire[spellID] then + curses.sharedDebuffGuids.faeriefire[targetGuid] = GetTime() end + + return end -- store pending cast @@ -441,6 +443,12 @@ function curses:HasCurse(spellName, targetGuid, minRemaining) minRemaining = 0 -- default to 0 end + -- handle faerie fire special case + if curses.isDruid and string.find(spellName, L["faerie fire"]) then + -- remove (feral) or (bear) from spell name + spellName = L["faerie fire"] + end + if curses.guids[targetGuid] and curses.guids[targetGuid][spellName] then local remaining = Cursive.curses:TimeRemaining(curses.guids[targetGuid][spellName]) if remaining > minRemaining then @@ -460,6 +468,27 @@ function curses:HasCurse(spellName, targetGuid, minRemaining) return nil end +-- Apply shared curse from another player +function curses:ApplySharedCurse(sharedDebuffKey, spellID, targetGuid, startTime) + local name = curses.sharedDebuffs[sharedDebuffKey][spellID].name + local rank = curses.sharedDebuffs[sharedDebuffKey][spellID].rank + local duration = curses.sharedDebuffs[sharedDebuffKey][spellID].duration + + if not curses.guids[targetGuid] then + curses.guids[targetGuid] = {} + end + + curses.guids[targetGuid][name] = { + rank = rank, + duration = duration, + start = startTime, + spellID = spellID, + targetGuid = targetGuid, + currentPlayer = false, + } +end + +-- Apply curse from player function curses:ApplyCurse(spellID, targetGuid, startTime) -- clear pending cast curses.pendingCast = {} @@ -477,7 +506,8 @@ function curses:ApplyCurse(spellID, targetGuid, startTime) duration = duration, start = startTime, spellID = spellID, - targetGuid = targetGuid + targetGuid = targetGuid, + currentPlayer = true, } end diff --git a/filter.lua b/filter.lua index 960d0f8..a489e49 100644 --- a/filter.lua +++ b/filter.lua @@ -98,44 +98,41 @@ function Cursive:ShouldDisplayGuid(guid) return true end - -- apply filters - local shouldDisplay = true -- default to true - - if Cursive.db.profile.filterincombat then - shouldDisplay = shouldDisplay and filter.infight(guid) + if Cursive.db.profile.filterincombat and not filter.infight(guid) then + return false end - if Cursive.db.profile.filterhascurse then - shouldDisplay = shouldDisplay and filter.hascurse(guid) + if Cursive.db.profile.filterhascurse and not filter.hascurse(guid) then + return false end - if Cursive.db.profile.filterhostile then - shouldDisplay = shouldDisplay and filter.hostile(guid) + if Cursive.db.profile.filterhostile and not filter.hostile(guid) then + return false end - if Cursive.db.profile.filterattackable then - shouldDisplay = shouldDisplay and filter.attackable(guid) + if Cursive.db.profile.filterattackable and not filter.attackable(guid) then + return false end - if Cursive.db.profile.filterrange then - shouldDisplay = shouldDisplay and filter.range(guid) + if Cursive.db.profile.filterrange and not filter.range(guid) then + return false end - if Cursive.db.profile.filterraidmark then - shouldDisplay = shouldDisplay and filter.icon(guid) + if Cursive.db.profile.filterraidmark and not filter.icon(guid) then + return false end - if Cursive.db.profile.filterplayer then - shouldDisplay = shouldDisplay and filter.player(guid) + if Cursive.db.profile.filterplayer and not filter.player(guid) then + return false end - if Cursive.db.profile.filternotplayer then - shouldDisplay = shouldDisplay and filter.notplayer(guid) + if Cursive.db.profile.filternotplayer and not filter.notplayer(guid) then + return false end - if Cursive.db.profile.filterignored then - shouldDisplay = shouldDisplay and filter.notignored(guid) + if Cursive.db.profile.filterignored and not filter.notignored(guid) then + return false end - return shouldDisplay + return true end diff --git a/settings.lua b/settings.lua index 4af37c0..bbbc78c 100644 --- a/settings.lua +++ b/settings.lua @@ -19,7 +19,10 @@ Cursive:RegisterDefaults("profile", { showraidicons = true, showhealthbar = true, showunitname = true, - sharedFaerieFire = false, + + shareddebuffs = { + faeriefire = false, + }, alwaysshowcurrenttarget = true, @@ -411,6 +414,22 @@ local mobFilters = { }, } +local sharedDebuffs = { + ["sharedFaerieFire"] = { + type = "toggle", + name = L["Shared Faerie Fire"], + desc = L["This will show other player's Faerie Fires and avoid trying to cast Faerie Fire on those mobs"], + order = 10, + get = function() + return Cursive.db.profile.shareddebuffs.faeriefire + end, + set = function(v) + Cursive.db.profile.shareddebuffs.faeriefire = v + Cursive.UpdateFramesFromConfig() + end, + }, +} + Cursive.cmdtable = { type = "group", handler = Cursive, @@ -499,9 +518,16 @@ Cursive.cmdtable = { type = "group", name = L["Mob filters"], desc = L["Target and Raid Marks always shown"], - order = 20, + order = 19, args = mobFilters }, + ["shareddebuffs"] = { + type = "group", + name = L["Shared Debuffs"], + desc = L["Shared Debuffs"], + order = 20, + args = sharedDebuffs + }, ["spacer2"] = { type = "header", name = " ", @@ -561,19 +587,6 @@ Cursive.cmdtable = { end end, }, - ["sharedFaerieFire"] = { - type = "toggle", - name = L["Shared Faerie Fire"], - desc = L["This will show other player's Faerie Fires as well as your own"], - order = 10, - get = function() - return Cursive.db.profile.sharedFaerieFire - end, - set = function(v) - Cursive.db.profile.sharedFaerieFire = v - Cursive.UpdateFramesFromConfig() - end, - }, } } diff --git a/spells/druid.lua b/spells/druid.lua index 2252af0..f8211c7 100644 --- a/spells/druid.lua +++ b/spells/druid.lua @@ -17,15 +17,15 @@ function getDruidSpells() [9749] = { name = L["faerie fire"], rank = 3, duration = 40 }, [9907] = { name = L["faerie fire"], rank = 4, duration = 40 }, - [16855] = { name = L["faerie fire (bear)()"], rank = 1, duration = 40 }, - [17387] = { name = L["faerie fire (bear)()"], rank = 2, duration = 40 }, - [17388] = { name = L["faerie fire (bear)()"], rank = 3, duration = 40 }, - [17389] = { name = L["faerie fire (bear)()"], rank = 4, duration = 40 }, + [16855] = { name = L["faerie fire"], rank = 1, duration = 40 }, -- use faerie fire instead of (bear) version so they block each other + [17387] = { name = L["faerie fire"], rank = 2, duration = 40 }, + [17388] = { name = L["faerie fire"], rank = 3, duration = 40 }, + [17389] = { name = L["faerie fire"], rank = 4, duration = 40 }, - [16857] = { name = L["faerie fire (feral)()"], rank = 1, duration = 40 }, - [17390] = { name = L["faerie fire (feral)()"], rank = 2, duration = 40 }, - [17391] = { name = L["faerie fire (feral)()"], rank = 3, duration = 40 }, - [17392] = { name = L["faerie fire (feral)()"], rank = 4, duration = 40 }, + [16857] = { name = L["faerie fire"], rank = 1, duration = 40 }, -- use faerie fire instead of (feral) version so they block each other + [17390] = { name = L["faerie fire"], rank = 2, duration = 40 }, + [17391] = { name = L["faerie fire"], rank = 3, duration = 40 }, + [17392] = { name = L["faerie fire"], rank = 4, duration = 40 }, [2637] = { name = L["hibernate"], rank = 1, duration = 20 }, [18657] = { name = L["hibernate"], rank = 2, duration = 30 }, diff --git a/spells/shared_debuffs.lua b/spells/shared_debuffs.lua new file mode 100644 index 0000000..4485ff9 --- /dev/null +++ b/spells/shared_debuffs.lua @@ -0,0 +1,21 @@ +local L = AceLibrary("AceLocale-2.2"):new("Cursive") +function getSharedDebuffs() + return { + faeriefire = { + [770] = { name = L["faerie fire"], rank = 1, duration = 40 }, + [778] = { name = L["faerie fire"], rank = 2, duration = 40 }, + [9749] = { name = L["faerie fire"], rank = 3, duration = 40 }, + [9907] = { name = L["faerie fire"], rank = 4, duration = 40 }, + + [16855] = { name = L["faerie fire"], rank = 1, duration = 40 }, -- use faerie fire instead of (bear) version so they block each other + [17387] = { name = L["faerie fire"], rank = 2, duration = 40 }, + [17388] = { name = L["faerie fire"], rank = 3, duration = 40 }, + [17389] = { name = L["faerie fire"], rank = 4, duration = 40 }, + + [16857] = { name = L["faerie fire"], rank = 1, duration = 40 }, -- use faerie fire instead of (feral) version so they block each other + [17390] = { name = L["faerie fire"], rank = 2, duration = 40 }, + [17391] = { name = L["faerie fire"], rank = 3, duration = 40 }, + [17392] = { name = L["faerie fire"], rank = 4, duration = 40 }, + } + } +end diff --git a/ui.lua b/ui.lua index ba2ce9a..e8e3948 100644 --- a/ui.lua +++ b/ui.lua @@ -416,6 +416,30 @@ local function GetBarCords(row, col) return x, y 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 + 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 + local function GetSortedCurses(guidCurses) -- Collect keys local curseNames = {} @@ -470,6 +494,20 @@ local function DisplayGuid(guid) unitFrame.pos = x .. -y end + -- check for shared debuffs + for sharedDebuffKey, guids in pairs(Cursive.curses.sharedDebuffGuids) do + if guids[guid] then + local sharedDebuffSpellIds = Cursive.curses.sharedDebuffs[sharedDebuffKey] + local spellId = hasAnySpellId(guid, sharedDebuffSpellIds) + if spellId ~= nil then + -- add curse to curses + Cursive.curses:ApplySharedCurse(sharedDebuffKey, spellId, guid, GetTime()) + -- remove guid + Cursive.curses.sharedDebuffGuids[sharedDebuffKey][guid] = nil + end + end + end + -- update curses local curseNumber = 1 @@ -491,6 +529,13 @@ local function DisplayGuid(guid) local curse = unitFrame["curse" .. curseNumber] if remaining >= 0 then curse:SetTexture(Cursive.curses.trackedCurseIds[curseData.spellID].texture) + + if curseData["currentPlayer"] == false then + curse:SetDesaturated(true); -- desaturate if not applied by current player + else + curse:SetDesaturated(false); -- saturate if applied by current player + end + -- curse:SetTexCoord(.078, .92, .079, .937) rounded icons curse.timer:SetText(remaining) curse.timer:Show()