CT_RA_DebuffOptions = { }; CT_RADebuff_CureTable = { [1] = { } }; CT_RADebuff_ActionButtons = { }; CT_RADebuff_NamePriorities = { }; CT_RADebuff_CureSpells = { [CT_RA_PRIEST] = { [CT_RA_MAGIC] = CT_RA_DISPELMAGIC, [CT_RA_DISEASE] = { CT_RA_CUREDISEASE, CT_RA_ABOLISHDISEASE } }, [CT_RA_SHAMAN] = { [CT_RA_DISEASE] = CT_RA_CUREDISEASE, [CT_RA_POISON] = CT_RA_CUREPOISON }, [CT_RA_DRUID] = { [CT_RA_CURSE] = CT_RA_REMOVECURSE, [CT_RA_POISON] = { CT_RA_CUREPOISON, CT_RA_ABOLISHPOISON } }, [CT_RA_MAGE] = { [CT_RA_CURSE] = CT_RA_REMOVELESSERCURSE }, [CT_RA_PALADIN] = { [CT_RA_MAGIC] = CT_RA_CLEANSE, [CT_RA_POISON] = { CT_RA_PURIFY, CT_RA_CLEANSE }, [CT_RA_DISEASE] = { CT_RA_PURIFY, CT_RA_CLEANSE } } }; CT_RADebuff_IgnoreDebuffs = { [CT_RA_DREAMLESSSLEEP] = 1, [CT_RA_GREATERDREAMLESSSLEEP] = 1, [CT_RA_MINDVISION] = 1 }; CT_RA_DebuffTemplates = { [1] = { ["debuffName"] = "Soul Burn", ["name"] = "Soul Burn", ["debuffDesc"] = ".*", ["cureOrder"] = { [1] = 1, [2] = 8, [3] = 15, [4] = 16, [5] = 17, [6] = 10, [7] = 11, [8] = 12, [9] = 14, [10] = 9, [11] = 13, [12] = 5, [13] = 6, [14] = 7, }, ["affectClasses"] = { ["Warrior"] = 1, ["Paladin"] = 1, ["Shaman"] = 1, ["Rogue"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, [2] = { ["debuffName"] = "Mark of Kazzak", ["name"] = "Mark of Kazzak", ["debuffDesc"] = ".*", ["cureOrder"] = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, }, ["affectClasses"] = { ["Paladin"] = 1, ["Shaman"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, [3] = { ["debuffName"] = "Twisted Reflection", ["name"] = "Twisted Reflection", ["debuffDesc"] = ".*", ["cureOrder"] = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, }, ["affectClasses"] = { ["Warrior"] = 1, ["Paladin"] = 1, ["Shaman"] = 1, ["Rogue"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, [4] = { ["debuffName"] = "Dominate Mind", ["name"] = "Dominate Mind", ["debuffDesc"] = ".*", ["cureOrder"] = { [1] = 8, [2] = 9, [3] = 1, [4] = 2, [5] = 3, [6] = 4, [7] = 5, [8] = 6, [9] = 7, }, ["affectClasses"] = { ["Warrior"] = 1, ["Paladin"] = 1, ["Shaman"] = 1, ["Rogue"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, [5] = { ["debuffName"] = "Ignite Mana", ["name"] = "Ignite Mana", ["debuffDesc"] = ".*", ["cureOrder"] = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 7, [7] = 6, [8] = 8, }, ["affectClasses"] = { ["Paladin"] = 1, ["Shaman"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, [6] = { ["debuffName"] = "Mind Control", ["name"] = "Mind Control", ["debuffDesc"] = ".*", ["cureOrder"] = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, }, ["affectClasses"] = { ["Warrior"] = 1, ["Paladin"] = 1, ["Shaman"] = 1, ["Rogue"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, [7] = { ["debuffName"] = ".*", ["name"] = "Silencing Spells", ["debuffDesc"] = ".*Cannot cast spells.*", ["cureOrder"] = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, }, ["affectClasses"] = { ["Warrior"] = 1, ["Paladin"] = 1, ["Shaman"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, [8] = { ["debuffName"] = ".*Polymorph.*", ["name"] = "Polymorph", ["debuffDesc"] = ".*", ["cureOrder"] = { [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, }, ["affectClasses"] = { ["Warrior"] = 1, ["Paladin"] = 1, ["Shaman"] = 1, ["Rogue"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, [9] = { ["debuffName"] = ".*", ["name"] = "All Spells", ["debuffDesc"] = ".*", ["cureOrder"] = { [1] = 1, [2] = 2, [3] = 3, [4] = 8, [5] = 4, [6] = 5, [7] = 6, [8] = 7, }, ["affectClasses"] = { ["Warrior"] = 1, ["Paladin"] = 1, ["Shaman"] = 1, ["Rogue"] = 1, ["Mage"] = 1, ["Pets"] = 1, ["Druid"] = 1, ["Priest"] = 1, ["Hunter"] = 1, ["Warlock"] = 1, }, ["debuffType"] = ".*", }, } CT_RADebuff_ClassIndexes = { [CT_RA_WARRIOR] = 1, [CT_RA_DRUID] = 2, [CT_RA_MAGE] = 3, [CT_RA_WARLOCK] = 4, [CT_RA_ROGUE] = 5, [CT_RA_HUNTER] = 6, [CT_RA_PRIEST] = 7, [CT_RA_PALADIN] = 8, [CT_RA_SHAMAN] = 9 }; -- Thanks to the author of Decursive for the blacklist idea CT_RADebuff_Blacklist = { }; CT_RADebuff_BlacklistTime = 3; CT_RADebuff_Debug = 1; ---------------------------------------------------------------- -- CT_RADebuff_DebugMsg(msg) -- -- Prints a message if the debug flag is enabled. -- ---------------------------------------------------------------- function CT_RADebuff_DebugMsg(msg) if ( CT_RADebuff_Debug ) then CT_Print(msg); end end ---------------------------------------------------------------- -- CT_RADebuff_ProcessBlacklist(elapsed) -- -- Processes the blacklist, removing people when -- -- they have been in there for three seconds. -- ---------------------------------------------------------------- function CT_RADebuff_ProcessBlacklist(elapsed) for k, v in CT_RADebuff_Blacklist do CT_RADebuff_Blacklist[k] = v - elapsed; if ( CT_RADebuff_Blacklist[k] <= 0 ) then CT_RADebuff_Blacklist[k] = nil; end end if ( CT_RADebuff_ResetCombat ) then CT_RADebuff_ResetCombat = CT_RADebuff_ResetCombat - elapsed; if ( CT_RADebuff_ResetCombat <= 0 ) then CT_RADebuff_ResetCombat = nil; if ( not CT_RADebuff_InCombat ) then AttackTarget(); end end end end ---------------------------------------------------------------- -- CT_RADebuff_UpdateCureTable() -- -- Updates the table holding all the debuffs. -- ---------------------------------------------------------------- function CT_RADebuff_UpdateCureTable() CT_RADebuff_CureTable = { }; if ( UnitExists("target") and ( UnitCanAttack("player", "target") or ( not UnitInRaid("target") and not UnitInParty("target") ) ) ) then local useBuffs = UnitDebuff; if ( UnitCanAttack("player", "target") and ( not UnitIsCharmed("target") or not UnitIsFriend("player", "target") ) ) then useBuffs = UnitBuff; end local iIndex = 1; -- Loop through the debuffs while ( useBuffs("target", iIndex) ) do -- Clear and set the tooltip CT_RATooltipTextLeft1:SetText(""); CT_RATooltipTextRight1:SetText(""); CT_RATooltip:SetOwner(WorldFrame, "ANCHOR_NONE"); if ( useBuffs == UnitBuff ) then CT_RATooltip:SetUnitBuff("target", iIndex); else CT_RATooltip:SetUnitDebuff("target", iIndex); end -- Control to make sure we have a new debuff if ( CT_RATooltipTextLeft1:GetText() ~= "" ) then -- Fetch the data local sName, sType, sDesc, iTblIndex = CT_RATooltipTextLeft1:GetText() or "", CT_RATooltipTextRight1:GetText() or "", CT_RATooltipTextLeft2:GetText() or "", -1; if ( sType ~= "" and CT_RADebuff_CanCure(sType) and not CT_RADebuff_IgnoreDebuffs[(sName or "")] ) then -- See if we can find the CT_RA_DebuffTemplates index for k, v in CT_RA_DebuffTemplates do -- See if we have a match if ( string.find(strlower(sName), strlower(v["debuffName"])) and string.find(strlower(sType), strlower(v["debuffType"])) and string.find(strlower(sDesc), strlower(v["debuffDesc"])) ) then iTblIndex = k; break; end end if ( iTblIndex > 0 and ( not CT_RADebuff_CureTable[2] or CT_RADebuff_CureTable[2] > iTblIndex ) ) then -- Clean the table CT_RADebuff_CureTable = { [1] = { { sName, sType, sDesc, "target", CT_RADebuff_ClassIndexes[UnitClass("target")], UnitHealth("target") } }, [2] = iTblIndex }; elseif ( iTblIndex > 0 and iTblIndex == CT_RADebuff_CureTable[2] ) then -- Add the data to the table, as well as class, health percentage, if the player is in your party or if the player is you tinsert(CT_RADebuff_CureTable[1], { sName, sType, sDesc, "target", CT_RADebuff_ClassIndexes[UnitClass("target")], UnitHealth("target") }); end end end iIndex = iIndex + 1; end end if ( GetNumRaidMembers() == 0 ) then local iIndex = 1; -- Loop through the debuffs while ( UnitDebuff("player", iIndex) ) do -- Clear and set the tooltip CT_RATooltipTextLeft1:SetText(""); CT_RATooltipTextRight1:SetText(""); CT_RATooltip:SetUnitDebuff("player", iIndex); -- Control to make sure we have a new debuff if ( CT_RATooltipTextLeft1:GetText() ~= "" ) then -- Fetch the data local sName, sType, sDesc, iTblIndex = CT_RATooltipTextLeft1:GetText() or "", CT_RATooltipTextRight1:GetText() or "", CT_RATooltipTextLeft2:GetText() or "", -1; if ( sType ~= "" and ( UIParent.GetEffectiveScale or CT_RADebuff_CanCure(sType) ) and not CT_RADebuff_IgnoreDebuffs[(sName or "")] ) then -- See if we can find the CT_RA_DebuffTemplates index for k, v in CT_RA_DebuffTemplates do -- See if we have a match if ( string.find(strlower(sName), strlower(v["debuffName"])) and string.find(strlower(sType), strlower(v["debuffType"])) and string.find(strlower(sDesc), strlower(v["debuffDesc"])) ) then iTblIndex = k; break; end end if ( iTblIndex > 0 and ( not CT_RADebuff_CureTable[2] or CT_RADebuff_CureTable[2] > iTblIndex ) ) then -- Clean the table CT_RADebuff_CureTable = { [1] = { { sName, sType, sDesc, "player", CT_RADebuff_ClassIndexes[UnitClass("player")], UnitHealth("player") } }, [2] = iTblIndex }; elseif ( iTblIndex > 0 and iTblIndex == CT_RADebuff_CureTable[2] ) then -- Add the data to the table, as well as class, health percentage, if the player is in your party or if the player is you tinsert(CT_RADebuff_CureTable[1], { sName, sType, sDesc, "player", CT_RADebuff_ClassIndexes[UnitClass("player")], UnitHealth("player") }); end end end iIndex = iIndex + 1; end if ( UnitExists("pet") ) then local iIndex = 1; -- Loop through the debuffs while ( UnitDebuff("pet", iIndex, 1) ) do -- Clear and set the tooltip CT_RATooltipTextLeft1:SetText(""); CT_RATooltipTextRight1:SetText(""); CT_RATooltip:SetUnitDebuff("pet", iIndex); -- Control to make sure we have a new debuff if ( CT_RATooltipTextLeft1:GetText() ~= "" ) then -- Fetch the data local sName, sType, sDesc, iTblIndex = CT_RATooltipTextLeft1:GetText() or "", CT_RATooltipTextRight1:GetText() or "", CT_RATooltipTextLeft2:GetText() or "", -1; if ( sType ~= "" and ( UIParent.GetEffectiveScale or CT_RADebuff_CanCure(sType) ) and not CT_RADebuff_IgnoreDebuffs[(sName or "")] ) then -- See if we can find the CT_RA_DebuffTemplates index for k, v in CT_RA_DebuffTemplates do -- See if we have a match if ( string.find(strlower(sName), strlower(v["debuffName"])) and string.find(strlower(sType), strlower(v["debuffType"])) and string.find(strlower(sDesc), strlower(v["debuffDesc"])) ) then iTblIndex = k; break; end end if ( iTblIndex > 0 and ( not CT_RADebuff_CureTable[2] or CT_RADebuff_CureTable[2] > iTblIndex ) ) then -- Clean the table CT_RADebuff_CureTable = { [1] = { { sName, sType, sDesc, "pet", CT_RADebuff_ClassIndexes[UnitClass("pet")], UnitHealth("pet") } }, [2] = iTblIndex }; elseif ( iTblIndex > 0 and iTblIndex == CT_RADebuff_CureTable[2] ) then -- Add the data to the table, as well as class, health percentage, if the player is in your party or if the player is you tinsert(CT_RADebuff_CureTable[1], { sName, sType, sDesc, "pet", CT_RADebuff_ClassIndexes[UnitClass("pet")], UnitHealth("pet") }); end end end iIndex = iIndex + 1; end end end local prefix, func = "raid", GetNumRaidMembers; if ( GetNumRaidMembers() == 0 and GetNumPartyMembers() > 0 ) then prefix, func = "party", GetNumPartyMembers; end -- Loop through the players in the raid for i = 1, func(), 1 do if ( not UnitCanAttack("player", prefix .. i) or ( UnitIsCharmed(prefix .. i) and UnitIsFriend("player", prefix .. i) ) ) then local iIndex = 1; -- Loop through the debuffs while ( UnitDebuff(prefix .. i, iIndex, 1) ) do -- Clear and set the tooltip CT_RATooltipTextLeft1:SetText(""); CT_RATooltipTextRight1:SetText(""); CT_RATooltip:SetUnitDebuff(prefix .. i, iIndex); -- Control to make sure we have a new debuff if ( CT_RATooltipTextLeft1:GetText() ~= "" ) then -- Fetch the data local sName, sType, sDesc, iTblIndex = CT_RATooltipTextLeft1:GetText() or "", CT_RATooltipTextRight1:GetText() or "", CT_RATooltipTextLeft2:GetText() or "", -1; if ( sType ~= "" and ( UIParent.GetEffectiveScale or CT_RADebuff_CanCure(sType) ) and not CT_RADebuff_IgnoreDebuffs[(sName or "")] ) then -- See if we can find the CT_RA_DebuffTemplates index for k, v in CT_RA_DebuffTemplates do -- See if we have a match if ( string.find(strlower(sName), strlower(v["debuffName"])) and string.find(strlower(sType), strlower(v["debuffType"])) and string.find(strlower(sDesc), strlower(v["debuffDesc"])) ) then iTblIndex = k; break; end end if ( iTblIndex > 0 and ( not CT_RADebuff_CureTable[2] or CT_RADebuff_CureTable[2] > iTblIndex ) ) then -- Clean the table CT_RADebuff_CureTable = { [1] = { { sName, sType, sDesc, prefix .. i, CT_RADebuff_ClassIndexes[UnitClass(prefix .. i)], UnitHealth(prefix .. i) } }, [2] = iTblIndex }; elseif ( iTblIndex > 0 and iTblIndex == CT_RADebuff_CureTable[2] ) then -- Add the data to the table, as well as class, health percentage, if the player is in your party or if the player is you tinsert(CT_RADebuff_CureTable[1], { sName, sType, sDesc, prefix .. i, CT_RADebuff_ClassIndexes[UnitClass(prefix .. i)], UnitHealth(prefix .. i) }); end end end iIndex = iIndex + 1; end end if ( UnitExists(prefix .. "pet" .. i) and ( not UnitCanAttack("player", prefix .. "pet" .. i) or ( UnitIsCharmed(prefix .. "pet" .. i) and UnitIsFriend("player", prefix .. "pet" .. i) ) ) ) then local iIndex = 1; -- Loop through the debuffs while ( UnitDebuff(prefix .. "pet" .. i, iIndex, 1) ) do -- Clear and set the tooltip CT_RATooltipTextLeft1:SetText(""); CT_RATooltipTextRight1:SetText(""); CT_RATooltip:SetUnitDebuff(prefix .. "pet" .. i, iIndex); -- Control to make sure we have a new debuff if ( CT_RATooltipTextLeft1:GetText() ~= "" ) then -- Fetch the data local sName, sType, sDesc, iTblIndex = CT_RATooltipTextLeft1:GetText() or "", CT_RATooltipTextRight1:GetText() or "", CT_RATooltipTextLeft2:GetText() or "", -1; if ( sType ~= "" and ( UIParent.GetEffectiveScale or CT_RADebuff_CanCure(sType) ) and not CT_RADebuff_IgnoreDebuffs[(sName or "")] ) then -- See if we can find the CT_RA_DebuffTemplates index for k, v in CT_RA_DebuffTemplates do -- See if we have a match if ( string.find(strlower(sName), strlower(v["debuffName"])) and string.find(strlower(sType), strlower(v["debuffType"])) and string.find(strlower(sDesc), strlower(v["debuffDesc"])) ) then iTblIndex = k; break; end end if ( iTblIndex > 0 and ( not CT_RADebuff_CureTable[2] or CT_RADebuff_CureTable[2] > iTblIndex ) ) then -- Clean the table CT_RADebuff_CureTable = { [1] = { { sName, sType, sDesc, prefix .. "pet" .. i, CT_RADebuff_ClassIndexes[UnitClass(prefix .. "pet" .. i)], UnitHealth(prefix .. "pet" .. i) } }, [2] = iTblIndex }; elseif ( iTblIndex > 0 and iTblIndex == CT_RADebuff_CureTable[2] ) then -- Add the data to the table, as well as class, health percentage, if the player is in your party or if the player is you tinsert(CT_RADebuff_CureTable[1], { sName, sType, sDesc, prefix .. "pet" .. i, CT_RADebuff_ClassIndexes[UnitClass(prefix .. "pet" .. i)], UnitHealth(prefix .. "pet" .. i) }); end end end iIndex = iIndex + 1; end end end end ---------------------------------------------------------------- -- CT_RADebuff_BeginRangeCheck() -- -- Finds the first cure ability available and uses it for -- -- range measurement. -- ---------------------------------------------------------------- function CT_RADebuff_BeginRangeCheck() -- Returns: -- nil -> Failure -- 0 -> Success -- 1 -> Success & Change target back local shallSwitch = false; if ( UnitExists("target") ) then if ( CT_RADebuff_InCombat ) then resetCombat = 1; end shallSwitch = true; ClearTarget(); end for k, v in CT_RADebuff_CureSpells[UnitClass("player")] do if ( type(v) == "table" ) then for key, val in v do if ( CT_RA_ClassSpells[val] ) then CastSpell(CT_RA_ClassSpells[val]["spell"], CT_RA_ClassSpells[val]["tab"]+1); break; end end else if ( CT_RA_ClassSpells[v] ) then CastSpell(CT_RA_ClassSpells[v]["spell"], CT_RA_ClassSpells[v]["tab"]+1); break; end end end if ( SpellIsTargeting() ) then return 1, ( shallSwitch and 1 ) or 0; else return nil, ( shallSwitch and 1 ) or 0; end end ---------------------------------------------------------------- -- CT_RADebuff_Cure() -- -- Cures the next person in the list, using the chosen order. -- -- This is where most of the curing stuff is done. -- ---------------------------------------------------------------- function CT_RADebuff_Cure() if ( not CT_RADebuff_CureSpells[UnitClass("player")] ) then return; end local cannotCast, cooldownStart, cooldownDuration, oorTargets; for k, v in CT_RADebuff_CureSpells[UnitClass("player")] do if ( type(v) == "table" ) then for key, val in v do if ( CT_RA_ClassSpells[val] ) then cooldownStart, cooldownDuration = GetSpellCooldown(CT_RA_ClassSpells[val]["spell"], SpellBookFrame.bookType); if ( cooldownStart > 0 and cooldownDuration > 0 ) then cannotCast = true; break; end end end else if ( CT_RA_ClassSpells[v] ) then cooldownStart, cooldownDuration = GetSpellCooldown(CT_RA_ClassSpells[v]["spell"], SpellBookFrame.bookType); if ( cooldownStart > 0 and cooldownDuration > 0 ) then cannotCast = true; break; end end end end if ( cannotCast ) then return; end CT_RADebuff_UpdateCureTable(); local success, retarget = CT_RADebuff_BeginRangeCheck(); if ( not success ) then -- We couldn't cast the spell for some reason... SpellStopTargeting(); if ( retarget == 1 ) then TargetLastTarget(); end return; end -- Make sure we have an index if ( CT_RADebuff_CureTable[2] ) then -- Process if we have a target to cure local blacklistTable, blacklistUId, uId, tblIndex; while ( getn(CT_RADebuff_CureTable[1]) > 0 ) do uId, tblIndex = CT_RADebuff_PriorityCure(CT_RA_DebuffTemplates[CT_RADebuff_CureTable[2]]["cureOrder"], CT_RADebuff_CureTable[1], CT_RA_DebuffTemplates[CT_RADebuff_CureTable[2]]["affectClasses"]); if ( uId ) then if ( uId == "target" ) then SpellStopCasting(); TargetLastTarget(); if ( not blacklistUId and CT_RADebuff_Blacklist[UnitName(uId)] ) then blacklistUId, blacklistTable = ( blacklistUId or uId), ( blacklistTable or CT_RADebuff_CureTable[1][tblIndex] ); else local shallReturn = CT_RADebuff_CureTarget(CT_RADebuff_CureTable[1][tblIndex][2], CT_RADebuff_CureTable[1][tblIndex][1], uId); if ( shallReturn == 1 ) then SpellStopTargeting(); if ( retarget == 1 ) then TargetLastTarget(); if ( resetCombat ) then CT_RADebuff_ResetCombat = 1; end end return; elseif ( not oorTargets and shallReturn == -1 ) then oorTargets = { UnitName(uId), CT_RADebuff_CureTable[1][tblIndex][1], CT_RADebuff_CureTable[1][tblIndex][2] }; end end -- Redo the check since we cleared target and spell success, retarget = CT_RADebuff_BeginRangeCheck(); if ( not success ) then -- We couldn't cast the spell for some reason... SpellStopTargeting(); if ( retarget == 1 ) then TargetLastTarget(); end return; end else if ( not blacklistUId and CT_RADebuff_Blacklist[UnitName(uId)] ) then blacklistUId, blacklistTable = ( blacklistUId or uId), ( blacklistTable or CT_RADebuff_CureTable[1][tblIndex] ); else if ( SpellCanTargetUnit(uId) ) then -- Unit could be cast upon! Grab the opportunity local shallReturn = CT_RADebuff_CureTarget(CT_RADebuff_CureTable[1][tblIndex][2], CT_RADebuff_CureTable[1][tblIndex][1], uId); if ( shallReturn == 1 ) then SpellStopTargeting(); if ( retarget == 1 ) then TargetLastTarget(); if ( resetCombat ) then CT_RADebuff_ResetCombat = 1; end end return; end elseif ( not oorTargets and shallReturn == -1 ) then oorTargets = { UnitName(uId), CT_RADebuff_CureTable[1][tblIndex][1], CT_RADebuff_CureTable[1][tblIndex][2] }; end end end elseif ( blacklistUId ) then uId, tblIndex, cureBlacklisted = blacklistUId, 1, 1; tinsert(CT_RADebuff_CureTable[1], 1, blacklistTable); blacklistUId, blacklistTable = nil; end if ( tblIndex ) then -- Remove the previous one, and check again table.remove(CT_RADebuff_CureTable[1], tblIndex); else break; end end if ( oorTargets ) then -- We could not cure due to targets being out of range CT_RA_Print(" Could not cure |c00FFFFFF" .. oorTargets[1] .. "|r of |c00FFFFFF" .. oorTargets[2] .. "|r (|c00FFFFFF" .. oorTargets[3] .. "|r) (out of range?).", 1, 0.5, 0); end end SpellStopTargeting(); if ( retarget == 1 ) then TargetLastTarget(); if ( resetCombat ) then CT_RADebuff_ResetCombat = 1; end end end function CT_RADebuff_Cure_DEPRECATED() if ( not CT_RADebuff_CureSpells[UnitClass("player")] ) then return; end local cannotCast, cooldownStart, cooldownDuration, oorTargets; for k, v in CT_RADebuff_CureSpells[UnitClass("player")] do if ( type(v) == "table" ) then for key, val in v do if ( CT_RA_ClassSpells[val] ) then cooldownStart, cooldownDuration = GetSpellCooldown(CT_RA_ClassSpells[val]["spell"], SpellBookFrame.bookType); if ( cooldownStart > 0 and cooldownDuration > 0 ) then cannotCast = true; break; end end end else if ( CT_RA_ClassSpells[v] ) then cooldownStart, cooldownDuration = GetSpellCooldown(CT_RA_ClassSpells[v]["spell"], SpellBookFrame.bookType); if ( cooldownStart > 0 and cooldownDuration > 0 ) then cannotCast = true; break; end end end end if ( cannotCast ) then return; end CT_RADebuff_UpdateCureTable(); -- Make sure we have an index if ( CT_RADebuff_CureTable[2] ) then -- Process if we have a target to cure local uId, tblIndex = CT_RADebuff_PriorityCure(CT_RA_DebuffTemplates[CT_RADebuff_CureTable[2]]["cureOrder"], CT_RADebuff_CureTable[1], CT_RA_DebuffTemplates[CT_RADebuff_CureTable[2]]["affectClasses"]); local firstBlacklistId, firstBlacklistIndex, firstBlacklistTable, cureBlacklisted; while ( uId ) do if ( UnitIsVisible(uId) ) then if ( not cureBlacklisted and CT_RADebuff_Blacklist[UnitName(uId)] ) then firstBlacklistId, firstBlacklistIndex, firstBlacklistTable = ( firstBlacklistId or uId ), ( firstBlacklistIndex or tblIndex ), CT_RADebuff_CureTable[1][tblIndex]; else local switchTarget, resetCombat; if ( not UnitIsUnit("target", uId) ) then TargetUnit(uId); switchTarget = 1; if ( CT_RADebuff_InCombat ) then resetCombat = 1; end end -- Make sure the target and the unit we're trying to cure are the same if ( UnitIsUnit(uId, "target") ) then -- Shall we perform a range check? if ( CT_RADebuff_ActionButtons[CT_RADebuff_CureTable[1][tblIndex][2]] ) then -- Make sure the spell is in range if ( IsActionInRange(CT_RADebuff_ActionButtons[CT_RADebuff_CureTable[1][tblIndex][2]][2]) == 1 ) then local shallReturn = CT_RADebuff_CureTarget(CT_RADebuff_CureTable[1][tblIndex][2], CT_RADebuff_CureTable[1][tblIndex][1], "target"); if ( switchTarget ) then TargetLastTarget(); switchTarget = nil; if ( resetCombat ) then CT_RADebuff_ResetCombat = 1; end end if ( shallReturn ) then return; end elseif ( not oorTargets ) then oorTargets = { UnitName(uId), CT_RADebuff_CureTable[1][tblIndex][1], CT_RADebuff_CureTable[1][tblIndex][2] }; end else -- If not, just try to target and cure local shallReturn = CT_RADebuff_CureTarget(CT_RADebuff_CureTable[1][tblIndex][2], CT_RADebuff_CureTable[1][tblIndex][1], "target"); if ( switchTarget ) then TargetLastTarget(); switchTarget = nil; if ( resetCombat ) then CT_RADebuff_ResetCombat = 1; end end if ( shallReturn ) then return; end end -- Target the previous target if ( switchTarget ) then TargetLastTarget(); if ( resetCombat ) then CT_RADebuff_ResetCombat = 1; end end elseif ( switchTarget and UnitIsUnit("target", uId) ) then TargetLastTarget(); if ( resetCombat ) then CT_RADebuff_ResetCombat = 1; end end end end -- Remove the previous one, and check again table.remove(CT_RADebuff_CureTable[1], tblIndex); uId, tblIndex = CT_RADebuff_PriorityCure(CT_RA_DebuffTemplates[CT_RADebuff_CureTable[2]]["cureOrder"], CT_RADebuff_CureTable[1], CT_RA_DebuffTemplates[CT_RADebuff_CureTable[2]]["affectClasses"]); if ( not uId and firstBlacklistId ) then uId, tblIndex, cureBlacklisted = firstBlacklistId, firstBlacklistIndex, 1; tinsert(CT_RADebuff_CureTable[1], tblIndex, firstBlacklistTable); firstBlacklistId, firstBlacklistIndex, firstBlacklistTable = nil, nil, nil; end end if ( oorTargets ) then -- We could not cure due to targets being out of range CT_RA_Print(" Could not cure |c00FFFFFF" .. oorTargets[1] .. "|r of |c00FFFFFF" .. oorTargets[2] .. "|r (|c00FFFFFF" .. oorTargets[3] .. "|r), target is out of range.", 1, 0.5, 0); end end end ------------------------------------------------------------------ -- CT_RADebuff_PriorityCure(order, tbl) -- -- Gets the person out of a table that contains the people that -- -- need it most based on the order given -- ------------------------------------------------------------------ function CT_RADebuff_PriorityCure(order, tbl, classes) local currLow, currIndex, currNamePriority, currLowHealth = 99, 99, 99, 99999; local classTbl = { [9] = CT_RA_WARRIOR, [10] = CT_RA_DRUID, [11] = CT_RA_MAGE, [12] = CT_RA_WARLOCK, [13] = CT_RA_ROGUE, [14] = CT_RA_HUNTER, [15] = CT_RA_PRIEST, [16] = CT_RA_PALADIN, [17] = CT_RA_SHAMAN }; for k, v in tbl do if ( CT_RADebuff_NamePriorities[v[1]] ) then v[8] = CT_RADebuff_NamePriorities[v[1]]; end for key, val in order do if ( ( UnitPowerType(v[4]) ~= 2 and classes[UnitClass(v[4])] ) or ( ( UnitPowerType(v[4]) == 2 or UnitCreatureFamily(v[4]) == CT_RA_IMP or UnitCreatureFamily(v[4]) == CT_RA_VOIDWALKER or UnitCreatureFamily(v[4]) == CT_RA_SUCCUBUS or UnitCreatureFamily(v[4]) == CT_RA_FELHUNTER or UnitCreatureFamily(v[4]) == CT_RA_DOOMGUARD or UnitCreatureFamily(v[4]) == CT_RA_INFERNAL ) and classes[CT_RA_PETS] ) ) then -- Target if ( val == 1 and UnitIsUnit(v[4], "target") ) then v[7] = key; break; -- Self elseif ( val == 2 and UnitIsUnit(v[4], "player") ) then v[7] = key; break; -- Party elseif ( val == 3 and UnitInParty(v[4]) ) then v[7] = key; break; -- Pet elseif ( val == 5 and UnitIsUnit(v[4], "pet") ) then v[7] = key; break; -- Party pets elseif ( val == 6 and string.find(v[4], "^partypet%d+$") ) then v[7] = key; break; -- Raid pets elseif ( val == 7 and string.find(v[4], "^raidpet%d+$") ) then v[7] = key; break; -- Main Tanks elseif ( val == 8 and CT_RADebuff_MainTankExists(UnitName(v[4])) ) then v[7] = key; break; -- Classes elseif ( val >= 9 and val <= 17 and classes[classTbl[val]] ) then v[7] = key; break; -- Raid elseif ( val == 4 and UnitInRaid(v[4]) ) then v[7] = key; break; end end end if ( ( ( v[7] and v[7] < currLow ) or ( v[7] and currLow and v[6] and currLowHealth and v[7] <= currLow and v[6] < currLowHealth ) ) and ( ( v[8] or 99 ) <= currNamePriority ) ) then currLow = v[7]; currLowHealth = v[6]; currIndex = k; currNamePriority = ( v[8] or 99 ); end end if ( currLow < 99 ) then return tbl[currIndex][4], currIndex; end end ------------------------------------------------------------------ -- CT_RADebuff_MainTankExists(name) -- -- Returns if the name is one of the main tanks in the raid. -- ------------------------------------------------------------------ function CT_RADebuff_MainTankExists(name) for k, v in CT_RA_MainTanks do if ( v == name ) then return 1; end end return nil; end ------------------------------------------------------------------ -- CT_RADebuff_GetActionButtonCures() -- -- Gets the action buttons that correspond to cure spells. -- ------------------------------------------------------------------ function CT_RADebuff_GetActionButtonCures() CT_RADebuff_ActionButtons = { }; local iIndex = 0; local arr = { [CT_RA_PRIEST] = { [CT_RA_DISPELMAGIC] = { CT_RA_MAGIC, 1 }, [CT_RA_CUREDISEASE] = { CT_RA_DISEASE, 2 }, [CT_RA_ABOLISHDISEASE] = { CT_RA_DISEASE, 1 } }, [CT_RA_SHAMAN] = { [CT_RA_CUREDISEASE] = { CT_RA_DISEASE, 1 }, [CT_RA_CUREPOISON] = { CT_RA_POISON, 1 } }, [CT_RA_DRUID] = { [CT_RA_REMOVECURSE] = { CT_RA_CURSE, 1 }, [CT_RA_CUREPOISON] = { CT_RA_POISON, 2 }, [CT_RA_ABOLISHPOISON] = { CT_RA_POISON, 1 } }, [CT_RA_MAGE] = { [CT_RA_REMOVELESSERCURSE] = { CT_RA_CURSE, 1 } }, [CT_RA_PALADIN] = { [CT_RA_CLEANSE] = { CT_RA_MAGIC, 1 }, [CT_RA_PURIFY] = { CT_RA_DISEASE, 2 }, [CT_RA_CLEANSE] = { CT_RA_DISEASE, 1 }, [CT_RA_PURIFY] = { CT_RA_POISON, 2 }, [CT_RA_CLEANSE] = { CT_RA_POISON, 1 } } }; if ( not arr[UnitClass("player")] ) then return; end -- Loop through the action buttons for i = 1, 120, 1 do if ( HasAction(i) ) then CT_RATooltipTextLeft1:SetText(""); CT_RATooltipTextRight1:SetText(""); CT_RATooltip:SetAction(i); -- Make sure we have a new spell local sName = CT_RATooltipTextLeft1:GetText(); if ( strlen(sName or "") > 0 and strlen(CT_RATooltipTextRight1:GetText() or "") > 0 ) then for key, val in arr[UnitClass("player")] do if ( key == sName and ( not CT_RADebuff_ActionButtons[val[1]] or CT_RADebuff_ActionButtons[val[1]][1] > val[2] ) ) then CT_RADebuff_ActionButtons[val[1]] = { val[2], i, key }; end end end end end end ------------------------------------------------------------------ -- CT_RADebuff_CureTarget(debuffType, debuffName, uId) -- -- Cures the unit id of the debuff type. -- ------------------------------------------------------------------ function CT_RADebuff_CureTarget(debuffType, debuffName, uId) SpellStopTargeting(); if ( CT_RADebuff_CureSpells[UnitClass("player")] and CT_RADebuff_CureSpells[UnitClass("player")][debuffType] ) then local tmp = CT_RADebuff_CureSpells[UnitClass("player")][debuffType]; if ( type(tmp) == "table" ) then for i = getn(tmp), 1, -1 do local spell = CT_RA_ClassSpells[tmp[i]]; if ( spell ) then if ( tmp[i] == CT_RA_ABOLISHDISEASE or tmp[i] == CT_RA_ABOLISHPOISON ) then if ( CT_RADebuff_HasBuff(uId, tmp[i]) ) then return 0; -- Skip end end CastSpell(spell["spell"], spell["tab"]+1); if ( not SpellCanTargetUnit(uId) ) then return -1; -- Flag as OOR end CT_RADebuff_CastingSpell = UnitName(uId); SpellTargetUnit(uId); if ( SpellIsTargeting() ) then return -1; -- Flag as OOR end CT_RA_Print(" Dispelling |c00FFFFFF" .. UnitName(uId) .. "|r of |c00FFFFFF" .. debuffType .. "|r (|c00FFFFFF" .. debuffName .. "|r).", 1, 0.5, 0); return 1; end end else local spell = CT_RA_ClassSpells[tmp]; if ( spell ) then if ( tmp == CT_RA_ABOLISHDISEASE or tmp == CT_RA_ABOLISHPOISON ) then if ( CT_RADebuff_HasBuff(uId, tmp) ) then return 0; -- Skip end end CastSpell(spell["spell"], spell["tab"]+1); if ( not SpellCanTargetUnit(uId) ) then return -1; -- Flag as OOR end CT_RADebuff_CastingSpell = UnitName(uId); SpellTargetUnit(uId); if ( SpellIsTargeting() ) then return -1; -- Flag as OOR end CT_RA_Print(" Dispelling |c00FFFFFF" .. UnitName(uId) .. "|r of |c00FFFFFF" .. debuffType .. "|r (|c00FFFFFF" .. debuffName .. "|r).", 1, 0.5, 0); return 1; end end end return 0; -- Skip end ------------------------------------------------------------------ -- CT_RADebuff_HasBuff(uId, buffName) -- -- Returns true if the unit has a buff named buffName. -- ------------------------------------------------------------------ function CT_RADebuff_HasBuff(uId, buffName) if ( UnitExists(uId) and buffName ~= "" ) then local iIndex = 1; -- Loop through the debuffs while ( UnitBuff(uId, iIndex) ) do -- Clear and set the tooltip CT_RATooltipTextLeft1:SetText(""); CT_RATooltip:SetUnitBuff(uId, iIndex); -- Control to see if we have the buff we're looking for if ( CT_RATooltipTextLeft1:GetText() == buffName ) then return 1; end iIndex = iIndex + 1; end end return nil; end ------------------------------------------------------------------ -- CT_RADebuff_CanCure(debuffType) -- -- Returns if the player can cure the debuff type. -- ------------------------------------------------------------------ function CT_RADebuff_CanCure(debuffType) local arr = { [CT_RA_PRIEST] = { [CT_RA_MAGIC] = CT_RA_DISPELMAGIC, [CT_RA_DISEASE] = { CT_RA_CUREDISEASE, CT_RA_ABOLISHDISEASE } }, [CT_RA_SHAMAN] = { [CT_RA_DISEASE] = CT_RA_CUREDISEASE, [CT_RA_POISON] = CT_RA_CUREPOISON }, [CT_RA_DRUID] = { [CT_RA_CURSE] = CT_RA_REMOVECURSE, [CT_RA_POISON] = { CT_RA_CUREPOISON, CT_RA_ABOLISHPOISON } }, [CT_RA_MAGE] = { [CT_RA_CURSE] = CT_RA_REMOVELESSERCURSE }, [CT_RA_PALADIN] = { [CT_RA_MAGIC] = CT_RA_CLEANSE, [CT_RA_POISON] = { CT_RA_PURIFY, CT_RA_CLEANSE }, [CT_RA_DISEASE] = { CT_RA_PURIFY, CT_RA_CLEANSE } } }; if ( arr[UnitClass("player")] and arr[UnitClass("player")][debuffType] ) then if ( type(arr[UnitClass("player")][debuffType]) == "table" ) then for k, v in arr[UnitClass("player")][debuffType] do if ( CT_RA_ClassSpells[v] ) then return 1; end end elseif ( CT_RA_ClassSpells[arr[UnitClass("player")][debuffType]] ) then return 1; end end return nil; end -- Slash command to cure CT_RA_RegisterSlashCmd("/racure", "Cures a debuff using the debuff curing system. Must be used in a macro.", 15, "RACURE", CT_RADebuff_Cure, "/racure"); -- Hook functions to call CT_RADebuff_GetActionButtonCures CT_RADebuff_oldPlaceAction = PlaceAction; function CT_RADebuff_newPlaceAction(id) CT_RADebuff_oldPlaceAction(id); CT_RADebuff_GetActionButtonCures(); end PlaceAction = CT_RADebuff_newPlaceAction; CT_RADebuff_oldPickupAction = PickupAction; function CT_RADebuff_newPickupAction(id) CT_RADebuff_oldPickupAction(id); CT_RADebuff_GetActionButtonCures(); end PickupAction = CT_RADebuff_newPickupAction; CT_RADebuff_oldUseAction = UseAction; function CT_RADebuff_newUseAction(id, check, self) local rebuild; if ( CursorHasSpell() and not IsShiftKeyDown() ) then rebuild = 1; end CT_RADebuff_oldUseAction(id, check, self); if ( rebuild ) then CT_RADebuff_GetActionButtonCures(); end end UseAction = CT_RADebuff_newUseAction;