Files
CallOfElements/COE_TotemData.lua
T
shaga 72ab7c8aa5 Throw the whole totem set on one press
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.
2026-10-15 07:05:15 +00:00

938 lines
34 KiB
Lua

--[[
CALL OF ELEMENTS
The All-In-One Shaman Addon
by Wyverex (2006)
Totem Module Data
]] --[[ ----------------------------------------------------------------
COE.TotemData contains a list of totem classes that are
returned by COE:CreateTotem
For every available totem the player has, one object is
added to this list
-------------------------------------------------------------------]] COE["TotemData"] =
{};
COE["TotemCount"] = 0;
--[[ ----------------------------------------------------------------
COE.MaxTotems stores the maximum number of totems per element
This is taken right from the current game content
-------------------------------------------------------------------]]
COE["MaxTotems"] = {Earth = 5, Fire = 5, Water = 7, Air = 7};
--[[ ----------------------------------------------------------------
COE.TotemsAvailable contains the number of totems available
of each element
-------------------------------------------------------------------]]
COE["TotemsAvailable"] = {};
COE.TotemsAvailable["Earth"] = 0;
COE.TotemsAvailable["Fire"] = 0;
COE.TotemsAvailable["Water"] = 0;
COE.TotemsAvailable["Air"] = 0;
--[[ ----------------------------------------------------------------
COE.ActiveTotems contains a pointer to the active totem of
each element
COE.TotemPending contains a pointer to the last totem spell
that was initiated but not yet completed. This lets COE check
whether something went wrong while casting (sitting etc.) by
activating the timer first when SPELLCAST_STOP is fired
After the timeout a pending totem timer is automatically removed
to prevent actions that trigger SPELLCAST_STOP and are not
hooked from activating the timer accidentally
-------------------------------------------------------------------]]
COE["ActiveTotems"] = {Earth = nil, Fire = nil, Water = nil, Air = nil};
COE["TotemPending"] = {Totem = nil, UseRank = 0, Timeout = 0.75};
COE["PendingTotems"] = {
Earth = {Totem = nil, Rank = 0, TimeoutStartMS = 0},
Fire = {Totem = nil, Rank = 0, TimeoutStartMS = 0},
Water = {Totem = nil, Rank = 0, TimeoutStartMS = 0},
Air = {Totem = nil, Rank = 0, TimeoutStartMS = 0}
};
--[[ ----------------------------------------------------------------
COE.TotemElementsByName is the fallback ScanTotems uses when the
element cannot be read from the spell tooltip. The
"Tools: <Element> Totem" line names the totem item, so it stays
incomplete until that item is in the client's item cache (WDB).
A client whose WDB was cleared (the OctoWoW launcher does this on
every launch by default) scans at login with an empty cache.
English spell names only; other locales still rely on the tooltip.
-------------------------------------------------------------------]]
COE["TotemElementsByName"] = {
["Earthbind Totem"] = "Earth",
["Stoneclaw Totem"] = "Earth",
["Stoneskin Totem"] = "Earth",
["Strength of Earth Totem"] = "Earth",
["Tremor Totem"] = "Earth",
["Fire Nova Totem"] = "Fire",
["Flametongue Totem"] = "Fire",
["Frost Resistance Totem"] = "Fire",
["Magma Totem"] = "Fire",
["Searing Totem"] = "Fire",
["Disease Cleansing Totem"] = "Water",
["Fire Resistance Totem"] = "Water",
["Healing Stream Totem"] = "Water",
["Mana Spring Totem"] = "Water",
["Mana Tide Totem"] = "Water",
["Poison Cleansing Totem"] = "Water",
["Grace of Air Totem"] = "Air",
["Grounding Totem"] = "Air",
["Nature Resistance Totem"] = "Air",
["Sentry Totem"] = "Air",
["Tranquil Air Totem"] = "Air",
["Windfury Totem"] = "Air",
["Windwall Totem"] = "Air"
};
--[[ ----------------------------------------------------------------
COE.CleansingTotems stores pointers to the buttons and totems
that are able to cleanse poisons, diseases and sleep, charm
or fear effects
-------------------------------------------------------------------]]
COE["CleansingTotems"] = {
Poison = {Totem = nil, Button = nil, Warn = false},
Disease = {Totem = nil, Button = nil, Warn = false},
Tremor = {Totem = nil, Button = nil, Warn = false}
};
--[[ ----------------------------------------------------------------
COE.TotemSets contains the totem pointers for each set and
element
-------------------------------------------------------------------]]
COE["TotemSetCount"] = 0;
COE["TotemSets"] = {}
--[[ ----------------------------------------------------------------
COE.SetCycle stores which totem of the active set have
already been thrown
-------------------------------------------------------------------]]
COE["SetCycle"] = {Earth = false, Fire = false, Water = false, Air = false};
--[[ ----------------------------------------------------------------
COE.SetThrown stores when ThrowSet last cast each element, so a
second press does not recast a totem whose cast is still
unconfirmed. COE.SetThrowGuard is that window in seconds
-------------------------------------------------------------------]]
COE["SetThrown"] = {};
COE["SetThrowGuard"] = 1;
--[[ ----------------------------------------------------------------
COE.NoTotem is a placeholder for an empty anchor button
-------------------------------------------------------------------]]
COE["NoTotem"] = {
SpellName = "",
Element = "",
Texture = "Interface\\Icons\\INV_Misc_Idol_03.blp",
ToolPresent = false,
Ranks = {SpellID = 0, Mana = 0, Duration = 0, Health = 0, Cooldown = 0},
MaxRank = 1,
isActive = false,
CurDuration = 0,
CurHealth = 0,
CurCooldown = 0
};
--[[ ----------------------------------------------------------------
METHOD: COE:CreateTotem
PURPOSE: Returns the totem class for a new totem
-------------------------------------------------------------------]]
function COE:CreateTotem()
return {
SpellName = "",
Element = "",
Texture = "",
ToolPresent = false,
Ranks = {},
MaxRank = 0,
isActive = false,
CurDuration = 0,
CurHealth = 0,
CurCooldown = 0,
isTrinket = false,
TrinketSlot = nil
};
end
--[[ ----------------------------------------------------------------
METHOD: COE:CreateTotemRank
PURPOSE: Returns the class for a new totem rank
-------------------------------------------------------------------]]
function COE:CreateTotemRank()
return {SpellID = 0, Mana = 0, Duration = 0, Health = 0, Cooldown = 0};
end
--[[ ----------------------------------------------------------------
METHOD: COE:ElementFromTool
PURPOSE: Returns the element corresponding to a totem tool.
This is needed for the french version to work. In the
english and german versions it just returns the input
-------------------------------------------------------------------]]
function COE:ElementFromTool(element)
if element == COESTR_TOTEMTOOLS_EARTH then
return COESTR_ELEMENT_EARTH;
elseif element == COESTR_TOTEMTOOLS_FIRE then
return COESTR_ELEMENT_FIRE;
elseif element == COESTR_TOTEMTOOLS_WATER then
return COESTR_ELEMENT_WATER;
elseif element == COESTR_TOTEMTOOLS_AIR then
return COESTR_ELEMENT_AIR;
end
end
--[[ ----------------------------------------------------------------
METHOD: COE:LocalizedElement
PURPOSE: Translates a localized element name into english
-------------------------------------------------------------------]]
function COE:LocalizedElement(element)
if (element == COESTR_ELEMENT_EARTH) then
return "Earth";
elseif (element == COESTR_ELEMENT_FIRE) then
return "Fire";
elseif (element == COESTR_ELEMENT_WATER) then
return "Water";
elseif (element == COESTR_ELEMENT_AIR) then
return "Air";
end
end
--[[ ----------------------------------------------------------------
METHOD: COE:ScanTotems
PURPOSE: Scans the spellbook for available totems and
populates the COE.TotemData list
-------------------------------------------------------------------]]
function COE:ScanTotems()
COE:DebugMessage("Scanning Totems...");
-- delete existing totem objects
-- ------------------------------
COE.TotemData = {};
COE.TotemCount = 0;
COE.TotemsAvailable.Earth = 0;
COE.TotemsAvailable.Fire = 0;
COE.TotemsAvailable.Water = 0;
COE.TotemsAvailable.Air = 0;
-- iterate over all spells in the spellbook
-- -----------------------------------------
local i = 1;
while true do
local SpellName, SpellRank = GetSpellName(i, BOOKTYPE_SPELL);
if not SpellName then do break end end
-- is this a totem?
-- -----------------
if (SpellName ~= "Totemic Recall" and SpellName ~= "Totemic Slam" and
string.find(SpellName, COESTR_SCANTOTEMS) ~= nil) then
local newtotem = true;
local totem = nil;
-- get the rank value
-- -------------------
local _, _, rank = string.find(SpellRank, COESTR_TOTEMRANK);
if (not rank) then
rank = 1;
else
rank = tonumber(rank);
end
-- =======================================================================
-- check if totem already exists with another rank in the list
-- =======================================================================
for k = 1, COE.TotemCount do
if (SpellName == COE.TotemData[k].SpellName) then
-- use existing totem object
-- --------------------------
totem = COE.TotemData[k];
newtotem = false;
break
end
end
COETotemTT:SetSpell(i, BOOKTYPE_SPELL);
-- =======================================================================
-- create new totem object if not found
-- =======================================================================
if (not totem) then
totem = COE:CreateTotem();
-- set totem spell name
-- ---------------------
totem.SpellName = SpellName;
-- get totem school from tooltip
-- ------------------------------
local text = COETotemTTTextLeft4;
if (text and text:GetText()) then
local _, _, element =
string.find(text:GetText(), COESTR_TOTEMTOOLS);
if (element) then
-- if element starts with a |, the player does
-- not possess the needed totem for this spell
-- extract the color code before using the element
-- ------------------------------------------------
if (string.sub(element, 1, 1) == "|") then
element = string.sub(element, 11);
end
-- get element from tool
-- ----------------------
element = COE:ElementFromTool(element);
-- translate element to english
-- -----------------------------
element = COE:LocalizedElement(element);
-- valid element?
-- ---------------
if (COE.TotemsAvailable[element] ~= nil) then
totem.Element = element;
COE.TotemsAvailable[element] =
COE.TotemsAvailable[element] + 1;
else
COE:Message(COESTR_INVALIDELEMENT .. SpellName);
end
end
end
-- no element from the tooltip: fall back to the
-- known totem names (see COE.TotemElementsByName)
-- ------------------------------------------------
if (totem.Element == "") then
local element = COE.TotemElementsByName[SpellName];
if (element) then
totem.Element = element;
COE.TotemsAvailable[element] =
COE.TotemsAvailable[element] + 1;
end
end
-- get totem texture
-- ------------------
totem.Texture = GetSpellTexture(i, BOOKTYPE_SPELL);
-- get tool presence
-- ------------------
totem.ToolPresent = COE:IsToolPresent(i);
end
-- =======================================================================
-- create new totem rank
-- =======================================================================
local totemrank = COE:CreateTotemRank();
-- set totem spell id
-- -------------------
totemrank.SpellID = i;
-- get totem mana cost from tooltip
-- ---------------------------------
text = COETotemTTTextLeft2;
if (text and text:GetText()) then
local _, _, mana = string.find(text:GetText(), COESTR_TOTEMMANA);
if (mana) then totemrank.Mana = tonumber(mana); end
end
-- get totem duration and health
-- ------------------------------
totemrank.Duration, totemrank.Health, totemrank.Cooldown =
COE:GetTotemDurationAndHealth(i);
-- store rank in totem
-- --------------------
totem.Ranks[rank] = totemrank;
if (rank > totem.MaxRank) then totem.MaxRank = rank; end
-- is this a new totem? a spell that only has "Totem" in its
-- name but no element is not a placeable totem: leave it out
-- ------------------------------------------------------------
if (newtotem and totem.Element ~= "") then
-- store totem
-- ------------
COE.TotemCount = COE.TotemCount + 1;
COE.TotemData[COE.TotemCount] = totem;
-- check if it's a cleansing totem
-- --------------------------------
if (SpellName == COESTR_TOTEMPOISON) then
COE.CleansingTotems.Poison.Totem = totem;
elseif (SpellName == COESTR_TOTEMDISEASE) then
COE.CleansingTotems.Disease.Totem = totem;
elseif (SpellName == COESTR_TOTEMTREMOR) then
COE.CleansingTotems.Tremor.Totem = totem;
end
COE:DebugMessage("Found totem: " .. SpellName);
end
-- =======================================================================
-- check visibility options
-- =======================================================================
if (totem.Element == "") then
COE:DebugMessage("Skipped spell without a totem element: " ..
SpellName);
elseif (COE_DisplayedTotems[SpellName] == nil) then
-- perhaps a new totem. set it to default visible
-- and reorder it when the element count is known
-- -----------------------------------------------
COE_DisplayedTotems[SpellName] = {
Order = 0,
Element = totem.Element,
Visible = true
};
else
-- update old saved variables versions by adding the element
-- ----------------------------------------------------------
COE_DisplayedTotems[SpellName]["Element"] = totem.Element;
end
end
i = i + 1;
end
-- ====================================
-- Trinket support
-- ====================================
-- create the trinket totem even if the player doesn't have it.
-- this makes handling it much simpler and the player can choose
-- to make it invisible anyway
-- the player needs to have at least one water totem though
-- --------------------------------------------------------------
if (COE.TotemsAvailable.Water > 0) then
local trinket = COE:CreateTotem();
trinket.SpellName = "Trinket";
trinket.Element = "Water";
trinket.Texture = "Interface\\Icons\\INV_Wand_01";
trinket.isTrinket = true;
trinket.ToolPresent, trinket.TrinketSlot = COE:IsTrinketPresent();
trinket.Ranks[0] = COE:CreateTotemRank();
trinket.Ranks[0].Duration = 24;
trinket.Ranks[0].Health = 5;
trinket.Ranks[0].Cooldown = 180;
-- store totem
-- ------------
COE.TotemsAvailable.Water = COE.TotemsAvailable.Water + 1;
COE.TotemCount = COE.TotemCount + 1;
COE.TotemData[COE.TotemCount] = trinket;
if (COE_DisplayedTotems[trinket.SpellName] == nil) then
-- perhaps a new totem. set it to default visible
-- and reorder it when the element count is known
-- -----------------------------------------------
COE_DisplayedTotems[trinket.SpellName] = {Order = 0, Visible = true};
end
end
-- ===================================
-- Finish
-- ===================================
COE:DebugMessage(
"Found " .. COE.TotemCount .. " totems in spellbook" .. "(" ..
COE.TotemsAvailable.Earth .. " Earth, " .. COE.TotemsAvailable.Fire ..
" Fire, " .. COE.TotemsAvailable.Water .. " Water, " ..
COE.TotemsAvailable.Air .. " Air)");
-- reorder new totems
-- -------------------
COE:ReorderNewTotems();
end
--[[ ----------------------------------------------------------------
METHOD: COE:GetTotemDurationAndHealth
PURPOSE: Extracts the duration of the totem out of the tooltip
When there is more than one time specification present,
the one with the longer duration is used since this is the
totem duration then
Also the health and the cooldown of the totem are returned
-------------------------------------------------------------------]]
function COE:GetTotemDurationAndHealth(spellid)
COETotemTTTextLeft5:SetText(nil);
COETotemTTTextRight3:SetText(nil);
COETotemTT:SetSpell(spellid, BOOKTYPE_SPELL);
text = COETotemTTTextLeft5:GetText();
-- the description is normally line 5 but moves up when the client
-- leaves out the "Tools:" line (totem item not in the item cache).
-- the description is always the last line
-- -----------------------------------------------------------------
if (not text) then
local last = getglobal("COETotemTTTextLeft" .. COETotemTT:NumLines());
if (last) then text = last:GetText(); end
end
-- callers assign all three values: returning fewer leaves the
-- rank's Cooldown nil and the cast errors in ActivateTotem
-- ------------------------------------------------------------
if (not text) then
COE:DebugMessage("nil text with id: " .. spellid);
return 0, 0, 0;
end
local duration = 0;
local health = 0;
local cooldown = 0;
-- ===============================================================
-- Duration
-- ===============================================================
-- first search for a minute specification
-- if we find one it is surely the totem duration
-- -----------------------------------------------
local _, _, minutetext = string.find(text, COESTR_MINUTEDURATION);
if (minutetext) then
-- calculate the duration in seconds
-- ----------------------------------
local min = tonumber(string.sub(minutetext, 1, 1));
local sec = tonumber(string.sub(minutetext, 3, 4)) / 100 * 60;
duration = min * 60 + sec;
else
_, _, minutetext = string.find(text, COESTR_MINUTEDURATION_INT);
if (minutetext) then
duration = tonumber(minutetext) * 60;
else
-- now test for a duration in seconds
-- -----------------------------------
local _, b, sectext1 = string.find(text, COESTR_SECDURATION);
if (sectext1) then
-- look if there are two second specifications
-- if so, take the greate one
-- --------------------------------------------
local _, _, sectext2 = string.find(string.sub(text, b),
COESTR_SECDURATION);
if (sectext2) then
duration = math.max(tonumber(sectext1), tonumber(sectext2));
else
duration = tonumber(sectext1);
end
end
end
end
-- ===============================================================
-- Health
-- ===============================================================
for num, regex in COESTR_TOTEMHEALTH do
local match = {string.gfind(text, regex)()};
if (table.getn(match) >= 1) then
health = tonumber(match[1]);
break
end
end
-- ===============================================================
-- Cooldown
-- ===============================================================
text = COETotemTTTextRight3:GetText();
if (not text) then
cooldown = 0;
else
_, _, cooldown = string.find(text, COESTR_SECDURATION);
if (cooldown) then
cooldown = tonumber(cooldown);
else
_, _, cooldown = string.find(text, COESTR_MINUTEDURATION_INT);
if (cooldown) then
cooldown = tonumber(cooldown) * 60;
else
cooldown = 0;
end
end
end
return duration, health, cooldown;
end
--[[ ----------------------------------------------------------------
METHOD: COE:IsToolPresent
PURPOSE: Checks if the player has the totem of the specified
element in his inventory
This is done by testing the color of the "Tools:" section
in the totem tooltip
-------------------------------------------------------------------]]
function COE:IsToolPresent(spellid)
-- get totem tooltip
-- ------------------
COETotemTT:SetSpell(spellid, BOOKTYPE_SPELL);
-- test for presence of the totem tool
-- ------------------------------------
local text = COETotemTTTextLeft4;
if (text and text:GetText()) then
local _, _, element = string.find(text:GetText(), COESTR_TOTEMTOOLS);
if (element) then
-- if element doesn't start with a |, the player
-- possesses the needed totem for this spell
-- ------------------------------------------------
if (string.sub(element, 1, 1) ~= "|") then return true; end
end
end
return false;
end
--[[ ----------------------------------------------------------------
METHOD: COE:IsTrinketPresent
PURPOSE: Checks if the player has the enamored water spirit
trinket equipped and returns the trinket slot
RETURNS: equipped, slot
-------------------------------------------------------------------]]
function COE:IsTrinketPresent()
for i = 0, 1 do
local slot = GetInventorySlotInfo("Trinket" .. i .. "Slot");
local item = GetInventoryItemLink("player", slot);
if (item) then
local itemname = string.find(item, COESTR_TRINKET);
if (itemname) then
-- trinket is equipped
-- --------------------
return true, slot;
end
end
end
return false, nil;
end
--[[ ----------------------------------------------------------------
METHOD: COE:ReorderNewTotems
PURPOSE: Assigns each COE_DisplayedTotems entry with a zero
order a valid order depending on the number of available
totems in this element
-------------------------------------------------------------------]]
function COE:ReorderNewTotems()
COE:DebugMessage("Executing ReorderNewTotems");
local nextslot = {
Earth = COE.TotemsAvailable.Earth,
Fire = COE.TotemsAvailable.Fire,
Water = COE.TotemsAvailable.Water,
Air = COE.TotemsAvailable.Air
};
local used = {Earth = {}, Fire = {}, Water = {}, Air = {}};
local bError = false;
COE:DebugMessage("ReorderNewTotems COE.TotemCount: " .. COE.TotemCount);
for k = 1, COE.TotemCount do
local totem = COE.TotemData[k];
COE:DebugMessage(
"ReorderNewTotems processing totem: " .. totem.Element .. " " ..
totem.SpellName);
if (COE_DisplayedTotems[totem.SpellName] ~= nil) then
if (COE_DisplayedTotems[totem.SpellName].Order == 0) then
-- this totem has just been added
-- assign the currently free slot
-- -------------------------------
if (not nextslot[totem.Element]) then
COE:DebugMessage(
"ReorderNewTotems nextslot[totem.Element] is nil");
end
COE_DisplayedTotems[totem.SpellName].Order =
nextslot[totem.Element];
nextslot[totem.Element] = nextslot[totem.Element] - 1;
end
-- register that this slot of the element is now in use
-- mark as error if already in use
-- -----------------------------------------------------
if (used[totem.Element][COE_DisplayedTotems[totem.SpellName].Order] ==
nil) then
used[totem.Element][COE_DisplayedTotems[totem.SpellName].Order] =
true;
else
bError = true;
end
end
end
-- are there multiple entries for one slot?
-- -----------------------------------------
if (bError) then
-- there is something wrong with the saved variables
-- reset all ordering and reassign it
-- --------------------------------------------------
for k = 1, COE.TotemCount do
local totem = COE.TotemData[k];
if (COE_DisplayedTotems[totem.SpellName] ~= nil) then
COE_DisplayedTotems[totem.SpellName].Order = 0;
end
end
COE:ReorderNewTotems();
end
end
--[[ ----------------------------------------------------------------
METHOD: COE:InitTotemSets
PURPOSE: Fills the COE.TotemSets list with the totem objects
corresponding to the spell names saved in COEOPT_TOTEMSETS
-------------------------------------------------------------------]]
function COE:InitTotemSets()
local indices = {"Earth", "Fire", "Water", "Air"};
COE.TotemSets = {};
-- for each standard set
-- ----------------------
for set = 1, table.getn(COE_SavedTotemSets) do
COE.TotemSets[set] = {
Earth = nil,
Fire = nil,
Water = nil,
Air = nil,
CastOrder = COE_SavedTotemSets[set].CastOrder
};
-- for each element
-- -----------------
for k = 1, 4 do
if (COE_SavedTotemSets[set][indices[k]] ~= "") then
-- iterate over all totems
-- ------------------------
for totem in COE.TotemData do
if (COE.TotemData[totem].SpellName ==
COE_SavedTotemSets[set][indices[k]]) then
COE.TotemSets[set][indices[k]] = COE.TotemData[totem];
end
end
end
end
end
-- for each custom set
-- --------------------
for set = 1, table.getn(COE_CustomTotemSets) do
COE.TotemSets[COESET_DEFAULT + set] = {
Earth = nil,
Fire = nil,
Water = nil,
Air = nil,
CastOrder = COE_CustomTotemSets[set].CastOrder
};
-- for each element
-- -----------------
local k, totem;
for k = 1, 4 do
if (COE_CustomTotemSets[set][indices[k]] ~= "") then
-- iterate over all totems
-- ------------------------
for totem in COE.TotemData do
if (COE.TotemData[totem].SpellName ==
COE_CustomTotemSets[set][indices[k]]) then
COE.TotemSets[COESET_DEFAULT + set][indices[k]] =
COE.TotemData[totem];
end
end
end
end
end
COE.TotemSetCount = table.getn(COE.TotemSets);
end
--[[ =============================================================================================
F I X E S
================================================================================================]]
--[[ ----------------------------------------------------------------
METHOD: COE:Fix_CastOrderLocalization
PURPOSE: Correctly localizes the element names in the
cast order in COE_SavedTotemSets
-------------------------------------------------------------------]]
function COE:Fix_CastOrderLocalization()
-- for each standard set
-- ----------------------
local set, k;
for set = 1, table.getn(COE_SavedTotemSets) do
for k = 1, 4 do
if (COE_SavedTotemSets[set].CastOrder[k] == "Earth") then
COE_SavedTotemSets[set].CastOrder[k] = COESTR_ELEMENT_EARTH;
elseif (COE_SavedTotemSets[set].CastOrder[k] == "Fire") then
COE_SavedTotemSets[set].CastOrder[k] = COESTR_ELEMENT_FIRE;
elseif (COE_SavedTotemSets[set].CastOrder[k] == "Water") then
COE_SavedTotemSets[set].CastOrder[k] = COESTR_ELEMENT_WATER;
elseif (COE_SavedTotemSets[set].CastOrder[k] == "Air") then
COE_SavedTotemSets[set].CastOrder[k] = COESTR_ELEMENT_AIR;
end
end
end
-- notify user
-- ------------
COE:Message(COESTR_FIXEDSETS);
end
--[[ ----------------------------------------------------------------
METHOD: COE:Fix_DisplayedTotems
PURPOSE: Fixes errors in the COE_DisplayedTotems array
-------------------------------------------------------------------]]
function COE:Fix_DisplayedTotems()
local i;
local fixed = false;
foreach(COE_DisplayedTotems, function(index, value)
-- is this an old-style entry?
-- ----------------------------
if (type(value) == "boolean") then
COE_DisplayedTotems[index] = {Order = 0, Visible = value};
fixed = true;
elseif (type(value) == "table") then
if (COE_DisplayedTotems[index].Visible == nil) then
COE_DisplayedTotems[index].Visible = true;
fixed = true;
end
if (COE_DisplayedTotems[index].Order == nil) then
COE_DisplayedTotems[index].Order = 0;
fixed = true;
end
else
COE_DisplayedTotems[index] = {Order = 0, Visible = value};
fixed = true;
end
end);
-- notify user
-- ------------
if (fixed) then COE:Message(COESTR_FIXEDDISPLAY); end
end
--[[ ----------------------------------------------------------------
METHOD: COE:Fix_CastOrderLocalization2
PURPOSE: Correctly localizes the element names in the
cast order in COE_SavedTotemSets
-------------------------------------------------------------------]]
function COE:Fix_CastOrderLocalization2()
-- for each standard set
-- ----------------------
local set, k;
for set = 1, table.getn(COE_SavedTotemSets) do
for k = 1, 4 do
if (COE_SavedTotemSets[set].CastOrder[k] == COESTR_TOTEMTOOLS_EARTH) then
COE_SavedTotemSets[set].CastOrder[k] = COESTR_ELEMENT_EARTH;
elseif (COE_SavedTotemSets[set].CastOrder[k] ==
COESTR_TOTEMTOOLS_FIRE) then
COE_SavedTotemSets[set].CastOrder[k] = COESTR_ELEMENT_FIRE;
elseif (COE_SavedTotemSets[set].CastOrder[k] ==
COESTR_TOTEMTOOLS_WATER) then
COE_SavedTotemSets[set].CastOrder[k] = COESTR_ELEMENT_WATER;
elseif (COE_SavedTotemSets[set].CastOrder[k] ==
COESTR_TOTEMTOOLS_AIR) then
COE_SavedTotemSets[set].CastOrder[k] = COESTR_ELEMENT_AIR;
end
end
end
-- for each custom set
-- --------------------
for set = 1, table.getn(COE_CustomTotemSets) do
for k = 1, 4 do
if (COE_CustomTotemSets[set].CastOrder[k] == COESTR_TOTEMTOOLS_EARTH) then
COE_CustomTotemSets[set].CastOrder[k] = COESTR_ELEMENT_EARTH;
elseif (COE_CustomTotemSets[set].CastOrder[k] ==
COESTR_TOTEMTOOLS_FIRE) then
COE_CustomTotemSets[set].CastOrder[k] = COESTR_ELEMENT_FIRE;
elseif (COE_CustomTotemSets[set].CastOrder[k] ==
COESTR_TOTEMTOOLS_WATER) then
COE_CustomTotemSets[set].CastOrder[k] = COESTR_ELEMENT_WATER;
elseif (COE_CustomTotemSets[set].CastOrder[k] ==
COESTR_TOTEMTOOLS_AIR) then
COE_CustomTotemSets[set].CastOrder[k] = COESTR_ELEMENT_AIR;
end
end
end
end