OctoWoW gives each totem element its own global cooldown category (Fire 105, Earth 106, Water 107, Air 108), so one totem per element can be cast at the same time. ThrowSet still stopped after the first totem it cast, as it had to when all totems shared one global cooldown, so "/coe throwset" dropped one totem per key press. - ThrowSet casts every ready, not yet thrown totem of the active set. - A second press within 1 second skips totems whose cast is not yet confirmed, so a double press does not drop them again. "/coe restartset" clears this. - Each element gets its own pending timeout. They shared one name, so casting several at once replaced the earlier timeouts.
1374 lines
48 KiB
Lua
1374 lines
48 KiB
Lua
--[[
|
|
|
|
CALL OF ELEMENTS
|
|
The All-In-One Shaman Addon
|
|
|
|
by Wyverex (2006)
|
|
|
|
|
|
Totem Module / Logical
|
|
|
|
]] if (not COE_Totem) then COE_Totem = {}; end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
stores the original functions hooked by SetupTimerHooks()
|
|
-------------------------------------------------------------------]]
|
|
COE_Totem["TimerHooks"] = {};
|
|
|
|
--[[ =============================================================================================
|
|
|
|
L O G I C
|
|
|
|
================================================================================================]]
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:Rescan
|
|
|
|
PURPOSE: Scans the totems and totem sets
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:Rescan()
|
|
COE:ScanTotems();
|
|
COE:InitTotemSets();
|
|
|
|
-- Reset all active totems
|
|
-- ------------------------
|
|
COE_Totem:ResetTimers();
|
|
|
|
COE.ActiveTotems.Earth = nil;
|
|
COE.ActiveTotems.Fire = nil;
|
|
COE.ActiveTotems.Water = nil;
|
|
COE.ActiveTotems.Air = nil;
|
|
|
|
COE_Totem:UpdateAllFrames();
|
|
COETotemFrame.Reconfigure = true;
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:ThrowTotem
|
|
|
|
PURPOSE: Throws the totem with the specified named id
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ThrowTotem(element, id)
|
|
COE:DebugMessage(
|
|
"COE_Totem:ThrowTotem element and id: " .. element .. " " .. id);
|
|
if (not COE.Initialized) then return; end
|
|
|
|
-- get associated button
|
|
-- ----------------------
|
|
local button = getglobal("COETotem" .. element .. id);
|
|
if (button == nil) then
|
|
COE:Message("Invalid Totem");
|
|
|
|
return;
|
|
end
|
|
|
|
local totem = button.totem;
|
|
if (totem == nil) then
|
|
COE:Message(COESTR_NOTOTEM);
|
|
return;
|
|
end
|
|
|
|
-- throw totem
|
|
-- ------------
|
|
CastSpellByName(totem.SpellName);
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:RankModifierDown
|
|
|
|
PURPOSE: Returns if the rank 1 modifier is currently pressed
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:RankModifierDown()
|
|
|
|
local overridekey = COE_Config:GetSaved(COEOPT_OVERRIDERANK);
|
|
|
|
-- check if the override key is down
|
|
-- ----------------------------------
|
|
if (overridekey == COEMODE_OVERRIDESHIFT and IsShiftKeyDown()) then
|
|
return true;
|
|
|
|
elseif (overridekey == COEMODE_OVERRIDEALT and IsAltKeyDown()) then
|
|
return true;
|
|
|
|
elseif (overridekey == COEMODE_OVERRIDECTRL and IsControlKeyDown()) then
|
|
return true;
|
|
end
|
|
|
|
return false;
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COESched_AdviseTotem
|
|
|
|
PURPOSE: If the totem warning is still active, a notification
|
|
is displayed and the function rescheduled
|
|
-------------------------------------------------------------------]]
|
|
function COESched_AdviseTotem(totem, msg)
|
|
|
|
if (COE_Config:GetSaved(COEOPT_ADVISOR) == 1 and totem.Warn) then
|
|
-- issue warning
|
|
-- --------------
|
|
COE:Notification(string.format(COESTR_CLEANSINGTOTEM, msg),
|
|
COECOL_TOTEMCLEANSING);
|
|
|
|
-- reschedule
|
|
-- -----------
|
|
Chronos.scheduleByName("COEAdvise" .. msg, COE.AdvisorWarningInterval,
|
|
COESched_AdviseTotem, totem, msg);
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COESched_RunAdvisor
|
|
|
|
PURPOSE: Scans the party/raid for debuffs that are curable by
|
|
totems and shows a notification if it finds such
|
|
-------------------------------------------------------------------]]
|
|
function COESched_RunAdvisor()
|
|
|
|
-- advisor still activated?
|
|
-- -------------------------
|
|
if (COE_Config:GetSaved(COEOPT_ADVISOR) == 0) then return; end
|
|
|
|
local warnPoison, warnDisease, warnTremor = false, false, false;
|
|
local poison, disease, tremor;
|
|
|
|
-- scan player first
|
|
-- ------------------
|
|
poison, disease, tremor = COE_Totem:ScanTargetForDebuff("player");
|
|
|
|
warnPoison = warnPoison or poison;
|
|
warnDisease = warnDisease or disease;
|
|
warnTremor = warnTremor or tremor;
|
|
|
|
-- scan party
|
|
-- -----------
|
|
local i;
|
|
for i = 1, GetNumPartyMembers() do
|
|
if (warnPoison and warnDisease and warnTremor) then break end
|
|
|
|
-- scan party member
|
|
-- ------------------
|
|
poison, disease, tremor = COE_Totem:ScanTargetForDebuff("party" .. i);
|
|
|
|
warnPoison = warnPoison or poison;
|
|
warnDisease = warnDisease or disease;
|
|
warnTremor = warnTremor or tremor;
|
|
|
|
-- scan party member's pet
|
|
-- ------------------------
|
|
if (UnitExists("partypet" .. i)) then
|
|
poison, disease, tremor = COE_Totem:ScanTargetForDebuff(
|
|
"partypet" .. i);
|
|
|
|
warnPoison = warnPoison or poison;
|
|
warnDisease = warnDisease or disease;
|
|
warnTremor = warnTremor or tremor;
|
|
end
|
|
end
|
|
|
|
-- issue warnings if necessary
|
|
-- ----------------------------
|
|
if (warnTremor and COE.CleansingTotems.Tremor.Totem and
|
|
(COE.ActiveTotems["Earth"] ~= COE.CleansingTotems.Tremor.Totem or
|
|
not COE_Totem:IsTimerActive(COE.ActiveTotems["Earth"]))) then
|
|
|
|
if (not COE.CleansingTotems.Tremor.Warn) then
|
|
COE.CleansingTotems.Tremor.Warn = true;
|
|
COESched_AdviseTotem(COE.CleansingTotems.Tremor, COESTR_TOTEMTREMOR);
|
|
end
|
|
else
|
|
COE.CleansingTotems.Tremor.Warn = false;
|
|
end
|
|
|
|
if (warnDisease and COE.CleansingTotems.Disease.Totem and
|
|
(COE.ActiveTotems["Water"] ~= COE.CleansingTotems.Disease.Totem or
|
|
not COE_Totem:IsTimerActive(COE.ActiveTotems["Water"]))) then
|
|
|
|
if (not COE.CleansingTotems.Disease.Warn) then
|
|
COE.CleansingTotems.Disease.Warn = true;
|
|
COESched_AdviseTotem(COE.CleansingTotems.Disease,
|
|
COESTR_TOTEMDISEASE);
|
|
end
|
|
else
|
|
COE.CleansingTotems.Disease.Warn = false;
|
|
end
|
|
|
|
if (warnPoison and COE.CleansingTotems.Poison.Totem and
|
|
(COE.ActiveTotems["Water"] ~= COE.CleansingTotems.Poison.Totem or
|
|
not COE_Totem:IsTimerActive(COE.ActiveTotems["Water"]))) then
|
|
|
|
if (not COE.CleansingTotems.Poison.Warn) then
|
|
COE.CleansingTotems.Poison.Warn = true;
|
|
COESched_AdviseTotem(COE.CleansingTotems.Poison, COESTR_TOTEMPOISON);
|
|
end
|
|
else
|
|
COE.CleansingTotems.Poison.Warn = false;
|
|
end
|
|
|
|
-- reschedule
|
|
-- -----------
|
|
Chronos.scheduleByName("COEAdvise", COE.AdvisorInterval, COESched_RunAdvisor);
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:ScanTargetForDebuff
|
|
|
|
PURPOSE: Scans the specified target for debuffs that are
|
|
curable by totems
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ScanTargetForDebuff(target)
|
|
|
|
local slot = 1;
|
|
local poison, disease, tremor = false, false, false;
|
|
|
|
-- iterate over all possible 16 debuff slots
|
|
-- ------------------------------------------
|
|
COETotemTTTextLeft1:SetText("");
|
|
COETotemTTTextRight1:SetText("");
|
|
COETotemTT:SetUnitDebuff(target, slot);
|
|
|
|
local debufftype = COETotemTTTextRight1:GetText();
|
|
local debuffname = COETotemTTTextLeft1:GetText();
|
|
|
|
while (debuffname and slot <= 16 and not (poison and disease and tremor)) do
|
|
|
|
if (debufftype) then
|
|
|
|
if (debufftype == COESTR_POISON) then
|
|
-- it's a poison debuff
|
|
-- ---------------------
|
|
poison = true;
|
|
elseif (debufftype == COESTR_DISEASE) then
|
|
-- it's a disease debuff
|
|
-- ---------------------
|
|
disease = true;
|
|
else
|
|
-- check if it's a debuff curable
|
|
-- by the tremor totem
|
|
-- -------------------------------
|
|
local debuff;
|
|
for debuff in COESTR_TREMOR do
|
|
if (debuffname == COESTR_TREMOR[debuff]) then
|
|
tremor = true;
|
|
break
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
slot = slot + 1;
|
|
COETotemTTTextLeft1:SetText("");
|
|
COETotemTTTextRight1:SetText("");
|
|
COETotemTT:SetUnitDebuff(target, slot);
|
|
|
|
debufftype = COETotemTTTextRight1:GetText();
|
|
debuffname = COETotemTTTextLeft1:GetText();
|
|
end
|
|
|
|
return poison, disease, tremor;
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:ThrowAdvisedTotem
|
|
|
|
PURPOSE: If there is an advised totem waiting to be thrown
|
|
is is done here
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ThrowAdvisedTotem()
|
|
|
|
if (COE.CleansingTotems.Tremor.Warn and
|
|
(COE.ActiveTotems.Earth ~= COE.CleansingTotems.Tremor.Totem or
|
|
not COE_Totem:IsTimerActive(COE.ActiveTotems["Earth"]))) then
|
|
|
|
CastSpellByName(COE.CleansingTotems.Tremor.Totem.SpellName);
|
|
|
|
elseif (COE.CleansingTotems.Disease.Warn and
|
|
(COE.ActiveTotems.Water ~= COE.CleansingTotems.Disease.Totem or
|
|
not COE_Totem:IsTimerActive(COE.ActiveTotems["Water"]))) then
|
|
|
|
CastSpellByName(COE.CleansingTotems.Disease.Totem.SpellName);
|
|
|
|
elseif (COE.CleansingTotems.Poison.Warn and
|
|
(COE.ActiveTotems.Water ~= COE.CleansingTotems.Poison.Totem or
|
|
not COE_Totem:IsTimerActive(COE.ActiveTotems["Water"]))) then
|
|
|
|
CastSpellByName(COE.CleansingTotems.Poison.Totem.SpellName);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:IsAdvisedTotem
|
|
|
|
PURPOSE: Returns if the specified totem is an advised totem
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:IsAdvisedTotem(totem)
|
|
|
|
if ((COE.CleansingTotems.Tremor.Warn and totem ==
|
|
COE.CleansingTotems.Tremor.Totem) or
|
|
(COE.CleansingTotems.Disease.Warn and totem ==
|
|
COE.CleansingTotems.Disease.Totem) or
|
|
(COE.CleansingTotems.Poison.Warn and totem ==
|
|
COE.CleansingTotems.Poison.Totem)) then
|
|
return true;
|
|
else
|
|
return false;
|
|
end
|
|
|
|
end
|
|
|
|
--[[ =============================================================================================
|
|
|
|
T O T E M - S E T S
|
|
|
|
================================================================================================]]
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:SwitchNamedSet
|
|
|
|
PURPOSE: If there exists a custom set with the name of the
|
|
playertarget and the target is hostile, switch to this set
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:SwitchNamedSet()
|
|
|
|
if (COE_Config:GetSaved(COEOPT_ENABLESETS) == 1) then
|
|
|
|
if (UnitIsEnemy("player", "target")) then
|
|
|
|
-- iterate over all custom sets
|
|
-- -----------------------------
|
|
local i;
|
|
for i = 1, table.getn(COE_CustomTotemSets) do
|
|
|
|
if (COE_CustomTotemSets[i].Name == UnitName("target")) then
|
|
COE_Totem:SwitchToSet(COE_CustomTotemSets[i].Name);
|
|
return true;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return false;
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:SwitchPVPSet
|
|
|
|
PURPOSE: If the playertarget is a hostile player, activate the
|
|
class totem set, else switch back to the last active set
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:SwitchPVPSet()
|
|
|
|
if (COE_Config:GetSaved(COEOPT_ENABLESETS) == 1 and
|
|
COE_Config:GetSaved(COEOPT_AUTOSWITCH) == 1) then
|
|
|
|
if (UnitIsEnemy("player", "target")) then
|
|
if (UnitIsPlayer("target")) then
|
|
-- switch to pvp set
|
|
-- ------------------
|
|
local class = UnitClass("target");
|
|
|
|
COE_Totem:SwitchToSet("[PVP] " .. class);
|
|
|
|
elseif (UnitExists("target")) then
|
|
-- targeted a mob. switch back to the last set
|
|
-- --------------------------------------------
|
|
if (COE.LastActiveSet ~= nil) then
|
|
COE_Totem:SwitchToSet(COE.LastActiveSet);
|
|
else
|
|
COE_Totem:SwitchToSet(COEUI_DEFAULTSET);
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:SwitchToNextSet
|
|
|
|
PURPOSE: If a pvp set is activated, the default set is activated
|
|
Otherwise the next custom set is activated
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:SwitchToNextSet()
|
|
|
|
if (COE_Config:GetSaved(COEOPT_ENABLESETS) == 1) then
|
|
local activeset = COE_Config:GetSaved(COEOPT_ACTIVESET);
|
|
|
|
if (activeset < COESET_DEFAULT) then
|
|
-- pvp set is active
|
|
-- switch to default set
|
|
-- ----------------------
|
|
COE_Totem:SwitchToSet(COEUI_DEFAULTSET);
|
|
|
|
elseif (activeset == COE.TotemSetCount) then
|
|
-- last custom set is active or none available
|
|
-- switch to default set
|
|
-- --------------------------------------------
|
|
COE_Totem:SwitchToSet(COEUI_DEFAULTSET);
|
|
|
|
elseif (activeset == COESET_DEFAULT) then
|
|
-- default set is active
|
|
-- switch to first custom set
|
|
-- ---------------------------
|
|
COE_Totem:SwitchToSet(COE_CustomTotemSets[1].Name);
|
|
|
|
else
|
|
-- switch to next custom set
|
|
-- --------------------------
|
|
COE_Totem:SwitchToSet(
|
|
COE_CustomTotemSets[activeset - COESET_DEFAULT + 1].Name);
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:SwitchToPriorSet
|
|
|
|
PURPOSE: If a pvp set is activated, the default set is activated
|
|
Otherwise the next custom set is activated
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:SwitchToPriorSet()
|
|
|
|
if (COE_Config:GetSaved(COEOPT_ENABLESETS) == 1) then
|
|
local activeset = COE_Config:GetSaved(COEOPT_ACTIVESET);
|
|
|
|
if (activeset < COESET_DEFAULT) then
|
|
-- pvp set is active
|
|
-- switch to default set
|
|
-- ----------------------
|
|
COE_Totem:SwitchToSet(COEUI_DEFAULTSET);
|
|
|
|
elseif (activeset == COESET_DEFAULT) then
|
|
-- default set is active
|
|
-- switch to last custom set
|
|
-- ---------------------------
|
|
COE_Totem:SwitchToSet(COE_CustomTotemSets[COE.TotemSetCount -
|
|
COESET_DEFAULT].Name);
|
|
|
|
elseif (activeset == COESET_DEFAULT + 1) then
|
|
-- first custom set is active
|
|
-- switch to default set
|
|
-- ---------------------------
|
|
COE_Totem:SwitchToSet(COEUI_DEFAULTSET);
|
|
|
|
else
|
|
-- switch to prior custom set
|
|
-- ---------------------------
|
|
COE_Totem:SwitchToSet(
|
|
COE_CustomTotemSets[activeset - COESET_DEFAULT - 1].Name);
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:SwitchToSet
|
|
|
|
PURPOSE: Activates the specified totem set
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:SwitchToSet(name)
|
|
|
|
if (COE_Config:GetSaved(COEOPT_ENABLESETS) == 0) then return; end
|
|
|
|
local pvpset = false;
|
|
|
|
-- check for pvp sets
|
|
-- -------------------
|
|
local i, set;
|
|
for i = 1, table.getn(COE_SavedTotemSets) do
|
|
if (COE_SavedTotemSets[i].Name == name) then
|
|
-- set found
|
|
-- ----------
|
|
set = i;
|
|
pvpset = i ~= COESET_DEFAULT;
|
|
break
|
|
end
|
|
end
|
|
|
|
-- check for custom sets
|
|
-- ----------------------
|
|
if (not set) then
|
|
for i = 1, table.getn(COE_CustomTotemSets) do
|
|
if (COE_CustomTotemSets[i].Name == name) then
|
|
-- set found
|
|
-- ----------
|
|
set = COESET_DEFAULT + i;
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if (not set) then return; end
|
|
|
|
-- activate set if not already active
|
|
-- chech this to stop notification spamming in a duel
|
|
-- ---------------------------------------------------
|
|
if (COE_Config:GetSaved(COEOPT_ACTIVESET) ~= set) then
|
|
COE_Config:ActivateSet(set);
|
|
|
|
if (not pvpset) then COE.LastActiveSet = name; end
|
|
|
|
-- reset set cycle
|
|
-- ----------------
|
|
COE_Totem:ResetSetCycle();
|
|
|
|
-- notify player
|
|
-- --------------
|
|
COE:Message(string.format(COESTR_SWITCHTOSET, name));
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:ThrowSet
|
|
|
|
PURPOSE: Throws every totem in the active set that is not yet
|
|
thrown and is ready. Each element has its own GCD category
|
|
on the server, so the whole set goes out on one press
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ThrowSet()
|
|
COE:DebugMessage("Method Executing: ThrowSet");
|
|
|
|
if (COE_Config:GetSaved(COEOPT_ENABLESETS) == 1) then
|
|
|
|
-- =======================================================================
|
|
-- check which totems to throw
|
|
-- =======================================================================
|
|
local activeset = COE_Config:GetSaved(COEOPT_ACTIVESET);
|
|
COE:DebugMessage("ThrowSet activeset value: " .. activeset);
|
|
|
|
local now = GetTime();
|
|
|
|
for k = 1, 4 do
|
|
COE:DebugMessage("ThrowSet k value: " .. k);
|
|
|
|
local element = COE:LocalizedElement(
|
|
COE.TotemSets[activeset].CastOrder[k]);
|
|
COE:DebugMessage("ThrowSet element value: " .. element);
|
|
|
|
local totem = COE.TotemSets[activeset][element];
|
|
|
|
COE:DebugMessage("ThrowSet COE.SetCycle[element] value: " ..
|
|
tostring(COE.SetCycle[element]));
|
|
if (COE.SetCycle[element] == false and totem) then
|
|
|
|
local thrown = COE.SetThrown[element];
|
|
|
|
if (thrown and now - thrown < COE.SetThrowGuard) then
|
|
-- cast sent moments ago and not yet confirmed
|
|
-- --------------------------------------------
|
|
COE:DebugMessage("ThrowSet skipping unconfirmed: " ..
|
|
element);
|
|
|
|
elseif (totem.isTrinket) then
|
|
|
|
if (totem.TrinketSlot) then
|
|
-- first check if the trinket is already usable
|
|
-- ---------------------------------------------
|
|
local start, duration =
|
|
GetInventoryItemCooldown("player", totem.TrinketSlot);
|
|
|
|
if (start == 0 and duration == 0) then
|
|
UseInventoryItem(totem.TrinketSlot);
|
|
COE.SetThrown[element] = now;
|
|
end
|
|
end
|
|
|
|
else
|
|
|
|
COE:DebugMessage("ThrowSet casting totem: " .. element);
|
|
-- first check if the totem is already usable
|
|
-- -------------------------------------------
|
|
local start, duration = GetSpellCooldown(
|
|
totem.Ranks[totem.MaxRank]
|
|
.SpellID, BOOKTYPE_SPELL);
|
|
COE:DebugMessage("ThrowSet spell cooldown duration: " ..
|
|
duration);
|
|
|
|
if (start == 0 and duration == 0) then
|
|
|
|
COE:DebugMessage(
|
|
"ThrowSet casting spell: " ..
|
|
COE.TotemSets[activeset][element].SpellName);
|
|
CastSpellByName(COE.TotemSets[activeset][element]
|
|
.SpellName);
|
|
-- COE_Totem:SetPendingTotem(totem, totem.MaxRank);
|
|
COE.SetThrown[element] = now;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:ResetSetCycle
|
|
|
|
PURPOSE: Marks all totems of the current set as not yet thrown
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ResetSetCycle()
|
|
|
|
COE:Message(COESTR_RESTARTINGSET);
|
|
COE.SetCycle = {Earth = false, Fire = false, Water = false, Air = false};
|
|
COE.SetThrown = {};
|
|
|
|
end
|
|
|
|
--[[ =============================================================================================
|
|
|
|
T I M E R - L O G I C
|
|
|
|
================================================================================================]]
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:SetPendingTotem
|
|
|
|
PURPOSE: Sets up or clears a pending totem
|
|
The pending totem's timer is activated on the next
|
|
successful SPELLCAST_STOP or removed if it times out first
|
|
|
|
PURPOSE: Sets up or clears a pending totem. The pending totem's
|
|
timer is activated when the spell is identified as cast. If
|
|
the spell is not identified as cast within 1 seconds, then
|
|
the pending status is removed.
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:SetPendingTotem(totem, rank)
|
|
COE:DebugMessage("Method Executing: SetPendingTotem");
|
|
|
|
if (totem) then
|
|
|
|
-- Set PendingTotems for the given totem element type
|
|
COE:DebugMessage("SetPendingTotem PendingTotems being set: " ..
|
|
totem.SpellName .. " with rank: " .. tostring(rank));
|
|
local pending = COE.PendingTotems[totem.Element];
|
|
if (not pending) then
|
|
-- no known element: cast without a timer instead of erroring
|
|
-- ------------------------------------------------------------
|
|
return;
|
|
end
|
|
pending.Totem = totem;
|
|
pending.Rank = rank;
|
|
-- COE.PendingTotems[totem.Element].TimeoutStartMS = GetTime();
|
|
|
|
-- get the current lag - Not used but saving if needed
|
|
-- --------------------
|
|
-- local _, _, lag = GetNetStats();
|
|
-- local timeout = lag / 1000 + COE.TotemPending.Timeout;
|
|
local timeoutSec = 1;
|
|
|
|
-- use lag + 0.5 seconds as pending timeout
|
|
-- -----------------------------------------
|
|
COE:DebugMessage("SetPendingTotem Setting pending timeout to: " ..
|
|
timeoutSec .. " seconds");
|
|
|
|
-- one timeout per element: a set throw has several pending at once
|
|
Chronos.scheduleByName("COE_Pending" .. totem.Element, timeoutSec,
|
|
COESched_CheckPendingTotem, totem.Element);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COESched_CheckPendingTotem
|
|
|
|
PURPOSE: Clears the pending totem if it is still active
|
|
|
|
PURPOSE: Clears the pending totem if it is still pending.
|
|
-------------------------------------------------------------------]]
|
|
function COESched_CheckPendingTotem(element)
|
|
COE:DebugMessage("Executing Method: COESched_CheckPendingTotem");
|
|
|
|
if (element) then
|
|
COE:DebugMessage("COESched_CheckPendingTotem for element: " .. element);
|
|
|
|
COE_Totem:ClearPendingTotem(COE.PendingTotems[element]);
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: ClearPendingTotem
|
|
|
|
PURPOSE: Clears the pending totem.
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ClearPendingTotem(pendingTotem)
|
|
COE:DebugMessage("Executing Method: ClearPendingTotem");
|
|
|
|
if (pendingTotem) then
|
|
pendingTotem.Totem = nil;
|
|
pendingTotem.Rank = nil;
|
|
end
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:GetTotemFromText
|
|
|
|
PURPOSE: Identifies a totem from the text value passed in. Can
|
|
return a nil totem.
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:GetTotemFromText(text)
|
|
local totem;
|
|
COE:DebugMessage("GetTotemFromText for text value: " .. text);
|
|
|
|
-- find the totem
|
|
for k = 1, COE.TotemCount do
|
|
if (string.find(text, COE.TotemData[k].SpellName)) then
|
|
-- use existing totem object
|
|
-- --------------------------
|
|
totem = COE.TotemData[k];
|
|
|
|
COE:DebugMessage("GetTotemFromText found totem: " .. totem.SpellName);
|
|
break
|
|
end
|
|
end
|
|
|
|
return totem;
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:ActivateTotem
|
|
|
|
PURPOSE: Activates the totem timer and deactivates a
|
|
still active timer of the same element
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ActivateTotem(totem)
|
|
COE:DebugMessage("Method Executing: ActivateTotem with totem parameter " ..
|
|
totem.SpellName);
|
|
|
|
local pendingTotemObj = COE.PendingTotems[totem.Element];
|
|
|
|
if (pendingTotemObj and pendingTotemObj.Totem) then
|
|
COE:DebugMessage("ActivateTotem identified pending totem : " ..
|
|
pendingTotemObj.Totem.SpellName);
|
|
|
|
-- deactivate still active totem of the same element
|
|
-- --------------------------------------------------
|
|
local active = COE.ActiveTotems[totem.Element];
|
|
if (active) then COE_Totem:DeactivateTimer(active); end
|
|
|
|
local pendingTotem = pendingTotemObj.Totem;
|
|
local pendingTotemRank = pendingTotemObj.Rank;
|
|
|
|
-- activate timer
|
|
-- ---------------
|
|
Chronos.startTimer("COE" .. totem.SpellName);
|
|
totem.CurDuration = pendingTotem.Ranks[pendingTotemRank].Duration;
|
|
totem.CurHealth = pendingTotem.Ranks[pendingTotemRank].Health;
|
|
|
|
-- activate cooldown timer if this totem has a cooldown
|
|
-- -----------------------------------------------------
|
|
if (pendingTotem.Ranks[pendingTotemRank].Cooldown > 0) then
|
|
totem.CurCooldown = pendingTotem.Ranks[pendingTotemRank].Cooldown;
|
|
Chronos.startTimer("COECooldown" .. totem.SpellName);
|
|
Chronos.scheduleByName("COECooldownSwitch" .. totem.SpellName,
|
|
totem.CurCooldown, COESched_CooldownEnd,
|
|
totem);
|
|
end
|
|
|
|
-- activate warning timers
|
|
-- ------------------------
|
|
if (totem.CurDuration >= 10) then
|
|
Chronos.scheduleByName("COEWarn10" .. totem.SpellName,
|
|
totem.CurDuration - 10,
|
|
COESched_ExpirationWarning, 10, totem);
|
|
end
|
|
Chronos.scheduleByName("COEWarn5" .. totem.SpellName,
|
|
totem.CurDuration - 5,
|
|
COESched_ExpirationWarning, 5, totem);
|
|
Chronos.scheduleByName("COEWarn0" .. totem.SpellName, totem.CurDuration,
|
|
COESched_ExpirationWarning, 0, totem);
|
|
|
|
-- mark totem as active
|
|
-- ---------------------
|
|
COE.ActiveTotems[pendingTotem.Element] = totem;
|
|
totem.isActive = true;
|
|
|
|
-- set totem in timer frame
|
|
-- -------------------------
|
|
if (COE_Config:GetSaved(COEOPT_TIMERFRAME) == 1) then
|
|
getglobal("COETimer" .. pendingTotem.Element).totem = totem;
|
|
COETimerFrame:Show();
|
|
end
|
|
|
|
-- mark totem as thrown if in current set
|
|
-- ---------------------------------------
|
|
local activeset = COE_Config:GetSaved(COEOPT_ACTIVESET);
|
|
|
|
if (COE.TotemSets[activeset][totem.Element] and
|
|
COE.TotemSets[activeset][totem.Element].SpellName == totem.SpellName) then
|
|
|
|
COE:DebugMessage("ActivateTotem Element " .. totem.Element ..
|
|
" in current cycle: SET");
|
|
COE.SetCycle[totem.Element] = true;
|
|
end
|
|
|
|
-- clear pending totem
|
|
-- --------------------
|
|
COE_Totem:ClearPendingTotem(pendingTotemObj);
|
|
|
|
-- if in timers only mode, reconfigure the totem bar
|
|
-- --------------------------------------------------
|
|
if (COE_Config:GetSaved(COEOPT_DISPLAYMODE) == COEMODE_TIMERSONLY) then
|
|
COE_Totem:Invalidate(getglobal("COE" .. totem.Element .. "Frame"),
|
|
true, true, true);
|
|
COETotemFrame.Reconfigure = true;
|
|
else
|
|
-- otherwise just invalidate the dynamic buttons
|
|
-- ----------------------------------------------
|
|
COE_Totem:Invalidate(getglobal("COE" .. totem.Element .. "Frame"),
|
|
false, false, true);
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
DEPRECATED: Use ActivateTotem
|
|
METHOD: COE_Totem:ActivatePendingTotem
|
|
|
|
PURPOSE: Activates the pending totem timer and deactivates a
|
|
still active timer of the same element
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ActivatePendingTotem(totem)
|
|
COE:DebugMessage(
|
|
"Method Executing: ActivatePendingTotem with totem parameter " ..
|
|
totem.SpellName);
|
|
|
|
-- deactivate still active totem of the same element
|
|
-- --------------------------------------------------
|
|
COE:DebugMessage(
|
|
"ActivatePendingTotem - identifying active totems of type" ..
|
|
COE.TotemPending.Totem.Element);
|
|
local active = COE.ActiveTotems[COE.TotemPending.Totem.Element];
|
|
if (active) then COE_Totem:DeactivateTimer(active); end
|
|
|
|
-- activate timer
|
|
-- ---------------
|
|
Chronos.startTimer("COE" .. totem.SpellName);
|
|
totem.CurDuration = COE.TotemPending.Totem.Ranks[COE.TotemPending.UseRank]
|
|
.Duration;
|
|
totem.CurHealth = COE.TotemPending.Totem.Ranks[COE.TotemPending.UseRank]
|
|
.Health;
|
|
|
|
-- activate cooldown timer if this totem has a cooldown
|
|
-- -----------------------------------------------------
|
|
if (COE.TotemPending.Totem.Ranks[COE.TotemPending.UseRank].Cooldown > 0) then
|
|
totem.CurCooldown = COE.TotemPending.Totem.Ranks[COE.TotemPending
|
|
.UseRank].Cooldown;
|
|
Chronos.startTimer("COECooldown" .. totem.SpellName);
|
|
Chronos.scheduleByName("COECooldownSwitch" .. totem.SpellName,
|
|
totem.CurCooldown, COESched_CooldownEnd, totem);
|
|
end
|
|
|
|
-- activate warning timers
|
|
-- ------------------------
|
|
if (totem.CurDuration >= 10) then
|
|
Chronos.scheduleByName("COEWarn10" .. totem.SpellName,
|
|
totem.CurDuration - 10,
|
|
COESched_ExpirationWarning, 10, totem);
|
|
end
|
|
Chronos.scheduleByName("COEWarn5" .. totem.SpellName, totem.CurDuration - 5,
|
|
COESched_ExpirationWarning, 5, totem);
|
|
Chronos.scheduleByName("COEWarn0" .. totem.SpellName, totem.CurDuration,
|
|
COESched_ExpirationWarning, 0, totem);
|
|
|
|
-- mark totem as active
|
|
-- ---------------------
|
|
COE.ActiveTotems[COE.TotemPending.Totem.Element] = totem;
|
|
totem.isActive = true;
|
|
|
|
-- set totem in timer frame
|
|
-- -------------------------
|
|
if (COE_Config:GetSaved(COEOPT_TIMERFRAME) == 1) then
|
|
getglobal("COETimer" .. COE.TotemPending.Totem.Element).totem = totem;
|
|
COETimerFrame:Show();
|
|
end
|
|
|
|
-- mark totem as thrown if in current set
|
|
-- ---------------------------------------
|
|
local activeset = COE_Config:GetSaved(COEOPT_ACTIVESET);
|
|
|
|
if (COE.TotemSets[activeset][totem.Element] and
|
|
COE.TotemSets[activeset][totem.Element].SpellName == totem.SpellName) then
|
|
|
|
COE:DebugMessage("Element " .. totem.Element .. " in current cycle: SET");
|
|
COE.SetCycle[totem.Element] = true;
|
|
end
|
|
|
|
-- clear pending totem
|
|
-- --------------------
|
|
COE_Totem:SetPendingTotem(nil);
|
|
|
|
-- if in timers only mode, reconfigure the totem bar
|
|
-- --------------------------------------------------
|
|
if (COE_Config:GetSaved(COEOPT_DISPLAYMODE) == COEMODE_TIMERSONLY) then
|
|
COE_Totem:Invalidate(getglobal("COE" .. totem.Element .. "Frame"), true,
|
|
true, true);
|
|
COETotemFrame.Reconfigure = true;
|
|
else
|
|
-- otherwise just invalidate the dynamic buttons
|
|
-- ----------------------------------------------
|
|
COE_Totem:Invalidate(getglobal("COE" .. totem.Element .. "Frame"),
|
|
false, false, true);
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:DeactivateTimer
|
|
|
|
PURPOSE: Deactivates an active totem timer
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:DeactivateTimer(totem)
|
|
|
|
if (totem and totem.isActive) then
|
|
|
|
COE:DebugMessage("Deactivating totem: " .. totem.SpellName);
|
|
|
|
-- end timers
|
|
-- -----------
|
|
Chronos.endTimer("COE" .. totem.SpellName);
|
|
Chronos.unscheduleByName("COEWarn10" .. totem.SpellName);
|
|
Chronos.unscheduleByName("COEWarn5" .. totem.SpellName);
|
|
Chronos.unscheduleByName("COEWarn0" .. totem.SpellName);
|
|
|
|
-- reset totem data
|
|
-- ------------------
|
|
totem.CurDuration = 0;
|
|
totem.CurHealth = 0;
|
|
totem.isActive = false;
|
|
|
|
-- unset totem in timerframe
|
|
-- --------------------------
|
|
local timer = getglobal("COETimer" .. totem.Element);
|
|
timer.totem = nil;
|
|
COETimerFrame:StopMovingOrSizing();
|
|
|
|
-- mark totem as unthrown if in current set
|
|
-- -----------------------------------------
|
|
local activeset = COE_Config:GetSaved(COEOPT_ACTIVESET);
|
|
|
|
if (COE.TotemSets[activeset][totem.Element] and
|
|
COE.TotemSets[activeset][totem.Element].SpellName == totem.SpellName) then
|
|
|
|
COE:DebugMessage("DeactivateTimer Element " .. totem.Element ..
|
|
" in current cycle: UNSET");
|
|
COE.SetCycle[totem.Element] = false;
|
|
end
|
|
|
|
-- invalidate dynamic buttons
|
|
-- ---------------------------
|
|
COE_Totem:Invalidate(getglobal("COE" .. totem.Element .. "Frame"),
|
|
false, false, true);
|
|
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:IsTimerActive
|
|
|
|
PURPOSE: Returns if the specified totem timer is active
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:IsTimerActive(totem)
|
|
|
|
if (not totem) then return false; end
|
|
|
|
return (totem.CurDuration > 0) and
|
|
(totem.CurDuration - Chronos.getTimer("COE" .. totem.SpellName) >
|
|
0);
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:GetTimeLeft
|
|
|
|
PURPOSE: Returns the amount of seconds left on the totem timer
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:GetTimeLeft(totem)
|
|
|
|
if (totem.CurDuration == 0) then
|
|
return 0;
|
|
else
|
|
return totem.CurDuration - Chronos.getTimer("COE" .. totem.SpellName);
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:GetCooldownLeft
|
|
|
|
PURPOSE: Returns the amount of seconds left on the totem cooldown
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:GetCooldownLeft(totem)
|
|
|
|
if (totem.CurCooldown == 0) then
|
|
return 0;
|
|
else
|
|
return totem.CurCooldown -
|
|
Chronos.getTimer("COECooldown" .. totem.SpellName);
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COESched_ExpirationWarning
|
|
|
|
PURPOSE: Issues an expiration warning for the specified totem
|
|
-------------------------------------------------------------------]]
|
|
function COESched_ExpirationWarning(timemark, totem)
|
|
COE:DebugMessage(
|
|
"Method Executing: COESched_ExpirationWarning with totem parameter " ..
|
|
totem.SpellName);
|
|
|
|
if (COE_Config:GetSaved(COEOPT_ENABLETOTEMBAR) == 1 and
|
|
COE_Config:GetSaved(COEOPT_ENABLETIMERS) == 1 and
|
|
COE_Config:GetSaved(COEOPT_TIMERNOTIFICATIONS) == 1) then
|
|
|
|
local text;
|
|
if (totem.isTrinket) then
|
|
text = COESTR_TRINKET_TOTEM;
|
|
else
|
|
text = totem.SpellName;
|
|
end
|
|
|
|
if (timemark > 0) then
|
|
COE:Notification(string.format(COESTR_TOTEMWARNING, text, timemark),
|
|
COECOL_TOTEMWARNING);
|
|
else
|
|
COE:Notification(string.format(COESTR_TOTEMEXPIRED, text),
|
|
COECOL_TOTEMDESTROYED);
|
|
COE_Totem:DeactivateTimer(totem);
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COESched_CooldownEnd
|
|
|
|
PURPOSE: Stops the cooldown timer of the totem when the
|
|
cooldown has ended
|
|
-------------------------------------------------------------------]]
|
|
function COESched_CooldownEnd(totem)
|
|
|
|
Chronos.endTimer("COECooldown" .. totem.SpellName);
|
|
totem.CurCooldown = 0;
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:TotemDamage
|
|
|
|
PURPOSE: Assigns damage to the totem being hit and triggers
|
|
a notification if the totem is destroyed
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:TotemDamage()
|
|
COE:DebugMessage("Method Executing: TotemDamage");
|
|
|
|
local num, regex, i;
|
|
for num, regex in COESTR_TOTEMDAMAGE do
|
|
local match = {string.gfind(arg1, regex)()};
|
|
if (table.getn(match) >= 1) then
|
|
|
|
-- find totem
|
|
-- -----------
|
|
for i = 1, COE.TotemCount do
|
|
if (COE.TotemData[i].SpellName == match[1]) then
|
|
-- subtract damage
|
|
-- ----------------
|
|
COE.TotemData[i].CurHealth =
|
|
COE.TotemData[i].CurHealth - tonumber(match[2]);
|
|
|
|
-- totem destroyed?
|
|
-- -----------------
|
|
if (COE_Config:GetSaved(COEOPT_ENABLETIMERS) == 1) then
|
|
if (COE.TotemData[i].CurHealth <= 0) then
|
|
COE:DebugMessage(match[1] .. " destroyed");
|
|
|
|
if (COE_Config:GetSaved(COEOPT_TIMERNOTIFICATIONS) ==
|
|
1) then
|
|
COE:Notification(string.format(
|
|
COESTR_TOTEMDESTROYED,
|
|
COE.TotemData[i].SpellName),
|
|
COECOL_TOTEMDESTROYED);
|
|
end
|
|
|
|
COE_Totem:DeactivateTimer(COE.TotemData[i]);
|
|
else
|
|
COE:DebugMessage(
|
|
match[1] .. " took " .. match[2] .. " damage. " ..
|
|
COE.TotemData[i].CurHealth .. " health left");
|
|
end
|
|
end
|
|
break
|
|
end
|
|
end
|
|
|
|
break
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:ResetTimers
|
|
|
|
PURPOSE: Resets all active timers to zero
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:ResetTimers()
|
|
COE:DebugMessage("Method Executing: COE_Totem:ResetTimers");
|
|
|
|
local k;
|
|
for k = 1, 4 do
|
|
if (COE.ActiveTotems[COE_Element[k]]) then
|
|
COE_Totem:DeactivateTimer(COE.ActiveTotems[COE_Element[k]]);
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
--[[ =============================================================================================
|
|
|
|
T I M E R - H O O K S
|
|
|
|
================================================================================================]]
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:SetupTimerHooks
|
|
|
|
PURPOSE: Stores the CastSpell, CastSpellByName, UseAction
|
|
and UseInventoryItem functions and replaces them with
|
|
a call to the corresponding hook functions and the
|
|
original function afterwards
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:SetupTimerHooks()
|
|
COE:DebugMessage("Method Executing: SetupTimerHooks");
|
|
|
|
COE_Totem.TimerHooks["UseAction"] = UseAction;
|
|
UseAction = function(id, book, onself)
|
|
COE_Totem:HookUseAction(id, book);
|
|
COE_Totem.TimerHooks["UseAction"](id, book, onself);
|
|
end;
|
|
|
|
COE_Totem.TimerHooks["CastSpell"] = CastSpell;
|
|
CastSpell = function(id, book)
|
|
COE_Totem:HookCastSpell(id, book);
|
|
COE_Totem.TimerHooks["CastSpell"](id, book);
|
|
end;
|
|
|
|
COE_Totem.TimerHooks["CastSpellByName"] = CastSpellByName;
|
|
CastSpellByName = function(SpellName)
|
|
COE_Totem:HookCastSpellByName(SpellName);
|
|
COE_Totem.TimerHooks["CastSpellByName"](SpellName);
|
|
end;
|
|
|
|
COE_Totem.TimerHooks["UseInventoryItem"] = UseInventoryItem;
|
|
UseInventoryItem = function(slotid)
|
|
COE_Totem:HookUseInventoryItem(slotid);
|
|
COE_Totem.TimerHooks["UseInventoryItem"](slotid);
|
|
end;
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:HookUseAction
|
|
|
|
PURPOSE: Setup the totem timer if the action triggered
|
|
a totem
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:HookUseAction(id, book)
|
|
COE:DebugMessage("Method Executing: HookUseAction");
|
|
-- use only when timers are enabled
|
|
-- ---------------------------------
|
|
if (COE_Config:GetSaved(COEOPT_ENABLETIMERS) == 0) then return; end
|
|
|
|
-- get action tooltip
|
|
-- -------------------
|
|
COETotemTT:SetAction(id);
|
|
|
|
-- check if this triggered a totem
|
|
-- --------------------------------
|
|
local text = COETotemTTTextLeft1:GetText();
|
|
local i, rank, ranktext, trinket;
|
|
|
|
-- check if this triggered the trinket
|
|
-- ------------------------------------
|
|
trinket = text == COESTR_TRINKET_TOOLTIP;
|
|
|
|
for i = 1, COE.TotemCount do
|
|
if ((trinket and COE.TotemData[i].isTrinket) or
|
|
COE.TotemData[i].SpellName == text) then
|
|
|
|
if (COE.TotemData[i].isTrinket) then
|
|
rank = 0;
|
|
|
|
else
|
|
-- get rank information
|
|
-- Since WOW doesn't seem to clear the rank information
|
|
-- when setting a tooltip for an action that doesn't
|
|
-- have such, we need to test if the rank info is
|
|
-- actually shown first
|
|
-- -----------------------------------------------------
|
|
if (COETotemTTTextRight1:IsShown()) then
|
|
ranktext = COETotemTTTextRight1:GetText();
|
|
end
|
|
if (ranktext) then
|
|
_, _, rank = string.find(ranktext, COESTR_TOTEMRANK);
|
|
rank = tonumber(rank);
|
|
else
|
|
rank = COE.TotemData[i].MaxRank;
|
|
end
|
|
end
|
|
|
|
-- set pending totem
|
|
-- ------------------
|
|
COE_Totem:SetPendingTotem(COE.TotemData[i], rank);
|
|
|
|
return;
|
|
end
|
|
|
|
end
|
|
|
|
-- no totem spell. remove pending totem if set
|
|
-- --------------------------------------------
|
|
COE_Totem:SetPendingTotem(nil);
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:HookCastSpell
|
|
|
|
PURPOSE: Setup the totem timer if the spell triggered
|
|
a totem
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:HookCastSpell(id, book)
|
|
COE:DebugMessage("Method Executing: HookCastSpell");
|
|
|
|
-- use only when timers are enabled
|
|
-- ---------------------------------
|
|
if (COE_Config:GetSaved(COEOPT_ENABLETIMERS) == 0) then return; end
|
|
|
|
-- get the associated totem object
|
|
-- --------------------------------
|
|
local i, k, totem;
|
|
for i = 1, COE.TotemCount do
|
|
for k = 1, COE.TotemData[i].MaxRank do
|
|
if (COE.TotemData[i].Ranks[k].SpellID == id) then
|
|
-- totem found. mark it as pending
|
|
-- --------------------------------
|
|
COE_Totem:SetPendingTotem(COE.TotemData[i], k);
|
|
|
|
return;
|
|
end
|
|
end
|
|
end
|
|
|
|
-- no totem spell. remove pending totem if set
|
|
-- --------------------------------------------
|
|
COE_Totem:SetPendingTotem(nil);
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:HookCastSpellByName
|
|
|
|
PURPOSE: Setup the totem timer if the spell triggered
|
|
a totem
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:HookCastSpellByName(SpellName)
|
|
COE:DebugMessage("Method Executing: HookCastSpellByName");
|
|
|
|
-- use only when timers are enabled
|
|
-- ---------------------------------
|
|
if (COE_Config:GetSaved(COEOPT_ENABLETIMERS) == 0) then return; end
|
|
|
|
-- extract rank information
|
|
-- -------------------------
|
|
local _, _, rank = string.find(SpellName, COESTR_CASTBYNAME);
|
|
local spell = string.gsub(SpellName, COESTR_CASTBYNAME, "");
|
|
|
|
-- get the associated totem object
|
|
-- --------------------------------
|
|
local i, k, totem;
|
|
for i = 1, COE.TotemCount do
|
|
if (COE.TotemData[i].SpellName == spell) then
|
|
if (rank) then
|
|
rank = tonumber(rank);
|
|
else
|
|
rank = COE.TotemData[i].MaxRank;
|
|
end
|
|
|
|
-- totem found. mark it as pending
|
|
-- --------------------------------
|
|
COE_Totem:SetPendingTotem(COE.TotemData[i], rank);
|
|
|
|
return;
|
|
end
|
|
end
|
|
|
|
-- no totem spell. remove pending totem if set
|
|
-- --------------------------------------------
|
|
COE_Totem:SetPendingTotem(nil);
|
|
|
|
end
|
|
|
|
--[[ ----------------------------------------------------------------
|
|
METHOD: COE_Totem:HookUseInventoryItem
|
|
|
|
PURPOSE: Setup the totem timer if the item triggered
|
|
a totem
|
|
-------------------------------------------------------------------]]
|
|
function COE_Totem:HookUseInventoryItem(slotid)
|
|
COE:DebugMessage("Method Executing: HookUseInventoryItem");
|
|
|
|
-- use only when timers are enabled
|
|
-- ---------------------------------
|
|
if (COE_Config:GetSaved(COEOPT_ENABLETIMERS) == 0) then return; end
|
|
|
|
-- only use for trinket slots
|
|
-- ---------------------------
|
|
if (slotid ~= GetInventorySlotInfo("Trinket0Slot") and slotid ~=
|
|
GetInventorySlotInfo("Trinket1Slot")) then return; end
|
|
|
|
-- iterate through out totems and find the trinket totem
|
|
-- ------------------------------------------------------
|
|
local i;
|
|
for i = 1, COE.TotemCount do
|
|
if (COE.TotemData[i].isTrinket) then
|
|
-- does the totem have the same slot id?
|
|
-- --------------------------------------
|
|
if (COE.TotemData[i].TrinketSlot == slotid) then
|
|
-- our trinket totem was cast
|
|
-- ---------------------------
|
|
COE_Totem:SetPendingTotem(COE.TotemData[i], 0);
|
|
|
|
return;
|
|
end
|
|
end
|
|
end
|
|
|
|
-- no totem spell. remove pending totem if set
|
|
-- --------------------------------------------
|
|
COE_Totem:SetPendingTotem(nil);
|
|
|
|
end
|
|
|