--[[
Decursive (v [Link]) add-on for World of Warcraft UI
Copyright (C) 2006 Archarodim ( [Link]
[Link] )
This is the continued work of the original Decursive (v1.9.4) by Quu
Decursive 1.9.4 is in public domain ( [Link] )
License:
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA.
--]]
-------------------------------------------------------------------------------
-- this will spam... really only use it for testing
local Dcr_Print_Spell_Found = false;
-- how many seconds... can be fractional... needs to be more than 0.4... 1.0 is
optimal
local Dcr_SpellCombatDelay = 1.0;
-- print out a fuckload of info
Dcr_Print_DEBUG = false;
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- and any internal HARD settings for decursive
DCR_MAX_LIVE_SLOTS = 15;
local DCR_TEXT_LIFETIME = 4.0;
-------------------------------------------------------------------------------
-- this is something I use for remote debugging
DCR_REMOTE_DEBUG = { };
-------------------------------------------------------------------------------
-- variables {{{
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- The stored variables {{{
-------------------------------------------------------------------------------
Dcr_Saved = {
-- this is the items that are stored...
Dcr_Print_DEBUG_bis = false;
-- this is the priority list of people to cure
PriorityList = { };
-- this is the people to skip
SkipList = { };
-- this is wether or not to show the "live" list
Hide_LiveList = false;
-- This will turn on and off the sending of messages to the default chat frame
Print_ChatFrame = false;
-- this will send the messages to a custom frame that is moveable
Print_CustomFrame = true;
-- this will disable error messages
Print_Error = true;
-- check for abolish before curing poison or disease
Check_For_Abolish = true;
-- this is "fix" for the fact that rank 1 of dispell magic does not always
remove
-- the high level debuffs properly. This carrys over to other things.
AlwaysUseBestSpell = true;
-- should we do the orders randomly?
Random_Order = false;
-- should we scan pets
Scan_Pets = true;
-- should we ignore stealthed units
Ingore_Stealthed = false;
-- how many to show in the livelist
Amount_Of_Afflicted = 5;
-- how many seconds to "black list" someone with a failed spell
CureBlacklist = 5.0;
-- how often to poll for afflictions in seconds
ScanTime = 0.2;
-- Are prio list members protected from blacklisting?
DoNot_Blacklist_Prio_List = false;
-- Play a sound when there is something to decurse
PlaySound = true;
-- Hide the buttons
HideButtons = false;
-- Cure magic if possible
CureMagic = true;
-- Cure Poison if possible
CurePoison = true;
-- Cure Disease if possible
CureDisease = true;
-- Cure Curse if possible
CureCurse = true;
-- Display text above in the custom frame
CustomeFrameInsertBottom = false;
-- Disable tooltips in affliction list
AfflictionTooltips = true;
-- Reverse LiveList Display
ReverseLiveDisplay = false;
-- Hide everything but the livelist
Hidden = false;
-- if true then the live list will show only if the main window is shown
LiveListTied = false;
-- allow to changes the default output window
Dcr_OutputWindow = DEFAULT_CHAT_FRAME;
-- cure order list
CureOrderList = {
[1] = DCR_MAGIC,
[2] = DCR_CURSE,
[3] = DCR_POISON,
[4] = DCR_DISEASE
}
}; -- // }}}
-------------------------------------------------------------------------------
-- This array avoid to test someone we've just blackisted twice.
local DCR_ThisCleanBlaclisted = { };
local Dcr_CuringAction_Icons = { };
-- the new spellbook (made it simpler due to localization problems)
local DCR_HAS_SPELLS = false;
local DCR_SPELL_MAGIC_1 = {0,"", ""};
local DCR_SPELL_MAGIC_2 = {0,"", ""};
DCR_CAN_CURE_MAGIC = false;
local DCR_SPELL_ENEMY_MAGIC_1 = {0,"", ""};
local DCR_SPELL_ENEMY_MAGIC_2 = {0,"", ""};
DCR_CAN_CURE_ENEMY_MAGIC = false;
local DCR_SPELL_DISEASE_1 = {0,"", ""};
local DCR_SPELL_DISEASE_2 = {0,"", ""};
DCR_CAN_CURE_DISEASE = false;
local DCR_SPELL_POISON_1 = {0,"", ""};
local DCR_SPELL_POISON_2 = {0,"", ""};
DCR_CAN_CURE_POISON = false;
local DCR_SPELL_CURSE = {0,"", ""};
DCR_CAN_CURE_CURSE = false;
local DCR_SPELL_COOLDOWN_CHECK = {0,"", ""};
-- for the blacklist
local Dcr_Casting_Spell_On = nil;
local Dcr_Blacklist_Array = { };
local DEBUFF_CACHE_LIFE = 30.0;
local Dcr_Debuff_Texture_to_name_cache = {};
local Dcr_Debuff_Texture_to_name_cache_life = 0.0;
local Dcr_Buff_Texture_to_name_cache = {};
local Dcr_Buff_Texture_to_name_cache_life = 0.0;
local Dcr_CheckingPET = false;
local Dcr_DelayedReconf = false;
Dcr_Groups_datas_are_invalid = false; -- not local because changed from the xml
file when clicking on random cure
local InternalPrioList = { };
local InternalSkipList = { };
local Dcr_Unit_Array = { };
local Dcr_Unit_ArrayByName = { };
local target_added = false;
local SortingTable = {};
local Dcr_CheckPet_Delay = 2;
local Dcr_DelayedReconf_delay = 1;
local Dcr_DelayedReconf_timer = 0;
local Dcr_CheckPet_Timer = 0;
local Dcr_Delay_Timer = 0;
local last_DemonType = nil;
local curr_DemonType = nil;
local Dcr_AlreadyCleanning = false;
local Dcr_RestoreTarget = true;
local Dcr_SoundPlayed = false;
local Dcr_CombatMode = false;
local Dcr_timeLeft = 0;
Dcr_PlayerClass = "";
-- The rotatibg cure table functions array
local Curing_functions = {};
Dcr_CureTypeCheckBoxes = {};
local RestorSelfAutoCastTimeOut = 1;
local RestorSelfAutoCast = false;
-- // }}}
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- The UI functions {{{
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- The printing functions {{{
-------------------------------------------------------------------------------
function Dcr_debug( Message) --{{{
if (Dcr_Print_DEBUG) then
[Link](DCR_REMOTE_DEBUG, Message);
Dcr_Saved.Dcr_OutputWindow:AddMessage(Message, 0.1, 0.1, 1);
end
return true;
end --}}}
function Dcr_debug_bis( Message) --{{{
if (Dcr_Saved.Dcr_Print_DEBUG_bis) then
[Link](DCR_REMOTE_DEBUG, Message);
Dcr_Saved.Dcr_OutputWindow:AddMessage(Message, 0.1, 0.1, 1);
end
return true;
end --}}}
function Dcr_Toggle_debug_bis() --{{{
if (Dcr_Saved.Dcr_Print_DEBUG_bis) then
Dcr_debug_bis("Debug: Disabled");
Dcr_Saved.Dcr_Print_DEBUG_bis = false;
DCR_REMOTE_DEBUG = {};
else
Dcr_Saved.Dcr_Print_DEBUG_bis = true;
Dcr_debug_bis("Debug: Enabled");
end
end --}}}
function MakePlayerName (name) --{{{
return "|cFFFFAA22|Hplayer:" .. name .. "|h" .. [Link](name) .. "|h|r";
end --}}}
function MakeAfflictionName (name) --{{{
if (name) then
return "|cFFFF6622" .. DCR_LOC_AF_TYPE[name] .. "|r";
else
return "";
end
end --}}}
function Dcr_println( Message) --{{{
if (Dcr_Saved.Print_ChatFrame) then
if (Dcr_Saved.Dcr_OutputWindow) then -- this FUCKING variable find the
fucking way of being fucking NIL for some players.... *spitting on LUA language*
Dcr_Saved.Dcr_OutputWindow:AddMessage(Message, 1, 1, 1);
else
DEFAULT_CHAT_FRAME:AddMessage(Message, 1, 1, 1);
end
end
if (Dcr_Saved.Print_CustomFrame) then
DecursiveTextFrame:AddMessage(Message, 1, 1, 1, 0.9);
end
end --}}}
function Dcr_errln( Message) --{{{
if (Dcr_Saved.Print_Error) then
if (Dcr_Saved.Print_ChatFrame) then
if (Dcr_Saved.Dcr_OutputWindow) then -- this FUCKING variable find the
fucking way of being fucking NIL for some players.... *spitting on LUA language*
Dcr_Saved.Dcr_OutputWindow:AddMessage(Message, 1, 0.1, 0.1);
else
DEFAULT_CHAT_FRAME:AddMessage(Message, 1, 0.1, 0.1);
end
end
if (Dcr_Saved.Print_CustomFrame) then
DecursiveTextFrame:AddMessage(Message, 1, 0.1, 0.1, 0.9);
end
end
end --}}}
function Dcr_PrintPriorityList() --{{{
for id, name in Dcr_Saved.PriorityList do
Dcr_println( id.." - "..name);
end
end --}}}
function TMP_pr() --{{{
for index, unit in Dcr_Unit_Array do
Dcr_println( unit.." - "..MakePlayerName((UnitName(unit))) .. " Index:
"..index);
end
end --}}}
-- }}}
-------------------------------------------------------------------------------
-- Show Hide FUNCTIONS -- {{{
function Dcr_ShowHideAfflictedListUI() --{{{-- here for compatibility --
deprecated
Dcr_Hide(false);
end --}}}
function Dcr_ShowHideLiveList(hide) --{{{
-- if hide is requested or if hide is not set and the live-list is shown
if (hide==1 or (not hide and DecursiveAfflictedListFrame:IsVisible())) then
Dcr_Saved.Hide_LiveList = true;
DecursiveAfflictedListFrame:Hide();
else
Dcr_Saved.Hide_LiveList = false;
DecursiveAfflictedListFrame:ClearAllPoints();
DecursiveAfflictedListFrame:SetPoint("TOPLEFT", "DecursiveMainBar",
"BOTTOMLEFT");
DecursiveAfflictedListFrame:Show();
end
if (Dcr_Saved.Hide_LiveList) then
DcrOptionsFrameHideLL:SetChecked(1);
else
DcrOptionsFrameHideLL:SetChecked(0);
end
end --}}}
function Dcr_Hide(hide) --{{{
if (hide==1 or (not hide and DecursiveMainBar:IsVisible())) then
if (Dcr_Saved.LiveListTied) then
Dcr_ShowHideLiveList(1);
end
Dcr_Saved.Hidden = true;
DecursiveMainBar:Hide();
else
if (Dcr_Saved.LiveListTied) then
Dcr_ShowHideLiveList(0);
end
Dcr_Saved.Hidden = false;
DecursiveMainBar:Show();
end
if DecursiveMainBar:IsVisible() and DecursiveAfflictedListFrame:IsVisible()
then
DecursiveAfflictedListFrame:ClearAllPoints();
DecursiveAfflictedListFrame:SetPoint("TOPLEFT", "DecursiveMainBar",
"BOTTOMLEFT");
else
Dcr_Saved.Dcr_OutputWindow:AddMessage(DCR_SHOW_MSG, 0.3, 0.5, 1);
end
end --}}}
function Dcr_ShowHidePriorityListUI() --{{{
if (DecursivePriorityListFrame:IsVisible()) then
DecursivePriorityListFrame:Hide();
else
DecursivePriorityListFrame:Show();
end
end --}}}
-- skip list stuff
function Dcr_ShowHideSkipListUI() --{{{
if (DecursiveSkipListFrame:IsVisible()) then
DecursiveSkipListFrame:Hide();
else
DecursiveSkipListFrame:Show();
end
end --}}}
function Dcr_ShowHideOptionsUI() --{{{
if (DcrOptionsFrame:IsVisible()) then
DcrOptionsFrame:Hide();
else
DcrOptionsFrame:Show();
DcrOptionsFrame2:ClearAllPoints();
DcrOptionsFrame2:SetPoint("TOPLEFT", "DcrOptionsFrame", "TOPRIGHT");
end
end --}}}
function Dcr_ShowHideTextAnchor() --{{{
if (DecursiveAnchor:IsVisible()) then
DecursiveAnchor:Hide();
else
DecursiveAnchor:Show();
end
end --}}}
function Dcr_ShowHideButtons(UseCurrentValue) --{{{
local DecrFrame = "DecursiveMainBar";
local buttons = {
DecrFrame .. "Priority",
DecrFrame .. "Skip",
DecrFrame .. "Options",
DecrFrame .. "Hide",
}
DCRframeObject = getglobal(DecrFrame);
if (not UseCurrentValue) then
Dcr_Saved.HideButtons = (not Dcr_Saved.HideButtons);
end
for _, ButtonName in buttons do
Button = getglobal(ButtonName);
if (Dcr_Saved.HideButtons) then
Button:Hide();
[Link] = 1;
else
Button:Show();
[Link] = 0;
end
end
end --}}}
-- }}}
-- OPTION RELATED FUNCTIONS {{{
function Dcr_ChangeTextFrameDirection(bottom) --{{{
buton = DecursiveAnchorDirection;
if (bottom) then
DecursiveTextFrame:SetInsertMode("BOTTOM");
buton:SetText("v");
else
DecursiveTextFrame:SetInsertMode("TOP");
buton:SetText("^");
end
end --}}}
function Dcr_AmountOfAfflictedSlider_OnShow() --{{{
getglobal(this:GetName().."High"):SetText("15");
getglobal(this:GetName().."Low"):SetText("5");
getglobal(this:GetName() .. "Text"):SetText(DCR_AMOUNT_AFFLIC ..
Dcr_Saved.Amount_Of_Afflicted);
this:SetMinMaxValues(1, 15);
this:SetValueStep(1);
this:SetValue(Dcr_Saved.Amount_Of_Afflicted);
end --}}}
function Dcr_AmountOfAfflictedSlider_OnValueChanged() --{{{
Dcr_Saved.Amount_Of_Afflicted = this:GetValue();
getglobal(this:GetName() .. "Text"):SetText(DCR_AMOUNT_AFFLIC ..
Dcr_Saved.Amount_Of_Afflicted);
end --}}}
function Dcr_ScanTimeSlider_OnShow() --{{{
getglobal(this:GetName().."High"):SetText("1");
getglobal(this:GetName().."Low"):SetText("0.1");
getglobal(this:GetName() .. "Text"):SetText(DCR_SCAN_LENGTH ..
Dcr_Saved.ScanTime);
this:SetMinMaxValues(0.1, 1);
this:SetValueStep(0.1);
this:SetValue(Dcr_Saved.ScanTime);
end --}}}
function Dcr_ScanTimeSlider_OnValueChanged() --{{{
Dcr_Saved.ScanTime = this:GetValue() * 10;
if (Dcr_Saved.ScanTime < 0) then
Dcr_Saved.ScanTime = ceil(Dcr_Saved.ScanTime - 0.5)
else
Dcr_Saved.ScanTime = floor(Dcr_Saved.ScanTime + 0.5)
end
Dcr_Saved.ScanTime = Dcr_Saved.ScanTime / 10;
getglobal(this:GetName() .. "Text"):SetText(DCR_SCAN_LENGTH ..
Dcr_Saved.ScanTime);
end --}}}
function Dcr_CureBlacklistSlider_OnShow() --{{{
getglobal(this:GetName().."High"):SetText("20");
getglobal(this:GetName().."Low"):SetText("1");
getglobal(this:GetName() .. "Text"):SetText(DCR_BLACK_LENGTH ..
Dcr_Saved.CureBlacklist);
this:SetMinMaxValues(1, 20);
this:SetValueStep(0.1);
this:SetValue(Dcr_Saved.CureBlacklist);
end --}}}
function Dcr_CureBlacklistSlider_OnValueChanged() --{{{
Dcr_Saved.CureBlacklist = this:GetValue() * 10;
if (Dcr_Saved.CureBlacklist < 0) then
Dcr_Saved.CureBlacklist = ceil(Dcr_Saved.CureBlacklist - 0.5)
else
Dcr_Saved.CureBlacklist = floor(Dcr_Saved.CureBlacklist + 0.5)
end
Dcr_Saved.CureBlacklist = Dcr_Saved.CureBlacklist / 10;
getglobal(this:GetName() .. "Text"):SetText(DCR_BLACK_LENGTH ..
Dcr_Saved.CureBlacklist);
end --}}}
function Dcr_On_CureOrderCheckBox_Update (CheckBox) -- {{{
--Dcr_debug_bis([Link] .. " cb called");
-- if it's unchecked
if ([Link] ~= 0 and not CheckBox:GetChecked()) then
Dcr_debug_bis("===> UN checked");
-- remove its position in the cure order list
[Link] = 0;
-- remove the debuff type from the saved ordered list
Dcr_tremovebyval(Dcr_Saved.CureOrderList, [Link]);
-- remove the green number before the checkbox text
getglobal(CheckBox:GetName().."LText"):SetText("");
-- if done here then update the actual cure order list
Dcr_SetCureOrderList ();
elseif ( [Link] == 0 and CheckBox:GetChecked()) then -- it seems that
(not [Link]) is not the same than ([Link] == false) in LUA so
we forgot booleans................
Dcr_debug_bis("===> CHECKED");
-- set the object position
[Link] = [Link](Dcr_Saved.CureOrderList) + 1;
-- register its type in the saved list
Dcr_Saved.CureOrderList[[Link]] = [Link];
-- if done here then update the actual cure order list
Dcr_SetCureOrderList ();
end
end -- }}}
function Dcr_SetCureOrderList () -- {{{
-- Dcr_debug_bis("Dcr_SetCureOrderList called");
local i;
local j = 0;
local CheckBox;
local temp_table = {};
-- clear curing functions
Curing_functions = {};
for i=1, 4 do
if (Dcr_Saved.CureOrderList[i]) then
-- set a shortcut to our checkbox object
CheckBox = Dcr_CureTypeCheckBoxes[Dcr_Saved.CureOrderList[i]];
-- re-index Dcr_Saved.CureOrderList
j = j + 1;
temp_table[j] = Dcr_Saved.CureOrderList[i];
-- register the curing function
Curing_functions[j] = [Link];
[Link] = j;
-- set a green number before the checkbox text
getglobal(CheckBox:GetName().."LText"):SetText("|cFF00FF00"..j.."|r ");
end
end
-- save our reordered Dcr_Saved.CureOrderList
Dcr_Saved.CureOrderList = temp_table;
end -- }}}
function VerifyOrderList ()
local TempTable = {};
local i;
Dcr_debug_bis("Verifying CureOrderList...");
-- take the 4 first value of the Dcr_Saved.CureOrderList table
for i=1, 4 do
-- add it only if not already listed
if ( Dcr_Saved.CureOrderList[i] and not Dcr_tcheckforval(TempTable,
Dcr_Saved.CureOrderList[i])) then
TempTable[i] = Dcr_Saved.CureOrderList[i];
Dcr_debug_bis("Already in list: "..TempTable[i]);
end
end
if (Dcr_Saved.CureMagic and not Dcr_tcheckforval(TempTable, DCR_MAGIC
)) then
[Link](TempTable, DCR_MAGIC);
Dcr_debug_bis("Adding " .. DCR_MAGIC);
end
if (Dcr_Saved.CureCurse and not Dcr_tcheckforval(TempTable, DCR_CURSE
)) then
[Link](TempTable, DCR_CURSE);
Dcr_debug_bis("Adding " .. DCR_CURSE);
end
if (Dcr_Saved.CurePoison and not Dcr_tcheckforval(TempTable, DCR_POISON
)) then
[Link](TempTable, DCR_POISON);
Dcr_debug_bis("Adding " .. DCR_POISON);
end
if (Dcr_Saved.CureDisease and not Dcr_tcheckforval(TempTable, DCR_DISEASE
)) then
[Link](TempTable, DCR_DISEASE);
Dcr_debug_bis("Adding " .. DCR_DISEASE);
end
Dcr_Saved.CureOrderList = TempTable;
end
function Dcr_tremovebyval(tab, val) -- {{{
local k;
local v;
for k,v in tab do
if(v==val) then
[Link](tab, k);
return true;
end
end
return false;
end -- }}}
function Dcr_tcheckforval(tab, val) -- {{{
local k;
local v;
for k,v in tab do
if(v==val) then
return true;
end
end
return false;
end -- }}}
-- // }}}
-- this resets the location of the windows
function Dcr_ResetWindow() --{{{
DecursiveMainBar:ClearAllPoints();
DecursiveMainBar:SetPoint("CENTER", "UIParent");
DecursiveMainBar:Show();
DecursiveAfflictedListFrame:ClearAllPoints();
DecursiveAfflictedListFrame:SetPoint("TOPLEFT", "DecursiveMainBar",
"BOTTOMLEFT");
DecursiveAfflictedListFrame:Show();
DecursivePriorityListFrame:ClearAllPoints();
DecursivePriorityListFrame:SetPoint("CENTER", "UIParent");
DecursiveSkipListFrame:ClearAllPoints();
DecursiveSkipListFrame:SetPoint("CENTER", "UIParent");
DecursivePopulateListFrame:ClearAllPoints();
DecursivePopulateListFrame:SetPoint("CENTER", "UIParent");
DcrOptionsFrame:ClearAllPoints();
DcrOptionsFrame:SetPoint("CENTER", "UIParent");
DcrOptionsFrame2:ClearAllPoints();
DcrOptionsFrame2:SetPoint("TOPLEFT", "DcrOptionsFrame", "TOPRIGHT");
end --}}}
function Dcr_ThisSetText(text) --{{{
getglobal(this:GetName().."Text"):SetText(text);
end --}}}
function Dcr_DisplayTooltip(Message, RelativeTo) --{{{
DcrDisplay_Tooltip:SetOwner(RelativeTo, "ANCHOR_TOPRIGHT");
DcrDisplay_Tooltip:ClearLines();
DcrDisplay_Tooltip:SetText(Message);
DcrDisplay_Tooltip:Show();
end --}}}
function Dcr_DebuffTemplate_OnEnter() --{{{
if (Dcr_Saved.AfflictionTooltips) then
DcrDisplay_Tooltip:SetOwner(this, "ANCHOR_CURSOR");
DcrDisplay_Tooltip:ClearLines();
DcrDisplay_Tooltip:SetUnitDebuff([Link],[Link]); -- OK
DcrDisplay_Tooltip:Show();
end
end --}}}
-- Prio and skip list LIST {{{
function Dcr_PriorityListEntryTemplate_OnClick() --{{{
local id = this:GetID();
if (id) then
if ([Link]) then
Dcr_RemoveIDFromPriorityList(id);
else
Dcr_RemoveIDFromSkipList(id);
end
end
[Link] = true;
end --}}}
function Dcr_PriorityListEntryTemplate_OnUpdate() --{{{
if ([Link]) then
[Link] = false;
local baseName = this:GetName();
local NameText = getglobal(baseName.."Name");
local id = this:GetID();
if (id) then
local name
if ([Link]) then
name = Dcr_Saved.PriorityList[id];
else
name = Dcr_Saved.SkipList[id];
end
if (name) then
NameText:SetText(id.." - "..name);
else
NameText:SetText("Error - ID Invalid!");
end
else
NameText:SetText("Error - No ID!");
end
end
end --}}}
function Dcr_PriorityListFrame_OnUpdate() --{{{
if ([Link]) then
[Link] = false;
Dcr_Groups_datas_are_invalid = true;
local baseName = this:GetName();
local up = getglobal(baseName.."Up");
local down = getglobal(baseName.."Down");
local size = [Link](Dcr_Saved.PriorityList);
if (size < 11 ) then
[Link] = 0;
up:Hide();
down:Hide();
else
if ([Link] <= 0) then
[Link] = 0;
up:Hide();
down:Show();
elseif ([Link] >= (size - 10)) then
[Link] = (size - 10);
up:Show();
down:Hide();
else
up:Show();
down:Show();
end
end
local i;
for i = 1, 10 do
local id = ""..i;
if (i < 10) then
id = "0"..i;
end
local btn = getglobal(baseName.."Index"..id);
btn:SetID( i + [Link]);
[Link] = true;
if (i <= size) then
btn:Show();
else
btn:Hide();
end
end
end
end --}}}
function Dcr_SkipListFrame_OnUpdate() --{{{
if ([Link]) then
[Link] = false;
Dcr_Groups_datas_are_invalid = true;
local baseName = this:GetName();
local up = getglobal(baseName.."Up");
local down = getglobal(baseName.."Down");
local size = [Link](Dcr_Saved.SkipList);
if (size < 11 ) then
[Link] = 0;
up:Hide();
down:Hide();
else
if ([Link] <= 0) then
[Link] = 0;
up:Hide();
down:Show();
elseif ([Link] >= (size - 10)) then
[Link] = (size - 10);
up:Show();
down:Hide();
else
up:Show();
down:Show();
end
end
local i;
for i = 1, 10 do
local id = ""..i;
if (i < 10) then
id = "0"..i;
end
local btn = getglobal(baseName.."Index"..id);
btn:SetID( i + [Link]);
[Link] = true;
if (i <= size) then
btn:Show();
else
btn:Hide();
end
end
end
end --}}}
function Dcr_PopulateButtonPress() --{{{
local addFunction = this:GetParent().addFunction;
if ([Link]) then
-- for the class type stuff... we do party
local _, pclass = UnitClass("player");
if (pclass == [Link]) then
addFunction("player");
end
_, pclass = UnitClass("party1");
if (pclass == [Link]) then
addFunction("party1");
end
_, pclass = UnitClass("party2");
if (pclass == [Link]) then
addFunction("party2");
end
_, pclass = UnitClass("party3");
if (pclass == [Link]) then
addFunction("party3");
end
_, pclass = UnitClass("party4");
if (pclass == [Link]) then
addFunction("party4");
end
end
local max = GetNumRaidMembers();
local i;
if (max > 0) then
for i = 1, max do
local _, _, pgroup, _, _, pclass = GetRaidRosterInfo(i);
if ([Link]) then
if (pclass == [Link]) then
addFunction("raid"..i);
end
end
if ([Link]) then
if (pgroup == [Link]) then
addFunction("raid"..i);
end
end
end
end
end --}}}
-- }}}
function Dcr_PlaySound () --{{{
if (Dcr_Saved.PlaySound and not Dcr_SoundPlayed) then
-- good sounds: Sound\\Doodad\\[Link]
-- Sound\\interface\\[Link]
PlaySoundFile("Sound\\Doodad\\[Link]");
Dcr_SoundPlayed = true;
end
end --}}}
-- LIVE DISPLAY functions {{{
function Dcr_AfflictedListFrame_OnUpdate(elapsed) --{{{
-- XXX find the use of this block
if Dcr_Saved.Amount_Of_Afflicted < 1 then
Dcr_Saved.Amount_Of_Afflicted = 1;
elseif Dcr_Saved.Amount_Of_Afflicted > DCR_MAX_LIVE_SLOTS then
Dcr_Saved.Amount_Of_Afflicted = DCR_MAX_LIVE_SLOTS;
end
Dcr_timeLeft = Dcr_timeLeft - elapsed;
if (Dcr_timeLeft <= 0) then
Dcr_timeLeft = Dcr_Saved.ScanTime;
local Dcr_Unit_Array = Dcr_Unit_Array;
local index = 1;
local targetexists = false;
Dcr_GetUnitArray();
-- First scan the current target
if (UnitExists("target") and UnitIsFriend("target", "player")) then
if (UnitIsVisible("target")) then
targetexists = true;
if (Dcr_ScanUnit("target", index)) then
if (index == 1) then
Dcr_PlaySound();
end
index = index + 1;
end
end
end
if (DCR_CAN_CURE_ENEMY_MAGIC) then
for _, unit in Dcr_Unit_Array do
if (index > Dcr_Saved.Amount_Of_Afflicted) then
break;
end
if (UnitIsVisible(unit) and not (targetexists and UnitIsUnit(unit,
"target"))) then
-- if the unit is even close by
if (UnitIsCharmed(unit)) then
-- if the unit is mind controlled
if (Dcr_ScanUnit(unit, index)) then
if (index == 1) then
Dcr_PlaySound();
end
index = index + 1;
end
end
end
end
end
-- Dcr_debug(" normal loop");
for _, unit in Dcr_Unit_Array do
if (index > Dcr_Saved.Amount_Of_Afflicted) then
break;
end
if (UnitIsVisible(unit) and not (targetexists and UnitIsUnit(unit,
"target"))) then
if (not UnitIsCharmed(unit)) then
-- if the unit is even close by
if (Dcr_ScanUnit(unit, index)) then
if (index == 1) then
Dcr_PlaySound();
end
index = index + 1;
end
end
end
end
-- clear livelist
local i;
for i = index, DCR_MAX_LIVE_SLOTS do
if i == 1 then
Dcr_SoundPlayed = false;
end
local Index = i;
if (Dcr_Saved.ReverseLiveDisplay and not (i >
Dcr_Saved.Amount_Of_Afflicted)) then
Index = Dcr_Saved.Amount_Of_Afflicted + -1 * (Index - 1);
end
local item = getglobal("DecursiveAfflictedListFrameListItem"..Index);
[Link] = "player";
[Link] = 0;
item:Hide();
end
-- for testing only
-- Dcr_UpdateLiveDisplay( 1, "player", 1)
end
end --}}}
function Dcr_ScanUnit( Unit, Index) --{{{
local AllUnitDebuffs = {};
AllUnitDebuffs = Dcr_GetUnitDebuffAll(Unit);
for debuff_name, debuff_params in AllUnitDebuffs do
-- test if we have to ignore this debuf {{{ --
if (DCR_IGNORELIST[debuff_name]) then
-- these are the BAD ones... the ones that make the target immune...
abort the user
-- Dcr_debug( [Link]( [Link](DCR_IGNORE_STRING, "$t",
(UnitName(Unit))), "$a", debuff_name));
return false;
end
if (DCR_SKIP_LIST[debuff_name]) then
-- these are just ones you don't care about
-- Dcr_debug( [Link]( [Link](DCR_IGNORE_STRING, "$t",
(UnitName(Unit))), "$a", debuff_name));
break;
end
if (UnitAffectingCombat("player")) then
if (DCR_SKIP_BY_CLASS_LIST[UClass]) then
if (DCR_SKIP_BY_CLASS_LIST[UClass][debuff_name]) then
-- these are just ones you don't care about by class
-- Dcr_debug( [Link]( [Link](DCR_IGNORE_STRING, "$t",
(UnitName(Unit))), "$a", debuff_name));
break;
end
end
end
-- }}}
if (debuff_params.debuff_type and debuff_params.debuff_type ~= "") then --
debuff_type can be an empty string
-- // {{{ --
if (debuff_params.debuff_type == DCR_MAGIC and Dcr_Saved.CureMagic) then
if (UnitIsCharmed(Unit)) then
if (DCR_CAN_CURE_ENEMY_MAGIC) then
Dcr_UpdateLiveDisplay(Index, Unit, debuff_params);
return true;
end
else
if (DCR_CAN_CURE_MAGIC) then
Dcr_UpdateLiveDisplay(Index, Unit, debuff_params);
return true;
end
end
elseif (debuff_params.debuff_type == DCR_DISEASE and
Dcr_Saved.CureDisease) then
if (DCR_CAN_CURE_DISEASE) then
Dcr_UpdateLiveDisplay(Index, Unit, debuff_params);
return true;
end
elseif (debuff_params.debuff_type == DCR_POISON and Dcr_Saved.CurePoison)
then
if (DCR_CAN_CURE_POISON) then
Dcr_UpdateLiveDisplay(Index, Unit, debuff_params);
return true;
end
elseif (debuff_params.debuff_type == DCR_CURSE and Dcr_Saved.CureCurse)
then
if (DCR_CAN_CURE_CURSE) then
-- Dcr_debug_bis("updating for curse");
Dcr_UpdateLiveDisplay(Index, Unit, debuff_params);
return true;
end
end
-- // }}}
end
end
return false;
end --}}}
function Dcr_UpdateLiveDisplay( Index, Unit, debuff_params) --{{{
if (Dcr_Saved.ReverseLiveDisplay) then
Index = Dcr_Saved.Amount_Of_Afflicted + -1 * (Index - 1);
end
local baseFrame = "DecursiveAfflictedListFrameListItem";
local item = getglobal(baseFrame..Index);
if ([Link] == debuff_params.index and item.debuff_name ==
debuff_params.debuff_name and [Link] == Unit and [Link] ==
debuff_params.debuffApplications) then
-- it's already displayed...
return
end
Dcr_debug_bis("Updating: "..baseFrame.. Index);
[Link] = Unit;
item.debuff_name = debuff_params.debuff_name;
[Link] = debuff_params.index;
[Link] = debuff_params.debuffApplications;
getglobal(baseFrame..Index.."DebuffIcon"):SetTexture(debuff_params.DebuffTexture);
if (debuff_params.debuffApplications > 0) then
getglobal(baseFrame..Index.."DebuffCount"):SetText(debuff_params.debuffApplications
);
else
getglobal(baseFrame..Index.."DebuffCount"):SetText("");
end
getglobal(baseFrame..Index.."Name"):SetText(MakePlayerName((UnitName(Unit))));
getglobal(baseFrame..Index.."Type"):SetText(MakeAfflictionName(debuff_params.debuff
_type));
getglobal(baseFrame..Index.."Affliction"):SetText(debuff_params.debuff_name);
--
--
-- [Link] = true;
item:Show();
item = getglobal(baseFrame..Index.."Debuff");
[Link] = Unit;
[Link] = debuff_params.index;
item = getglobal(baseFrame..Index.."ClickMe");
[Link] = Unit;
[Link] = debuff_params.index;
end --}}}
-- }}}
-- // }}}
-------------------------------------------------------------------------------
-- TODO see how to implement a conditional rescan (use RAID_ROSTER_UPDATE)
-------------------------------------------------------------------------------
-- the priority and skip list function... stuff to manage the lists // {{{
-------------------------------------------------------------------------------
function Dcr_AddTargetToPriorityList() --{{{
Dcr_debug( "Adding the target to the priority list");
DcrAddUnitToPriorityList("target");
end --}}}
function DcrAddUnitToPriorityList( unit) --{{{
if (UnitExists(unit)) then
if (UnitIsPlayer(unit)) then
local name = (UnitName( unit));
for _, pname in Dcr_Saved.PriorityList do
if (name == pname) then
return;
end
end
[Link](Dcr_Saved.PriorityList,name);
end
[Link] = true;
end
end --}}}
function Dcr_RemoveIDFromPriorityList(id) --{{{
[Link]( Dcr_Saved.PriorityList,id);
[Link] = true;
end --}}}
function Dcr_ClearPriorityList() --{{{
Dcr_Saved.PriorityList = {};
[Link] = true;
end --}}}
function Dcr_AddTargetToSkipList() --{{{
Dcr_debug( "Adding the target to the Skip list");
DcrAddUnitToSkipList("target");
end --}}}
function DcrAddUnitToSkipList( unit) --{{{
if (UnitExists(unit)) then
if (UnitIsPlayer(unit)) then
local name = (UnitName( unit));
for _, pname in Dcr_Saved.SkipList do
if (name == pname) then
return;
end
end
[Link](Dcr_Saved.SkipList,name);
[Link] = true;
end
end
end --}}}
function Dcr_RemoveIDFromSkipList(id) --{{{
[Link]( Dcr_Saved.SkipList,id);
[Link] = true;
end --}}}
function Dcr_ClearSkipList() --{{{
local i;
Dcr_Saved.SkipList = { };
--[[
local max = [Link](Dcr_Saved.SkipList);
for i = 1, max do
[Link]( Dcr_Saved.SkipList);
end
]]
[Link] = true;
end --}}}
function Dcr_PrintSkipList() --{{{
for id, name in Dcr_Saved.SkipList do
Dcr_println( id.." - "..name);
end
end --}}}
function Dcr_IsInPriorList (name) --{{{
for _, PriorName in Dcr_Saved.PriorityList do
if (PriorName == name) then
return true;
end
end
return false;
end --}}}
function Dcr_IsInSkipList (name) --{{{
for _, SkipName in Dcr_Saved.SkipList do
if (SkipName == name) then
return true;
end
end
return false
end --}}}
function Dcr_IsInSkipOrPriorList( name ) --{{{-- used internally
if (InternalSkipList[name]) then
return true;
end
if (InternalPrioList[name]) then
return true;
end
return false;
end --}}}
-- }}}
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- init functions and configuration functions {{{
-------------------------------------------------------------------------------
StaticPopupDialogs["DCR_DISABLE_AUTOSELFCAST"] = {
text = DCR_DISABLE_AUTOSELFCAST,
button1 = TEXT(ACCEPT),
button2 = TEXT(CANCEL),
OnAccept = function()
SetCVar("autoSelfCast", "0");
end,
timeout = 0,
whileDead = 1,
hideOnEscape = 1,
ShowAlert = 1,
};
function Dcr_CheckAuSelfCastStaus ()
if (GetCVar("autoSelfCast") == "1") then
StaticPopup_Show ("DCR_DISABLE_AUTOSELFCAST", AUTO_SELF_CAST_TEXT);
end
end
function Dcr_Init() --{{{
-- I don't know for you but I personally hate Dcr_Saved.Dcr_OutputWindow...
if (Dcr_Saved.Dcr_OutputWindow == nil or not Dcr_Saved.Dcr_OutputWindow) then
Dcr_Saved.Dcr_OutputWindow = DEFAULT_CHAT_FRAME;
end
Dcr_println(DCR_VERSION_STRING);
Dcr_debug_bis( "Decursive Initialization started!");
-- Dcr_CheckAuSelfCastStaus ();
-- Register the / cmds {{{
Dcr_debug( "Registering the slash commands");
SLASH_DECURSIVE1 = DCR_MACRO_COMMAND;
SlashCmdList["DECURSIVE"] = function(msg)
Dcr_Clean();
end
SLASH_DECURSIVEPRADD1 = DCR_MACRO_PRADD;
SlashCmdList["DECURSIVEPRADD"] = function(msg)
Dcr_AddTargetToPriorityList();
end
SLASH_DECURSIVEPRCLEAR1 = DCR_MACRO_PRCLEAR;
SlashCmdList["DECURSIVEPRCLEAR"] = function(msg)
Dcr_ClearPriorityList();
end
SLASH_DECURSIVEPRLIST1 = DCR_MACRO_PRLIST;
SlashCmdList["DECURSIVEPRLIST"] = function(msg)
Dcr_PrintPriorityList();
end
SLASH_DECURSIVEPRSHOW1 = DCR_MACRO_PRSHOW;
SlashCmdList["DECURSIVEPRSHOW"] = function(msg)
Dcr_ShowHidePriorityListUI();
end
SLASH_DECURSIVESKADD1 = DCR_MACRO_SKADD;
SlashCmdList["DECURSIVESKADD"] = function(msg)
Dcr_AddTargetToSkipList();
end
SLASH_DECURSIVESKCLEAR1 = DCR_MACRO_SKCLEAR;
SlashCmdList["DECURSIVESKCLEAR"] = function(msg)
Dcr_ClearSkipList();
end
SLASH_DECURSIVESKLIST1 = DCR_MACRO_SKLIST;
SlashCmdList["DECURSIVESKLIST"] = function(msg)
Dcr_PrintSkipList();
end
SLASH_DECURSIVESKSHOW1 = DCR_MACRO_SKSHOW;
SlashCmdList["DECURSIVESKSHOW"] = function(msg)
Dcr_ShowHideSkipListUI();
end
SLASH_DECURSIVESHOW1 = DCR_MACRO_SHOW;
SlashCmdList["DECURSIVESHOW"] = function(msg)
Dcr_Hide(0);
end
SLASH_DECURSIVERESET1 = DCR_MACRO_RESET;
SlashCmdList["DECURSIVERESET"] = function(msg)
Dcr_ResetWindow();
end
SLASH_DECURSIVEHIDE1 = DCR_MACRO_HIDE;
SlashCmdList["DECURSIVEHIDE"] = function(msg)
Dcr_Hide(1);
end
SLASH_DECURSIVEOPTION1 = DCR_MACRO_OPTION;
SlashCmdList["DECURSIVEOPTION"] = function(msg)
Dcr_ShowHideOptionsUI();
end
SLASH_DECURSIVEDBGBISTOG1 = DCR_MACRO_DEBUG
SlashCmdList["DECURSIVEDBGBISTOG"] = function(msg)
Dcr_Toggle_debug_bis();
end
-- }}}
if (Dcr_Saved.Hide_LiveList) then
DecursiveAfflictedListFrame:Hide();
else
DecursiveAfflictedListFrame:ClearAllPoints();
DecursiveAfflictedListFrame:SetPoint("TOPLEFT", "DecursiveMainBar",
"BOTTOMLEFT");
DecursiveAfflictedListFrame:Show();
end
if (Dcr_Saved.Hidden) then
DecursiveMainBar:Hide();
else
DecursiveMainBar:Show();
end
if (Dcr_Saved.AlwaysUseBestSpell == nil) then
Dcr_Saved.AlwaysUseBestSpell = true;
end
if (Dcr_Saved.HideButtons == nil) then
Dcr_Saved.HideButtons = false;
end
if (Dcr_Saved.CureMagic == nil) then
Dcr_Saved.CureMagic = true;
end
if (Dcr_Saved.CurePoison == nil) then
Dcr_Saved.CurePoison = true;
end
if (Dcr_Saved.CureDisease == nil) then
Dcr_Saved.CureDisease = true;
end
if (Dcr_Saved.CureCurse == nil) then
Dcr_Saved.CureCurse = true;
end
if (Dcr_Saved.AfflictionTooltips == nil) then
Dcr_Saved.AfflictionTooltips = true;
end
if (Dcr_Saved.CureOrderList == nil) then
Dcr_Saved.CureOrderList = {
[1] = DCR_MAGIC,
[2] = DCR_CURSE,
[3] = DCR_POISON,
[4] = DCR_DISEASE
}
end
Dcr_ShowHideButtons(true);
Dcr_ChangeTextFrameDirection(Dcr_Saved.CustomeFrameInsertBottom);
if (Dcr_Saved.Print_CustomFrame) then
DcrOptionsFrameAnchor:Enable();
else
DcrOptionsFrameAnchor:Disable();
end
-- check the spellbook once
Dcr_Configure();
Dcr_Saved.Dcr_OutputWindow:AddMessage(DCR_IS_HERE_MSG, 0.3, 0.5, 1);
Dcr_Saved.Dcr_OutputWindow:AddMessage(DCR_SHOW_MSG, 0.3, 0.5, 1);
DecursiveTextFrame:SetFading(true);
DecursiveTextFrame:SetFadeDuration(DCR_TEXT_LIFETIME / 3);
DecursiveTextFrame:SetTimeVisible(DCR_TEXT_LIFETIME);
-- add support Earth panel
if(EarthFeature_AddButton) then
EarthFeature_AddButton(
{
id = "Decursive";
name = BINDING_HEADER_DECURSIVE;
subtext = DCR_SKIP_OPT_STR;
tooltip = BINDING_NAME_DCRSHOW;
icon = "Interface\\Icons\\Spell_Nature_RemoveCurse";
callback = Dcr_ShowHidePriorityListUI;
}
);
end
end --}}}
function Dcr_ReConfigure() --{{{
if not DCR_HAS_SPELLS then
return;
end
Dcr_debug_bis("Dcr_ReConfigure was called!");
local DoNotReconfigure = true;
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_MAGIC_1[1],
DCR_SPELL_MAGIC_1[2], DCR_SPELL_MAGIC_1[3]);
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_MAGIC_2[1],
DCR_SPELL_MAGIC_2[2], DCR_SPELL_MAGIC_2[3]);
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_ENEMY_MAGIC_1[1],
DCR_SPELL_ENEMY_MAGIC_1[2], DCR_SPELL_ENEMY_MAGIC_1[3]);
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_ENEMY_MAGIC_2[1],
DCR_SPELL_ENEMY_MAGIC_2[2], DCR_SPELL_ENEMY_MAGIC_2[3]);
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_DISEASE_1[1],
DCR_SPELL_DISEASE_1[2], DCR_SPELL_DISEASE_1[3]);
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_DISEASE_2[1],
DCR_SPELL_DISEASE_2[2], DCR_SPELL_DISEASE_2[3]);
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_POISON_1[1],
DCR_SPELL_POISON_1[2], DCR_SPELL_POISON_1[3]);
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_POISON_2[1],
DCR_SPELL_POISON_2[2], DCR_SPELL_POISON_2[3]);
DoNotReconfigure = Dcr_CheckSpellName(DCR_SPELL_CURSE[1], DCR_SPELL_CURSE[2],
DCR_SPELL_CURSE[3]);
if DoNotReconfigure == false then
Dcr_debug_bis("Dcr_ReConfigure RECONFIGURATION!");
Dcr_Configure();
return;
end
Dcr_debug_bis("Dcr_ReConfigure No reconfiguration required!");
end --}}}
function Dcr_Configure() --{{{
-- first empty out the old "spellbook"
DCR_HAS_SPELLS = false;
DCR_SPELL_MAGIC_1 = {0,"", ""};
DCR_SPELL_MAGIC_2 = {0,"", ""};
DCR_CAN_CURE_MAGIC = false;
DCR_SPELL_ENEMY_MAGIC_1 = {0,"", ""};
DCR_SPELL_ENEMY_MAGIC_2 = {0,"", ""};
DCR_CAN_CURE_ENEMY_MAGIC = false;
DCR_SPELL_DISEASE_1 = {0,"", ""};
DCR_SPELL_DISEASE_2 = {0,"", ""};
DCR_CAN_CURE_DISEASE = false;
DCR_SPELL_POISON_1 = {0,"", ""};
DCR_SPELL_POISON_2 = {0,"", ""};
DCR_CAN_CURE_POISON = false;
DCR_SPELL_CURSE = {0,"", ""};
DCR_CAN_CURE_CURSE = false;
Dcr_debug_bis("Configuring Decursive...");
-- parse through the entire library...
-- look for known cleaning spells...
-- this will be called everytime the spellbook changes
-- this is just used to make things simpler in the checking
local Dcr_Name_Array = {
[DCR_SPELL_CURE_DISEASE] = true,
[DCR_SPELL_ABOLISH_DISEASE] = true,
[DCR_SPELL_PURIFY] = true,
[DCR_SPELL_CLEANSE] = true,
[DCR_SPELL_DISPELL_MAGIC] = true,
[DCR_SPELL_CURE_POISON] = true,
[DCR_SPELL_ABOLISH_POISON] = true,
[DCR_SPELL_REMOVE_LESSER_CURSE] = true,
[DCR_SPELL_REMOVE_CURSE] = true,
[DCR_SPELL_PURGE] = true,
[DCR_PET_FEL_CAST] = true,
[DCR_PET_DOOM_CAST] = true,
}
local i = 1;
local BookType = BOOKTYPE_SPELL;
local break_flag = false
while not break_flag do
while (true) do -- I wish there was a continue statement in LUA...
local spellName, spellRank = GetSpellName(i, BookType);
if (not spellName) then
if (BookType == BOOKTYPE_PET) then
break_flag = true;
break;
end
BookType = BOOKTYPE_PET;
i = 1;
break;
end
Dcr_debug( "Checking spell - "..spellName);
if (Dcr_Name_Array[spellName]) then
Dcr_debug( "Its one we care about");
DCR_HAS_SPELLS = true;
-- any of them will work for the cooldown... we store the last
DCR_SPELL_COOLDOWN_CHECK[1] = i; DCR_SPELL_COOLDOWN_CHECK[2] =
BookType;
-- put it in the range icon array
--local icon = GetSpellTexture(i, BookType)
--Dcr_CuringAction_Icons[icon] = spellName;
-- print out the spell
Dcr_debug( [Link](DCR_SPELL_FOUND, "$s", spellName));
if (Dcr_Print_Spell_Found) then
Dcr_println( [Link](DCR_SPELL_FOUND, "$s", spellName));
end
-- big ass if statement... due to the way that the different
localizations work
-- I used to do this more elegantly... but the german WoW broke it
if ((spellName == DCR_SPELL_CURE_DISEASE) or (spellName ==
DCR_SPELL_ABOLISH_DISEASE) or
(spellName == DCR_SPELL_PURIFY) or (spellName ==
DCR_SPELL_CLEANSE)) then
DCR_CAN_CURE_DISEASE = true;
if ((spellName == DCR_SPELL_CURE_DISEASE) or (spellName ==
DCR_SPELL_PURIFY)) then
Dcr_debug_bis( "Adding to disease 1");
DCR_SPELL_DISEASE_1[1] = i; DCR_SPELL_DISEASE_1[2] = BookType;
DCR_SPELL_DISEASE_1[3] = spellName;
else
Dcr_debug_bis( "Adding to disease 2");
DCR_SPELL_DISEASE_2[1] = i; DCR_SPELL_DISEASE_2[2] = BookType;
DCR_SPELL_DISEASE_2[3] = spellName;
end
end
if ((spellName == DCR_SPELL_CURE_POISON) or (spellName ==
DCR_SPELL_ABOLISH_POISON) or
(spellName == DCR_SPELL_PURIFY) or (spellName ==
DCR_SPELL_CLEANSE)) then
DCR_CAN_CURE_POISON = true;
if ((spellName == DCR_SPELL_CURE_POISON) or (spellName ==
DCR_SPELL_PURIFY)) then
Dcr_debug_bis( "Adding to poison 1");
DCR_SPELL_POISON_1[1] = i; DCR_SPELL_POISON_1[2] = BookType;
DCR_SPELL_POISON_1[3] = spellName;
else
Dcr_debug_bis( "Adding to poison 2");
DCR_SPELL_POISON_2[1] = i; DCR_SPELL_POISON_2[2] = BookType;
DCR_SPELL_POISON_2[3] = spellName;
end
end
if ((spellName == DCR_SPELL_REMOVE_CURSE) or (spellName ==
DCR_SPELL_REMOVE_LESSER_CURSE)) then
Dcr_debug_bis( "Adding to curse");
DCR_CAN_CURE_CURSE = true;
DCR_SPELL_CURSE[1] = i; DCR_SPELL_CURSE[2] = BookType;
DCR_SPELL_CURSE[3] = spellName;
end
if ((spellName == DCR_SPELL_DISPELL_MAGIC) or (spellName ==
DCR_SPELL_CLEANSE) or (spellName == DCR_PET_FEL_CAST) or (spellName ==
DCR_PET_DOOM_CAST)) then
DCR_CAN_CURE_MAGIC = true;
if (spellName == DCR_SPELL_CLEANSE) then
Dcr_debug_bis( "Adding to magic 1");
DCR_SPELL_MAGIC_1[1] = i; DCR_SPELL_MAGIC_1[2] = BookType;
DCR_SPELL_MAGIC_1[3] = spellName;
else
if (spellRank == DCR_SPELL_RANK_1) then
Dcr_debug_bis( "Adding to magic 1");
DCR_SPELL_MAGIC_1[1] = i; DCR_SPELL_MAGIC_1[2] = BookType;
DCR_SPELL_MAGIC_1[3] = spellName;
else
Dcr_debug( "adding to magic 2");
Dcr_debug_bis( "Adding to magic 2");
DCR_SPELL_MAGIC_2[1] = i; DCR_SPELL_MAGIC_2[2] = BookType;
DCR_SPELL_MAGIC_2[3] = spellName;
end
end
end
if ((spellName == DCR_SPELL_DISPELL_MAGIC) or (spellName ==
DCR_SPELL_PURGE) or (spellName == DCR_PET_FEL_CAST) or (spellName ==
DCR_PET_DOOM_CAST)) then
DCR_CAN_CURE_ENEMY_MAGIC = true;
if (spellRank == DCR_SPELL_RANK_1) then
Dcr_debug_bis( "Adding to enemy magic 1");
DCR_SPELL_ENEMY_MAGIC_1[1] = i; DCR_SPELL_ENEMY_MAGIC_1[2] =
BookType; DCR_SPELL_ENEMY_MAGIC_1[3] = spellName;
else
Dcr_debug_bis( "Adding to enemy magic 2");
DCR_SPELL_ENEMY_MAGIC_2[1] = i; DCR_SPELL_ENEMY_MAGIC_2[2] =
BookType; DCR_SPELL_ENEMY_MAGIC_2[3] = spellName;
end
end
end
i = i + 1
end
end
local _, PlayerClass = UnitClass("player");
Dcr_PlayerClass = PlayerClass;
-- verify OrderList consistency
VerifyOrderList();
-- configure the cure order list
Dcr_SetCureOrderList ();
end --}}}
function Dcr_CheckSpellName (id, booktype, spellname) --{{{
if id ~= 0 then
Dcr_debug_bis("testing spell for name changes: id="..id);
local found_spellname, spellrank = GetSpellName(id, booktype);
if spellname ~= found_spellname then
return false;
end
end
return true;
end --}}}
--[[
function Dcr_DecurseChoose (button, )
end
--]]
-- }}}
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- EVENT AND MAIN ONUPDATE FUNCTIONS {{{
-------------------------------------------------------------------------------
function Dcr_OnLoad (Frame) --{{{
Frame:RegisterEvent("PLAYER_LOGIN");
end --}}}
function Dcr_OnEvent (event) --{{{
local Frame = this;
-- Dcr_debug_bis ("Event was catch: " .. event);
if (event == "UNIT_PET" ) then
if (UnitInRaid(arg1) or UnitInParty(arg1)) then
Dcr_Groups_datas_are_invalid = true;
end
if ( arg1 == "player" and not Dcr_CheckingPET) then
Dcr_CheckingPET = true;
Dcr_debug_bis ("PLAYER pet detected! Poll in 2 seconds");
end
return;
elseif (event == "PLAYER_ENTER_COMBAT") then
Dcr_EnterCombat();
return;
elseif (event == "PLAYER_LEAVE_COMBAT") then
Dcr_LeaveCombat();
return;
elseif (event == "UI_ERROR_MESSAGE") then
if (arg1 == SPELL_FAILED_LINE_OF_SIGHT or arg1 == SPELL_FAILED_BAD_TARGETS)
then
Dcr_SpellCastFailed();
-- Throw an error if WE were casting something
if (Dcr_Casting_Spell_On and arg1 == SPELL_FAILED_LINE_OF_SIGHT) then
Dcr_errln("Out of sight!");
end
end
return;
elseif (event == "SPELLCAST_STOP") then
Dcr_SpellWasCast();
return;
elseif (not Dcr_DelayedReconf and event == "SPELLS_CHANGED" and arg1==nil) then
Dcr_DelayedReconf = true;
return;
elseif (event == "PARTY_MEMBERS_CHANGED" or event == "PARTY_LEADER_CHANGED")
then
Dcr_Groups_datas_are_invalid = true;
Dcr_debug_bis("Groups changed");
return;
elseif (event == "LEARNED_SPELL_IN_TAB") then
Dcr_Configure();
return;
end
if (event == "PLAYER_LOGIN") then
Frame:RegisterEvent("PLAYER_ENTERING_WORLD");
Frame:RegisterEvent("PLAYER_LEAVING_WORLD");
Dcr_Init();
return;
end
if (
(event == "PLAYER_ENTERING_WORLD")
) then
Dcr_Groups_datas_are_invalid = true;
Frame:RegisterEvent("PLAYER_ENTER_COMBAT");
Frame:RegisterEvent("PLAYER_LEAVE_COMBAT");
-- Frame:RegisterEvent("SPELLCAST_FAILED");
-- Frame:RegisterEvent("SPELLCAST_INTERRUPTED");
Frame:RegisterEvent("SPELLCAST_STOP");
Frame:RegisterEvent("UNIT_PET");
Frame:RegisterEvent("SPELLS_CHANGED");
Frame:RegisterEvent("LEARNED_SPELL_IN_TAB");
Frame:RegisterEvent("UI_ERROR_MESSAGE");
Frame:RegisterEvent("PARTY_MEMBERS_CHANGED");
Frame:RegisterEvent("PARTY_LEADER_CHANGED");
elseif (event == "PLAYER_LEAVING_WORLD") then
Frame:UnregisterEvent("PLAYER_ENTER_COMBAT");
Frame:UnregisterEvent("PLAYER_LEAVE_COMBAT");
-- Frame:UnregisterEvent("SPELLCAST_FAILED");
-- Frame:UnregisterEvent("SPELLCAST_INTERRUPTED");
Frame:UnregisterEvent("SPELLCAST_STOP");
Frame:UnregisterEvent("UNIT_PET");
Frame:UnregisterEvent("SPELLS_CHANGED");
Frame:UnregisterEvent("LEARNED_SPELL_IN_TAB");
Frame:UnregisterEvent("UI_ERROR_MESSAGE");
Frame:UnregisterEvent("PARTY_MEMBERS_CHANGED");
Frame:UnregisterEvent("PARTY_LEADER_CHANGED");
end
end --}}}
-- This function update Decursive states :
-- - Reconf if needed
-- - check for a pet
-- - clear the black list
-- - clear cached buff and debuffs
function Dcr_OnUpdate(arg1) --{{{
--checkinfgfor reconf need
if Dcr_DelayedReconf then
Dcr_DelayedReconf_timer = Dcr_DelayedReconf_timer + arg1;
if (Dcr_DelayedReconf_timer >= Dcr_DelayedReconf_delay) then
Dcr_DelayedReconf_timer = 0;
Dcr_ReConfigure();
Dcr_DelayedReconf = false;
return;
end
end
-- checking for pet
if (Dcr_CheckingPET) then
Dcr_CheckPet_Timer = Dcr_CheckPet_Timer + arg1;
if (Dcr_CheckPet_Timer >= Dcr_CheckPet_Delay) then
Dcr_CheckPet_Timer = 0;
curr_DemonType = UnitCreatureFamily("pet");
if (curr_DemonType) then Dcr_debug_bis ("Pet Type: " .. curr_DemonType);
end;
if (last_DemonType ~= curr_DemonType) then
if (curr_DemonType) then Dcr_debug_bis ("Pet name changed: " ..
curr_DemonType); else Dcr_debug_bis ("No more pet!"); end;
last_DemonType = curr_DemonType;
Dcr_Configure();
end
Dcr_CheckingPET = false;
return;
end
end
-- clean up the blacklist
for unit in Dcr_Blacklist_Array do
Dcr_Blacklist_Array[unit] = Dcr_Blacklist_Array[unit] - arg1;
if (Dcr_Blacklist_Array[unit] < 0) then
Dcr_Blacklist_Array[unit] = nil;
end
end
-- wow the next command SPAMS alot
-- Dcr_debug("got update "..arg1);
-- this is the fix for the AttackTarget() bug
if (Dcr_Delay_Timer > 0) then
Dcr_Delay_Timer = Dcr_Delay_Timer - arg1;
if (Dcr_Delay_Timer <= 0) then
if (not Dcr_CombatMode) then
Dcr_debug("trying to reset the combat mode");
AttackTarget();
else
Dcr_debug("already in combat mode");
end
end;
end
-- clear Debuffs and Buffs caches
if (Dcr_Debuff_Texture_to_name_cache_life ~= 0) then
Dcr_Debuff_Texture_to_name_cache_life = Dcr_Debuff_Texture_to_name_cache_life
- arg1;
if (Dcr_Debuff_Texture_to_name_cache_life < 0) then
Dcr_Debuff_Texture_to_name_cache_life = 0;
Dcr_Debuff_Texture_to_name_cache = {};
Dcr_debug_bis("Debuff cache cleared!");
end
end
if (Dcr_Buff_Texture_to_name_cache_life ~= 0) then
Dcr_Buff_Texture_to_name_cache_life = Dcr_Buff_Texture_to_name_cache_life -
arg1;
if (Dcr_Buff_Texture_to_name_cache_life < 0) then
Dcr_Buff_Texture_to_name_cache_life = 0;
Dcr_Buff_Texture_to_name_cache = {};
Dcr_debug_bis("Buff cache cleared!");
end
end
if (RestorSelfAutoCast) then
RestorSelfAutoCastTimeOut = RestorSelfAutoCastTimeOut - arg1;
if (RestorSelfAutoCastTimeOut < 0) then
RestorSelfAutoCast = false;
SetCVar("autoSelfCast", "1");
Dcr_debug_bis("autoSelfCast restored!");
end
end
end --}}}
-- the combat saver functions and events. These keep us in combat mode // {{{
-------------------------------------------------------------------------------
function Dcr_EnterCombat() --{{{
Dcr_debug("Entering combat");
Dcr_CombatMode = true;
end --}}}
function Dcr_LeaveCombat() --{{{
Dcr_debug("Leaving combat");
Dcr_CombatMode = false;
end --}}}
-- }}}
function Dcr_SpellCastFailed() --{{{
if (
Dcr_Casting_Spell_On -- a cast failed and we were casting on someone
and not (
UnitIsUnit(Dcr_Casting_Spell_On, "player") -- we do not blacklist ourself
or
(
-- we do not blacklist people in the priority list
Dcr_Saved.DoNot_Blacklist_Prio_List and Dcr_IsInPriorList
( (UnitName(Dcr_Casting_Spell_On)) )
)
)
) then
Dcr_Blacklist_Array[Dcr_Casting_Spell_On] = nil;
Dcr_Blacklist_Array[Dcr_Casting_Spell_On] = Dcr_Saved.CureBlacklist;
DCR_ThisCleanBlaclisted[Dcr_Casting_Spell_On] = true;
end
end --}}}
function Dcr_SpellWasCast() --{{{
Dcr_Casting_Spell_On = nil;
end --}}}
-- }}}
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Scanning functionalties {{{
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- GROUP STATUS UPDATE, these functions update the UNIT table to scan {{{
-------------------------------------------------------------------------------
-- this gets an array of units for us to check
function Dcr_GetUnitArray() --{{{
-- if the groups composition did not changed
if (not Dcr_Groups_datas_are_invalid) then
return;
end
Dcr_debug_bis ("|cFFFF44FF-->|r Updating Units Array");
local pname;
local raidnum = GetNumRaidMembers();
local MyName = (UnitName( "player"));
local SortIndex = 1;
-- clear all the arrays
InternalPrioList = { };
InternalSkipList = { };
Dcr_Unit_Array = { };
SortingTable = { };
-- First sort the prioritylist (remove missing units) and add its content to
the main list
for _, pname in Dcr_Saved.PriorityList do
local unit = Dcr_NameToUnit( pname );
if (unit) then
InternalPrioList[pname] = unit;
-- use this loop to add prio characters to the main list
Dcr_Unit_Array[pname] = unit;
Dcr_AddToSort(unit, SortIndex); SortIndex = SortIndex + 1;
end
end
-- The same with the skip list
for _, pname in Dcr_Saved.SkipList do
local unit = Dcr_NameToUnit( pname );
if (unit) then
InternalSkipList[pname] = unit;
end
end
-- Add the player to the main list if needed
if (not Dcr_IsInSkipOrPriorList(MyName)) then
Dcr_Unit_Array[MyName] = "player";
Dcr_AddToSort( "player", SortIndex); SortIndex = SortIndex + 1;
end
-- add the party members... if they exist
for i = 1, 4 do
if (UnitExists("party"..i)) then
pname = (UnitName("party"..i));
if (not pname) then -- at logon sometimes pname is nil...
pname = "party"..i;
end
-- check the name to see if we skip
if (not Dcr_IsInSkipOrPriorList(pname)) then
-- we don't skip him
Dcr_Unit_Array[pname] = "party"..i;
Dcr_AddToSort("party"..i, SortIndex); SortIndex = SortIndex + 1;
end
end
end
if ( raidnum > 0 ) then -- if we are in a raid
local temp_raid_table = {}; -- used to avoid the repeated call of
GetRaidRosterInfo
local currentGroup = 0;
-- Cache the raid roster info eliminating useless info and already listed
members
for i = 1, raidnum do
local rName, _, rGroup = GetRaidRosterInfo(i);
-- find our group (a whole iteration is required, raid info are not
ordered)
if ( currentGroup==0 and rName == MyName) then
currentGroup = rGroup;
end
-- add all except: our own group and member to skip
if (currentGroup ~= rGroup and not Dcr_IsInSkipOrPriorList(rName)) then
temp_raid_table[i] = {};
if (not rName) then -- at logon sometimes rName is nil...
rName = rGroup.."unknown"..i;
end
temp_raid_table[i].rName = rName;
temp_raid_table[i].rGroup = rGroup;
temp_raid_table[i].rIndex = i; -- I can't trust lua, the manual is
not clear at all about table behavior...
end
end
for _, raidMember in temp_raid_table do
if ([Link] > currentGroup) then
Dcr_Unit_Array[[Link]] = "raid" .. [Link];
-- add first the groups that are after ours
Dcr_AddToSort("raid" .. [Link], [Link] * 100
+ SortIndex); SortIndex = SortIndex + 1;
end
if ([Link] < currentGroup) then
Dcr_Unit_Array[[Link]] = "raid" .. [Link];
-- add then the groups that are before ours
Dcr_AddToSort("raid" .. [Link], [Link] * 100
+ 1000 + SortIndex); SortIndex = SortIndex + 1;
end
end
SortIndex = SortIndex + 8 * 100 + 1000 + 1;
end -- END if we are in a raid
-- Exit if we don't have to scan pets...
if ( Dcr_Saved.Scan_Pets) then
-- add our own pet
if (UnitExists("pet")) then
Dcr_Unit_Array[(UnitName("pet"))] = "pet";
Dcr_AddToSort("pet", SortIndex); SortIndex = SortIndex + 1;
end
-- the parties pets if they have them
for i = 1, 4 do
if (UnitExists("partypet"..i)) then
pname = (UnitName("partypet"..i));
if (not pname) then -- at logon sometimes pname is nil...
pname = "partypet"..i;
end
Dcr_Unit_Array[pname] = "partypet"..i;
Dcr_AddToSort("partypet"..i, SortIndex); SortIndex = SortIndex + 1;
end
end
-- and then the raid pets if they are out
if (raidnum > 0) then
for i = 1, raidnum do
if (UnitExists("raidpet"..i)) then
pname = (UnitName("raidpet"..i));
if (not pname) then -- at logon sometimes pname is nil...
pname = "raidpet"..i;
end
-- add it only of not already in
if (not Dcr_Unit_Array[pname]) then
Dcr_Unit_Array[pname] = "raidpet"..i;
Dcr_AddToSort("raidpet"..i, SortIndex); SortIndex = SortIndex +
1;
end
end
end
end
end
local Lua_Table_Library_Is_Really_A_Piece_Of_Shit = {};
for _, value in Dcr_Unit_Array do
[Link](Lua_Table_Library_Is_Really_A_Piece_Of_Shit, value);
end
Dcr_Unit_ArrayByName = Dcr_Unit_Array;
Dcr_Unit_Array = Lua_Table_Library_Is_Really_A_Piece_Of_Shit;
[Link](Dcr_Unit_Array, function (a,b) return SortingTable[a] <
SortingTable[b] end);
target_added = false;
Dcr_Groups_datas_are_invalid = false;
return;
end --}}}
function Dcr_AddToSort (unit, index) -- // {{{
if (Dcr_Saved.Random_Order and (not InternalPrioList[(UnitName(unit))]) and not
UnitIsUnit(unit,"player")) then
index = random (1, 3000);
end
SortingTable[unit] = index;
-- Dcr_debug_bis(unit.." - "..index.." ");
end --}}}
-- Raid/Party Name Check Function (a terrible function, need optimising)
-- this returns the UnitID that the Name points to
-- this does not check "target" or "mouseover"
function Dcr_NameToUnit( Name) --{{{
if (not Name) then
return false;
elseif (Name == (UnitName("player"))) then
return "player";
elseif (Name == (UnitName("pet"))) then
return "pet";
elseif (Name == (UnitName("party1"))) then
return "party1";
elseif (Name == (UnitName("party2"))) then
return "party2";
elseif (Name == (UnitName("party3"))) then
return "party3";
elseif (Name == (UnitName("party4"))) then
return "party4";
elseif (Name == (UnitName("partypet1"))) then
return "partypet1";
elseif (Name == (UnitName("partypet2"))) then
return "partypet2";
elseif (Name == (UnitName("partypet3"))) then
return "partypet3";
elseif (Name == (UnitName("partypet4"))) then
return "partypet4";
else
local numRaidMembers = GetNumRaidMembers();
if (numRaidMembers > 0) then
-- we are in a raid
local i;
for i=1, numRaidMembers do
local RaidName = GetRaidRosterInfo(i);
if ( Name == RaidName) then
return "raid"..i;
end
if ( Name == (UnitName("raidpet"..i))) then
return "raidpet"..i;
end
end
end
end
return false;
end --}}}
-- }}}
-------------------------------------------------------------------------------
function Dcr_Clean(UseThisTarget, SwitchToTarget) --{{{
-----------------------------------------------------------------------
-- first we do the setup, make sure we can cast the spells
-----------------------------------------------------------------------
-- reset autoSelfCast restor timeout while you're spamming...
RestorSelfAutoCastTimeOut = 1;
if (GetCVar("autoSelfCast") == "1") then
RestorSelfAutoCast = true;
Dcr_debug_bis("autoSelfCast is active... Temp disabling");
SetCVar("autoSelfCast", "0");
end
-- Dcr_CheckAuSelfCastStaus ();
if (not DCR_HAS_SPELLS) then
-- check the spellbook again... (mod by Archarodim)
Dcr_errln(DCR_NO_SPELLS);
Dcr_Configure();
if (not DCR_HAS_SPELLS) then
Dcr_errln(DCR_NO_SPELLS);
return false;
end
end
Dcr_RestoreTarget = true;
if (UseThisTarget and SwitchToTarget) then
TargetUnit(UseThisTarget);
Dcr_RestoreTarget = false;
end
if (Dcr_AlreadyCleanning) then
Dcr_debug_bis("I'm already cleaning!!!!"); -- seems to be useless
return false;
end
Dcr_AlreadyCleanning = true;
-- will cancel anyspell upon Decursive call, may be dangerous...
SpellStopTargeting();
-- always cancel current spell unless it's pet
if ( DCR_SPELL_COOLDOWN_CHECK[2] ~= "pet") then SpellStopCasting(); end
local _, cooldown = GetSpellCooldown(DCR_SPELL_COOLDOWN_CHECK[1],
DCR_SPELL_COOLDOWN_CHECK[2]);
if (cooldown ~= 0) then
-- this used to be an errline... changed it to debugg
Dcr_debug_bis(DCR_NO_SPELLS_RDY);
Dcr_AlreadyCleanning = false;
return false;
end
-- reset blaclisted people in this clean session
DCR_ThisCleanBlaclisted = { };
-- reset the number of out of ranged units for this clean session
DCR_ThisNumberOoRUnits = 0;
-----------------------------------------------------------------------
-----------------------------------------------------------------------
-- then we see what our target looks like, if freindly, check them
-----------------------------------------------------------------------
local targetEnemy = false;
local targetName = nil; -- if friendly
local cleaned = false;
local resetCombatMode = false;
Dcr_Casting_Spell_On = nil;
if (UnitExists("target")) then
Dcr_debug("We have a target");
-- if we are currently targeting something
-- ###
-- This block is here to know what the current target is, so we can clean it,
restor it
-- or clear the target at the end of this function
-- ###
if (Dcr_CombatMode) then
Dcr_debug("when done scanning... if switched target reset the mode!");
resetCombatMode = true;
end
if (
( UnitIsFriend("target", "player") ) -- unit is a friend ie: not FriendLY
just a friend that could be MC :/
and
(not UnitIsCharmed("target")) -- and is not mind controlled
) then
Dcr_debug(" It is friendly");
-- try cleaning the current target first
-- if we are not asked to clean a specific target
-- or if we already switched to the target to clean
if (not UseThisTarget or SwitchToTarget) then
cleaned = Dcr_CureUnit("target");
end
-- we are targeting a player that is not MC, save the name to switch back
later
targetName = (UnitName("target"));
else -- unit is aggressiv or is charmed
Dcr_debug(" It is not friendly");
-- we are targeting an enemy... switch back when done
targetEnemy = true;
if ( UnitIsCharmed("target")) then
Dcr_debug( "Unit is enemey... and charmed... so its a mind controlled
friendly");
-- try cleaning mind controlled person first
if (not UseThisTarget or SwitchToTarget) then
cleaned = Dcr_CureUnit("target");
end
end
end
end
if (UseThisTarget and not SwitchToTarget and not cleaned) then
Dcr_debug( "A target to clean was specifyed");
if (UnitIsVisible(UseThisTarget)) then
-- if the unit is even close by
if (DCR_CAN_CURE_ENEMY_MAGIC and UnitIsCharmed(UseThisTarget)) then
-- if the unit is mind controlled and we can cure it
if (Dcr_CureUnit(UseThisTarget)) then
cleaned = true;
end
else -- we can't cure magic on enemies or the unit is not charmed
if (not Dcr_CheckUnitStealth(UseThisTarget)) then
-- we are either not ignoring the stealthed people,
-- or it's not stealthed
if (Dcr_CureUnit(UseThisTarget)) then
cleaned = true;
end
end
end
end
end
if (not cleaned) then
-----------------------------------------------------------------------
-----------------------------------------------------------------------
-- now we check the partys (raid and local)
-----------------------------------------------------------------------
Dcr_debug( "Checking the arrays");
-- this is the cleaning loops...
Dcr_GetUnitArray();
-- the order is player, party1-4, raid, pet, partypet1-4, raidpet1-40
-- the raid is current party + 1 to 8... then 1 to current party - 1
-- mind control first
if( not cleaned) then
Dcr_debug(" looking for mind controll");
if (DCR_CAN_CURE_ENEMY_MAGIC) then
for _, unit in Dcr_Unit_Array do
-- all of the units...
if (not Dcr_Blacklist_Array[unit]) then
-- if the unit is not black listed
if (UnitIsVisible(unit)) then
-- if the unit is even close by
if (UnitIsCharmed(unit)) then
-- if the unit is mind controlled
if (Dcr_CureUnit(unit)) then
cleaned = true;
break;
end
end
end
end
end
end
end
-- normal cleaning
if( not cleaned) then
-- Dcr_debug(" normal loop");
for _, unit in Dcr_Unit_Array do
-- all of the units...
if (not Dcr_Blacklist_Array[unit]) then
-- if the unit is not black listed
if (UnitIsVisible(unit)) then
-- if the unit is even close by
if (not UnitIsCharmed(unit)) then
-- we can't cure mind controlled people
if (not Dcr_CheckUnitStealth(unit)) then
-- we are either not ignoring the stealthed people,
-- or it's not stealthed
if (Dcr_CureUnit(unit)) then
cleaned = true;
break;
end
end
end
end
end
end
end
if ( not cleaned) then
Dcr_debug(" double check the black list");
for unit in Dcr_Blacklist_Array do
-- now... all of the black listed units
if (not DCR_ThisCleanBlaclisted[unit]) then
-- we do not re-check unit that have been blaclisted just before
if (UnitExists(unit)) then
-- if the unit still exists
if (UnitIsVisible(unit)) then
-- if the unit is even close by
if (not Dcr_CheckUnitStealth(unit)) then
-- we are either not ignoring the stealthed people,
-- or it's not stealthed
if (Dcr_CureUnit(unit)) then
-- hey... we cleaned it... remove from the black list
Dcr_Blacklist_Array[unit] = nil;
cleaned = true;
break;
end
end
end
end
end
end
end
end
-----------------------------------------------------------------------
-----------------------------------------------------------------------
-- ok... done with the cleaning... lets try to clean this up
-- basically switch targets back if they were changed
-----------------------------------------------------------------------
if (not SwitchToTarget) then -- if not explicitly ask to switch to the target
if (targetEnemy) then
-- we had somethign "bad" targeted
if (not UnitIsEnemy("target", "player")) then
-- and we tested for range, cast dispell magic, or some how broke
target... switch back
Dcr_debug("targeting enemy");
TargetUnit("playertarget"); -- XXX to test
if (resetCombatMode) then
-- resetCombatMode is the fix for "auto attack"
Dcr_Delay_Timer = Dcr_SpellCombatDelay;
Dcr_debug("done... now we wait for the leave combat event");
end
end
elseif (targetName) then
-- we had a friendly targeted... switch back if not still targeted
if ( targetName ~= (UnitName("target")) ) then
TargetByName(targetName);
end
else
-- we had nobody targeted originally
if (UnitExists("target")) then
-- we checked for range
ClearTarget();
end
end
end
if (not cleaned) then
Dcr_println( DCR_NOT_CLEANED);
end
Dcr_AlreadyCleanning = false;
return cleaned;
end --}}}
-- Buff and debuffs scanning functions {{{
function Dcr_GetUnitBuff (Unit, i) --{{{
Dcr_ScanningTooltipTextLeft1:SetText("");
Dcr_ScanningTooltip:SetUnitBuff(Unit, i); -- fill this fake thing with buff
info
return Dcr_ScanningTooltipTextLeft1:GetText(); -- get the buff name
end --}}}
function Dcr_GetUnitDebuff (Unit, i) --{{{
local DebuffTexture, debuffApplications, debuff_type;
DebuffTexture, debuffApplications, debuff_type = UnitDebuff(Unit, i);
if (DebuffTexture) then
debuff_name = Dcr_GetUnitDebuffName(Unit, i, DebuffTexture);
return debuff_name, debuff_type, debuffApplications, DebuffTexture;
else
return false, false, false, false;
end
end --}}}
function Dcr_GetUnitDebuffName (Unit, i, DebuffTexture) --{{{
local debuff_name;
if (not Dcr_Debuff_Texture_to_name_cache[DebuffTexture]) then
Dcr_ScanningTooltipTextLeft1:SetText(""); -- clean
Dcr_ScanningTooltip:SetUnitDebuff(Unit, i); -- fill this fake thing with
Debuff info
debuff_name = Dcr_ScanningTooltipTextLeft1:GetText(); -- get the debuff name
from the tooltip
if (debuff_name == nil) then
-- this should only happen when things are "broke"
Dcr_errln("%$#@*& !!! Impossible to get debuff info from tooltip :'(, if
this error continues to show up, type /console reloadui");
Dcr_debug( "Debuff name not found!");
elseif (debuff_name ~= "") then
-- reset cache lifetime
Dcr_Debuff_Texture_to_name_cache_life = DEBUFF_CACHE_LIFE;
Dcr_debug_bis("Debuff cache lifetime RESET (assignement) !");
-- save the name to cache for faster access
Dcr_Debuff_Texture_to_name_cache[DebuffTexture] = debuff_name;
Dcr_debug_bis(debuff_name .. " put in cache ( " .. DebuffTexture ..
" )");
end
else
debuff_name = Dcr_Debuff_Texture_to_name_cache[DebuffTexture];
end
-- reset cache lifetime
-- Dcr_debug_bis("Debuff cache lifetime RESET (normal) !");
Dcr_Debuff_Texture_to_name_cache_life = DEBUFF_CACHE_LIFE;
return debuff_name;
end --}}}
function Dcr_GetUnitDebuffAll (unit) --{{{
local DebuffTexture, debuffApplications, debuff_type, debuff_name, i;
local ThisUnitDebuffs = {};
i = 1;
while (true) do
debuff_name, debuff_type, debuffApplications, DebuffTexture =
Dcr_GetUnitDebuff(unit, i);
if (not debuff_name) then
break;
end
ThisUnitDebuffs[debuff_name] = {};
ThisUnitDebuffs[debuff_name].DebuffTexture = DebuffTexture;
ThisUnitDebuffs[debuff_name].debuffApplications = debuffApplications;
ThisUnitDebuffs[debuff_name].debuff_type = debuff_type;
ThisUnitDebuffs[debuff_name].debuff_name = debuff_name;
ThisUnitDebuffs[debuff_name].index = i;
i = i + 1;
end
return ThisUnitDebuffs;
end --}}}
function Dcr_CheckUnitForBuff(Unit, BuffNameToCheck) --{{{
local i = 1, texture, found_buff_name;
while (true) do
texture = UnitBuff (Unit, i);
if (not texture) then
break;
end
if (not Dcr_Buff_Texture_to_name_cache[texture]) then
found_buff_name = Dcr_GetUnitBuff(Unit, i);
if (found_buff_name == nil) then
-- this should only happen when things are "broke"
Dcr_errln("%$#@*& !!! Impossible to get buff info from tooltip :'(, if
this error continues to show up, type /console reloadui");
Dcr_debug( "Buff name not found!");
elseif (found_buff_name ~= "") then
-- reset cache lifetime
Dcr_Buff_Texture_to_name_cache_life = DEBUFF_CACHE_LIFE;
-- save the name to cache for faster access
Dcr_Buff_Texture_to_name_cache[texture] = found_buff_name;
Dcr_debug_bis(found_buff_name .. " put in cache ( " .. texture ..
" )");
end
else
found_buff_name = Dcr_Buff_Texture_to_name_cache[texture];
end
if (i > 1) then
-- reset cache lifetime
Dcr_Buff_Texture_to_name_cache_life = DEBUFF_CACHE_LIFE;
end
if (found_buff_name == BuffNameToCheck) then
return true;
end
i = i + 1;
end
return false;
end --}}}
function Dcr_CheckUnitStealth(Unit) --{{{
if (Dcr_Saved.Ingore_Stealthed) then
for BuffName in DCR_INVISIBLE_LIST do
if Dcr_CheckUnitForBuff(Unit, BuffName) then
return true;
end
end
end
return false;
end --}}}
-- }}}
function Dcr_UnitInRange(Unit) --{{{
if (CheckInteractDistance(Unit, 4)) then
return true;
end
return false;
end --}}}
-- }}}
-------------------------------------------------------------------------------
-- Curring functions {{{
-------------------------------------------------------------------------------
function Dcr_CureUnit(Unit) --{{{
Dcr_debug( "Scanning to cure unit - "..Unit);
local Magic_Count = 0;
local Disease_Count = 0;
local Poison_Count = 0;
local Curse_Count = 0;
local TClass, UClass = UnitClass(Unit);
local AllUnitDebuffs = {};
AllUnitDebuffs = Dcr_GetUnitDebuffAll(Unit);
local Go_On;
for debuff_name, debuff_params in AllUnitDebuffs do
-- the "break" was not working all that well, so we stor a go on variable
Go_On = true;
Dcr_debug( debuff_name.." found!");
-- test if we have to ignore this debuff {{{ --
-- Ignore the ones that make the target immune... abort the user
if (DCR_IGNORELIST[debuff_name]) then
Dcr_errln( [Link]( [Link](DCR_IGNORE_STRING, "$t",
(UnitName(Unit))), "$a", debuff_name));
return false;
end
-- Ignore debuffs that are in fact buffs
if (DCR_SKIP_LIST[debuff_name]) then
Dcr_errln( [Link]( [Link](DCR_IGNORE_STRING, "$t",
(UnitName(Unit))), "$a", debuff_name));
Go_On = false; -- == continue
end
-- If we are in combat lets see if there is any debuffs we can afford to not
remove until ths fight is over
if (UnitAffectingCombat("player")) then
if (DCR_SKIP_BY_CLASS_LIST[UClass]) then
if (DCR_SKIP_BY_CLASS_LIST[UClass][debuff_name]) then
-- these are just ones you don't care about by class
Dcr_errln( [Link]( [Link](DCR_IGNORE_STRING, "$t",
(UnitName(Unit))), "$a", debuff_name));
Go_On = false; -- == continue
end
end
end
-- }}}
if (Go_On) then
-- it is one we "care" about... lets catalog it -- {{{ --
if (debuff_params.debuff_type and debuff_params.debuff_type ~= "") then
if (debuff_params.debuff_type == DCR_MAGIC) then
Dcr_debug( "it's magic");
Magic_Count = Magic_Count + debuff_params.debuffApplications + 1;
elseif (debuff_params.debuff_type == DCR_DISEASE) then
Dcr_debug( "it's disease");
Disease_Count = Disease_Count + debuff_params.debuffApplications +
1;
elseif (debuff_params.debuff_type == DCR_POISON) then
Dcr_debug( "it's poison");
Poison_Count = Poison_Count + debuff_params.debuffApplications + 1;
elseif (debuff_params.debuff_type == DCR_CURSE) then
Dcr_debug( "it's curse");
Curse_Count = Curse_Count + debuff_params.debuffApplications + 1
else
Dcr_debug( "it's unknown - "..debuff_params.debuff_type);
end
else
Dcr_debug( "it's untyped");
end
-- }}}
end
end
local res = false;
local counts = {};
counts.Magic_Count = Magic_Count;
counts.Curse_Count = Curse_Count;
counts.Poison_Count = Poison_Count;
counts.Disease_Count = Disease_Count;
local i;
for i = 1, 4 do
if Curing_functions[i] then
res = Curing_functions[i](counts, Unit);
if res then
break;
end
end
end
-- order these in the way you find most important
--[[
if (not res) then
res = Dcr_Cure_Magic( counts, Unit);
end
if (not res) then
res = Dcr_Cure_Curse( counts, Unit);
end
if (not res) then
res = Dcr_Cure_Poison( counts, Unit);
end
if (not res) then
res = Dcr_Cure_Disease( counts, Unit);
end
--]]
return res;
end -- // }}}
function Dcr_Cure_Magic(counts, Unit) --{{{
Dcr_debug( "magic count "..counts.Magic_Count);
if (DCR_CAN_CURE_MAGIC) then
Dcr_debug( "Can cure magic");
end
if (DCR_CAN_CURE_ENEMY_MAGIC) then
Dcr_debug( "Can cure enemy magic");
end
if ( (not (DCR_CAN_CURE_MAGIC or DCR_CAN_CURE_ENEMY_MAGIC)) or
(counts.Magic_Count == 0) or not Dcr_Saved.CureMagic) then
-- here is no magical effects... or
-- we can't cure magic don't bother going forward
Dcr_debug( "no magic");
return false;
end
Dcr_debug( "curing magic");
if ( DCR_CAN_CURE_ENEMY_MAGIC and UnitIsCharmed(Unit) and
UnitCanAttack("player", Unit) ) then
-- unit is charmed... and has magic debuffs on them... and we CAN attack it
-- there is a good chance that it is the mind controll type spell
-- the checking for the UnitCanAttack is due to the mind controlled pets and
other enslaves
if (DCR_SPELL_ENEMY_MAGIC_2[1] ~= 0 ) and (Dcr_Saved.AlwaysUseBestSpell or
(counts.Magic_Count > 1) or (DCR_SPELL_MAGIC_1[1] == 0)) then
return Dcr_Cast_CureSpell( DCR_SPELL_ENEMY_MAGIC_2 , Unit,
DCR_CHARMED, true);
else
return Dcr_Cast_CureSpell( DCR_SPELL_ENEMY_MAGIC_1 , Unit,
DCR_CHARMED, true);
end
elseif (DCR_CAN_CURE_MAGIC and (not UnitCanAttack("player", Unit))) then
-- we can cure magic... and the unit is NOT hostile to us (we can't cast on
those)
if (DCR_SPELL_MAGIC_2[1] ~= 0 ) and (Dcr_Saved.AlwaysUseBestSpell or
(counts.Magic_Count > 1) or (DCR_SPELL_MAGIC_1[1] == 0)) then
return Dcr_Cast_CureSpell( DCR_SPELL_MAGIC_2 , Unit, DCR_MAGIC,
DCR_CAN_CURE_ENEMY_MAGIC);
else
return Dcr_Cast_CureSpell( DCR_SPELL_MAGIC_1, Unit, DCR_MAGIC,
DCR_CAN_CURE_ENEMY_MAGIC);
end
-- else
-- what it means:
-- not (DCR_CAN_CURE_ENEMY_MAGIC and UnitIsCharmed(Unit) and
UnitCanAttack("player", Unit)
-- not (DCR_CAN_CURE_MAGIC and (not UnitCanAttack("player", Unit)))
--
-- !DCR_CAN_CURE_ENEMY_MAGIC or !UnitIsCharmed(Unit) or !
UnitCanAttack("player", Unit) =====> not MC or we can't attack it
-- AND
-- !DCR_CAN_CURE_MAGIC UnitCanAttack("player", Unit)
--
-- we can't cure enemy magic
-- Dcr_errln("Something strange happened :/ Dcr_Cure_Magic() did nothing :-
o");
end
return false;
end -- // }}}
function Dcr_Cure_Curse( counts, Unit) -- {{{
if ( (not DCR_CAN_CURE_CURSE) or (counts.Curse_Count == 0) or not
Dcr_Saved.CureCurse) then
-- no curses or no curse curing spells
Dcr_debug( "no curse");
return false;
end
Dcr_debug( "curing curse");
if (UnitIsCharmed(Unit)) then
-- we can not cure a mind contorolled player
return;
end
if (DCR_SPELL_CURSE ~= 0) then
return Dcr_Cast_CureSpell(DCR_SPELL_CURSE, Unit, DCR_CURSE, false);
end
return false;
end -- // }}}
function Dcr_Cure_Poison(counts, Unit) -- {{{
if ( (not DCR_CAN_CURE_POISON) or (counts.Poison_Count == 0) or not
Dcr_Saved.CurePoison) then
-- here is no magical effects... or
-- we can't cure magic don't bother going forward
Dcr_debug( "no poison");
return false;
end
Dcr_debug( "curing poison");
if (UnitIsCharmed(Unit)) then
-- we can not cure a mind contorolled player
return;
end
if (Dcr_Saved.Check_For_Abolish and Dcr_CheckUnitForBuff(Unit,
DCR_SPELL_ABOLISH_POISON)) then
return false;
end
if (DCR_SPELL_POISON_2[1] ~= 0 ) and (Dcr_Saved.AlwaysUseBestSpell or
(counts.Poison_Count > 1)) then
return Dcr_Cast_CureSpell( DCR_SPELL_POISON_2, Unit, DCR_POISON, false);
else
return Dcr_Cast_CureSpell( DCR_SPELL_POISON_1, Unit, DCR_POISON, false);
end
end -- // }}}
function Dcr_Cure_Disease(counts, Unit) --{{{
if ( (not DCR_CAN_CURE_DISEASE) or (counts.Disease_Count == 0) or not
Dcr_Saved.CureDisease) then
-- here is no magical effects... or
-- we can't cure magic don't bother going forward
Dcr_debug( "no disease");
return false;
end
Dcr_debug( "curing disease");
if (UnitIsCharmed(Unit)) then
-- we can not cure a mind contorolled player
return;
end
if (Dcr_Saved.Check_For_Abolish and Dcr_CheckUnitForBuff(Unit,
DCR_SPELL_ABOLISH_DISEASE)) then
return false;
end
if (DCR_SPELL_DISEASE_2[1] ~= 0 ) and (Dcr_Saved.AlwaysUseBestSpell or
(counts.Disease_Count > 1)) then
return Dcr_Cast_CureSpell( DCR_SPELL_DISEASE_2, Unit, DCR_DISEASE, false);
else
return Dcr_Cast_CureSpell( DCR_SPELL_DISEASE_1, Unit, DCR_DISEASE, false);
end
end --}}}
function Dcr_Cast_CureSpell( spellID, Unit, AfflictionType, ClearCurrentTarget) --
{{{
local name = (UnitName(Unit));
if (spellID[1] == 0) then
Dcr_errln("Stupid call to Dcr_Cast_CureSpell() with a null spellID!!!");
return false;
end
-- check to see if we are in range
if (
(spellID[2] ~= BOOKTYPE_PET) and
(not Dcr_UnitInRange(Unit))
) then
-- XXX We do not blacklist out of range people any more, they don't prevent
anything from hapenning
-- it will just spam a bit if there are a lot of them...
-- Dcr_Blacklist_Array[Unit] = nil; -- attempt to remove it
-- Dcr_Blacklist_Array[Unit] = Dcr_Saved.CureBlacklist; -- add it to the
blacklist, hopefully at the end
-- DCR_ThisCleanBlaclisted[Unit] = true;
Dcr_errln( [Link]( [Link](DCR_OUT_OF_RANGE, "$t",
MakePlayerName(name)), "$a", MakeAfflictionName(AfflictionType)));
-- DCR_ThisNumberOoRUnits = DCR_ThisNumberOoRUnits + 1;
return false;
end
Dcr_debug_bis( "try to cast: "..spellID[1] .." - ".. spellID[2]);
local spellName = GetSpellName(spellID[1], spellID[2]);
Dcr_debug( "casting - "..spellName);
-- clear the target if it will interfear
if (ClearCurrentTarget) then
-- it can target enemys... do don't target ANYTHING else
if ( not UnitIsUnit( "target", Unit) ) then
ClearTarget();
end
elseif ( UnitIsFriend( "player", "target") ) then
-- we can accedenally cure friendly targets...
if ( not UnitIsUnit( "target", Unit) ) then
-- and we want to cure someone else who is not targeted
ClearTarget();
end
end
Dcr_println( [Link]( [Link](DCR_CLEAN_STRING, "$t",
MakePlayerName(name)), "$a", MakeAfflictionName(AfflictionType)));
Dcr_debug_bis( "casting on " .. (UnitName(Unit)) .. " -- " .. Unit);
if (spellID[2] == BOOKTYPE_PET or spellID[3] == DCR_SPELL_PURGE) then
TargetUnit(Unit);
end
-- if a spell is awaiting for a target, cancel it
-- if ( SpellIsTargeting()) then
-- SpellStopTargeting();
-- always cancel current spell
-- SpellStopCasting();
-- end
-- cast the spell
Dcr_Casting_Spell_On = Unit;
CastSpell(spellID[1], spellID[2]);
-- if the spell doesn't need a target
if (Dcr_RestoreTarget and (spellID[2] == BOOKTYPE_PET or spellID[3] ==
DCR_SPELL_PURGE)) then
TargetUnit("playertarget"); -- restore previous target
else
-- if the cast succeeded
if (SpellIsTargeting()) then
SpellTargetUnit(Unit);
end
end
-- if the targeting failed (still waiting for a target), cancel the cast
if ( SpellIsTargeting()) then
SpellStopTargeting();
end
return true;
end --}}}
-- }}}
-------------------------------------------------------------------------------