Mercurial > wow > emfor1
diff CensusPlus.lua @ 0:edfa01041183
Census+ Mod :
- TLJ guild search
- searchstart at Level 1 for community events
| author | EmFor <EmFor.hg@mroe.de> |
|---|---|
| date | Tue, 30 Mar 2010 13:42:05 +0200 |
| parents | |
| children | 10c85be19b56 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CensusPlus.lua Tue Mar 30 13:42:05 2010 +0200 @@ -0,0 +1,4010 @@ +--[[ + CensusPlus for World of Warcraft(tm). + + Copyright 2005 - 2007 Cooper Sellers and WarcraftRealms.com + + 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(see GLP.txt); if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +]] + + +------------------------------------------------------------------------------------ +-- +-- CensusPlus +-- A WoW UI customization by Cooper Sellers +-- +-- +------------------------------------------------------------------------------------ + +---------------------------------------------------------------------------------- +-- +-- EURO vs US localization problem workaround for common server names +-- +--------------------------------------------------------------------------------- +local g_InterfaceVersion = 30000; +g_CensusPlusLocale = "N/A"; -- Must read either US or EU +g_CensusPlusTZOffset = -999; +local g_LocaleSet = false; +local g_TZWarningSent = false; + + +---------------------------------------------------------------------------------- +-- +-- Constants +--rm +local CensusPlus_MYGUILD = "The Last Journey"; -- Special guild to search +--------------------------------------------------------------------------------- +local CensusPlus_VERSION = "4.2.2"; -- version +local CensusPlus_MAXBARHEIGHT = 128; -- Length of blue bars +local CensusPlus_NUMGUILDBUTTONS = 10; -- How many guild buttons are on the UI? +local MAX_CHARACTER_LEVEL = 80; -- Maximum level a PC can attain +--rm +local MAX_LEVEL_DISPLAY = 255; -- Maximum level a PC can attain +local MAX_WHO_RESULTS = 45; -- Maximum number of who results the server will return +CensusPlus_GUILDBUTTONSIZEY = 16; +local CensusPlus_UPDATEDELAY = 5; -- Delay time between /who messages +local CP_MAX_TIMES = 50; + +local g_ServerPrefix = ""; -- US VERSION!! +--local g_ServerPrefix = "EU-"; -- EU VERSION!! + +local wholib +---------------------------------------------------------------------------------- +-- +-- Print a string to the chat frame +-- msg - message to print +-- +--------------------------------------------------------------------------------- +function CensusPlus_Msg(msg) + if( msg == nil ) then + msg = " NIL "; + end + ChatFrame1:AddMessage("Census+: "..msg, 1.0, 1.0, 0.5); +end + +function CensusPlus_WhoMsg(msg) + if( msg == nil ) then + msg = " NIL "; + end + ChatFrame1:AddMessage("Census+ Who: "..msg, 0.8, 0.8, 0.1); +end + +local function CensusPlus_Msg2( msg ) + if( msg == nil ) then + msg = " NIL "; + end + ChatFrame2:AddMessage("Census+: "..msg, 0.5, 1.0, 1.0); +end + +---------------------------------------------------------------------------------- +-- +-- Global scope variables +-- +--------------------------------------------------------------------------------- +CensusPlus_Database = {}; -- Database of all CensusPlus results +CensusPlus_BGInfo = {}; -- Battleground info +CensusPlus_PerCharInfo = {}; -- Per character settings +CensusPlus_Unhandled = {}; +local g_TrackUnhandled = false; + +---------------------------------------------------------------------------------- +-- +-- File scope variables +-- +--------------------------------------------------------------------------------- +local g_CensusPlusInitialized; -- Is CensusPlus initialized? +local g_JobQueue = {}; -- The queue of pending jobs +local g_CurrentJob = {}; -- Current job being executed +g_IsCensusPlusInProgress = false; -- Is a CensusPlus in progress? +g_CensusPlusPaused = false; -- Is CensusPlus in progress paused? +g_CensusPlusManuallyPaused = false; -- Is CensusPlus in progress manually paused? +local g_WhoAutoClose = 0; -- AutoClose who window? + +local g_NumNewCharacters = 0; -- How many new characters found this CensusPlus +local g_NumUpdatedCharacters = 0; -- How many characters were updated during this CensusPlus + +local g_MobXPByLevel = {}; -- XP earned for killing +local g_CharacterXPByLevel = {}; -- XP required to advance through the given level +local g_TotalCharacterXPPerLevel = {}; -- Total XP required to attain the given level + +CensusPlus_Guilds = {}; -- All known guild + +local g_TotalCharacterXP = 0; -- Total character XP for currently selected search +local g_TotalCount = 0; -- Total number of characters which meet search criteria +local g_RaceCount = {}; -- Totals for each race given search criteria +local g_ClassCount = {}; -- Totals for each class given search criteria +local g_LevelCount = {}; -- Totals for each level given search criteria +local g_TempCount = {}; +local g_TempZoneCount = {}; + +g_GuildSelected = nil; -- Search criteria: Currently selected guild, 0 indicates none +g_RaceSelected = 0; -- Search criteria: Currently selected race, 0 indicates none +g_ClassSelected = 0; -- Search criteria: Currently selected class, 0 indicates none +g_LevelSelected = 0; + +local g_LastOnUpdateTime = 0; -- Last time OnUpdate was called +local g_WaitingForWhoUpdate = false; -- Are we waiting for a who update event? + +local g_WhoAttempts = 0; -- Counter for detecting stuck who results +local g_MiniOnStart = 1; -- Flag to have the mini-censusP displayed on startup + +local g_CompleteCensusStarted = false; -- Flag for counter +local g_TakeHour = 0; -- Our timing hour +local g_TimeDatabase = {}; -- Time database +local g_ResetHour = true; -- Rest hour +local g_VariablesLoaded = false; -- flag to tell us if vars are loaded +local g_FirstRun = true; +local g_LastCensusRun = time() - 1500; -- timer used if auto census is turned on + +local g_Pre_FriendsFrameOnHideOverride = nil; -- override for friend's frame to stop the close window sound +local g_Pre_FriendsFrameOnShowOverride = nil; -- override for friend's frame to stop the close window sound +local g_Pre_WhoList_UpdateOverride = nil; -- override for friend's frame to stop the close window sound +local g_Pre_WhoHandler = nil; -- override for submiting a who +local CP_Pre_OnEvent = nil; +local g_Pre_FriendsFrame_Update = nil; +local g_SetItemRef_Override = nil; +local CP_updatingGuild = nil; +g_CensusPlusLastTarget = nil; +g_CensusPlusLastTargetName = nil; +local g_CurrentlyInBG = false; +local g_CurrentlyInBG_Msg = false; +local g_InternalSearchName = nil; +local g_InternalSearchLevel = nil; +local g_InternalSearchCount = 0; +CensusPlus_EnableProfiling = false; +local g_CensusPlus_StartTime = 0; +local g_CensusWhoOverrideMsg = nil; +local g_WaitingForOverrideUpdate = false; +local g_ProblematicMessageShown = false; +local g_WhoLibLoaded = false; +local g_PratLoaded = false; +local g_WhoLibSubvert = nil; +local g_WhoLibSendWhoSubvert = nil; +local g_whoLibResultSubvert = nil; +local g_WhoLibChatSubvert = nil; +local g_WhoLibAskWhoSubvert = nil; + +-- Battleground info +CENSUSPLUS_CURRENT_BATTLEFIELD_QUEUES = {}; + +local g_AccumulatedPruneData = {}; + +g_RaceClassList = { }; -- Used to pick the right icon +g_RaceClassList[CENSUSPlus_DRUID] = 10; +g_RaceClassList[CENSUSPlus_HUNTER] = 11; +g_RaceClassList[CENSUSPlus_MAGE] = 12; +g_RaceClassList[CENSUSPlus_PRIEST] = 13; +g_RaceClassList[CENSUSPlus_ROGUE] = 14; +g_RaceClassList[CENSUSPlus_WARLOCK] = 15; +g_RaceClassList[CENSUSPlus_WARRIOR] = 16; +g_RaceClassList[CENSUSPlus_SHAMAN] = 17; +g_RaceClassList[CENSUSPlus_PALADIN] = 18; +g_RaceClassList[CENSUSPlus_DEATHKNIGHT] = 30; + +g_RaceClassList[CENSUSPlus_DWARF] = 20; +g_RaceClassList[CENSUSPlus_GNOME] = 21; +g_RaceClassList[CENSUSPlus_HUMAN] = 22; +g_RaceClassList[CENSUSPlus_NIGHTELF] = 23; +g_RaceClassList[CENSUSPlus_ORC] = 24; +g_RaceClassList[CENSUSPlus_TAUREN] = 25; +g_RaceClassList[CENSUSPlus_TROLL] = 26; +g_RaceClassList[CENSUSPlus_UNDEAD] = 27; +g_RaceClassList[CENSUSPlus_DRAENEI] = 28; +g_RaceClassList[CENSUSPlus_BLOODELF] = 29; + +g_TimeDatabase[CENSUSPlus_DRUID] = 0; +g_TimeDatabase[CENSUSPlus_HUNTER] = 0; +g_TimeDatabase[CENSUSPlus_MAGE] = 0; +g_TimeDatabase[CENSUSPlus_PRIEST] = 0; +g_TimeDatabase[CENSUSPlus_ROGUE] = 0; +g_TimeDatabase[CENSUSPlus_WARLOCK] = 0; +g_TimeDatabase[CENSUSPlus_WARRIOR] = 0; +g_TimeDatabase[CENSUSPlus_SHAMAN] = 0; +g_TimeDatabase[CENSUSPlus_PALADIN] = 0; +g_TimeDatabase[CENSUSPlus_DEATHKNIGHT] = 0; +g_TimeDatabase[CENSUSPlus_WarsongGulch] = 0; +g_TimeDatabase[CENSUSPlus_AlteracValley] = 0; +g_TimeDatabase[CENSUSPlus_ArathiBasin] = 0; + +-- These two DO NOT need to be localized +local CENSUSPlus_HORDE = "Horde"; +local CENSUSPlus_ALLIANCE = "Alliance"; + + +local g_FactionCheck = {}; +g_FactionCheck[CENSUSPlus_ORC] = CENSUSPlus_HORDE; +g_FactionCheck[CENSUSPlus_TAUREN] = CENSUSPlus_HORDE; +g_FactionCheck[CENSUSPlus_TROLL] = CENSUSPlus_HORDE; +g_FactionCheck[CENSUSPlus_UNDEAD] = CENSUSPlus_HORDE; +g_FactionCheck[CENSUSPlus_BLOODELF] = CENSUSPlus_HORDE; + +g_FactionCheck[CENSUSPlus_DWARF] = CENSUSPlus_ALLIANCE; +g_FactionCheck[CENSUSPlus_GNOME] = CENSUSPlus_ALLIANCE; +g_FactionCheck[CENSUSPlus_HUMAN] = CENSUSPlus_ALLIANCE; +g_FactionCheck[CENSUSPlus_NIGHTELF] = CENSUSPlus_ALLIANCE; +g_FactionCheck[CENSUSPlus_DRAENEI] = CENSUSPlus_ALLIANCE; +local g_ReturnedZero = false; + +do + -- HACK + --[[ + seeing as Blizzard improperly coded GuildControlPopupFrame_OnEvent to mess up when GUILD_ROSTER_EVENT is dispatched, + and there is no real harm in removing the handler entirely, that's what's happening. If and when Blizzard decides to fix it, this should be removed. + Thanks to ckknight of wowace for this + ]] + GuildControlPopupFrame:SetScript("OnEvent", nil) +end + + +---------------------------------------------------------------------------------- +-- +-- Set up confirmation boxes +-- +--------------------------------------------------------------------------------- +StaticPopupDialogs["CP_PURGE_CONFIRM"] = { + text = CENSUSPlus_PURGE_LOCAL_CONFIRM, + button1 = CENSUSPlus_YES, + button2 = CENSUSPlus_NO, + OnAccept = function() + CensusPlus_DoPurge(); + end, + sound = "levelup2", + timeout = 0, + whileDead = 1, + hideOnEscape = 1, + showAlert = 1 +}; + +---------------------------------------------------------------------------------- +-- +-- Set up Continue after override box +-- +--------------------------------------------------------------------------------- +StaticPopupDialogs["CP_CONTINUE_CENSUS"] = { + text = CENSUSPlus_OVERRIDE_COMPLET_PAUSED, + button1 = CENSUSPlus_CONTINUE, + OnAccept = function() + g_CensusPlusManuallyPaused = false; + CensusPlusTakeButton:SetText( CENSUSPlus_PAUSE ); + end, + sound = "levelup2", + timeout = 0, + whileDead = 1, + hideOnEscape = 1, + showAlert = 1 +}; + +---------------------------------------------------------------------------------- +-- +-- Chat msg hook +-- +--------------------------------------------------------------------------------- +local function CP_HookAddMessage(frame) + local AddMessage = frame.AddMessage; + -- Create a closure to cleanly hook the AddMessage routine. + frame.AddMessage = + function (this, msg, r, g, b, id) + if( ( g_TrackUnhandled or g_IsCensusPlusInProgress ) and msg ) then + local s, e; + local results = { }; + local whoMsg = false; +--CensusPlus_Msg2( "Something : " .. msg ); + + -- + -- We don't need to process results from chat, we can get it straight from the who window (DUHH!) + -- So, we just need to see if we have a match, and suppress the output if so + -- + +-- results = CensusPlus_GatherSingleReturn( msg ); +-- if( results["NAME"] ~= nil ) then + results = { }; + s, e = strmatch(msg, CENSUS_SINGLE_MATCH_PATTERN); + if( s ~= nil ) then +-- CensusPlus_Msg2( " Name : " .. results["NAME"] .. " L: " .. results["LEVEL"] .. " R: " .. results["RACE"] .. " C: " .. results["CLASS"].. " G: " .. results["GUILD"].. " Z: " .. results["ZONE"] ); + whoMsg = true; +-- WR_ProcessSingleEntry( results["NAME"], results["LEVEL"], results["RACE"], results["CLASS"], results["GUILD"], results["ZONE"] ); + else + if( g_TrackUnhandled ) then + CensusPlus_Unhandled[msg] = 1; + end + end + + results = { }; + s, e = strmatch(msg, WHO_NUM_RESULTS); + if( s ~= nil ) then + -- We got a match, now just need to determine if it's 0 or not, so we'll use a bit more lax check + whoMsg = true; + + local result; + s, e, result = string.find( msg, "(%d+).*" ); + if( result == "0" ) then + g_ReteurnedZero = true; + end + + CensusPlus_ProcessWhoResults(); + end + + + if( whoMsg ) then + -- + -- Also bail out of an override if in place + -- + if( g_CensusWhoOverrideMsg ~= nil and g_WaitingForOverrideUpdate == true ) then + -- + -- Allow the who to act normally + -- + g_CensusWhoOverrideMsg = nil; + g_WaitingForOverrideUpdate = false; + CensusPlus_Msg( CENSUSPlus_OVERRIDE_COMPLETE ); + return AddMessage(this, msg, r, g, b, id) + elseif( CensusPlus_PerCharInfo["Verbose"] ~= true and + not g_CensusPlusPaused and + not g_CensusPlusManuallyPaused ) then + return; + + end + + g_WaitingForWhoUpdate = false; + end + + return AddMessage(this, msg, r, g, b, id) + else + return AddMessage(this, msg, r, g, b, id) + end + end +end + + + +----------------------------------------------------------------------------------- +-- +-- Insert a job at the end of the job queue +-- +----------------------------------------------------------------------------------- +local function InsertJobIntoQueue(job) +--CensusPlus_DumpJob( job ); + table.insert(g_JobQueue, job); +end + +----------------------------------------------------------------------------------- +-- +-- Initialize the tables of constants for XP calculations +-- +----------------------------------------------------------------------------------- +local function InitConstantTables() + -- + -- XP earned for killing + -- + --rm + for i = 1, MAX_LEVEL_DISPLAY, 1 do + g_MobXPByLevel[i] = i; + end + + -- + -- XP required to advance through the given level + -- + for i = 1, MAX_LEVEL_DISPLAY, 1 do + g_CharacterXPByLevel[i] = ((8 * i * g_MobXPByLevel[i]) / 100) * 100; + end + + -- + -- Total XP required to attain the given level + -- + local totalCharacterXP = 0; + for i = 1, MAX_LEVEL_DISPLAY, 1 do +-- g_TotalCharacterXPPerLevel[i] = totalCharacterXP; + --totalCharacterXP = totalCharacterXP + g_CharacterXPByLevel[i]; + val = (i*5)/MAX_LEVEL_DISPLAY; + g_TotalCharacterXPPerLevel[i] = math.exp(val); + end + +end + +----------------------------------------------------------------------------------- +-- +-- Return a table of races for the input faction +-- +----------------------------------------------------------------------------------- +function CensusPlus_GetFactionRaces(faction) + local ret = {}; + if (faction == CENSUSPlus_HORDE) then + ret = {CENSUSPlus_ORC, CENSUSPlus_TAUREN, CENSUSPlus_TROLL, CENSUSPlus_UNDEAD, CENSUSPlus_BLOODELF}; + elseif (faction == CENSUSPlus_ALLIANCE) then + ret = {CENSUSPlus_DWARF, CENSUSPlus_GNOME, CENSUSPlus_HUMAN, CENSUSPlus_NIGHTELF, CENSUSPlus_DRAENEI}; + end + return ret; +end + +----------------------------------------------------------------------------------- +-- +-- Return a table of classes for the input faction +-- +----------------------------------------------------------------------------------- +function CensusPlus_GetFactionClasses(faction) + local ret = {}; + if (faction == CENSUSPlus_HORDE) then + ret = {CENSUSPlus_DRUID, CENSUSPlus_HUNTER, CENSUSPlus_MAGE, CENSUSPlus_PRIEST, CENSUSPlus_ROGUE, CENSUSPlus_WARLOCK, CENSUSPlus_WARRIOR, CENSUSPlus_PALADIN, CENSUSPlus_SHAMAN, CENSUSPlus_DEATHKNIGHT}; + elseif (faction == CENSUSPlus_ALLIANCE) then + ret = {CENSUSPlus_DRUID, CENSUSPlus_HUNTER, CENSUSPlus_MAGE, CENSUSPlus_PRIEST, CENSUSPlus_ROGUE, CENSUSPlus_WARLOCK, CENSUSPlus_WARRIOR, CENSUSPlus_PALADIN, CENSUSPlus_SHAMAN, CENSUSPlus_DEATHKNIGHT}; + end + return ret; +end + +----------------------------------------------------------------------------------- +-- +-- Return a table of classes for the input race +-- +----------------------------------------------------------------------------------- +local function GetRaceClasses(race) + local ret = {}; + if (race == CENSUSPlus_ORC) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_HUNTER, CENSUSPlus_ROGUE, CENSUSPlus_SHAMAN, CENSUSPlus_WARLOCK, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_TAUREN) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_HUNTER, CENSUSPlus_SHAMAN, CENSUSPlus_DRUID, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_TROLL) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_HUNTER, CENSUSPlus_ROGUE, CENSUSPlus_PRIEST, CENSUSPlus_SHAMAN, CENSUSPlus_MAGE, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_UNDEAD) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_ROGUE, CENSUSPlus_PRIEST, CENSUSPlus_MAGE, CENSUSPlus_WARLOCK, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_DWARF) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_PALADIN, CENSUSPlus_HUNTER, CENSUSPlus_ROGUE, CENSUSPlus_PRIEST, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_GNOME) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_ROGUE, CENSUSPlus_MAGE, CENSUSPlus_WARLOCK, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_HUMAN) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_PALADIN, CENSUSPlus_ROGUE, CENSUSPlus_PRIEST, CENSUSPlus_MAGE, CENSUSPlus_WARLOCK, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_NIGHTELF) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_HUNTER, CENSUSPlus_ROGUE, CENSUSPlus_PRIEST, CENSUSPlus_DRUID, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_BLOODELF) then + ret = {CENSUSPlus_PALADIN, CENSUSPlus_HUNTER, CENSUSPlus_ROGUE, CENSUSPlus_PRIEST, CENSUSPlus_MAGE, CENSUSPlus_WARLOCK, CENSUSPlus_DEATHKNIGHT}; + elseif (race == CENSUSPlus_DRAENEI) then + ret = {CENSUSPlus_WARRIOR, CENSUSPlus_PALADIN, CENSUSPlus_HUNTER, CENSUSPlus_PRIEST, CENSUSPlus_SHAMAN, CENSUSPlus_MAGE, CENSUSPlus_DEATHKNIGHT}; + end + return ret; +end + +----------------------------------------------------------------------------------- +-- +-- Return common letters found in zone names +-- +----------------------------------------------------------------------------------- +local function GetZoneLetters() + return {"t", "d", "g", "f", "h", "b", "x", "gulch", "valley", "basin" }; +end + +----------------------------------------------------------------------------------- +-- +-- Return common letters found in names, may override this for other languages +-- Worst case scenario is to do it for every letter in the alphabet +-- +----------------------------------------------------------------------------------- +local function GetNameLetters() +--rm +-- return { "a", "b", "c", "d", "e", "f", "g", "i", "o", "p", "r", "s", "t", "u", "y" }; +-- return { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "\195\134", "\195\164", "\195\182", "\195\188", "\195\152" }; + return { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "\195\134", "\195\164", "\195\182", "\195\188", "\195\152", "\195\184" }; +end + +--------------------------------------------------------------------------------- +-- +-- Register with Cosmos UI +-- +--------------------------------------------------------------------------------- +local function CensusPlus_RegisterCosmos() + -- + -- If Cosmos is installed, add a button to the Cosmos page to activate CensusPlus + -- + if ( EarthFeature_AddButton ) then + EarthFeature_AddButton( + { + id = "CensusPlus"; + name = CENSUSPlus_BUTTON_TEXT; + subtext = CENSUSPlus_BUTTON_SUBTEXT; + tooltip = CENSUSPlus_BUTTON_TIP; + icon = "Interface\\AddOns\\CensusPlus\\Skin\\CensusPlus_Icon"; + callback = CensusPlus_Toggle; + } + ); + elseif ( Cosmos_RegisterButton ) then + Cosmos_RegisterButton(CENSUSPlus_BUTTON_TEXT, CENSUSPlus_BUTTON_SUBTEXT, CENSUSPlus_BUTTON_TIP, "Interface\\AddOns\\CensusPlus\\Skin\\CensusPlus_Icon", CensusPlus_Toggle); + end +end + + +---------------------------------------------------------------------------------- +-- +-- Called when the main window is shown +-- +--------------------------------------------------------------------------------- +function CensusPlus_OnShow() + -- Initialize if this is the first OnShow event + if (g_CensusPlusInitialized == false) then + g_CensusPlusInitialized = true; + end + CensusPlus_UpdateView(); +end + +---------------------------------------------------------------------------------- +-- +-- Toggle hidden status +-- +--------------------------------------------------------------------------------- +function CensusPlus_Toggle() + if ( CensusPlus:IsVisible() ) then + CensusPlus:Hide(); + else + CensusPlus:Show(); + end +end + +---------------------------------------------------------------------------------- +-- +-- Toggle options pane +-- +--------------------------------------------------------------------------------- +function CensusPlus_ToggleOptions() + if ( CP_OptionsWindow:IsVisible() ) then + CP_OptionsWindow:Hide(); + else + CP_OptionsWindow:Show(); + end +end + +----------------------------------------------------------------------------------- +-- +-- Called once on load +-- +----------------------------------------------------------------------------------- +function CensusPlus_OnLoad() + -- + -- Update the version number + -- + CensusPlusText:SetText("Census+ EmSpe\195\167ial v"..CensusPlus_VERSION .. " " .. g_CensusPlusLocale ); + CensusPlusText2:SetText( CENSUSPlus_UPLOAD ); + + -- + -- Init constant tables + -- + InitConstantTables(); + + -- + -- Register with Cosmos, if it is installed + -- + CensusPlus_RegisterCosmos(); + + -- + -- Register for events + -- + this:RegisterEvent("VARIABLES_LOADED"); +-- this:RegisterEvent("WHO_LIST_UPDATE"); + + + this:RegisterEvent("CHAT_MSG_SYSTEM"); + + + this:RegisterEvent("ZONE_CHANGED_NEW_AREA"); + + -- + -- Register a slash command + -- + SLASH_CensusPlusCMD1 = "/CensusPlus"; + SLASH_CensusPlusCMD2 = "/Census+"; + SLASH_CensusPlusCMD3 = "/Census"; + SlashCmdList["CensusPlusCMD"] = CensusPlus_Command; + + SLASH_CensusPlusVerbose1 = "/censusverbose"; + SlashCmdList["CensusPlusVerbose"] = CensusPlus_Verbose; + + -- + -- Set the auto close to true + -- + CensusPlus_AutoCloseWho( 1 ); + --AutoClose:SetChecked( 1 ); + +-- g_Pre_FriendsFrameOnHideOverride = FriendsFrame_OnHide; +-- FriendsFrame_OnHide = CensusPlus_FriendsFrame_OnHide; + +-- g_Pre_FriendsFrameOnShowOverride = FriendsFrame_OnShow; +-- FriendsFrame_OnShow = CensusPlus_FriendsFrame_OnShow; + +-- g_Pre_WhoList_UpdateOverride = WhoList_Update; +-- WhoList_Update = CensusPlus_WhoList_Update; + +-- g_Pre_FriendsFrame_Update = FriendsFrame_Update; +-- FriendsFrame_Update = CensusPlus_FriendsFrame_Update; + + g_SetItemRef_Override = SetItemRef; + SetItemRef = CensusPlus_SetItemRef; + + CP_Pre_OnEvent = FriendsFrame_OnEvent; + FriendsFrame_OnEvent = CensusPlus_FriendsFrame_OnEvent; + + g_Pre_WhoHandler = SlashCmdList["WHO"]; + SlashCmdList["WHO"] = CensusPlus_WhoHandler; + + CensusPlus_CheckForBattleground(); + + -- Hook the default chat frame's AddMessage method. + CP_HookAddMessage(ChatFrame1); + + -- + -- Set up an empty frame to do updates + -- + local updateFrame = CreateFrame("Frame"); + updateFrame:SetScript("OnUpdate", CensusPlus_OnUpdate); + CensusPlusTakeGuildButton:SetText( CENSUSPlus_TAKEGUILD.." \""..CensusPlus_MYGUILD.."\"" ); +end + +function CensusPlus_FriendsFrame_OnEvent(...) + +-- CensusPlus_Msg( "CP_FF_OE Message =>" .. event ); + + if(wholib == nil and + event == "WHO_LIST_UPDATE" and g_IsCensusPlusInProgress and g_WaitingForWhoUpdate ) then + -- + -- First check for an override + -- + if( g_CensusWhoOverrideMsg ~= nil and g_WaitingForOverrideUpdate == true ) then + -- + -- Allow the who to act normally + -- + g_CensusWhoOverrideMsg = nil; + g_WaitingForOverrideUpdate = false; + CensusPlus_Msg( CENSUSPlus_OVERRIDE_COMPLETE_BUT_PAUSED ); +-- g_Pre_WhoList_UpdateOverride(); + + + g_WaitingForWhoUpdate = false; + CP_Pre_OnEvent(...); + -- + -- If we opened the who window, do a manual pause and open a dialog + -- + g_CensusPlusManuallyPaused = true; + CensusPlusTakeButton:SetText( CENSUSPlus_UNPAUSE ); + + StaticPopup_Show ("CP_CONTINUE_CENSUS"); + + elseif ( g_IsCensusPlusInProgress ) then + -- + -- Only process who results if a CensusPlus is in progress + -- + + CP_ProcessWhoEvent() + + + else + -- + -- This is just a random /who done by the player + -- + CensusPlus_ProcessWhoResults(); + end + -- + -- We got the who update + -- + g_WaitingForWhoUpdate = false; + + return; + + end + + CP_Pre_OnEvent(...); + +end + +function CP_ProcessWhoEvent(query, ...) + local numWhoResults = GetNumWhoResults(); + if( numWhoResults == 0 ) then + return; + end + + CensusPlus_ProcessWhoResults(); + if (numWhoResults > MAX_WHO_RESULTS) then + -- + -- Who list is overflowed, split the query to make the return smaller + -- + local minLevel = g_CurrentJob.m_MinLevel; + local maxLevel = g_CurrentJob.m_MaxLevel; + local race = g_CurrentJob.m_Race; + local class = g_CurrentJob.m_Class; + local zoneLetter = g_CurrentJob.m_zoneLetter; + local letter = g_CurrentJob.m_Letter; +--rmg + local guild = g_CurrentJob.m_Guild; + + if (minLevel ~= maxLevel) then + + -- + -- The level range is greater than a single level, so split it in half and submit the two jobs + -- + local pivot = floor((minLevel + maxLevel) / 2); + local jobLower = CensusPlus_CreateJob( minLevel, pivot, nil, nil, nil , guild ); + InsertJobIntoQueue(jobLower); + local jobUpper = CensusPlus_CreateJob( pivot + 1, maxLevel, nil, nil, nil , guild ); + InsertJobIntoQueue(jobUpper); + else + -- + -- We cannot split the level range any more + -- + local factionGroup = UnitFactionGroup("player"); + local level = minLevel; + if (race == nil) then + -- + -- This job does not specify race, so split it that way, making four new jobs + -- + local thisFactionRaces = CensusPlus_GetFactionRaces(factionGroup); + local numRaces = table.getn(thisFactionRaces); + for i = 1, numRaces, 1 do + local job = CensusPlus_CreateJob( level, level, thisFactionRaces[i], nil, nil , guild ); + InsertJobIntoQueue(job); + end + else + if (class == nil) then + -- + -- This job does not specify class, so split it that way, making more jobs + -- + local thisRaceClasses = GetRaceClasses(race); + local numClasses = table.getn(thisRaceClasses); + for i = 1, numClasses, 1 do + local job = CensusPlus_CreateJob( level, level, race, thisRaceClasses[i], nil , guild ); + InsertJobIntoQueue(job); + end + else + if( letter == nil ) then + -- There are too many characters with a single level, class and race + -- The work around we are going to pursue is to check by name for a,e,i,o,r,s,t,u + local letters = GetNameLetters(); + for i=1, table.getn( letters ), 1 do + local job = CensusPlus_CreateJob( level, level, race, class, letters[i] , guild ); + InsertJobIntoQueue(job); + end + else + -- There are too many characters with a single level, class, race and letter, give up + local whoText = CensusPlus_CreateWhoText(g_CurrentJob); + CensusPlus_Msg(format(CENSUSPlus_TOOMANY, whoText)); + end + end + end + end + end + + local whoText = CensusPlus_CreateWhoText(g_CurrentJob); + + if whoText == query then + g_WaitingForWhoUpdate = false + end +end + +----------------------------------------------------------------------------------- +-- +-- Load Handler for options box +-- +----------------------------------------------------------------------------------- +function CP_OptionsOnShow() + CP_OptionAutoClose:SetChecked(g_WhoAutoClose); + CP_OptionAutoStartButton:SetChecked(g_MiniOnStart); + CP_OptionVerboseButton:SetChecked(CensusPlus_PerCharInfo["Verbose"]); + CP_OptionAutoCensusButton:SetChecked( CensusPlus_Database["Info"]["AutoCensus"] ); +-- CP_OptionProcessCharProfileButton:SetChecked( CensusPlus_DoThisCharacter ); +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus Friends Frame override to stop the window close sound +-- +----------------------------------------------------------------------------------- +function CensusPlus_FriendsFrame_OnHide() + g_Pre_FriendsFrameOnHideOverride(); +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus Friends Frame override to stop the window close sound +-- +----------------------------------------------------------------------------------- +function CensusPlus_FriendsFrame_OnShow() + g_Pre_FriendsFrameOnShowOverride(); +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus_WhoList_Update +-- +----------------------------------------------------------------------------------- +function CensusPlus_WhoList_Update() +--InCombatLockdown() == false + if( g_IsCensusPlusInProgress == true and g_WhoAutoClose ) then + local numWhos, totalCount = GetNumWhoResults(); + local name, guild, level, race, class, zone, group; + local button; + local columnTable; + local whoOffset = FauxScrollFrame_GetOffset(WhoListScrollFrame); + local whoIndex; + local showScrollBar = nil; + if ( numWhos > WHOS_TO_DISPLAY ) then + showScrollBar = 1; + end + local displayedText = ""; + if ( totalCount > MAX_WHOS_FROM_SERVER ) then + displayedText = format(WHO_FRAME_SHOWN_TEMPLATE, MAX_WHOS_FROM_SERVER); + end + WhoFrameTotals:SetText(format(GetText("WHO_FRAME_TOTAL_TEMPLATE", nil, totalCount), totalCount).." "..displayedText); + for i=1, WHOS_TO_DISPLAY, 1 do + whoIndex = whoOffset + i; + button = getglobal("WhoFrameButton"..i); + button.whoIndex = whoIndex; + name, guild, level, race, class, zone, group = GetWhoInfo(whoIndex); + columnTable = { zone, guild, race }; + getglobal("WhoFrameButton"..i.."Name"):SetText(name); + getglobal("WhoFrameButton"..i.."Level"):SetText(level); + getglobal("WhoFrameButton"..i.."Class"):SetText(class); + local variableText = getglobal("WhoFrameButton"..i.."Variable"); + variableText:SetText(columnTable[UIDropDownMenu_GetSelectedID(WhoFrameDropDown)]); + if ( not group ) then + group = ""; + end + --getglobal("WhoFrameButton"..i.."Group"):SetText(getglobal(strupper(group))); + + -- If need scrollbar resize columns + if ( showScrollBar ) then + variableText:SetWidth(95); + else + variableText:SetWidth(110); + end + + -- Highlight the correct who + if ( WhoFrame.selectedWho == whoIndex ) then + button:LockHighlight(); + else + button:UnlockHighlight(); + end + + if ( whoIndex > numWhos ) then + button:Hide(); + else + button:Show(); + end + end + + if ( not WhoFrame.selectedWho ) then + WhoFrameGroupInviteButton:Disable(); + WhoFrameAddFriendButton:Disable(); + else + WhoFrameGroupInviteButton:Enable(); + WhoFrameAddFriendButton:Enable(); + WhoFrame.selectedName = GetWhoInfo(WhoFrame.selectedWho); + end + + -- If need scrollbar resize columns + if ( showScrollBar ) then + WhoFrameColumn_SetWidth(WhoFrameColumnHeader2, 105); + UIDropDownMenu_SetWidth(WhoFrameDropDown, 80); + else + WhoFrameColumn_SetWidth(WhoFrameColumnHeader2, 120); + UIDropDownMenu_SetWidth(WhoFrameDropDown, 95); + end + + -- ScrollFrame update + FauxScrollFrame_Update(WhoListScrollFrame, numWhos, WHOS_TO_DISPLAY, FRIENDS_FRAME_WHO_HEIGHT ); + + else + g_Pre_WhoList_UpdateOverride(); + end +end + + +----------------------------------------------------------------------------------- +-- +-- CensusPlus_FriendsFrame_Update +-- +----------------------------------------------------------------------------------- +function CensusPlus_FriendsFrame_Update() + if ( FriendsFrame.selectedTab == 3 and g_IsCensusPlusInProgress == true and g_WhoAutoClose ) then + FriendsFrameTopLeft:SetTexture("Interface\\ClassTrainerFrame\\UI-ClassTrainer-TopLeft"); + FriendsFrameTopRight:SetTexture("Interface\\ClassTrainerFrame\\UI-ClassTrainer-TopRight"); + FriendsFrameBottomLeft:SetTexture("Interface\\FriendsFrame\\GuildFrame-BotLeft"); + FriendsFrameBottomRight:SetTexture("Interface\\FriendsFrame\\GuildFrame-BotRight"); + local guildName, title, rank = GetGuildInfo("player"); + if ( guildName ) then + FriendsFrameTitleText:SetText(format(GUILD_TITLE_TEMPLATE, title, guildName)); + else + FriendsFrameTitleText:SetText(""); + end + --GuildStatus_Update(); + FriendsFrameTitleText:SetText(guildName); + FriendsFrame_ShowSubFrame("GuildFrame"); + else + g_Pre_FriendsFrame_Update(); + end +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus Who Handler +-- +----------------------------------------------------------------------------------- +function CensusPlus_WhoHandler( msg ) + if( g_IsCensusPlusInProgress == true ) then +CensusPlus_Msg( "Census Who Handler" ); + if ( msg == "" ) then + msg = WhoFrame_GetDefaultWhoCommand(); + ShowWhoPanel(); + elseif ( msg == "cheat" ) then + -- Remove the "cheat" part later! + ShowWhoPanel(); + end + + -- + -- Queue up the command to run next + -- + g_CensusWhoOverrideMsg = msg; + CensusPlus_Msg( CENSUSPlus_OVERRIDE ); +-- CensusPlus_SendWho(msg); + else + g_Pre_WhoHandler(msg); + end +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus command +-- +----------------------------------------------------------------------------------- +function CensusPlus_Command( param ) + + local i,j, command, value = string.find(param, "^([^ ]+) (.+)$"); + +-- local firsti, lasti, command, value = string.find (param, "(%w+) (%w+) (%w+)") ; + +-- if( string.lower(param) == "locale" ) then +-- CP_EU_US_Version:Show(); +-- else + if( string.lower(param) == "options" ) then + CP_OptionsWindow:Show(); +-- elseif( string.lower(param) == "tz" ) then +-- CensusPlus_DetermineServerDate(); + elseif( command ~= nil and string.lower(command) == "prune" ) then + if( value ~= nil ) then + CensusPlus_PruneData( value, nil ); + else + CensusPlus_PruneData( 30, nil ); + end + elseif( command ~= nil and string.lower(command) == "timer" ) then + if( value ~= nil ) then + CensusPlus_Database["Info"]["AutoCensusTimer"] = value * 60; + CensusPlus_Msg( "Set autocensus timer to " .. value .. " minutes" ); + else + CensusPlus_Database["Info"]["AutoCensusTimer"] = 1800; + CensusPlus_Msg( "Set autocensus timer to 30 minutes" ); + end + elseif( string.lower(param) == "serverprune" ) then + CensusPlus_PruneData( 0, 1 ); + elseif( string.lower(param) == "bufftest" ) then + showAllUnitBuffs("player"); + elseif( string.lower(param) == "verbose" ) then + CensusPlus_Verbose(); + elseif( string.lower(param) == "take" ) then + CensusPlus_Take_OnClick(); + elseif( string.lower(param) == "stop" ) then + CensusPlus_StopCensus(); + elseif( string.lower(param) == "track" ) then + if( g_TrackUnhandled ) then + CensusPlus_Msg( "Tracking disabled!" ); + g_TrackUnhandled = false; + else + CensusPlus_Msg( "TRACKING ALL CHAT!" ); + g_TrackUnhandled = true; + end + elseif( command ~= nil and string.lower(command) == "who" ) then + local m,n, check, level = string.find(value, "(%w+) (%w+)"); + if( check ~= nil ) then + CensusPlus_InternalWho( string.lower(check), level ); + else + CensusPlus_InternalWho( string.lower(value), nil ); + end + elseif( command ~= nil and string.lower(command) == "test" ) then + if( value ~= nil ) then + CensusPlus_Test( value ); + else + CensusPlus_Test( 1 ); + end + else + CensusPlus_DisplayUsage(); + end +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus Display Usage +-- +----------------------------------------------------------------------------------- +function CensusPlus_DisplayUsage() + local text; + + CensusPlus:Show(); + + CensusPlus_Msg("Usage:\n /CensusPlus"); + CensusPlus_Msg(" /censusPlus verbose Toggle verbose mode off/on"); +-- CensusPlus_Msg(" /CensusPlus locale Bring up the locale selection dialog - (WARNING -- CHANGING YOUR LOCALE WILL PURGE YOUR DATABASE)"); + CensusPlus_Msg(" /CensusPlus options Bring up the Option window"); + CensusPlus_Msg(" /CensusPlus take Start a Census snapshot"); + CensusPlus_Msg(" /CensusPlus stop Stop a Census snapshot"); + CensusPlus_Msg(" /CensusPlus prune X Prune the database by removing characters not seen in X days"); + CensusPlus_Msg(" /CensusPlus serverprune Prune the database by removing all data from servers other than the one you are currently on."); + CensusPlus_Msg(" /CensusPlus who XXX Will display info that matches names or guilds."); + CensusPlus_Msg(" /CensusPlus who unguilded ## Will list unguilded characters of that level."); + CensusPlus_Msg(" /CensusPlus timer X ## Will set the autocensus timer (in minutes)."); +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus_InternalWho - will go through our local database and see if we have +-- any info on this person +-- +----------------------------------------------------------------------------------- +function CensusPlus_InternalWho( search, level ) + + if( g_CensusPlusLocale == "N/A" ) then + return; + end + + g_InternalSearchName = search; + g_InternalSearchLevel = level; + g_InternalSearchCount = 0; + local realmName = g_CensusPlusLocale .. GetCVar("realmName"); + CensusPlus_ForAllCharacters( realmName, UnitFactionGroup("player"), nil, nil, nil, nil, CensusPlus_InternalWhoResult) + + CensusPlus_WhoMsg( "Found " .. g_InternalSearchCount .. " players." ); +end + +function CensusPlus_InternalWhoResult(name, level, guild, race, class, lastSeen ) + lowerName = string.lower( name ); + level = string.lower( level ); + lowerGuild = string.lower( CensusPlus_SafeCheck( guild ) ); + + if( g_InternalSearchName == "unguilded" ) then + if( guild == "" ) then + local doit = 1; + if( g_InternalSearchLevel ~= nil ) then + if( g_InternalSearchLevel ~= level ) then + doit = 0; + end + end + if( doit == 1 ) then + local out = name .. " : Level " .. level .. " " .. race .. " " .. " " .. class; + out = out .. " Last Seen: " .. lastSeen; + CensusPlus_WhoMsg( out ); + g_InternalSearchCount = g_InternalSearchCount + 1; + end + end + elseif( string.find( lowerName, g_InternalSearchName ) or string.find( lowerGuild, g_InternalSearchName ) ) then + -- found someone! + local out = name .. " : Level " .. level .. " " .. race .. " " .. " " .. class; + if( guild ~= "" ) then + out = out .. " <" .. guild .. ">"; + end + out = out .. " Last Seen: " .. lastSeen; + CensusPlus_WhoMsg( out ); + g_InternalSearchCount = g_InternalSearchCount + 1; + end +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus Verbose option +-- +----------------------------------------------------------------------------------- +function CensusPlus_Verbose() + if( CensusPlus_PerCharInfo["Verbose"] == true ) then + CensusPlus_Msg( "Verbose Mode : OFF" ); + CensusPlus_PerCharInfo["Verbose"] = false; + else + CensusPlus_Msg( "Verbose Mode : ON" ); + CensusPlus_PerCharInfo["Verbose"] = true; + end +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus Auto Census set flag +-- +----------------------------------------------------------------------------------- +function CensusPlus_SetAutoCensus( flag ) + if( flag == 1 ) then + CensusPlus_Database["Info"]["AutoCensus"] = true; + else + CensusPlus_Database["Info"]["AutoCensus"] = false; + end +end + +----------------------------------------------------------------------------------- +-- +-- Minimize the window +-- +----------------------------------------------------------------------------------- +function CensusPlus_OnClickMinimize() + if( CensusPlus:IsVisible() ) then +-- MiniCensusPlus:Show(); + CensusPlus:Hide(); + end +end + +----------------------------------------------------------------------------------- +-- +-- Minimize the window +-- +----------------------------------------------------------------------------------- +function CensusPlus_OnClickMaximize() + if( MiniCensusPlus:IsVisible() ) then + MiniCensusPlus:Hide(); + CensusPlus:Show(); + end +end + +----------------------------------------------------------------------------------- +-- +-- Take or pause a census depending on current status +-- +----------------------------------------------------------------------------------- +function CensusPlus_Take_OnClick() + if (g_IsCensusPlusInProgress) then + CensusPlus_TogglePause(); + else + CensusPlus_StartCensus(); + end +end + +--rm +----------------------------------------------------------------------------------- +-- Take or pause a census depending on current status +----------------------------------------------------------------------------------- +function CensusPlus_TakeGuild_OnClick() + if (g_IsCensusPlusInProgress) then + CensusPlus_TogglePause(); + else + CensusPlus_StartGuildCensus(); + end +end + +----------------------------------------------------------------------------------- +-- +-- Display a tooltip for the take button +-- +----------------------------------------------------------------------------------- +function CensusPlus_Take_OnEnter() + if (g_IsCensusPlusInProgress) then + if (g_CensusPlusManuallyPaused) then + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText(CENSUSPlus_UNPAUSECENSUS, 1.0, 1.0, 1.0); + GameTooltip:Show(); + else + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText(CENSUSPlus_PAUSECENSUS, 1.0, 1.0, 1.0); + GameTooltip:Show(); + end + else + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText(CENSUSPlus_TAKECENSUS, 1.0, 1.0, 1.0); + GameTooltip:Show(); + end +end + +--rm +----------------------------------------------------------------------------------- +-- Display a tooltip for the take guild button +----------------------------------------------------------------------------------- +function CensusPlus_TakeGuild_OnEnter() + if (g_IsCensusPlusInProgress) then + if (g_CensusPlusManuallyPaused) then + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText(CENSUSPlus_UNPAUSECENSUS, 1.0, 1.0, 1.0); + GameTooltip:Show(); + else + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText(CENSUSPlus_PAUSECENSUS, 1.0, 1.0, 1.0); + GameTooltip:Show(); + end + else + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText(CENSUSPlus_TAKEGUILDCENSUS, 1.0, 1.0, 1.0); + GameTooltip:Show(); + end +end + +----------------------------------------------------------------------------------- +-- +-- Pause the current census +-- +----------------------------------------------------------------------------------- +function CensusPlus_TogglePause() + if (g_IsCensusPlusInProgress == true) then + if( g_CensusPlusManuallyPaused == true ) then + CensusPlusTakeButton:SetText( CENSUSPlus_PAUSE ); + g_CensusPlusManuallyPaused = false; + else + CensusPlusTakeButton:SetText( CENSUSPlus_UNPAUSE ); + g_CensusPlusManuallyPaused = true; + end + end +end + +----------------------------------------------------------------------------------- +-- +-- Purge the database for this realm and faction +-- +----------------------------------------------------------------------------------- +function CensusPlus_Purge() + StaticPopup_Show ("CP_PURGE_CONFIRM"); +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus_DoPurge +-- +----------------------------------------------------------------------------------- +function CensusPlus_DoPurge() + if( CensusPlus_Database["Servers"] ~= nil ) then + CensusPlus_Database["Servers"] = nil; + end + CensusPlus_Database["Servers"] = {}; + CensusPlus_UpdateView(); + CensusPlus_Msg(CENSUSPlus_PURGEMSG); + + if( CensusPlus_Database["Guilds"] ~= nil ) then + CensusPlus_Database["Guilds"] = nil; + end + CensusPlus_Database["Guilds"] = {}; + + if( CensusPlus_Database["TimesPlus"] ~= nil ) then + CensusPlus_Database["TimesPlus"] = nil; + end + CensusPlus_Database["TimesPlus"] = {}; + + if( CensusPlus_Profile ~= nil ) then + CensusPlus_Profile = nil; + end + CensusPlus_Profile = {}; + + if( CensusPlus_BGInfo ~= nil ) then + CensusPlus_BGInfo = nil; + end + CensusPlus_BGInfo = {}; + + CensusPlus_Msg( "Data Purged" ); +end + +----------------------------------------------------------------------------------- +-- +-- Handler for auto close checkbox +-- +----------------------------------------------------------------------------------- +function CensusPlus_AutoCloseWho(close) + g_WhoAutoClose = close; +end + +--function CensusPlus_WhoLibEvent(event, query, ...) +-- CensusPlus_Msg( event ) +--end + +--rm +----------------------------------------------------------------------------------- +-- Take a guild CensusPlus +----------------------------------------------------------------------------------- +function CensusPlus_StartGuildCensus() + if (g_IsCensusPlusInProgress) then + -- Do not initiate a new CensusPlus while one is in progress + CensusPlus_Msg(CENSUSPlus_ISINPROGRESS); + elseif( g_CurrentlyInBG ) then + g_LastCensusRun = time()-600; + if( not g_CurrentlyInBG_Msg ) then + CensusPlus_Msg(CENSUSPlus_ISINBG); + g_CurrentlyInBG_Msg = true; + end + else + -- Set a timer + g_CensusPlus_StartTime = time(); + -- Initialize the job queue and counters + CensusPlus_Msg(CENSUSPlus_TAKINGONLINE); + g_NumNewCharacters = 0; + g_NumUpdatedCharacters = 0; + g_JobQueue = {}; + g_TempCount = nil; + g_TempCount = {}; + g_TempZoneCount = nil; + g_TempZoneCount = {}; +-- The Job List Works as LIFO; last in, first out +-- for Cataclysm, ... and GM's :) after all following Jobs + local job = CensusPlus_CreateJob( ( MAX_CHARACTER_LEVEL + 1 ) , MAX_LEVEL_DISPLAY, nil, nil, nil , CensusPlus_MYGUILD ); + InsertJobIntoQueue(job); +-- ending with lvl MAX_CHARACTER_LEVEL + local counter = MAX_CHARACTER_LEVEL; + local LowCounter = counter; + local LowCharDetailLevel = 3; + local LevelStep = 10; + + local job = CensusPlus_CreateJob( counter, counter, nil, nil, nil , CensusPlus_MYGUILD ); + InsertJobIntoQueue(job); + counter = counter - 1; + while (counter > LowCharDetailLevel) do + LowCounter = counter - LevelStep + 1 ; + if (LowCounter <= LowCharDetailLevel) then + LowCounter = LowCharDetailLevel +1 ; + end + local job = CensusPlus_CreateJob( LowCounter, counter, nil, nil, nil , CensusPlus_MYGUILD ); + InsertJobIntoQueue(job); + counter = LowCounter - 1 ; + end + while (counter > 0) do + LowCounter = counter ; + local job = CensusPlus_CreateJob( LowCounter, counter, nil, nil, nil , CensusPlus_MYGUILD ); + InsertJobIntoQueue(job); + counter = LowCounter - 1 ; + end +------------------ +-- Test inserts +-- local job = CensusPlus_CreateJob( 11, 12, "Troll", nil, nil , CensusPlus_MYGUILD ); +-- InsertJobIntoQueue(job); + g_IsCensusPlusInProgress = true; + g_WaitingForWhoUpdate = false; + g_CensusPlusManuallyPaused = false; + local hour, minute = GetGameTime(); + g_TakeHour = hour; + g_ResetHour = true; + wholib = wholib or LibStub:GetLibrary("LibWho-2.0", true); + -- Subvert WhoLib + if( wholib ) then + CensusPlus_Msg( "Using WhoLib" ); + end + end + CensusPlusTakeButton:SetText( CENSUSPlus_PAUSE ); + CensusPlusTakeGuildButton:SetText( CENSUSPlus_TAKINGGUILD.." \""..CensusPlus_MYGUILD.."\"" ); +end + + +----------------------------------------------------------------------------------- +-- +-- Take a CensusPlus +-- +----------------------------------------------------------------------------------- +function CensusPlus_StartCensus() + + if (g_IsCensusPlusInProgress) then + if( g_CensusPlusManuallyPaused == true ) then + g_CensusPlusManuallyPaused = false; + CensusPlusPauseButton:SetText( CENSUSPlus_PAUSE ); + else + -- Do not initiate a new CensusPlus while one is in progress + CensusPlus_Msg(CENSUSPlus_ISINPROGRESS); + end + elseif( g_CurrentlyInBG ) then + g_LastCensusRun = time()-600; + if( not g_CurrentlyInBG_Msg ) then + CensusPlus_Msg(CENSUSPlus_ISINBG); + g_CurrentlyInBG_Msg = true; + end + else + -- + -- Set a timer + -- + g_CensusPlus_StartTime = time(); + + -- + -- Initialize the job queue and counters + -- + CensusPlus_Msg(CENSUSPlus_TAKINGONLINE); + g_NumNewCharacters = 0; + g_NumUpdatedCharacters = 0; + g_JobQueue = {}; + + g_TempCount = nil; + g_TempCount = {}; + + g_TempZoneCount = nil; + g_TempZoneCount = {}; +-- +-- First job covers all characters by searching all levels +-- +-- The Job List Works as LIFO; last in, first out +-- local job = {m_MinLevel = 1, m_MaxLevel = MAX_CHARACTER_LEVEL}; +-- InsertJobIntoQueue(job); +--rm +-- for Cataclysm, ... and GM's :) after all following Jobs + local job = CensusPlus_CreateJob( ( MAX_CHARACTER_LEVEL + 1 ) , MAX_LEVEL_DISPLAY, nil, nil, nil , nil ); + InsertJobIntoQueue(job); +---- ending with lvl 1-10 +-- local counter = 0; +-- for counter = 0, 6, 1 do +-- local job = CensusPlus_CreateJob( counter*10 + 1, counter*10+10, nil, nil, nil , nil ); +-- InsertJobIntoQueue(job); +-- end +---- do 71-79 before the above jobs +-- job = CensusPlus_CreateJob( 71, 79, nil, nil, nil , nil ); +-- InsertJobIntoQueue(job); +---- do 80-80 before the above jobs +-- job = CensusPlus_CreateJob( 80, 80, nil, nil, nil , nil ); +-- InsertJobIntoQueue(job); + +-- ending with lvl MAX_CHARACTER_LEVEL + local counter = MAX_CHARACTER_LEVEL; + local LowCounter = counter; + local LowCharDetailLevel = 3; + local LevelStep = 10; + + + local job = CensusPlus_CreateJob( counter, counter, nil, nil, nil , nil ); + InsertJobIntoQueue(job); + counter = counter - 1; + while (counter > LowCharDetailLevel) do + LowCounter = counter - LevelStep + 1 ; + if (LowCounter <= LowCharDetailLevel) then + LowCounter = LowCharDetailLevel +1 ; + end + local job = CensusPlus_CreateJob( LowCounter, counter, nil, nil, nil , nil ); + InsertJobIntoQueue(job); + counter = LowCounter - 1 ; + end + while (counter > 0) do + LowCounter = counter ; + local job = CensusPlus_CreateJob( LowCounter, counter, nil, nil, nil , nil ); + InsertJobIntoQueue(job); + counter = LowCounter - 1 ; + end +------------------ + + +-- for counter = 60, MAX_CHARACTER_LEVEL, 1 do +-- local job = CensusPlus_CreateJob( counter, counter, nil, nil, nil , nil ); +-- InsertJobIntoQueue(job); +-- end + +-- Test inserts +-- local job = CensusPlus_CreateJob( 11, 12, "Troll", nil, nil , nil ); +-- InsertJobIntoQueue(job); + g_IsCensusPlusInProgress = true; + g_WaitingForWhoUpdate = false; + g_CensusPlusManuallyPaused = false; + + local hour, minute = GetGameTime(); + g_TakeHour = hour; + g_ResetHour = true; + + wholib = wholib or LibStub:GetLibrary("LibWho-2.0", true); + -- + -- Subvert WhoLib + -- + if( wholib ) then + -- + -- Be prepared to subvert the WhoLib mechanic + -- +-- g_WhoLibSubvert = SlashCmdList["WHO"]; +-- SlashCmdList["WHO"] = CensusPlus_WhoHandler; +-- +-- g_WhoLibSendWhoSubvert = SendWho; +-- SendWho = WhoLibByALeX.hooks.SendWho; +-- +-- g_WhoLibResultSubvert = WhoLibByALeX.WHO_LIST_UPDATE; +-- g_WhoLibChatSubvert = WhoLibByALeX.CHAT_MSG_SYSTEM; +-- g_WhoLibAskWhoSubvert = WhoLibByALeX.AskWho; +-- +-- WhoLibByALeX.WHO_LIST_UPDATE = function( args ) end +-- WhoLibByALeX.CHAT_MSG_SYSTEM = function( args ) end +-- WhoLibByALeX.AskWho = function( args ) end + + CensusPlus_Msg( "Using WhoLib" ); + + + --wholib.RegisterCallback("CensusPlus", "WHOLIB_QUERY_RESULT", CensusPlus_WhoLibEvent) + + end + end + CensusPlusTakeButton:SetText( CENSUSPlus_PAUSE ); +end + +----------------------------------------------------------------------------------- +-- +-- Stop a CensusPlus +-- +----------------------------------------------------------------------------------- +function CensusPlus_StopCensus( ) + if (g_IsCensusPlusInProgress) then + CensusPlusTakeButton:SetText( CENSUSPlus_TAKE ); + CensusPlusTakeGuildButton:SetText( CENSUSPlus_TAKEGUILD.." \""..CensusPlus_MYGUILD.."\"" ); CensusPlusTakeGuildButton:SetText( CENSUSPlus_TAKEGUILD.." \""..CensusPlus_MYGUILD.."\"" ); + g_CensusPlusManuallyPaused = false; + + CensusPlusScanProgress:SetText( CENSUSPlus_SCAN_PROGRESS_0 ); + + g_JobQueue = {}; + g_JobQueue = nil; + g_JobQueue = {}; + + CensusPlus_DisplayResults( ); + + -- Clean up the times + CensusPlus_PruneTimes(); + +-- if( wholib ) then +-- SlashCmdList["WHO"] = g_WhoLibSubvert; +-- +-- SendWho = g_WhoLibSendWhoSubvert; +-- WhoLibByALeX.WHO_LIST_UPDATE = g_WhoLibResultSubvert; +-- WhoLibByALeX.CHAT_MSG_SYSTEM = g_WhoLibChatSubvert; +-- WhoLibByALeX.AskWho = g_WhoLibAskWhoSubvert; + + +-- CensusPlus_Msg( "Unregistering with WhoLib" ); + + --wholib.UnregisterAllCallbacks("CensusPlus") +-- end + + else + CensusPlus_Msg(CENSUSPlus_NOCENSUS); + end +end + +----------------------------------------------------------------------------------- +-- +-- Display Census results +-- +----------------------------------------------------------------------------------- +function CensusPlus_DisplayResults( ) + -- + -- We are all done, report our results + -- + g_IsCensusPlusInProgress = false; + + + -- + -- Finish our timer + -- + local total_time = time() - g_CensusPlus_StartTime; + + CensusPlus_Msg(format(CENSUSPlus_FINISHED, g_NumNewCharacters, g_NumUpdatedCharacters, SecondsToTime( total_time ))); + ChatFrame1:AddMessage(CENSUSPlus_UPLOAD, 0.5, 1.0, 1.0); + + CensusPlus_UpdateView(); + g_LastCensusRun = time(); + + CensusPlusTakeButton:SetText( CENSUSPlus_TAKE ); + CensusPlusTakeGuildButton:SetText( CENSUSPlus_TAKEGUILD.." \""..CensusPlus_MYGUILD.."\"" ); +end + +----------------------------------------------------------------------------------- +-- +-- Create a who command text for the input job +-- +----------------------------------------------------------------------------------- +function CensusPlus_CreateWhoText(job) + local whoText = ""; + local race = job.m_Race; + if (race ~= nil) then + whoText = whoText.." r-\""..race.."\""; + end + + local class = job.m_Class; + if (class ~= nil) then + whoText = whoText.." c-\""..class.."\""; + end + + local minLevel = tostring( job.m_MinLevel ); + if (minLevel == nil) then + minLevel = 1; + end + local maxLevel = job.m_MaxLevel; + if (maxLevel == nil) then + maxLevel = MAX_CHARACTER_LEVEL; + end + whoText = whoText.." ".. minLevel .."-".. maxLevel; + + local zoneLetter = job.m_zoneLetter; + if ( zoneLetter ~= nil) then + whoText = whoText.." z-"..zoneLetter; + end + + local letter = job.m_Letter; + if( letter ~= nil ) then + whoText = whoText.." n-"..letter; + end +--rmg + local guild = job.m_Guild; + if( guild ~= nil ) then + whoText = whoText.." g-\""..guild.."\""; + end + + return whoText; +end + +----------------------------------------------------------------------------------- +-- +-- Create a job +-- +----------------------------------------------------------------------------------- +function CensusPlus_CreateJob( minLevel, maxLevel, race, class, letter, guild ) + local job = {}; + job.m_MinLevel = minLevel; + job.m_MaxLevel = maxLevel; + job.m_Race = race; + job.m_Class = class; + job.m_Letter = letter; + job.m_Guild = guild; + +CensusPlus_DumpJob( job ); + + return job; +end + +----------------------------------------------------------------------------------- +-- +-- Debug function do dump a job +-- +----------------------------------------------------------------------------------- +function CensusPlus_DumpJob( job ) + local whoText = ""; + local race = job.m_Race; + if (race ~= nil) then + whoText = whoText.." R: "..race; + end + + local class = job.m_Class; + if (class ~= nil) then + whoText = whoText.." C: "..class; + end + + local minLevel = job.m_MinLevel; + if (minLevel ~= nil) then + whoText = whoText.." min: ".. minLevel; + end + + local maxLevel = job.m_MaxLevel; + if (maxLevel ~= nil) then + whoText = whoText.." max: ".. maxLevel; + end + + local zoneLetter = job.m_zoneLetter; + if ( zoneLetter ~= nil) then + whoText = whoText.." Z: "..zoneLetter; + end + + local letter = job.m_Letter; + if( letter ~= nil ) then + whoText = whoText.." N: "..letter; + end +--rmg + local guild = job.m_Guild; + if( guild ~= nil ) then + whoText = whoText.." G: \""..guild.."\""; + end + +--CensusPlus_Msg( "JOB DUMP: " .. whoText ); +end + +----------------------------------------------------------------------------------- +-- +-- Called on events +-- +----------------------------------------------------------------------------------- +function CensusPlus_OnEvent(event,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) + + if( arg1 == nil ) then + arg1 = "nil" + end + if( arg2 == nil ) then + arg2 = "nil" + end + if( arg3 == nil ) then + arg3 = "nil" + end + if( arg4 == nil ) then + arg4 = "nil" + end + + -- + -- If we have not been initialized, do nothing + -- + if (g_CensusPlusInitialized == false) then + return + end + +-- CensusPlus_Msg( "Message =>" .. event ); + + -- + -- WHO_LIST_UPDATE + -- + if( event == "TRAINER_SHOW" or event == "MERCHANT_SHOW" or event == "TRADE_SHOW" or event == "GUILD_REGISTRAR_SHOW" + or event == "AUCTION_HOUSE_SHOW" or event == "BANKFRAME_OPENED" or event == "QUEST_DETAIL" ) then + if( g_IsCensusPlusInProgress ) then + g_CensusPlusPaused = true; + end + elseif( event == "TRAINER_CLOSED" or event == "MERCHANT_CLOSED" or event == "TRADE_CLOSED" or event == "GUILD_REGISTRAR_CLOSED" + or event == "AUCTION_HOUSE_CLOSED" or event == "BANKFRAME_CLOSED" or event == "QUEST_FINISHED" ) then + if( g_IsCensusPlusInProgress ) then + g_CensusPlusPaused = false; + end + elseif (event == "GUILD_ROSTER_SHOW") then + -- + -- Process Guild info + -- +--CensusPlus_Msg( " SHOW GUILD " ); + CensusPlus_ProcessGuildResults(); + + elseif (event == "GUILD_ROSTER_UPDATE") then + -- + -- Process Guild info + -- +--CensusPlus_Msg( " UPDATE GUILD " ); + if(not CP_updatingGuild ) then + CP_updatingGuild = 1; + CensusPlus_ProcessGuildResults(); + CP_updatingGuild = nil; + end + + + elseif ( event == "VARIABLES_LOADED" ) then + -- + -- Initialize our variables + -- + CensusPlus_InitializeVariables(); + elseif( event == "ZONE_CHANGED_NEW_AREA" ) then + -- + -- We need to check to see if we entered a battleground + -- + CensusPlus_CheckForBattleground(); + elseif( event == "UPDATE_BATTLEFIELD_STATUS" ) then + CensusPlus_UpdateBattleGroundInfo(); + end +end + +----------------------------------------------------------------------------------- +-- +-- ProcessTarget -- called when UNIT_FOCUS event is fired +-- +----------------------------------------------------------------------------------- +function CensusPlus_ProcessTarget( unit ) + -- have to totally disable this due to X-server bg's + if( true ) then + return; + end + + if ( UnitIsPlayer(unit) == nil or (not UnitIsPlayer(unit)) or unit == "player" or unit == nil ) then + return; + end + + local sightingData = CensusPlus_CollectSightingData( unit ); + if( sightingData == nil or sightingData.faction == nil ) then + return + end + + if (sightingData ~= nil and (sightingData.faction == "Alliance" or sightingData.faction == "Horde")) then + + -- + -- Do a quick check to see if this is an MC'd person + -- + if( sightingData.faction ~= g_FactionCheck[sightingData.race] ) then + return; + end + + + if( sightingData.guild == nil ) then + sightingData.guild = ""; + end + -- + -- Get the portion of the database for this server + -- + local realmName = g_CensusPlusLocale .. GetCVar("realmName"); + local realmDatabase = CensusPlus_Database["Servers"][realmName]; + if (realmDatabase == nil) then + CensusPlus_Database["Servers"][realmName] = {}; + realmDatabase = CensusPlus_Database["Servers"][realmName]; + end + + -- + -- Get the portion of the database for this faction + -- + local factionDatabase = realmDatabase[sightingData.faction]; + if (factionDatabase == nil) then + realmDatabase[sightingData.faction] = {}; + factionDatabase = realmDatabase[sightingData.faction]; + end + + -- + -- Get racial database + -- + local raceDatabase = factionDatabase[sightingData.race]; + if (raceDatabase == nil) then + factionDatabase[sightingData.race] = {}; + raceDatabase = factionDatabase[sightingData.race]; + end + + -- + -- Get class database + -- + local classDatabase = raceDatabase[sightingData.class]; + if (classDatabase == nil) then + raceDatabase[sightingData.class] = {}; + classDatabase = raceDatabase[sightingData.class]; + end + + -- + -- Get this player's entry + -- + local entry = classDatabase[sightingData.name]; + if (entry == nil) then + classDatabase[sightingData.name] = {}; + entry = classDatabase[sightingData.name]; + end + + -- + -- Update the information + -- + entry[1] = sightingData.level; + entry[2] = sightingData.guild; + entry[3] = CensusPlus_DetermineServerDate() .. ""; + + entry[7] = CensusPlus_DetermineServerDate() .. ""; + + -- + -- Update their rank info + -- + rankNumber = UnitPVPRank(unit); + if( rankNumber ~= 0 ) then +-- rankName= GetPVPRankInfo( rankNumber ) + entry[8] = rankNumber; -- slot 8 will be current rank + else + entry[8] = 0; -- slot 8 will be current rank + end + + -- + -- Trigger an update on the inspect honor frame to get honor information + -- + if ( UnitIsPlayer( unit ) and sightingData.level >= 30 + and CheckInteractDistance( unit, 1) + and not UnitIsUnit("player", unit) and unit == "target" + and g_CensusPlusLastTarget == nil + and g_CensusPlusLastTargetName == nil + and CensusPlus_IsInspectLoaded() ) then + NotifyInspect(unit); + InspectFrame.unit = unit; + if ( not HasInspectHonorData() ) then + g_CensusPlusLastTarget = entry; + g_CensusPlusLastTargetName = sightingData.name; + RequestInspectHonorData(); + else + InspectHonorFrame_Update(); + end + end + end +end + + +----------------------------------------------------------------------------------- +-- +-- Gather targeting data +-- +----------------------------------------------------------------------------------- +function CensusPlus_CollectSightingData(unit) + if ( UnitIsPlayer(unit) and UnitName(unit) ~= "Unknown Entity" ) then + return { + name=UnitName(unit), + level=UnitLevel(unit), + sex=UnitSex(unit), + race=UnitRace(unit), + class=UnitClass(unit), + guild=GetGuildInfo(unit), + faction=UnitFactionGroup(unit) + }; + else + return nil; + end +end + + +----------------------------------------------------------------------------------- +-- +-- Initialize our primary save variables -- called when VARIABLES_LOADED event is fired +-- +----------------------------------------------------------------------------------- +function CensusPlus_InitializeVariables() + + if( CensusPlus_Database["Servers"] == nil ) then + CensusPlus_Database["Servers"] = {}; + end + + if( CensusPlus_Database["Times"] ~= nil ) then + CensusPlus_Database["Times"] = nil; + end + + if( CensusPlus_Database["TimesPlus"] == nil ) then + CensusPlus_Database["TimesPlus"] = {}; + end + + if( CensusPlus_BGInfo == nil ) then + CensusPlus_BGInfo = {}; + end + + -- + -- Make sure info is last so it will be first in the output so we can grab the version number + -- + if( CensusPlus_Database["Info"] == nil ) then + CensusPlus_Database["Info"] = {}; + end + CensusPlus_Database["Info"]["Version"] = CensusPlus_VERSION; + CensusPlus_Database["Info"]["ClientLocale"] = GetLocale(); + if( CensusPlus_Database["Info"]["ClientLocale"] == "enUS" and GetCVar("realmList") == "eu.logon.worldofwarcraft.com" ) then + CensusPlus_Database["Info"]["ClientLocale"] = "enGB"; + end + if( CensusPlus_Database["Info"]["LoginServer"] ~= nil ) then + -- already present, make sure it equals, and if + -- not, force a purge + if( CensusPlus_Database["Info"]["LoginServer"] ~= GetCVar("realmList") ) then + -- + -- We have to nuke the data in the case that someone is playing on both + -- US and EU servers + -- + CensusPlus_DoPurge() + end + end + CensusPlus_Database["Info"]["LoginServer"] = GetCVar("realmList"); + + local firstVersionRun = CensusPlus_Database["Info"][g_InterfaceVersion]; + local localeSetting = CensusPlus_Database["Info"]["Locale"]; + if( localeSetting == "??" ) then + -- We had problems previously.. we must purge =( + CensusPlus_DoPurge(); + localeSetting = nil; + end + + -- + -- Have a new way to detect locale, yay! + -- + if( CensusPlus_Database["Info"]["ClientLocale"] == "enUS" ) then + CensusPlus_VerifyLocale( "US" ); + CensusPlus_Database["Info"]["Locale"] = "US"; + elseif( CensusPlus_Database["Info"]["ClientLocale"] == "enGB" or + CensusPlus_Database["Info"]["ClientLocale"] == "frFR" or + CensusPlus_Database["Info"]["ClientLocale"] == "deDE" or + CensusPlus_Database["Info"]["ClientLocale"] == "esES" ) then + CensusPlus_VerifyLocale( "EU" ); + CensusPlus_Database["Info"]["Locale"] = "EU"; + else + CensusPlus_VerifyLocale( "??" ); + CensusPlus_Database["Info"]["Locale"] = "??"; + end + + if( firstVersionRun == nil and g_InterfaceVersion == 21000 ) then + -- + -- Clean out all character entries that are irregular + -- + CensusPlus_CleanChars(); + CensusPlus_Database["Info"][g_InterfaceVersion] = true; + end + + local locale = CensusPlus_Database["Info"]["Locale"]; + CensusPlus_SelectLocale( CensusPlus_Database["Info"]["Locale"], true ); + + local miniStart = CensusPlus_Database["Info"]["MiniStart"]; + if( miniStart == nil ) then + miniStart = 0; + end + + if( CensusPlus_Database["Info"]["AutoCensus"] == nil ) then + CensusPlus_Database["Info"]["AutoCensus"] = false; + end + + if( CensusPlus_Database["Info"]["AutoCensusTimer"] == nil ) then + CensusPlus_Database["Info"]["AutoCensusTimer"] = 1800; + end + + if( CensusPlus_Database["Info"]["CensusButtonPosition"] == nil ) then + CensusPlus_Database["Info"]["CensusButtonPosition"] = 370; + end + + if( CensusPlus_Database["Info"]["CensusButtonShown"] == nil ) then + CensusPlus_Database["Info"]["CensusButtonShown"] = 1; + end + + if( CensusPlus_Database["Info"]["CensusButtonShown"] == 1 ) then + CensusButtonFrame:Show(); + else + CensusButtonFrame:Hide(); + end + + if( CensusPlus_Database["Info"]["UseLogBars"] == nil ) then + CensusPlus_Database["Info"]["UseLogBars"] = 1; + end + CP_OptionUseLogarithmicBars:SetChecked( CensusPlus_Database["Info"]["UseLogBars"] ); + + CensusPlus_AutoStart(miniStart); + + if( miniStart ) and (not Khaos) then + CensusPlus_Msg(" V"..CensusPlus_VERSION..CENSUSPlus_MSG1); + end + + g_VariablesLoaded = true; + + CensusPlus_CheckTZ(); + + InitConstantTables(); + + CP_OptionAutoShowMinimapButton:SetChecked(CensusPlus_Database["Info"]["CensusButtonShown"]); +-- CP_SliderButtonPos:SetValue(CensusPlus_Database["Info"]["CensusButtonPosition"]); + + if( CensusPlus_PerCharInfo["PlayFinishSound"] == nil ) then + CensusPlus_PerCharInfo["PlayFinishSound"] = true; + end + + CP_OptionPlaySoundOnCompleteButton:SetChecked( CensusPlus_PerCharInfo["PlayFinishSound"] ); + + if( CensusPlus_PerCharInfo["Verbose"] == nil ) then + CensusPlus_PerCharInfo["Verbose"] = false; + end + + + -- + -- If we are in a guild, attempt to gather the guild roster data + -- + if (IsInGuild()) then + GuildRoster(); + end + + -- + -- Prune times if we have too many + -- + CensusPlus_PruneTimes(); + + -- + -- Prune BG info if we have too many + -- + CensusPlus_PruneBGInfo(); + + -- + -- Check for WhoLib since it does not play nice with C+ + -- + CensusPlus_CheckForWhoLib(); + CensusPlus_CheckForPrat(); + + CensusPlus_Unhandled = nil; + CensusPlus_Unhandled = {}; +end + +function CensusPlus_CheckForWhoLib() + if( WhoLibByALeX and WhoLibByALeX.AskWho ) then + g_WhoLibLoaded = true; + CensusPlus_Msg( "ACE WhoLib detected - WhoLib does not play nice with other mods and as such, some WhoLib functionality must be disabled while a Census scan is in progress." ); + end +end + +function CensusPlus_CheckForPrat() + if( Prat ) then + g_PratLoaded = true; + CensusPlus_Msg( "Prat detected. CensusPlus will attempt to capture the 3 or less /who results that are displayed in chat, but may be unsuccessful." ); + end +end +----------------------------------------------------------------------------------- +-- +-- Call on the update event +-- +----------------------------------------------------------------------------------- +function CensusPlus_OnUpdate() + if( g_VariablesLoaded and g_IsCensusPlusInProgress == false and CensusPlus_Database["Info"]["AutoCensus"] == true and g_LastCensusRun < time() - CensusPlus_Database["Info"]["AutoCensusTimer"] ) then + CensusPlus_Take_OnClick(); + end + + if (g_IsCensusPlusInProgress == true and g_CensusPlusPaused == false and g_CensusPlusManuallyPaused == false ) then + + -- + -- update our progress + -- + local numJobs = table.getn(g_JobQueue); + if( numJobs > 0 ) then + CensusPlusScanProgress:SetText(format(CENSUSPlus_SCAN_PROGRESS, numJobs, CensusPlus_CreateWhoText( g_JobQueue[numJobs] ) )); + end + + if( g_ReturnedZero == true ) then + g_ReturnedZero = false; + -- + -- Determine if there is any more work to do + -- + if (numJobs > 0) then + -- + -- Remove the top job from the queue and send it + -- + local job = g_JobQueue[numJobs]; + table.remove(g_JobQueue); + local whoText = CensusPlus_CreateWhoText(job); + + -- + -- Zap our current job + -- + g_CurrentJob = nil; + + g_CurrentJob = job; + g_WaitingForWhoUpdate = true; + + CensusPlus_SendWho(whoText); + g_WhoAttempts = 0; + else + -- + -- We are all done, hide the friends frame and report our results + -- + if( CensusPlus_PerCharInfo["PlayFinishSound"] ) then + PlaySoundFile("Interface\\AddOns\\CensusPlus\\Sounds\\CensusComplete.ogg") + end + + CensusPlus_DoTimeCounts(); + CensusPlus_DisplayResults(); + end + end + + local now = GetTime(); + local delta = now - g_LastOnUpdateTime; + if (not g_WaitingForWhoUpdate or delta > CensusPlus_UPDATEDELAY) then + g_LastOnUpdateTime = now; + if (g_WaitingForWhoUpdate == true ) then + + -- + -- First check to see if we are waiting for an override + -- + if( g_WaitingForOverrideUpdate == true ) then + CensusPlus_SendWho( g_CensusWhoOverrideMsg ); + else + -- + -- Resend /who command + -- + g_WhoAttempts = g_WhoAttempts + 1; + local whoText = CensusPlus_CreateWhoText(g_CurrentJob); + if( CensusPlus_PerCharInfo["Verbose"] == true ) then + CensusPlus_Msg(CENSUSPlus_WAITING); + end + if( g_WhoAttempts < 2 ) then + CensusPlus_SendWho(whoText); + else + g_WaitingForWhoUpdate = false; + end + end + else + + -- + -- Check to see if we have an override waiting + -- + if( g_CensusWhoOverrideMsg ~= nil ) then + CensusPlus_SendWho( g_CensusWhoOverrideMsg ); + g_WaitingForOverrideUpdate = true; + g_WaitingForWhoUpdate = true; + else + -- + -- Determine if there is any more work to do + -- + local numJobs = table.getn(g_JobQueue); + if (numJobs > 0) then + -- + -- Remove the top job from the queue and send it + -- + local job = g_JobQueue[numJobs]; + table.remove(g_JobQueue); + local whoText = CensusPlus_CreateWhoText(job); + g_CurrentJob = nil; + g_CurrentJob = job; + g_WaitingForWhoUpdate = true; + CensusPlus_SendWho(whoText); + g_WaitingForWhoUpdate = true; + g_WhoAttempts = 0; + else + -- + -- We are all done, hide the friends frame and report our results + -- + if( CensusPlus_PerCharInfo["PlayFinishSound"] ) then + PlaySoundFile("Interface\\AddOns\\CensusPlus\\Sounds\\CensusComplete.ogg") + end + + CensusPlus_DoTimeCounts(); + CensusPlus_DisplayResults(); + end + end + end + end + end +end + +----------------------------------------------------------------------------------- +-- +-- Take final tally +-- +----------------------------------------------------------------------------------- +function CensusPlus_DoTimeCounts() + + if( g_CensusPlusLocale == "N/A" ) then + return; + end + + -- Zero out the times + g_TimeDatabase[CENSUSPlus_DRUID] = 0; + g_TimeDatabase[CENSUSPlus_HUNTER] = 0; + g_TimeDatabase[CENSUSPlus_MAGE] = 0; + g_TimeDatabase[CENSUSPlus_PRIEST] = 0; + g_TimeDatabase[CENSUSPlus_ROGUE] = 0; + g_TimeDatabase[CENSUSPlus_WARLOCK] = 0; + g_TimeDatabase[CENSUSPlus_WARRIOR] = 0; + g_TimeDatabase[CENSUSPlus_SHAMAN] = 0; + g_TimeDatabase[CENSUSPlus_PALADIN] = 0; + g_TimeDatabase[CENSUSPlus_DEATHKNIGHT] = 0; + g_TimeDatabase[CENSUSPlus_WarsongGulch] = 0; + g_TimeDatabase[CENSUSPlus_AlteracValley]= 0; + g_TimeDatabase[CENSUSPlus_ArathiBasin] = 0; + + g_NumUpdatedCharacters = 0; + + for charName, charClass in pairs(g_TempCount) do + if (CENSUSPlusFemale[charClass] ~= nil) then + charClass = CENSUSPlusFemale[charClass]; + end + g_TimeDatabase[charClass] = g_TimeDatabase[charClass] + 1; + g_NumUpdatedCharacters = g_NumUpdatedCharacters + 1; + end + + -- Collect some zone info + for charName, charZone in pairs(g_TempZoneCount) do + if( charZone == CENSUSPlus_WarsongGulch or charZone == CENSUSPlus_AlteracValley or charZone == CENSUSPlus_ArathiBasin ) then + g_TimeDatabase[charZone] = g_TimeDatabase[charZone] + 1; + end + end + + + local realmName = g_CensusPlusLocale .. GetCVar("realmName"); + if( CensusPlus_Database["TimesPlus"][realmName] == nil ) then + CensusPlus_Database["TimesPlus"][realmName]= {}; + end + + if( CensusPlus_Database["TimesPlus"][realmName][UnitFactionGroup("player")] == nil ) then + CensusPlus_Database["TimesPlus"][realmName][UnitFactionGroup("player")] = {}; + end + + local hour, minute = GetGameTime(); +-- CensusPlus_Database["TimesPlus"][realmName][UnitFactionGroup("player")]["" .. hour .. ""] = g_TimeDatabase; + CensusPlus_Database["TimesPlus"][realmName][UnitFactionGroup("player")][CensusPlus_DetermineServerDate() .. "&" .. hour .. ":" .. minute .. ":00"] = + g_TimeDatabase[CENSUSPlus_DRUID] .. "&" .. + g_TimeDatabase[CENSUSPlus_HUNTER] .. "&" .. + g_TimeDatabase[CENSUSPlus_MAGE] .. "&" .. + g_TimeDatabase[CENSUSPlus_PRIEST] .. "&" .. + g_TimeDatabase[CENSUSPlus_ROGUE] .. "&" .. + g_TimeDatabase[CENSUSPlus_WARLOCK] .. "&" .. + g_TimeDatabase[CENSUSPlus_WARRIOR] .. "&" .. + g_TimeDatabase[CENSUSPlus_SHAMAN] .. "&" .. + g_TimeDatabase[CENSUSPlus_PALADIN] .. "&" .. + g_TimeDatabase[CENSUSPlus_DEATHKNIGHT] .. "&" .. + g_TimeDatabase[CENSUSPlus_WarsongGulch] .. "&" .. + g_TimeDatabase[CENSUSPlus_AlteracValley] .. "&" .. + g_TimeDatabase[CENSUSPlus_ArathiBasin]; +end + +----------------------------------------------------------------------------------- +-- +-- Add the contents of the guild results to the database +-- +----------------------------------------------------------------------------------- +function CensusPlus_ProcessGuildResults() + + if( g_VariablesLoaded == false ) then + return; + end + + if( CensusPlus_Database["Info"]["Locale"] == nil ) then + return; + end + + if( g_CensusPlusLocale == "N/A" ) then + return; + end + + + -- + -- Grab temp var + -- + local showOfflineTemp = GetGuildRosterShowOffline(); + SetGuildRosterShowOffline(1); + + + -- + -- Walk through the guild info + -- + local numGuildMembers = GetNumGuildMembers(); +-- CensusPlus_Msg("Processing "..numGuildMembers.." guild members."); + + local realmName = g_CensusPlusLocale .. GetCVar("realmName"); + CensusPlus_Database["Guilds"] = nil; + if( CensusPlus_Database["Guilds"] == nil ) then + CensusPlus_Database["Guilds"] = {}; + end + + if (CensusPlus_Database["Guilds"][realmName] == nil) then + CensusPlus_Database["Guilds"][realmName] = {}; + end + + local guildRealmDatabase = CensusPlus_Database["Guilds"][realmName]; + if (guildRealmDatabase == nil) then + CensusPlus_Database["Guilds"][realmName] = {}; + guildRealmDatabase = CensusPlus_Database["Guilds"][realmName]; + end + + local factionGroup = UnitFactionGroup("player"); + if( factionGroup == nil ) then + CensusPlus_Database["Guilds"] = nil; + SetGuildRosterShowOffline(showOfflineTemp); + return; + end + + local factionDatabase = guildRealmDatabase[factionGroup]; + if (factionDatabase == nil) then + guildRealmDatabase[factionGroup] = {}; + factionDatabase = guildRealmDatabase[factionGroup]; + end + + CensusPlus_Database["Guilds"][realmName][factionGroup] = nil; + CensusPlus_Database["Guilds"][realmName][factionGroup] = {}; + + factionDatabase = CensusPlus_Database["Guilds"][realmName][factionGroup]; + + local Ginfo = GetGuildInfo("player"); + if( Ginfo == nil ) then + CensusPlus_Database["Guilds"] = nil; + SetGuildRosterShowOffline(showOfflineTemp); + return; + end + local guildDatabase = factionDatabase[Ginfo]; + if (guildDatabase == nil) then + factionDatabase[Ginfo] = {}; + guildDatabase = factionDatabase[Ginfo]; + end + + local info = guildDatabase["GuildInfo"]; + if (info == nil) then + guildDatabase["GuildInfo"] = {}; + info = guildDatabase["GuildInfo"]; + end + + info["Update"] = date( "%m-%d-%Y", time()) .. ""; + info["ShowOnline"] = 1; -- Variable comes from FriendsFrame + + guildDatabase["Members"] = nil; + guildDatabase["Members"] = {}; + + local members = guildDatabase["Members"]; + + for index = 1, numGuildMembers, 1 do + local name, rank, rankIndex, level, class, zone, note, officernote, online, status = GetGuildRosterInfo(index); + + if( members[name] == nil ) then + members[name] = {}; + end + +-- CensusPlus_Msg( "Name =>" .. name ); +-- CensusPlus_Msg( "rank =>" .. rank ); +-- CensusPlus_Msg( "rankIndex =>" .. rankIndex ); +-- CensusPlus_Msg( "level =>" .. level ); +-- CensusPlus_Msg( "class =>" .. class ); + members[name]["Rank"] = rank; + members[name]["RankIndex"] = rankIndex; + members[name]["Level"]= level; + members[name]["Class"]= class; +-- members[name]["Zone"]= zone; +-- members[name]["Note"]= CensusPlus_SafeSet( note ); +-- members[name]["OfficerNote"]= CensusPlus_SafeSet( officernote ); +-- members[name]["Online"]= online; +-- members[name]["Status"]= CensusPlus_SafeSet( status ); + end + + SetGuildRosterShowOffline(showOfflineTemp); +end + +function CensusPlus_SafeCheck( param ) + if( param == nil ) then + return "nil"; + else + return param; + end +end + +----------------------------------------------------------------------------------- +-- +-- Add the contents of the who results to the database +-- +----------------------------------------------------------------------------------- +function CensusPlus_ProcessWhoResults() + + -- + -- If we are in a BG then stop a census + -- + if( g_CurrentlyInBG and g_IsCensusPlusInProgress ) then + g_LastCensusRun = time()-600; + CensusPlus_Msg(CENSUSPlus_ISINBG); + CensusPlus_StopCensus( ); + end + + if( g_CensusPlusLocale == "N/A" ) then + return; + end + + -- + -- Get the portion of the database for this server + -- + local realmName = g_CensusPlusLocale .. GetCVar("realmName"); + local realmDatabase = CensusPlus_Database["Servers"][realmName]; + if (realmDatabase == nil) then + CensusPlus_Database["Servers"][realmName] = {}; + realmDatabase = CensusPlus_Database["Servers"][realmName]; + end + + -- + -- Get the portion of the database for this faction + -- + local factionGroup = UnitFactionGroup("player"); + if( factionGroup == nil ) then + return + end + + local factionDatabase = realmDatabase[factionGroup]; + if (factionDatabase == nil) then + realmDatabase[factionGroup] = {}; + factionDatabase = realmDatabase[factionGroup]; + end + + -- + -- Walk through all the who results + -- + local numWhoResults = GetNumWhoResults(); + if( CensusPlus_PerCharInfo["Verbose"] == true ) then + CensusPlus_Msg(format(CENSUSPlus_PROCESSING, numWhoResults)); + end + for i = 1, numWhoResults, 1 do + -- + -- Get who result entry + -- + local name, guild, level, race, class, zone, group = GetWhoInfo(i); + + if (CENSUSPlusFemale[race] ~= nil) then + race = CENSUSPlusFemale[race]; + end + + if (CENSUSPlusFemale[class] ~= nil) then + class = CENSUSPlusFemale[class]; + end + + -- + -- Test the name for possible color coding + -- + -- for example |cffff0000Rollie|r + local karma_check = string.find( name, "|cff" ); + if( karma_check ~= nil ) then + name = string.sub( name, 11, -3 ); + end + + -- + -- Further check for problematic chars + -- + local pattern = "[0-9\| -]"; + if( string.find( name, pattern ) ~= nil ) then + if( not g_ProblematicMessageShown ) then + CensusPlus_Msg( "This name is problematic => " .. name .. ", name skipped. This message will only be shown once." ); + g_ProblematicMessageShown = true; + end + return; + end + + + -- + -- Get racial database + -- + local raceDatabase = factionDatabase[race]; + if (raceDatabase == nil) then + factionDatabase[race] = {}; + raceDatabase = factionDatabase[race]; + end + + -- + -- Get class database + -- + local classDatabase = raceDatabase[class]; + if (classDatabase == nil) then + raceDatabase[class] = {}; + classDatabase = raceDatabase[class]; + end + + -- + -- Get this player's entry + -- + local entry = classDatabase[name]; + if (entry == nil) then + classDatabase[name] = {}; + entry = classDatabase[name]; + g_NumNewCharacters = g_NumNewCharacters + 1; + end + + -- + -- Update the information + -- + entry[1] = level; + entry[2] = guild; +-- local hour, minute = GetGameTime(); + entry[3] = CensusPlus_DetermineServerDate() .. ""; + + g_TempCount[name] = class; + g_TempZoneCount[name] = zone; + + end +-- CensusPlus_UpdateView(); +end + + +---------------------------------------------------------------------------------- +-- +-- Process a single entry +-- +--------------------------------------------------------------------------------- +function WR_ProcessSingleEntry( name, level, race, class, guild, zone ) + +CensusPlus_Msg2( "Processing " .. name ); + + if( g_CensusPlusLocale == "N/A" ) then + return; + end + + if (CENSUSPlusFemale[race] ~= nil) then + race = CENSUSPlusFemale[race]; + end + + if (CENSUSPlusFemale[class] ~= nil) then + class = CENSUSPlusFemale[class]; + end + + -- + -- Get the portion of the database for this server + -- + local realmName = g_CensusPlusLocale .. GetCVar("realmName"); + local realmDatabase = CensusPlus_Database["Servers"][realmName]; + if (realmDatabase == nil) then + CensusPlus_Database["Servers"][realmName] = {}; + realmDatabase = CensusPlus_Database["Servers"][realmName]; + end + + -- + -- Get the portion of the database for this faction + -- + local factionGroup = UnitFactionGroup("player"); + if( factionGroup == nil ) then + return + end + + local factionDatabase = realmDatabase[factionGroup]; + if (factionDatabase == nil) then + realmDatabase[factionGroup] = {}; + factionDatabase = realmDatabase[factionGroup]; + end + + -- + -- Remove the trailing ] that I can't remove through patterns + -- +-- local oldname = name; +-- name = string.sub( oldname, 1, string.len(oldname) - 3 ); + + level = tonumber( level ); + + -- + -- Test the name for possible color coding + -- + -- for example |cffff0000Rollie|r + local karma_check = string.find( name, "|cff" ); + if( karma_check ~= nil ) then + name = string.sub( name, 11, -3 ); + end + + local pattern = "[0-9\| :]"; + if( string.find( name, pattern ) ~= nil ) then + if( not g_ProblematicMessageShown ) then + CensusPlus_Msg( "This name is problematic => " .. name .. ", name skipped. This message will only be shown once." ); + end + return; + end + + -- + -- Do a race check just to be sure this is working + -- + if( g_FactionCheck[race] == nil ) then + CensusPlus_Msg( "Found an unknown race (" .. race .. "), please tell Rollie at WarcraftRealms.com" ); + return; + end + + -- + -- Get racial database + -- + local raceDatabase = factionDatabase[race]; + if (raceDatabase == nil) then + factionDatabase[race] = {}; + raceDatabase = factionDatabase[race]; + end + + -- + -- Get class database + -- + local classDatabase = raceDatabase[class]; + if (classDatabase == nil) then + raceDatabase[class] = {}; + classDatabase = raceDatabase[class]; + end + + -- + -- Get this player's entry + -- + local entry = classDatabase[name]; + if (entry == nil) then + classDatabase[name] = {}; + entry = classDatabase[name]; + g_NumNewCharacters = g_NumNewCharacters + 1; + end + + -- + -- Update the information + -- + entry[1] = level; + entry[2] = guild; +-- local hour, minute = GetGameTime(); + entry[3] = CensusPlus_DetermineServerDate() .. ""; + + g_TempCount[name] = class; + g_TempZoneCount[name] = zone; + +-- CensusPlus_Msg2( "Processed " .. name ); +end + +---------------------------------------------------------------------------------- +-- +-- Find a guild in the CensusPlus_Guilds array by name +-- +--------------------------------------------------------------------------------- +local function FindGuildByName(name) + local i; + local size = table.getn(CensusPlus_Guilds); + for i = 1, size, 1 do + local entry = CensusPlus_Guilds[i]; + if (entry.m_Name == name) then + return i; + end + end + return nil; +end + +---------------------------------------------------------------------------------- +-- +-- Add up the total character XP and count +-- +--------------------------------------------------------------------------------- +local g_AccumulateGuildTotals = true; +local function TotalsAccumulator(name, level, guild) + -- + -- Add character to our player list + -- + CensusPlus_AddPlayerToList( name, level, guild ); + + if( g_TotalCharacterXPPerLevel[level] ) then + InitConstantTables(); + end + + local totalCharacterXP = g_TotalCharacterXPPerLevel[level]; + if( totalCharacterXP == nil ) then + totalCharacterXP = 0; + end + if( g_TotalCharacterXP == nil ) then + g_TotalCharacterXP = 0; + end + g_TotalCharacterXP = g_TotalCharacterXP + totalCharacterXP; + g_TotalCount = g_TotalCount + 1; + if (g_AccumulateGuildTotals and (guild ~= nil)) then + local index = FindGuildByName(guild); + if (index == nil) then + local size = table.getn(CensusPlus_Guilds); + index = size + 1; + CensusPlus_Guilds[index] = {m_Name = guild, m_TotalCharacterXP = 0, m_Count = 0}; + end + local entry = CensusPlus_Guilds[index]; + entry.m_TotalCharacterXP = entry.m_TotalCharacterXP + totalCharacterXP; + entry.m_Count = entry.m_Count + 1; + end +end + +---------------------------------------------------------------------------------- +-- +-- Predicate function which can be used to compare two guilds for sorting +-- +--------------------------------------------------------------------------------- +local function GuildPredicate(lhs, rhs) + -- + -- nil references are always less than + -- + if (lhs == nil) then + if (rhs == nil) then + return false; + else + return true; + end + elseif (rhs == nil) then + return false; + end + -- + -- Sort by total XP first + -- + if (rhs.m_TotalCharacterXP < lhs.m_TotalCharacterXP) then + return true; + elseif (lhs.m_TotalCharacterXP < rhs.m_TotalCharacterXP) then + return false; + end + -- + -- Sort by name + -- + if (lhs.m_Name < rhs.m_Name) then + return true; + elseif (rhs.m_Name < lhs.m_Name) then + return false; + end + + -- + -- identical + -- + return false; +end + + +---------------------------------------------------------------------------------- +-- +-- Another accumulator for adding up XP and counts +-- +--------------------------------------------------------------------------------- +local g_AccumulatorCount = 0; +local g_AccumulatorXPTotal = 0; +local function CensusPlus_Accumulator(name, level, guild) + if( g_TotalCharacterXPPerLevel[level] == nil ) then + InitConstantTables(); + end + local totalCharacterXP = g_TotalCharacterXPPerLevel[level]; + if( totalCharacterXP == nil or g_TotalCharacterXPPerLevel[level] == nil ) then + return; + end + g_AccumulatorXPTotal = g_AccumulatorXPTotal + totalCharacterXP; + g_AccumulatorCount = g_AccumulatorCount + 1; +end + +---------------------------------------------------------------------------------- +-- +-- Reset the above accumulator +-- +--------------------------------------------------------------------------------- +function CensusPlus_ResetAccumulator() + g_AccumulatorCount = 0; + g_AccumulatorXPTotal = 0; +end + + +---------------------------------------------------------------------------------- +-- +-- Search the character database using the search criteria and update display +-- +--------------------------------------------------------------------------------- +function CensusPlus_UpdateView() + + -- + -- No need to do anything if the window is not open + -- + if( not CensusPlus:IsVisible() ) then + return; + end + + if( g_CensusPlusLocale == "N/A" ) then + return; + end + + -- + -- Get realm and faction + -- + local realmName = g_CensusPlusLocale .. GetCVar("realmName"); + if( realmName == nil ) then + return; + end + CensusPlusRealmName:SetText(format(CENSUSPlus_REALMNAME, realmName)); + + local factionGroup = UnitFactionGroup("player"); + if( factionGroup == nil ) then + return; + end + + CensusPlusFactionName:SetText(format(CENSUSPlus_FACTION, factionGroup)); + + if( CensusPlus_Database["Info"]["Locale"] ~= nil ) then + CensusPlusLocaleName:SetText(format(CENSUSPlus_LOCALE, CensusPlus_Database["Info"]["Locale"])); + end + + local guildKey = nil; + local raceKey = nil; + local classKey = nil; + local levelKey = nil; + g_TotalCharacterXP = 0; + g_TotalCount = 0; + + -- + -- Has the user selected a guild? + -- + if (g_GuildSelected ~= nil ) then + guildKey = g_GuildSelected; + end + if (g_RaceSelected > 0) then + local thisFactionRaces = CensusPlus_GetFactionRaces(factionGroup); + raceKey = thisFactionRaces[g_RaceSelected]; + end + if (g_ClassSelected > 0) then + local thisFactionClasses = CensusPlus_GetFactionClasses(factionGroup); + classKey = thisFactionClasses[g_ClassSelected]; + end + if (g_LevelSelected > 0 or g_LevelSelected < 0) then + levelKey = g_LevelSelected; + end + + debugprofilestart(); + + -- + -- Has the user added any search criteria? + -- + if ((guildKey ~= nil) or (raceKey ~= nil) or (classKey ~= nil) or (levelKey ~= nil)) then + -- + -- Get totals for this criteria + -- + CensusPlus_Guilds = {}; + g_AccumulateGuildTotals = true; + CensusPlus_ForAllCharacters(realmName, factionGroup, raceKey, classKey, guildKey, levelKey, TotalsAccumulator); + + if( CensusPlus_EnableProfiling ) then + CensusPlus_Msg( "PROFILE: Time to do calcs 1 " .. debugprofilestop() / 1000000000 ); + debugprofilestart(); + end + + else + -- + -- Get the overall totals and find guild information + -- + CensusPlus_Guilds = {}; + g_AccumulateGuildTotals = true; + CensusPlus_ForAllCharacters(realmName, factionGroup, nil, nil, nil, nil, TotalsAccumulator); + + if( CensusPlus_EnableProfiling ) then + CensusPlus_Msg( "PROFILE: Time to do calcs 1 " .. debugprofilestop() / 1000000000 ); + debugprofilestart(); + end + + local size = table.getn(CensusPlus_Guilds); + if (size) then + table.sort(CensusPlus_Guilds, GuildPredicate); + end + + if( CensusPlus_EnableProfiling ) then + CensusPlus_Msg( "PROFILE: Time to sort guilds " .. debugprofilestop() / 1000000000 ); + debugprofilestart(); + end + end + + local levelSearch = nil; + if (levelKey ~= nil) then + levelSearch = " ("..CENSUSPlus_LEVEL..": "; + local level = levelKey; + if (levelKey < 0) then + levelSearch = levelSearch.."!"; + level = 0 - levelKey; + end + levelSearch = levelSearch..level..")"; + end + + local totalCharactersText = nil; + if (levelSearch ~= nil) then + totalCharactersText = format(CENSUSPlus_TOTALCHAR, g_TotalCount)..levelSearch; + else + totalCharactersText = format(CENSUSPlus_TOTALCHAR, g_TotalCount); + end + CensusPlusTotalCharacters:SetText(totalCharactersText); + CensusPlusTotalCharacterXP:SetText(format(CENSUSPlus_TOTALCHARXP, g_TotalCharacterXP)); + CensusPlus_UpdateGuildButtons(); + + if( CensusPlus_EnableProfiling ) then + CensusPlus_Msg( "PROFILE: Update Guilds " .. debugprofilestop() / 1000000000 ); + debugprofilestart(); + end + + -- + -- Accumulate totals for each race + -- + local maxCount = 0; + local thisFactionRaces = CensusPlus_GetFactionRaces(factionGroup); + local numRaces = table.getn(thisFactionRaces); + for i = 1, numRaces, 1 do + local race = thisFactionRaces[i]; + CensusPlus_ResetAccumulator(); + if ((raceKey == nil) or (raceKey == race)) then + CensusPlus_ForAllCharacters(realmName, factionGroup, race, classKey, guildKey, levelKey, CensusPlus_Accumulator); + end + if (g_AccumulatorCount > maxCount) then + maxCount = g_AccumulatorCount; + end + g_RaceCount[i] = g_AccumulatorCount; + end + + -- + -- Update race bars + -- + for i = 1, numRaces, 1 do + local race = thisFactionRaces[i]; + local buttonName = "CensusPlusRaceBar"..i; + local button = getglobal(buttonName); + local thisCount = g_RaceCount[i]; + if ((thisCount ~= nil) and (thisCount > 0) and (maxCount > 0)) then + local height = floor((thisCount * CensusPlus_MAXBARHEIGHT / maxCount) ); + if (height < 2 or height == nil ) then height = 2; end + button:SetHeight(height); + button:Show(); + else + button:Hide(); + end + local normalTextureName="Interface\\AddOns\\CensusPlus\\Skin\\CensusPlus_"..g_RaceClassList[race]; + local legendName = "CensusPlusRaceLegend"..i; + local legend = getglobal(legendName); + legend:SetNormalTexture(normalTextureName); + if (g_RaceSelected == i) then + legend:LockHighlight(); + else + legend:UnlockHighlight(); + end + end + + if( CensusPlus_EnableProfiling ) then + CensusPlus_Msg( "PROFILE: Update Races " .. debugprofilestop() / 1000000000 ); + debugprofilestart(); + end + + -- + -- Accumulate totals for each class + -- + local maxCount = 0; + local thisFactionClasss = CensusPlus_GetFactionClasses(factionGroup); + local numClasses = table.getn(thisFactionClasss); + for i = 1, numClasses, 1 do + local class = thisFactionClasss[i]; + CensusPlus_ResetAccumulator(); + if ((classKey == nil) or (classKey == class)) then + CensusPlus_ForAllCharacters(realmName, factionGroup, raceKey, class, guildKey, levelKey, CensusPlus_Accumulator); + end + if (g_AccumulatorCount > maxCount) then + maxCount = g_AccumulatorCount; + end + g_ClassCount[i] = g_AccumulatorCount; + end + + -- + -- Update class bars + -- + for i = 1, numClasses, 1 do + local class = thisFactionClasss[i]; + + local buttonName = "CensusPlusClassBar"..i; + local button = getglobal(buttonName); + local thisCount = g_ClassCount[i]; + if ((thisCount ~= nil) and (thisCount > 0) and (maxCount > 0)) then + local height = floor((thisCount * CensusPlus_MAXBARHEIGHT / maxCount) ); + if (height < 2 or height == nil ) then height = 2; end + button:SetHeight(height); + button:Show(); + else + button:Hide(); + end + + local normalTextureName="Interface\\AddOns\\CensusPlus\\Skin\\CensusPlus_"..g_RaceClassList[class]; + local legendName = "CensusPlusClassLegend"..i; + local legend = getglobal(legendName); + legend:SetNormalTexture(normalTextureName); + if (g_ClassSelected == i) then + legend:LockHighlight(); + else + legend:UnlockHighlight(); + end + end + + if( CensusPlus_EnableProfiling ) then + CensusPlus_Msg( "PROFILE: Update Classes " .. debugprofilestop() / 1000000000 ); + debugprofilestart(); + end + + -- + -- Accumulate totals for each level + -- + local maxCount = 0; + for i = 1, MAX_CHARACTER_LEVEL, 1 do + if ((levelKey == nil) or (levelKey == i) or (levelKey < 0 and levelKey + i ~= 0)) then + CensusPlus_ResetAccumulator(); + CensusPlus_ForAllCharacters(realmName, factionGroup, raceKey, classKey, guildKey, i, CensusPlus_Accumulator); + if (g_AccumulatorCount > maxCount) then + maxCount = g_AccumulatorCount; + end + g_LevelCount[i] = g_AccumulatorCount; + else + g_LevelCount[i] = 0; + end + end + local logMaxCount = math.log( maxCount / 3 + 1 ); + + -- + -- To make the data easier to use, we need to massage it a bit for levels + -- + + + -- + -- Update level bars + -- + for i = 1, MAX_CHARACTER_LEVEL, 1 do + local buttonName = "CensusPlusLevelBar"..i; + local buttonEmptyName = "CensusPlusLevelBarEmpty"..i; + local button = getglobal(buttonName); + local emptyButton = getglobal(buttonEmptyName); + local thisCount = g_LevelCount[i]; + if ((thisCount ~= nil) and (thisCount > 0) and (maxCount > 0)) then + local height = floor(( math.log(thisCount / 3 + 1) * CensusPlus_MAXBARHEIGHT / logMaxCount) ); + if( CensusPlus_Database["Info"]["UseLogBars"] == 0 ) then + height = floor(( CensusPlus_MAXBARHEIGHT * (thisCount) / maxCount) ); + end + + if (height < 2 or height == nil ) then height = 2; end + button:SetHeight(height); + button:Show(); + if (emptyButton ~= nil) then + emptyButton:Hide(); + end + else + button:Hide(); + if (emptyButton ~= nil) then + emptyButton:SetHeight(CensusPlus_MAXBARHEIGHT); + emptyButton:Show(); + end + end + end + + if( CensusPlus_EnableProfiling ) then + CensusPlus_Msg( "PROFILE: Update Levels " .. debugprofilestop() / 1000000000 ); + debugprofilestart(); + end + + if( CP_PlayerListWindow:IsVisible() ) then + CensusPlus_PlayerListOnShow(); + end + + + debugprofilestop(); + +end + +---------------------------------------------------------------------------------- +-- +-- Walk the character database and call the callback function for every entry that matches the search criteria +-- +--------------------------------------------------------------------------------- +function CensusPlus_ForAllCharacters(realmKey, factionKey, raceKey, classKey, guildKey, levelKey, callback) + for realmName, realmDatabase in pairs(CensusPlus_Database["Servers"]) do + if ((realmKey == nil) or (realmKey == realmName)) then + for factionName, factionDatabase in pairs(realmDatabase) do + if ((factionKey == nil) or (factionKey == factionName)) then + for raceName, raceDatabase in pairs(factionDatabase) do + if ((raceKey == nil) or (raceKey == raceName)) then + for className, classDatabase in pairs(raceDatabase) do + if ((classKey == nil) or (classKey == className)) then + for characterName, character in pairs(classDatabase) do + local characterGuild = character[2]; + if ((guildKey == nil) or (guildKey == characterGuild)) then + local characterLevel = character[1]; + if( characterLevel == nil ) then + characterLevel = 0; + end + if ((levelKey == nil) or (levelKey == characterLevel) or (levelKey < 0 and levelKey + characterLevel ~= 0)) then + callback(characterName, characterLevel, characterGuild, raceName, className, character[3] ); + end + end + end + end + end + end + end + end + end + end + end +end + +---------------------------------------------------------------------------------- +-- +-- Race legend clicked +-- +--------------------------------------------------------------------------------- +function CensusPlus_OnClickRace() + local id = this:GetID(); + if (id == g_RaceSelected) then + g_RaceSelected = 0; + else + g_RaceSelected = id; + end + CensusPlus_UpdateView(); +end + +---------------------------------------------------------------------------------- +-- +-- Class legend clicked +-- +--------------------------------------------------------------------------------- +function CensusPlus_OnClickClass() + local id = this:GetID(); + if (id == g_ClassSelected) then + g_ClassSelected = 0; + else + g_ClassSelected = id; + end + CensusPlus_UpdateView(); +end + + +---------------------------------------------------------------------------------- +-- +-- Level bar loaded +-- +--------------------------------------------------------------------------------- +function CensusPlus_OnLoadLevel() + this:RegisterForClicks("LeftButtonUp","RightButtonUp"); +end + +---------------------------------------------------------------------------------- +-- +-- Level bar clicked +-- +--------------------------------------------------------------------------------- +function CensusPlus_OnClickLevel(button) + local id = this:GetID(); + if (((button == "LeftButton") and (id == g_LevelSelected)) or ((button == "RightButton") and (id + g_LevelSelected == 0))) then + g_LevelSelected = 0; + elseif (button == "RightButton") then + g_LevelSelected = 0 - id; + else + g_LevelSelected = id; + end + CensusPlus_UpdateView(); +end + +---------------------------------------------------------------------------------- +-- +-- Race tooltip +-- +--------------------------------------------------------------------------------- +function CensusPlus_OnEnterRace() + local factionGroup = UnitFactionGroup("player"); + local thisFactionRaces = CensusPlus_GetFactionRaces(factionGroup); + local id = this:GetID(); + local raceName = thisFactionRaces[id]; + local count = g_RaceCount[id]; + if (count ~= nil) then + local percent = floor((count / g_TotalCount) * 100); + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText(raceName.."\n"..count.."\n"..percent.."%", 1.0, 1.0, 1.0); + GameTooltip:Show(); + end +end + +---------------------------------------------------------------------------------- +-- +-- Class tooltip +-- +--------------------------------------------------------------------------------- +function CensusPlus_OnEnterClass() + local factionGroup = UnitFactionGroup("player"); + local thisFactionClasses = CensusPlus_GetFactionClasses(factionGroup); + local id = this:GetID(); + local className = thisFactionClasses[id]; + local count = g_ClassCount[id]; + if (count ~= nil) then + local percent = floor((count / g_TotalCount) * 100); + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText(className.."\n"..count.."\n"..percent.."%", 1.0, 1.0, 1.0); + GameTooltip:Show(); + end +end + +---------------------------------------------------------------------------------- +-- +-- Level tooltip +-- +--------------------------------------------------------------------------------- +function CensusPlus_OnEnterLevel() + local id = this:GetID(); + local count = g_LevelCount[id]; + if (count ~= nil) then + local percent = floor(count * 100 / g_TotalCount); + GameTooltip:SetOwner(this, "ANCHOR_RIGHT"); + GameTooltip:SetText("Level "..id.."\n"..count.."\n"..percent.."%", 1.0, 1.0, 1.0); + GameTooltip:Show(); + end +end + +---------------------------------------------------------------------------------- +-- +-- Clicked a guild button +-- +--------------------------------------------------------------------------------- +function CensusPlus_GuildButton_OnClick() + local id = this:GetID(); + local offset = FauxScrollFrame_GetOffset(CensusPlusGuildScrollFrame); + local newSelection = id + offset; + local guildKey = CensusPlus_Guilds[newSelection].m_Name; + if (g_GuildSelected ~= guildKey) then + g_GuildSelected = guildKey; + else + g_GuildSelected = nil; + end + CensusPlus_UpdateView(); +end + +---------------------------------------------------------------------------------- +-- +-- Update the guild button contents +-- +--------------------------------------------------------------------------------- +function CensusPlus_UpdateGuildButtons() + -- + -- Determine where the scroll bar is + -- + local offset = FauxScrollFrame_GetOffset(CensusPlusGuildScrollFrame); + -- + -- Walk through all the rows in the frame + -- + local size = table.getn(CensusPlus_Guilds); + local i = 1; + while (i <= CensusPlus_NUMGUILDBUTTONS) do + -- + -- Get the index to the ad displayed in this row + -- + local iGuild = i + offset; + -- + -- Get the button on this row + -- + local button = getglobal("CensusPlusGuildButton"..i); + -- + -- Is there a valid guild on this row? + -- + if (iGuild <= size) then + local guild = CensusPlus_Guilds[iGuild]; + -- + -- Update the button text + -- + button:Show(); + local textField = "CensusPlusGuildButton"..i.."Text"; + if (guild.m_Name == "") then + getglobal(textField):SetText(CENSUSPlus_UNGUILDED); + else + getglobal(textField):SetText(guild.m_Name); + end + -- + -- If this is the guild, highlight it + -- + local guildName = CensusPlus_Guilds[iGuild].m_Name + if (g_GuildSelected == guildName) then + button:LockHighlight(); + else + button:UnlockHighlight(); + end + else + -- + -- Hide the button + -- + button:Hide(); + end + -- + -- Next row + -- + i = i + 1; + end + -- + -- Update the scroll bar + -- + FauxScrollFrame_Update(CensusPlusGuildScrollFrame, size, CensusPlus_NUMGUILDBUTTONS, CensusPlus_GUILDBUTTONSIZEY); +end + + +---------------------------------------------------------------------------------- +-- +-- Census_AutoStartOnLoad +-- +--------------------------------------------------------------------------------- +function Census_AutoStartOnLoad( ) + CP_OptionAutoStartButton:SetChecked(g_MiniOnStart); + if( g_MiniOnStart == 1 ) then + MiniCensusPlus:Show(); + else + MiniCensusPlus:Hide(); + end + MiniCensusPlus:Hide(); +end + +---------------------------------------------------------------------------------- +-- +-- CensusPlus_AutoStart - Set the auto-start option +-- +--------------------------------------------------------------------------------- +function CensusPlus_AutoStart( check ) + g_MiniOnStart = check; + CensusPlus_Database["Info"]["MiniStart"] = g_MiniOnStart; + Census_AutoStartOnLoad(); +end + + +---------------------------------------------------------------------------------- +-- +-- CensusPlus_VerifyLocale - Set the locale (US or EU) +-- +--------------------------------------------------------------------------------- +function CensusPlus_VerifyLocale( locale ) + if( CensusPlus_Database["Info"]["Locale"] ~= locale ) then + -- + -- Purge + -- + CensusPlus_DoPurge() + end +end + +---------------------------------------------------------------------------------- +-- +-- CensusPlus_SelectLocale - Set the locale (US or EU) +-- +--------------------------------------------------------------------------------- +function CensusPlus_SelectLocale( locale, auto ) + + if( not auto ) then + CensusPlus_Msg( "You have set your locale to " .. locale .. " from " .. g_CensusPlusLocale ); + end + + g_CensusPlusLocale = locale; + if( g_CensusPlusLocale == "EU" ) then + g_CensusPlusLocale = g_CensusPlusLocale .. "-"; + else + g_CensusPlusLocale = ""; + end + + + if( CensusPlus_Database["Info"]["Locale"] ~= locale ) then + if( not ( CensusPlus_Database["Info"]["Locale"] == nil and locale == "US" ) ) then + CensusPlus_Msg( "Locale differs from previous setting, purging database." ); + CensusPlus_DoPurge(); + CensusPlus_Database["Info"]["Locale"] = locale; + end + end + CensusPlus_Database["Info"]["Locale"] = locale; + + textLine = getglobal("CensusPlusText"); + textLine:SetText("Census+ EmSpe\195\167ial v"..CensusPlus_VERSION .. " " .. g_CensusPlusLocale ); + + if(( CENSUSPlus_DWARF == "Nain" or CENSUSPlus_DWARF == "Zwerg" ) and GetLocale() == "usEN") then + CensusPlus_Msg( "You appear to have a US Census version, yet your localization is set to French or German." ); + CensusPlus_Msg( "Please do not upload stats to WarcraftRealms until this has been resolved." ); + CensusPlus_Msg( "If this is incorrect, please let Rollie know at www.WarcraftRealms.com about your situation so he can make corrections." ); + end + + CP_EU_US_Version:Hide(); + +end + +---------------------------------------------------------------------------------- +-- +-- Walk the character database prune all characters entries that are older than 30 days +-- +--------------------------------------------------------------------------------- +function CensusPlus_PruneData( nDays, sServer ) + + if( g_CensusPlusLocale == "N/A" ) then + return; + end + + + local thisRealmName = g_CensusPlusLocale .. GetCVar("realmName"); + + if( sServer == 1 ) then + nDays = 0; + end + + local pruneTime = 24 * 60 * 60 * nDays; + + for realmName, realmDatabase in pairs(CensusPlus_Database["Servers"]) do + if ((realmKey == nil) or (realmKey == realmName)) then + for factionName, factionDatabase in pairs(realmDatabase) do + if ((factionKey == nil) or (factionKey == factionName)) then + for raceName, raceDatabase in pairs(factionDatabase) do + if ((raceKey == nil) or (raceKey == raceName)) then + for className, classDatabase in pairs(raceDatabase) do + if ((classKey == nil) or (classKey == className)) then + for characterName, character in pairs(classDatabase) do + if( characterName ~= nil ) then + if( sServer == 1 ) then + if( realmName ~= thisRealmName ) then + CensusPlus_AccumulatePruneData( realmName, factionName, raceName, className, characterName ); + end + else + local lastSeen = character[3]; -- 2005-05-02 + + local tYear, tMonth, tDay; + tYear = string.sub( lastSeen, 1, 4 ); + tMonth = string.sub( lastSeen, 6, 7 ); + tDay = string.sub( lastSeen, 9 ); + + local lastSeenTime = time( {year=tYear, month=tMonth, day=tDay, hour=0} ); + + if( time() - lastSeenTime > pruneTime ) then + CensusPlus_AccumulatePruneData( realmName, factionName, raceName, className, characterName ); + end + end + end + end + end + end + end + end + end + end + end + end + + CensusPlus_PruneTimes(); + CensusPlus_UpdateView(); + CensusPlus_PruneTheData(); +end + +----------------------------------------------------------------------------------- +-- +-- Prune the accumulation +-- +----------------------------------------------------------------------------------- +function CensusPlus_AccumulatePruneData( realm, faction, race, class, name ) + local pruneData = {}; + pruneData.realm = realm; + pruneData.faction = faction; + pruneData.race = race; + pruneData.class = class; + pruneData.name = name; + + table.insert(g_AccumulatedPruneData, pruneData); +end +----------------------------------------------------------------------------------- +-- +-- Prune the accumulation +-- +----------------------------------------------------------------------------------- +function CensusPlus_PruneTheData() + local num = table.getn(g_AccumulatedPruneData); + CensusPlus_Msg( format(CENSUSPlus_PRUNEINFO, num ) ); + while( num > 0 )do + -- + -- Remove the top job from the queue and send it + -- + local pruneData = g_AccumulatedPruneData[num]; + + CensusPlus_Database["Servers"][pruneData.realm][pruneData.faction][pruneData.race][pruneData.class][pruneData.name] = {}; + CensusPlus_Database["Servers"][pruneData.realm][pruneData.faction][pruneData.race][pruneData.class][pruneData.name] = nil; + + table.remove(g_AccumulatedPruneData); + num = table.getn(g_AccumulatedPruneData); + end +end + +----------------------------------------------------------------------------------- +-- +-- Prune time entries +-- +----------------------------------------------------------------------------------- +function CensusPlus_PruneTimes() + local pruneDays = 60*60*24*21; -- num seconds + + local accumTimesData = {}; + for realmName, realmDatabase in pairs(CensusPlus_Database["TimesPlus"]) do + if (realmName ~= nil ) then + for factionName, factionDatabase in pairs(realmDatabase) do + if ( factionName ~= nil) then + for moment, count in pairs( factionDatabase ) do + -- Moment is in format of YYYY-MM-DD&HH:MM + local test = string.sub( moment, 1, 2 ); + local tYear, tMonth, tDay; + tYear = string.sub( moment, 1, 4 ); + tMonth = string.sub( moment, 6, 7 ); + tDay = string.sub( moment, 9, 10 ); + local momentTime = time( {year=tYear, month=tMonth, day=tDay, hour=0} ); + + if( time() - momentTime > pruneDays ) then + -- cull entry + local pruneData = {}; + pruneData.realm = realmName; + pruneData.faction = factionName; + pruneData.entry = moment; + table.insert(accumTimesData, pruneData); + end + end + end + end + end + end + + local num = table.getn(accumTimesData); + while( num > 0 )do + local pruneData = accumTimesData[num]; + + CensusPlus_Database["TimesPlus"][pruneData.realm][pruneData.faction][pruneData.entry] = {}; + CensusPlus_Database["TimesPlus"][pruneData.realm][pruneData.faction][pruneData.entry] = nil; + + table.remove(accumTimesData); + num = table.getn(accumTimesData); + end +end + + +function CensusPlus_CheckForBattleground() + + +-- CensusPlus_Msg( "Checking for BG" ); + g_CurrentlyInBG_Msg = false; + + local battlefieldTime = GetBattlefieldInstanceRunTime(); + if( battlefieldTime > 0 ) then + -- + -- We are in a battleground so cancel the current take + -- + g_CurrentlyInBG = true; + else + if( GetBattlefieldStatInfo(1) ~= nil ) then + g_CurrentlyInBG = true; + else + g_CurrentlyInBG = false; + end + end + +end + +function CensusPlus_IsInspectLoaded() + if (IsAddOnLoaded("Blizzard_InspectUI")) then + --ChatFrame1:AddMessage("Inspect Loaded"); + return true; + end + + if (CensusPlus_Database["Info"]["LoadInspect"] ~= nil and CensusPlus_Database["Info"]["LoadInspect"] == true) then + --ChatFrame1:AddMessage("Loading Inspect Frame"); + LoadAddOn("Blizzard_InspectUI"); + end + + --ChatFrame1:AddMessage("Inspect Not Loaded"); + return false; +end + +function CensusPlus_IsTalentLoaded() + if (IsAddOnLoaded("Blizzard_TalentUI")) then + --ChatFrame1:AddMessage("Talent Loaded"); + return true; + end + + if (CensusPlus_Database["Info"]["LoadTalent"] ~= nil and CensusPlus_Database["Info"]["LoadTalent"] == true) then + --ChatFrame1:AddMessage("Loading Talent Frame"); + LoadAddOn("Blizzard_TalentUI"); + end + + --ChatFrame1:AddMessage("Talent Not Loaded"); + return false; +end + + + +function showAllUnitBuffs(sUnitname) + local iIterator = 1 + DEFAULT_CHAT_FRAME:AddMessage(format("[%s] Buffs", sUnitname)) + while (UnitBuff(sUnitname, iIterator)) do + DEFAULT_CHAT_FRAME:AddMessage(UnitBuff(sUnitname, iIterator), 1, 1, 0) + iIterator = iIterator + 1 + end + DEFAULT_CHAT_FRAME:AddMessage("---", 1, 1, 0) +end + +function CensusPlus_GetUTCDateTimeStr() + return date( "!%Y-%m-%d %H:%M", time() ); +end + +----------------------------------------------------------------------------------- +-- +-- CensusPlus_DetermineServerDate +-- +----------------------------------------------------------------------------------- +function CensusPlus_DetermineServerDate() + + CensusPlus_CheckTZ(); + + local strDate; + local TZOffset = g_CensusPlusTZOffset; + + -- + -- Timezone offsets should fall into distinct numbers for now + -- And now that we know if they are playing on US or EU servers + -- we can be even better estimates + -- + + -- + -- For US servers, the offset should be either -9 to -5 or 16/19 depending on DST for NA times + -- and for oceana it is +11/-13 + -- EU servers are either +1 or 0 or -23 depending on DST + -- + + if( CensusPlus_Database["Info"]["Locale"] == "US" ) then + if( TZOffset > 12 ) then + -- NA server times but wrong day + TZOffset = TZOffset - 24; + elseif( TZOffset < -11 ) then + -- Oceana times but wrong day + TZOffset = 24 - TZOffset; + end + else + if( TZOffset == -23 ) then + TZOffset = 1; + end + end + + -- Now, take the TZOffset and modify our time to give us server date + strDate = date( "!%Y-%m-%d", time() + (TZOffset * 3600 ) ); + +-- local strDate2 = date( "%Y-%m-%d : %H:%M", time() ); +-- CensusPlus_Msg("Server date = " .. strDate .. " for TZOffset : " .. TZOffset .. " curr local: " .. strDate2 ); + + return strDate; +end + +----------------------------------------------------------------------------------- +-- +-- Check time zone +-- +----------------------------------------------------------------------------------- +function CensusPlus_CheckTZ() + + local UTCTimeHour = date( "!%H", time() ); + local LocTimeHour = date( "%H", time() ); + local hour, minute = GetGameTime(); + + local locDiff = LocTimeHour - UTCTimeHour; + local servDiff = hour - UTCTimeHour; + g_CensusPlusTZOffset = servDiff; +end + + +function CensusPlus_UpdateBattleGroundInfo() + local status, mapName, instanceID, lowestLevel, highestLevel; + local numberQueues = 0; + local waitTime, timeInQueue; + local map = {}; + + if( g_CensusPlusLocale == "N/A" ) then + return; + end + + for i=1, MAX_BATTLEFIELD_QUEUES do + map = {}; + status, mapName, instanceID, lowestLevel, highestLevel = GetBattlefieldStatus(i); + + if ( status ~= "none" ) then + numberQueues = numberQueues+1; + + if ( status == "queued" ) then + -- Update queue info + waitTime = GetBattlefieldEstimatedWaitTime(i)/1000; + timeInQueue = GetBattlefieldTimeWaited(i)/1000; + + map[0] = waitTime; + map[1] = timeInQueue; + map[2] = mapName; + map[3] = "Inactive"; + +-- CensusPlus_Msg( "INSERT " .. mapName .. " : " .. map[2] .. " to " .. i ); + CENSUSPLUS_CURRENT_BATTLEFIELD_QUEUES[i] = map; + + elseif ( status == "confirm" ) then + -- In the battleground + -- Check to see if we know we've already entered, and if so, add info to + -- our database + map = CENSUSPLUS_CURRENT_BATTLEFIELD_QUEUES[i]; + +-- CensusPlus_Msg( "ACTIVE " .. mapName ); +-- CensusPlus_Msg( map[2] ); + if( map ~= nil and map[3] == "Inactive" ) then + map[3] = "Active"; + + CENSUSPLUS_CURRENT_BATTLEFIELD_QUEUES[i] = map; + + -- Make an entry in our database + + -- + -- Get the portion of the database for this server + -- + local realmName = g_CensusPlusLocale .. GetCVar("realmName"); + if (CensusPlus_BGInfo[realmName] == nil) then + CensusPlus_BGInfo[realmName] = {}; + end + + -- + -- Get the portion of the database for this faction + -- + local factionGroup = UnitFactionGroup("player"); + if( factionGroup ~= nil ) then + if (CensusPlus_BGInfo[realmName][factionGroup] == nil) then + CensusPlus_BGInfo[realmName][factionGroup] = {}; + end + + local playerLevel = UnitLevel( "player" ); + if( playerLevel ~= nil ) then + if (CensusPlus_BGInfo[realmName][factionGroup][playerLevel] == nil) then + CensusPlus_BGInfo[realmName][factionGroup][playerLevel] = {}; + end + + local hour, minute = GetGameTime(); + CensusPlus_BGInfo[realmName][factionGroup][playerLevel][CensusPlus_DetermineServerDate() .. "&" .. hour .. ":" .. minute .. ":00"] = + map[2] .. "&" .. map[0] .. "&" .. map[1] .. "&" .. lowestLevel .. "&" .. highestLevel; + end + end + end + end + end + end +end + +function CensusPlus_PruneBGInfo() + local pruneDays = 60*60*24*21; -- num seconds + + local accumData = {}; + for realmName, realmDatabase in pairs(CensusPlus_BGInfo) do + if (realmName ~= nil and table.getn( realmDatabase ) > 0 ) then + for factionName, factionDatabase in pairs(realmDatabase) do + if ( factionName ~= nil and table.getn( factionDatabase ) > 0 ) then + for level, levelDatabase in pairs( factionDatabase ) do + if( level ~= nil and table.getn( levelDatabase ) > 0 ) then + for moment, data in pairs( levelDatabase ) do + -- Moment is in format of YYYY-MM-DD&HH:MM + local test = string.sub( moment, 1, 2 ); + local tYear, tMonth, tDay; + tYear = string.sub( moment, 1, 4 ); + tMonth = string.sub( moment, 6, 7 ); + tDay = string.sub( moment, 9, 10 ); + local momentTime = time( {year=tYear, month=tMonth, day=tDay, hour=0} ); + + if( time() - momentTime > pruneDays ) then + -- cull entry + local pruneData = {}; + pruneData.realm = realmName; + pruneData.faction = factionName; + pruneData.level = level; + pruneData.entry = moment; + table.insert(accumData, pruneData); + end + end + end + end + end + end + end + end + + local num = table.getn(accumData); + while( num > 0 )do + local pruneData = accumData[num]; + + CensusPlus_BGInfo[pruneData.realm][pruneData.faction][pruneData.level][pruneData.entry] = {}; + CensusPlus_BGInfo[pruneData.realm][pruneData.faction][pruneData.level][pruneData.entry] = nil; + + table.remove(accumData); + num = table.getn(accumData); + end +end + +----------------------------------------------------------------------------------- +-- +-- My Test function +-- +----------------------------------------------------------------------------------- +function CensusPlus_Test( val ) + + +-- local file = "Interface\\AddOns\\CensusPlus\\Sounds\\CensusComplete.ogg"; +-- CensusPlus_Msg( "Play sound " .. file ); +-- PlaySoundFile( file ); + +local test = {}; +test[1] = "|Hplayer:Cdrom|h[Cdrom]|h: Level 60 Tauren Warrior <CSM AND NOVA SUX> - Hellfire Peninsula"; +test[2] = "|Hplayer:Cdrom|h[Cdrom]|h: Level 60 Tauren Warrior - Hellfire Peninsula"; +test[3] = "|Hplayer:Cdrom|h[Cdrom]|h: Level 60 Troll Death Knight <CSM AND NOVA SUX> - Hellfire Peninsula"; +test[4] = "|Hplayer:Cdrom|h[Cdrom]|h: Level 60 Troll Death Knight - Hellfire Peninsula"; +test[5] = "|Hplayer:Frostbiite|h[Frostbiite]|h: Level 61 Troll Death Knight - Hellfire Peninsula"; +test[6] = "|Hplayer:Dynanite|h[Dynanite]|h: Level 60 Troll Death Knight - Hellfire Peninsula"; +test[7] = "|Hplayer:Physco|h[Physco]|h: Level 61 Troll Death Knight - Hellfire Peninsula"; +test[8] = "|Hplayer:Gordoom|h[Gordoom]|h: Level 60 Troll Death Knight <Hellfire Club> - Hellfire Peninsula"; +test[9] = "|Hplayer:Seroa|h[Seroa]|h: Level 67 Blood Elf Death Knight <Carnage> - Nagrand"; +test[10] = "|Hplayer:Seroa|h[Seroa]|h: Level 67 Night Elf Death Knight <Carnage> - Nagrand"; +test[11] = "|Hplayer:Seroa|h[Seroa]|h: Level 67 Blood Elf Death Knight - Nagrand"; +test[12] = "|Hplayer:Seroa|h[Seroa]|h: Level 67 Night Elf Death Knight - Nagrand"; +test[13] = "|Hplayer:Seroa|h[Seroa]|h: Level 67 Blood Elf Paladin <Carnage> - Nagrand"; +test[14] = "|Hplayer:Seroa|h[Seroa]|h: Level 67 Night Elf Paladin <Carnage> - Nagrand"; +test[15] = "|Hplayer:Seroa|h[Seroa]|h: Level 67 Blood Elf Paladin - Nagrand"; +test[16] = "|Hplayer:Seroa|h[Seroa]|h: Level 67 Night Elf Paladin - Nagrand"; + + + for index, case in pairs(test) do + CensusPlus_Msg( "Checking : " .. case ); + local t = CensusPlus_GatherSingleReturn( case ); + if( t ~= nil ) then + CensusPlus_Msg( index .. " Name : " .. t["NAME"] + .. " L: " .. t["LEVEL"] + .. " R: " .. t["RACE"] + .. " C: " .. t["CLASS"] + .. " G: " .. t["GUILD"] + .. " Z: " .. t["ZONE"] ); + end + end + + +--[[ + local pattern = "[0-9\| ]"; + + local name = "11:58]|r |Hplayer:Azide|h[Azide"; + if( string.find( name, pattern ) ~= nil ) then + CensusPlus_Msg( "This name is problematic => " .. name ); + end + + name = "Rollie"; + if( string.find( name, pattern ) ~= nil ) then + CensusPlus_Msg( "This name is problematic => " .. name ); + else + CensusPlus_Msg( "This name is NOT problematic => " .. name ); + end +]]-- + +end + +function CensusPlus_GatherSingleReturn( line ) + local t = {}; + local s, e, name, level_text, level, rcg, zone, junk; + local RCG = {}; + local presults = {}; + local RCG_Pattern = "(.+) <(.+)>"; + local possibles = {}; + possibles[1] = "(" .. CENSUSPlus_NIGHTELF .. ")" .. " ([%a%s]+)"; + possibles[2] = "(" .. CENSUSPlus_BLOODELF .. ")" .. " ([%a%s]+)"; + possibles[3] = "(%a+) " .. "(" .. CENSUSPlus_DEATHKNIGHT .. ")"; + possibles[4] = "(%a+) (%a+)"; + +--CensusPlus_Msg2( " CHECKING " .. line ); + + if( g_PratLoaded ) then + s, e, junk, junk, junk, name, junk, junk, level_text, level, rcg, zone = string.find(line, CENSUS_SINGLE_MATCH_PATTERN_PRAT ); + else + s, e, junk, junk, name, level_text, level, rcg, zone = string.find(line, CENSUS_SINGLE_MATCH_PATTERN); + end + if( name ~= nil ) then + -- + -- Now let's break out our race, class & guild + -- + local race_class = rcg; + t["GUILD"] = ''; + t["NAME"] = name; + t["LEVEL"] = level; + t["ZONE"] = zone; + s, e, RCG[0], RCG[1] = string.find(rcg, RCG_Pattern); + if( RCG[0] ~= nil ) then + race_class = RCG[0]; + t["GUILD"] = RCG[1]; + end + + -- + -- Now we need to figure out race/class + -- + for pi, poss in pairs(possibles) do + s, e, presults[0], presults[1] = string.find(race_class, poss); + if( presults[0] ~= nil ) then +-- CensusPlus_Msg( pi .. " 0: " .. presults[0] .. " 1: " .. presults[1]); + t["RACE"] = presults[0]; + t["CLASS"] = presults[1]; + break; + end + end + +-- CensusPlus_Msg2( " IN Fn Name : " .. t["NAME"] .. " L: " .. t["LEVEL"] .. " R: " .. t["RACE"] .. " C: " .. t["CLASS"].. " G: " .. t["GUILD"] .. " Z: " .. t["ZONE"] ); + end + + return t; +end + + +function CensusPlus_SetItemRef(link, text, button) + -- + -- We only care about if they are sending a who, otherwise send on through + -- + if ( g_IsCensusPlusInProgress and strsub(link, 1, 6) == "player" ) then + if ( strsub(link, 1, 6) == "player" ) then + local namelink = strsub(link, 8); + local name, lineid = strsplit(":", namelink); + if ( name and (strlen(name) > 0) ) then + name = gsub(name, "([^%s]*)%s+([^%s]*)%s+([^%s]*)", "%3"); + name = gsub(name, "([^%s]*)%s+([^%s]*)", "%2"); + if ( IsShiftKeyDown() ) then + if ( not ChatFrameEditBox:IsVisible() ) then + -- + -- This is the part we need to snag + -- + + -- + -- Queue up the command to run next + -- + g_CensusWhoOverrideMsg = "n-"..name; + CensusPlus_Msg( CENSUSPlus_OVERRIDE ); + +-- CensusPlus_SendWho("n-"..name); + return; + end + end + end + end + end + + g_SetItemRef_Override( link, text, button ); +end + +function CensusPlus_CleanChars() + + local pattern = "[0-9\| -]"; + local count = 0; + + for realmName, realmDatabase in pairs(CensusPlus_Database["Servers"]) do + if ((realmKey == nil) or (realmKey == realmName)) then + for factionName, factionDatabase in pairs(realmDatabase) do + if ((factionKey == nil) or (factionKey == factionName)) then + for raceName, raceDatabase in pairs(factionDatabase) do + if ((raceKey == nil) or (raceKey == raceName)) then + for className, classDatabase in pairs(raceDatabase) do + if ((classKey == nil) or (classKey == className)) then + for characterName, character in pairs(classDatabase) do + if( characterName ~= nil ) then + if( string.find( characterName, pattern ) ~= nil ) then + CensusPlus_AccumulatePruneData( realmName, factionName, raceName, className, characterName ); + count = count + 1; + end + end + end + end + end + end + end + end + end + end + end + + CensusPlus_PruneTheData(); + CensusPlus_Msg( "Found " .. count .. " entries to remove" ); +end + +function CensusPlus_SendWho( msg ) + + if( CensusPlus_PerCharInfo["Verbose"] == true ) then + CensusPlus_Msg(format(CENSUSPlus_SENDING, msg)); + end + + if wholib then + wholib:AskWho({query = msg, queue = wholib.WHOLIB_QUEUE_QUIET, callback = CP_ProcessWhoEvent }) + else + SendWho( msg ); + end +end
