WoWInterface SVN AKA

[/] [trunk/] [aka.lua] - Rev 18

Compare with Previous | Blame | View Log

-- AKA
--   Author: Lon Koenig
--   License: Creative Commons Attribution-Noncommercial 3.0 Unported License (see Readme.txt)

-- Globals:
-- ========
-- AKASavedVars = {};

AKA_Version=2.8;
AKA_HighestSeenVersion=0;
AKA_FormatVersion=1.2;
AKA_variablesLoaded = false;
AKA_RaidInfoByName = {};


local VISIBLE_MAX=17; -- for scrolling menu
AKA_DEBUG=false;
AKA_ShowEvent=false;
AKA_TRAFFICMONITOR=false;

AKA_LinkedName=nil; -- keep this global for testing
AKA_LinkedName="";
AKA_USERID=nil;
AKA_LastSeen={};


AKAPrefs_PanelFrames ={"AKAUsersPanel","AKAOptionsPanel"};
AKAPrefs_CurrentPanel=0;
AKA_ToonListDirty=true; -- whether we need to redraw the scrolling character list

AKA_SessionList={};
AKA_PendingWhispers={};


AKA_GuildNotes={};
-- data structures
-- 
-- AKASavedVars={
--      AKA_Defaults["MyToons"]={
--              ToonID -- toon Name + "**" + Realm name
--                      {"name"=name, etc. -- list below in messageFields
--                      };
--      AKA_Defaults["FriendToons"] ={ -- same format as MyToons
-- 




-- Locals:
-- =======

-- constants:
local MYADDON_NAME = "AKA";
local MYADDON_VERSION = "2.8";
local MYADDON_AUTHOR = "Schnoggo";
local MYADDON_EMAIL = "schnoggo@gmail.com";
local MYADDON_WEBSITE = "http://war-monkey.com/files/";
local OPTIONS_FRAME = "AKA_PrefsFrame";
local MSG_DELIMITER="`";
local REQ_TOKEN="R3Q";
local HEARTBEAT_INTERVAL = 3.0; -- how many seconds per heartbeat of our internal timer
local NOISE_THRESHHOLD = 2.5; -- how many seconds must pass before we consider the channel clear
local TRANSMIT_INTERVAL = .5; -- how many seconds between our own messages
local MSG_PREFIX = "AKAT2_";
local CHANNEL_PREFIX="<AKA_";
local GUILD_NOTE_STRINGS={};
GUILD_NOTE_STRINGS[0]="";       -- none,
GUILD_NOTE_STRINGS[1]='%s-(%a-)%A+.*$'; -- 1st word
GUILD_NOTE_STRINGS[2]='.*%((.*)%).-$';  -- parenthese
GUILD_NOTE_STRINGS[3]='.*%[(.*)%].-$';  --brackets
GUILD_NOTE_STRINGS[4]='[aA][lL][tT]%s+(%a-).-$'; --ALT primary char name
local BASE64={
"0","1","2","3","4","5",
"6","7","8","9","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",
"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","+","/"};
local BASE10={};


-- build reverse table for professions: (For compressing Profession skill names
AKA_ProfessionIndex = {};
for k, v in pairs (AKA_ProfessionList) do
  AKA_ProfessionIndex[v] = k;
end

-- build reverse table for races: (For compressing race names)
AKA_RaceIndex = {};
for k, v in pairs (AKA_RaceList) do
  AKA_RaceIndex[v] = k;
end



local MESSAGE_FORMAT=BASE64[1]; -- version 1

local messageFields={
"name",
"userid",
"nickname",
"class",
"race",
"guild",
"level",
"profession1",
"profession2",
"realm",
"zone",
"note"};


local displayFields={
"name","nickname","level","gender","race","class","prof1name", "prof1skill","prof2name","prof2skill", "zone"};

local tooltipFields={
"name","level","gender","race","class","prof1name", "prof1skill","prof2name","prof2skill", "zone"};
local tooltipDelimiters={
  ": ",    " ",     " ",   " ",    " ",        " ",          " ",         " ",        " ",     ""};

local daysAtyear={};
daysAtyear[2004]=-364;
daysAtyear[2005]=0;
daysAtyear[2006]=365;
daysAtyear[2007]=730;
daysAtyear[2008]=1095;
daysAtyear[2009]=1460;
daysAtyear[2010]=1824;
-- date stuff:
local wowEpoch=38; -- Nove 23, was 38 days from end of year 2004
local todayTable=date("*t");
local TODAY=daysAtyear[todayTable["year"]]+todayTable["yday"]+wowEpoch; -- days at year start + day-of-year
-- TODAY is an integer of days since game launch
-- if the user never logs out, calculating this only here could be a problem
local myPlayerRealm=GetCVar("realmName");
local myPlayerName=UnitName("player");
local myPlayerClassText, myPlayerClassType = UnitClass("player");
local myPlayerID=myPlayerName.."**"..myPlayerRealm;
local myPlayerZone="";
local myPlayerFaction, myLocalizedFaction=UnitFactionGroup("player"); 


local DEFAULT_COM_CHANNELS={};
DEFAULT_COM_CHANNELS["Guild"]={};
DEFAULT_COM_CHANNELS["Guild"]["active"]="yes";
DEFAULT_COM_CHANNELS["Raid"]={};
DEFAULT_COM_CHANNELS["Raid"]["active"]="no";
DEFAULT_COM_CHANNELS["Chat"]={};
DEFAULT_COM_CHANNELS["Chat"]["active"]="no";


local guildieNames={};
local guildiePlayers={};
-- default config settings   
local AKA_Defaults={};
                AKA_Defaults["MyToons"]={};
                AKA_Defaults["FriendToons"]={};
                AKA_Defaults["AKA_PrefsShowMeCheck"]=false;
                AKA_Defaults["realmchannels"]={};
--              AKA_Defaults["MyNickname"]="*pending*";
                AKA_Defaults["MyNickname"]=UnitName("player"); -- just to get them started

        
-- scoped vars:
local secondsSinceUpdate = 0;
local pendingSingleAnnounce=false;
local secondsUntilMyRequest = 0;
local secondsSinceLastMsg = 0;
local secondsSinceLastScreenDraw = 0;
local needHello=true;
local hasHookedChat=false;
local hasHookedCalendar=false;
local original_CalendarDayButton_OnEnter = nil;
local originalChatFrame_OnEvent = nil;
local hasHookedGatherer=false;
local originalGathererChat=nil;



-- gatherer chat function is Gatherer.Util.ChatPrint in GatherUtil.lua


local hasHookedChatLink=false;
local originalSetItemRef = nil;
local MessagesSentPerChannel={};
MessagesSentPerChannel["GUILD"]=0;
MessagesSentPerChannel["RAID"]=0;
MessagesSentPerChannel["PARTY"]=0;
MessagesSentPerChannel["WHISPER"]=0;

local MessagesRxPerChannel={};
MessagesRxPerChannel["GUILD"]=0;
MessagesRxPerChannel["RAID"]=0;
MessagesRxPerChannel["PARTY"]=0;
MessagesRxPerChannel["WHISPER"]=0;

local pendingRequests={};


local k,v;



-- My local functions:
-- ====================



local function UnpackProfession(packedProf)

-- AKA_ProfessionList

end

local function NoNull(inString)
        
        if (inString == nil) then
                return ""
        else
                return inString
        end
end


local function UpdateRadios()
        local guildNoteOption=AKA_SavedVars["MyToons"][myPlayerID]["guildnotes"];
        if (guildNoteOption==nil) then
                guildNoteOption=0;
        end
        for i = 0, 4 do
                if (i==guildNoteOption) then
                        getglobal("AKA_Prefs_RB"..i):SetChecked(true);
                else
                        getglobal("AKA_Prefs_RB"..i):SetChecked(false);
                end
                i=i+1;
        end
end


function tcount(tab)
   local n=0;
   local k,v;
   for k,v in pairs(tab) do
     n=n+1;
   end
   return n;
 end


local function Dec2BASE64(inDec)
-- Convert numeric value into Base64 string
-- Inputs: 
--   inDec - INT *NOTE* This MUST be an integer in this implementation
-- Outputs:
--   return numeric value
local outStr="";
local tDec = inDec; -- make a copy to destroy
local rem,dig;
        while (tDec>63) do
                rem=mod(tDec, 64);
                dig=BASE64[rem+1];
                outStr=dig..outStr;
                tDec=tDec-rem;
                tDec=tDec/64;
        end

        dig=BASE64[tDec+1];
        outStr=dig..outStr;
        return outStr;

end

local function BASE642Dec(in64)
-- Convert Base64 string into decimal number
-- Inputs: 
--   in64 - STR
-- Outputs:
--   return numeric value

local res=0;
local len=strlen(in64);

        for i=1, len do
                res=res+BASE10[strsub(in64, i, i)];
                if (i ~= len) then
                        res=res*64;
                end
        end

        return res;
end

local function InitMath()
-- Creates reverse lookup table for Base64 routines
-- BASE64 must be created and populated
-- BASE10 must be declared and scoped
-- populates BASE10
        BASE10={};
        for i=1, 64 do
                BASE10[BASE64[i]]=i-1;
        end
end

local function GenerateUSERID()
-- UserId format is 
-- char 1 - flags (None defined, current value must be 0)
-- chars 2-6 Base64 digits (this yields slightly over 1 billion possibilities. Close enough to unique for our purposes)
        local outStr="0"; -- noflags currently defined
        for i = 1, 5 do
                outStr=outStr..BASE64[random(64)];
        end
        return outStr;
end





local function ShowSpells()
AKA_SpellBookList={};
    local i = 1
        while true do
           local spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL)
           if not spellName then
                  do break end
           end
           table.insert(AKA_SpellBookList,"'"..spellName .."'".. "(" .. spellRank .. ")");
        DEFAULT_CHAT_FRAME:AddMessage( "'"..spellName .."'".. "(" .. spellRank .. ")" );
        i = i + 1
        end
end



local function GetNickname(visibleName, noColor)
-- Return a nickname string in parenthesis if one should be displayed
-- nickame contains color codes from CleanChat if available
-- the optional {noColor} parameter will return the nickname without color codes if present
-- This function is global in case other mods want to call it

        local speakerID=visibleName.."**"..myPlayerRealm;
        local speakerNick="";
        if ((speakerID ~= myPlayerID) or (AKA_SavedVars["AKA_PrefsShowMe"]) ) then -- Only show our own name if set in preferences
                if (AKA_SavedVars["FriendToons"] == nil) then
                        FixDefaults(); -- needs to be an array
                end
                if (AKA_SavedVars["FriendToons"][speakerID]) then -- if there is an entry for this person
                        local speakerRec=AKA_SavedVars["FriendToons"][speakerID];
                        speakerNick=speakerRec["nickname"];
                else -- no FriendToons entry for this player, try the guild notes
                        if (guildieNames[visibleName]) then -- if there is an entry for this person
                                speakerNick=guildieNames[visibleName];
                        end
                end -- was an entry for this speaker
        end -- skip our own name?


        if ((speakerNick ~= "") and (speakerNick~=visibleName) and (noColor==nil)) then
                if (CleanChat_GetColorFor) then -- if cleanchat colors are available then use those
                        speakerNick=CleanChat_GetColorFor(visibleName) .."("..speakerNick..")|r";
                else
                        speakerNick="|c909090FF("..speakerNick..")|r ";
                end
        end -- something we want to change for speakerNick
        return speakerNick;
end




-- function AKA_AddMessage(this, msg, r, g, b, id) -- this, msg, r, g, b, id
--      -- arg[1]=arg[1].."!!";
--      if (msg ~= nil) then
--      msg=msg.."!!";
--      end
--                      this:AKA_AddMessage_Orig(this, msg, r, g, b, id) 
                        
 -- local rettab = { this:AKA_AddMessage_Orig(unpack(arg)) }
   -- return unpack(rettab);
  
-- end





local function ParseMessage(msg, whoSent, whichChannel)

-- whichChannel = "PARTY", "RAID", "GUILD", "BATTLEGROUND", "WHISPER" or chat channel name
-- Split each comma separated element into individual Tokens
-- so that they can be handled properly

-- local messageFields={
-- "name", "class", "race", "guild", "level", "prof1name", "prof1skill", 
-- "prof2name", "prof2skill", "note"};

-- update the list of speakers to mark that this person has AKA:
        if (AKA_SessionList[whoSent] ~= nil) then
                AKA_SessionList[whoSent]['status']='available';
                AKA_SessionList[whoSent]['lastcontact']=GetTime(); -- seconds
                AKA_SessionList[whoSent]['channelList'][whichChannel]=true;             
        else
                AKA_SessionList[whoSent]={};
                AKA_SessionList[whoSent]['status']='available'; -- 'unknown' when first seen, 'na' if request has timed out, 'available' if AKA request has been answered
                AKA_SessionList[whoSent]['lastcontact']=GetTime(); -- seconds
                AKA_SessionList[whoSent]['channelList']={};
                AKA_SessionList[whoSent]['channelList'][whichChannel]=true;             
                AKA_SessionList[whoSent]['bestchannel']=whichChannel;
        end     


        AKA_ErrorMsg("ParseMessage("..msg..","..whoSent..", "..whichChannel..")");
        local pString =msg; -- make a copy to take apart
        -- pString="hoser`dude`hooman`flying monkeys`2`sproting`1`dancing`300`the coolist dud in the wowerzerverserse.";
        local dashOffset=string.find(whoSent, "-");
        local senderID=whoSent.."**"..myPlayerRealm;
        if (dashOffset ~= nil) then
                -- battlegroup format with dash:
                senderID=string.gsub(whoSent,"\-","**");
        end
        AKA_ParsedMsg={};

        for count = 1, table.getn(messageFields) do
                commaIndex = string.find(pString, MSG_DELIMITER);
                local thisFieldName=messageFields[count];
                if (commaIndex) then
                        AKA_ParsedMsg[thisFieldName] = strsub(pString, 1, commaIndex - 1);
                        pString = strsub(pString, commaIndex + 1);
                         AKA_ErrorMsg("parsed: "..thisFieldName.."->"..AKA_ParsedMsg[messageFields[count]]);
                else -- last entry
                        AKA_ParsedMsg[thisFieldName] = pString;
                        -- AKA_ErrorMsg(AKA_ParsedMsg[messageFields[count]]);
                        break;
                end
        end
        if (AKA_SavedVars["FriendToons"] == nil) then
                AKA_SavedVars["FriendToons"]={};
        end
        local altID="";
        if ((AKA_ParsedMsg["realm"] == nil) or (AKA_ParsedMsg["realm"] == "")) then
                 altID=AKA_ParsedMsg["name"].."**"..myPlayerRealm;
         else
                altID=AKA_ParsedMsg["name"].."**"..AKA_ParsedMsg["realm"];
        end
        
        
        
        -- AKA_SavedVars["FriendToons"][whoSent.."**"..myPlayerRealm]=AKA_ParsedMsg; -- save the parsed table in FriendToons
        if (altID == senderID) then
                AKA_ParsedMsg["firsthand"]=true;
        else
                AKA_ParsedMsg["firsthand"]=false;
        end
        if (AKA_ParsedMsg["profession1"] ~= nil) then
                AKA_ParsedMsg["prof1name"]=AKA_ProfessionList[strsub(AKA_ParsedMsg["profession1"], 1, 1)];
                AKA_ParsedMsg["prof1skill"]=BASE642Dec(strsub(AKA_ParsedMsg["profession1"], 2, 3));
        end                     
        if (AKA_ParsedMsg["profession1"] ~= nil) then
                AKA_ParsedMsg["prof2name"]=AKA_ProfessionList[strsub(AKA_ParsedMsg["profession2"], 1, 1)];
                AKA_ParsedMsg["prof2skill"]=BASE642Dec(strsub(AKA_ParsedMsg["profession2"], 2, 3));
        end
        
        if (AKA_ParsedMsg["race"] ~= nil) then
                if (strlen(AKA_ParsedMsg["race"])>1) then -- upacked version of race
                else
                        -- needs unpacking
                        local raceSexValue=BASE642Dec(AKA_ParsedMsg["race"]);
                        -- thisToon["race_sex"]=((gender-1)*16)+raceValue;      
                        local raceValue = mod(raceSexValue, 16);
                        local sexValue= (raceSexValue-raceValue)/16;
                        AKA_ParsedMsg["race"]=AKA_RaceList[raceValue];
                        if (sexValue == 0) then -- "unknown"
                                AKA_ParsedMsg["gender"]="";
                        else
                                AKA_ParsedMsg["gender"]=AKA_GenderList[sexValue+1];
                        end
                end -- race is packed
        end -- race not nil
        
        
        -- altID=AKA_ParsedMsg["userid"];
        AKA_ParsedMsg["lastupdate"]=TODAY;
        AKA_SavedVars["FriendToons"][altID]=AKA_ParsedMsg; -- save the parsed table in FriendToons
        AKA_ErrorMsg("from:"..whoSent..msg);
        if (AKA_ParsedMsg["userid"] ~= nil) then
                AKA_LastSeen[AKA_ParsedMsg["userid"]]={["name"]=whoSent,["time"]=GetTime()};
        end
        AKA_ToonListDirty=true; -- we have new data to display
end







-- local minimapzonetext = GetMinimapZoneText();
-- if GetNumRaidMembers()>0 then


local function UpdateMyData()
        local guildName, guildRankName, guildRankIndex = GetGuildInfo("player");
        local level= UnitLevel("player");
        local race = UnitRace("player");
        local raceNum=AKA_RaceIndex[race];
        local raceValue=BASE642Dec(raceNum);
        local gender=UnitSex("player"); -- 1=unknown,2=male,3=female as of 1.10
        local genderText=AKA_GenderList[gender];
        local englishFaction, toss =UnitFactionGroup("player"); -- we are just comparing, so English will be used
        local thisToon={};
        thisToon["name"]=myPlayerName;
        thisToon["realm"]=myPlayerRealm;
        thisToon["class"]=myPlayerClassText;
        thisToon["race"]=race;
        thisToon["guild"]=guildName;
        thisToon["level"]=level;
        thisToon["race"]=race;
        thisToon["raceNum"]=raceNum;
        thisToon["faction"]=englishFaction;
        thisToon["gender"]=genderText;
        thisToon["race_sex"]=Dec2BASE64(((gender-1)*16)+raceValue);     
        
        if (AKA_SavedVars["MyToons"]) then
                if (AKA_SavedVars["MyToons"][myPlayerID]) then
        
                        -- copy over per-toon preferences:
                        if (AKA_SavedVars["MyToons"][myPlayerID]["guildnotes"]) then
                                thisToon["guildnotes"]=AKA_SavedVars["MyToons"][myPlayerID]["guildnotes"];
                        else
                                thisToon["guildnotes"]=0;
                        end
                
                        if (AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]) then
                                thisToon["com_channels"]=AKA_SavedVars["MyToons"][myPlayerID]["com_channels"];
                        else
                                thisToon["com_channels"]=DEFAULT_COM_CHANNELS;
                        end
                else
                        thisToon["guildnotes"]=0;
                        thisToon["com_channels"]=DEFAULT_COM_CHANNELS;
                end
                
        else
                thisToon["guildnotes"]=0;
                thisToon["com_channels"]=DEFAULT_COM_CHANNELS;
        end
        
        
        
        
        if (myPlayerZone=="") then
                myPlayerZone=GetRealZoneText(); -- GetMinimapZoneText();
        end
        
        thisToon["zone"]=myPlayerZone;  
        
        -- Get trade skill information:
        local professionCount=1;
        local skillCategory="";
        for i=1, GetNumSkillLines() do
                
                local skillName, isHeader, isExpanded, skillRank, numTempPoints, skillModifier, skillMaxRank, isAbandonable, stepCost, rankCost, minLevel, skillCostType, skillDescription = GetSkillLineInfo(i);
                if (skillName) then
                -- DEFAULT_CHAT_FRAME:AddMessage("skill:"..skillName.." "..skillRank.."type:"..skillCostType, 0.5, 1.0, 0.5, 3);
                        if (isHeader) then
                                skillCategory=skillName;
                        else
                                if (skillCategory == "Professions") then
                                thisToon["prof"..professionCount.."name"]=skillName;
                                thisToon["prof"..professionCount.."num"]=AKA_ProfessionIndex[skillName];
                                thisToon["prof"..professionCount.."skill"]=skillRank;
                                -- DEFAULT_CHAT_FRAME:AddMessage("skill:"..skillName.." "..skillRank, 0.5, 1.0, 0.5, 3);
                                professionCount=professionCount+1;
                                
                                end
                        
                        end
                        
                end -- testing for nil skill
        end -- for loop
        
        -- Now step through spell book and check for trade skill specializations:
        local p1=thisToon["prof1num"];
        if (p1 == nil) then
                p1="";
        end
        local p2=thisToon["prof2num"];
        if (p2 == nil) then
                p2="";
        end
        local pRank1=0;
        local pRank2=0;
        local thisSpellNumber="";
        if ((p1 ~= "") or (p2 ~= "")) then -- only test specialization if necessary
                
                local i = 1
                while true do
                   local spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL)
                   if not spellName then
                          do break end
                   end
                   thisSpellNumber=AKA_ProfessionIndex[spellName];
                   if (( thisSpellNumber ~= nil) and (AKA_ProfSpecialMap[thisSpellNumber] ~= nil)) then
                                -- DEFAULT_CHAT_FRAME:AddMessage( "thisSpellNumber="..thisSpellNumber.." Special= "..AKA_ProfessionList[thisSpellNumber]);

                                local tList=AKA_ProfSpecialMap[thisSpellNumber];
                                
                                if ((tList[1]==p1) and (tList[2]>pRank1)) then
                                        thisToon["prof1num"]=thisSpellNumber;
                                        pRank1=tList[2];
                                        -- DEFAULT_CHAT_FRAME:AddMessage( "upgrading skill "..thisToon["prof1name"].." to "..AKA_ProfessionList[thisSpellNumber]);

                                end
                                if ((tList[1]==p2) and (tList[2]>pRank2)) then
                                        thisToon["prof2num"]=thisSpellNumber;
                                        pRank2=tList[2];
                                        -- DEFAULT_CHAT_FRAME:AddMessage( "upgrading skill "..thisToon["prof2name"].." to "..AKA_ProfessionList[thisSpellNumber]);
                                end
                        
                        end                     
                
                
                i = i + 1
                end
        end -- p1,p1 ~= nil
        
        
        
        
        if (AKA_SavedVars["MyToons"] == nil) then
        AKA_SavedVars["MyToons"]={};
        end
        
        AKA_SavedVars["MyToons"][myPlayerID]=thisToon;


-- local myPlayerRealm=GetCVar("realmName");
-- local myPlayerName=UnitName("player");
-- local myPlayerClassText, myPlayerClassType = UnitClass("player");
-- local myPlayerID=myPlayerName.."**"..myPlayerRealm;

end





local function TransmitMyData(destToon)
-- transmit the data for this toon?
        local myNickname=AKA_SavedVars["MyNickname"];
        if ((myNickname=="*pending*") or (myNickname ==nil)) then
                -- they have not set up the system yet - we should warn them.
        else
                local toonIndex=0;
                local fieldCount=0;
                local thisID="";
                local thisRecord={};
                local myToonList=AKA_SavedVars["MyToons"];
           local k,v;

                AKA_SuperToonList=AKA_SavedVars["MyToons"];
                if (myToonList == nil) then
                -- something is wrong. we should have at least the current toon on file
                AKA_ErrorMsg("No toons on file.");
                
                else
                        -- AKA_ErrorMsg("Toon count = "..table.getn(myToonList));
                        -- if (table.getn(myToonList)>0) then -- make sure somethign is in the table before iterating
                                -- for toonIndex = 1, table.getn(myToonList) do
                                
                                
                        for k,v in pairs(myToonList) do 
                                local outStr,fieldValue;
                                if ((v["faction"] == myPlayerFaction) and (v["realm"]==myPlayerRealm)) then
                                        outStr="";
                                        AKA_ErrorMsg(k..":"..v["name"]);
                                        
                                        for fieldCount = 1, table.getn(messageFields) do
                                                -- AKA_ErrorMsg(fieldCount.."->"..messageFields[fieldCount]);
                                                fieldName=messageFields[fieldCount];
                                                fieldValue=v[fieldName];
                                                if (fieldName == "nickname") then
                                                        fieldValue=myNickname;
                                                end
                                                
                                                if (fieldName == "race") then
                                                        if (v["race_sex"] ~= nil) then
                                                                fieldValue=v["race_sex"]; 
                                                        end
                                                end
                                                
                                                if (fieldName == "profession1") then
                                                        if (v["prof1num"] ~= nil) then
                                                                fieldValue=v["prof1num"]..Dec2BASE64(v["prof1skill"]);
                                                        else                                                    
                                                                if (v["prof1name"] == nil) then
                                                                        fieldValue="";
                                                                else
                                                                        fieldValue=AKA_ProfessionIndex[v["prof1name"]]..Dec2BASE64(v["prof1skill"]);
                                                                end
                                                        end -- prof1num
                                                end -- profession1
                                                
                                                if (fieldName == "profession2") then
                                                        if (v["prof2num"] ~= nil) then
                                                                fieldValue=v["prof2num"]..Dec2BASE64(v["prof2skill"]);
                                                        else
                                                                if (v["prof2name"] == nil) then
                                                                        fieldValue="";
                                                                else
                                                                        fieldValue=AKA_ProfessionIndex[v["prof2name"]]..Dec2BASE64(v["prof2skill"]);
                                                                end
                                                        end -- prof2num
                                                end -- profession2
                                                
                                                if (fieldName == "userid") then
                                                        fieldValue=AKA_USERID;
                                                end
                                                
                                                if (fieldValue==nil) then
                                                        outStr=outStr..MSG_DELIMITER;
                                                else
                                                        outStr=outStr.. fieldValue..MSG_DELIMITER;
                                                end
                                                
                                        end -- for fieldCount
                                        AKA_SendMsg(outStr,destToon);
                                end -- faction & realm match
                        end -- pairs

        
                                
                        -- end -- if >0 toons
                end -- if (myToonList == nil)
        end
        AKA_SendVersion();
end






 
 
 
local function DrawScrollContents(topline)
-- Doesn't actually DRAW the contents?
-- Just returns a table items to be placed the buttons used for the Faux Scroller 
 -- Inputs: AKA_SavedVars["FriendToons"]
 -- outputs:
 --   AKA_BIGLIST -- linnear list of content lines for the scroller
 --   AKA_BIGKEY -- list of toonIDs being displayed in the scroller, indexed by toonID
 -- AKA_BIGIDS -- list of friend ID in {name}**{realm} format
 
        local lineCount = 1;
        local toonList = AKA_SavedVars["FriendToons"];
        local toonKey={};
        local toonAlts={};
        local filtered;
        local k,v;
         if (topline == nil) then
                topline=1;
         end
         -- step one: build a key of known toons:
 


        AKA_BIGLIST={};
        AKA_BIGKEY={};
        AKA_BIGIDS={};
        
        
        
        if (toonList == nil) then
                -- AKA_PrefsNickList:SetText("No nicknames known.");=
        else
                local listText="";
                -- table.foreach(toonList, function(k,v)
                for k,v in pairs(toonList) do 
                        -- if (v["userid"] ~= nil) then
                        --      DEFAULT_CHAT_FRAME:AddMessage( v["name"].."   "..v["userid"].."  "..v["realm"]);
                        -- else
                        --      DEFAULT_CHAT_FRAME:AddMessage( v["name"].."   "..v["realm"]);
                        -- end
                                -- if ((v["realm"] == myPlayerRealm) and (v["faction"] == myFaction)) then -- displayable for this toon
                                if ((v["realm"] == myPlayerRealm) ) then 
                                        local thisToonID=v["userid"];
                                        if (thisToonID ~= nil)  then
                                                if (lineCount>= topline) then
                                                        if (AKA_BIGKEY[thisToonID] == nil) then -- create an index:
                                                                local nick=v["nickname"];
                                                                if (nick == nil) then
                                                                        nick="NO NICKNAME";
                                                                end
                                                                table.insert(AKA_BIGLIST,"|cFF8080FF"..nick.."|r: ");
                                                                AKA_BIGKEY[thisToonID]=table.getn(AKA_BIGLIST);
                                                                table.insert(AKA_BIGIDS,v["name"].."**"..v["realm"])
                                                                
                                                        end
                                                        local thisToonName=v["name"];
                                                        if (thisToonName == nil) then
                                                                thisToonName="NO NAME";
                                                        end
                                                        -- if (UnitIsConnected(thisToonName)) then
                                                        -- thisToonName
                                                        -- else
                                                        local thisToonNameText=thisToonName;
                                                        if (AKA_LastSeen[thisToonID] ~= nil) then
                                                                if (AKA_LastSeen[thisToonID]["name"]==thisToonName) then
                                                                        thisToonNameText="|cFFFFCC00["..thisToonNameText.."]|r";
                                                                end
                                                        end
                                                        local oStr=AKA_BIGLIST[AKA_BIGKEY[thisToonID]];
                                                        if (strsub(oStr,-1) ~= " ") then
                                                                oStr=oStr..", ";
                                                        end
                                                                AKA_BIGLIST[AKA_BIGKEY[thisToonID]]=oStr..thisToonNameText;
                                                        -- end
                                                end -- toonID not nil
                                        end -- within the display range? (topline)
                                end -- realm/action filter
                        lineCount = lineCount+1;                
                end -- pairs (toonList)

        end -- toonlist == nil
 
         -- at this point AKA_BIGLIST is a linear array of toons info strings
 end
 
 

local function FixDefaults()
-- inputs:
-- AKA_SavedVars
-- ouputs:
-- AKA_SavedVars

        if not (AKA_SavedVars) then
                AKA_SavedVars = {};
                AKA_SavedVars=AKA_Defaults;
                AKA_SavedVars["Version"]=AKA_SavedVars;
                AKA_SavedVars["FormatVersion"]=AKA_FormatVersion;
                DEFAULT_CHAT_FRAME:AddMessage("AKA loading defaults.", 0.5, 1.0, 0.5, 3);
                
        end
                
        if (AKA_SavedVars["FormatVersion"] == nil) then
                AKA_SavedVars["FormatVersion"]=AKA_FormatVersion;
        end
        
        if (AKA_SavedVars["FormatVersion"] < AKA_FormatVersion) then
        -- convert from ealier format
        -- 1st version so nothing to do here yet
                 if (AKA_SavedVars["FormatVersion"] == 1.1) then
                        DEFAULT_CHAT_FRAME:AddMessage("AKA version change. converting character data.", 0.5, 1.0, 0.5, 3); 
                 
                 else
                        
                        if (AKA_SavedVars["FormatVersion"] < 1.01) then
                                DEFAULT_CHAT_FRAME:AddMessage("AKA database change from 1.0. Erasing old data. Sorry for the inconvenience.", 0.5, 1.0, 0.5, 3);
                                local tempNick=AKA_SavedVars["myNickName"]
                                AKA_SavedVars = {};
                                AKA_SavedVars=AKA_Defaults;
                                AKA_SavedVars["Version"]=AKA_Version;
                                AKA_SavedVars["myNickName"]=tempNick;
                                UpdateMyData();
                        end
                end
                AKA_SavedVars["FormatVersion"]=AKA_FormatVersion;
        end
        
        
        if ((AKA_SavedVars["FriendToons"] == nil) or (AKA_SavedVars["FriendToons"] == {})) then
                local fToons={};
                AKA_SavedVars["FriendToons"] =fToons;
        end
        
        if ((AKA_SavedVars["MyNickname"] == nil) or (AKA_SavedVars["MyNickname"] == "")) then   
                AKA_SavedVars["MyNickname"] =myPlayerName;
        end


        -- updateMyData must be last since it actually uses some of the above fields
        if (AKA_SavedVars["MyToons"][myPlayerID] == nil) then
                UpdateMyData();
        end     
        
        if (AKA_SavedVars["MyToons"][myPlayerID]["guildnotes"] == nil) then
                AKA_SavedVars["MyToons"][myPlayerID]["guildnotes"]=0;
        end
        
        
        if (AKA_SavedVars["MyToons"][myPlayerID]["com_channels"] == nil) then
                DEFAULT_CHAT_FRAME:AddMessage("AKA Communications preferences set to defaults.", 0.5, 1.0, 0.5, 3);
                AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]=DEFAULT_COM_CHANNELS;
        end
        if (AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]["Raid"] == nil) then
                DEFAULT_CHAT_FRAME:AddMessage("AKA Communications preferences set to defaults.", 0.5, 1.0, 0.5, 3);
                AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]=DEFAULT_COM_CHANNELS;
        end
        

        
end


-- Guild Functions:
local function UpdateGuildNotes()
         -- AKA_SavedVars["MyToons"][myPlayerID]["guildnotes"]=arg1; -- 0=no, 1=1st word, 2=(), 3=[]
         local guildNoteExp="";
         local guildNoteOption=AKA_SavedVars["MyToons"][myPlayerID]["guildnotes"];
         if (guildNoteOption ==nil) then 
                 guildNoteOption=0;
         end
         guildNoteExp=GUILD_NOTE_STRINGS[guildNoteOption];
        guildieNames={};
        guildiePlayers={};
        if (guildNoteOption>0) then
                local name, rank, rankIndex, level, class, zone, note, officernote, online, status;
                local guildNick, matchcount;
                local numGuildMembers = GetNumGuildMembers();
                        for     i=1, numGuildMembers do
                                note = ""; 
                                officernote = "";
                                name, rank, rankIndex, level, class, zone, note, officernote, online, status = GetGuildRosterInfo(i);
                                
                                guildNick, matchcount=string.gsub(note, guildNoteExp, "%1");
                                if (matchcount>0)then
                                        -- DEFAULT_CHAT_FRAME:AddMessage(name..","..guildNick, 0.5, 1.0, 0.5, 3); 
                                        guildieNames[name]=guildNick;
                                end
                        end
        end -- guildNoteOption>0

end
    
  
  
        
-- Tooltip (Chat):
-- ---------------


local function ShowWhoTooltip2()

-- this will be the one called by the regular /who event
        --[[if (numWhos > 0) then
                for i=1, numWhos do
                        name, guild, level, race, class, zone, group = GetWhoInfo(i);
                        if (name == AKA_LinkedName) then
                                foundAWho=true;
                                break;
                        end
                end ]]--
                -- if (follow_mouse) then
                --      GameTooltip:SetOwner(UIParent, "ANCHOR_CURSOR");
                -- else
                        GameTooltip_SetDefaultAnchor(GameTooltip, UIParent);
                -- end
                
                -- at this point:
                -- name, guild, et al = the info for the clicked-on player
                
--              local speakerID=name.."**"..myPlayerRealm;
end



local function ShowWhoTooltip() 
        local numWhos, totalCount = GetNumWhoResults(); -- numWhos is # of results returned (max 49). totalCount is matches on server
        local name, guild, level, race, class, zone, group;
        local foundAWho=false;
        local outStr="";
        local speakerRec=nil;
        local linkedNickname=nil;
        local altTable={};
        local toonAlts={};
        local fieldCount
        
        if (numWhos > 0) then
                for i=1, numWhos do
                        name, guild, level, race, class, zone, group = GetWhoInfo(i);
                        if (name == AKA_LinkedName) then
                                foundAWho=true;
                                break;
                        end
                end
                -- if (follow_mouse) then
                --      GameTooltip:SetOwner(UIParent, "ANCHOR_CURSOR");
                -- else
                        GameTooltip_SetDefaultAnchor(GameTooltip, UIParent);
                -- end
                
                -- at this point:
                -- name, guild, et al = the info for the clicked-on player
                
                local speakerID=name.."**"..myPlayerRealm;
        
                if (AKA_SavedVars["FriendToons"] == nil) then -- repair FriendToons if necessary
                        AKA_FixDefaults();
                end
                if (AKA_SavedVars["FriendToons"][speakerID]) then -- if there is an entry for this person
                        speakerRec=AKA_SavedVars["FriendToons"][speakerID];
                        if ((speakerRec["nickname"] ~= "")  and (speakerRec["nickname"] ~= nil)) then -- there is a nickname
                                linkedNickname=speakerRec["nickname"] ;
                        end -- there is a nickname
                                                        
                -- build a structure of alts
                
                
                
                
                local toonList = AKA_SavedVars["FriendToons"];
                local toonKey={};
        
                 if (toonList == nil) then
                        -- we are done
                                
                else
                        table.insert(toonAlts,"AKA:\"|c9090FFFF"..linkedNickname.."\"|r");
                        for k,v in pairs(toonList) do 
                                if (((v["faction"] == myPlayerFaction) and (v["realm"]==myPlayerRealm)) or (v["faction"] == nil) or (v["realm"] == nil)) then
                                        
                                        AKA_ErrorMsg(k..":"..v["name"]);
                                        if (v["nickname"] == linkedNickname) then
                                                local thisToonText = "";
                                                for fieldCount = 1, table.getn(tooltipFields) do -- tooltipDelimiters
                                                        local fieldName=tooltipFields[fieldCount];
                                                        local fieldValue=v[fieldName];
                                                                if ((fieldValue ~= nil) and (fieldValue ~= "")) then -- if no value, skip
                                                                        thisToonText=thisToonText.. fieldValue..tooltipDelimiters[fieldCount];
                                                                end     
                                                end -- for fieldCount
                                                table.insert(toonAlts,thisToonText);
                                        end -- nickname matches
                                 end -- meets factio/realm criteria
                        end -- pairs (toonList)
                        
                end -- toonlist == nil
        
        end -- there are alts to check
        
        
        AKA_TAL=toonAlts; -- debugging
        
        
        
        
        
        GameTooltip:AddLine(name, .6,1.0,.8); -- GameTooltip:AddLine(name, GameTooltip_UnitColor("player"));            
                if (guild == "") then
                outStr=outStr.."Level "..level.." "..race.." "..class.." - "..zone;
                
                else
                        outStr=outStr.."Level "..level.." "..race.." "..class.." <"..guild.."> - "..zone;
        -- GameTooltip:AddLine("<"..guild..">", 1, .8, 0);
                end
                GameTooltip:AddLine(outStr, 1, 1, 1);

                -- GameTooltip:AddLine(zone, 1, 1, 1);
-- WHO_LIST_FORMAT                      %s : Level %d %s %s - %s                "Lonk: Level 21 Troll Hunter - Undercity"
-- WHO_LIST_GUILD_FORMAT        %s : Level %d %s %s <%s> - %s   "Rumplestump: Level 60 Gnome Rogue - Iron Forge"

   if (table.getn(toonAlts))>0 then
           for fieldCount = 1, table.getn(toonAlts) do
                 GameTooltip:AddLine(toonAlts[fieldCount], .8, .8, 1.8);
                end -- for fieldCount
    end
    
                GameTooltip:Show();
--       GameTooltip:FadeOut();
        end -- there was a /who response to show
        
end
        
        
function AKA_SetItemRef (link, text, button)
-- Get hooked into chat links
-- keeping it global on purpose...


        AKA_LinkedName="";      
        if (strsub(link, 1, 6) == "player") then -- "player:{plaeryname}"
                local namelink = strsub(link, 8);
                local name, lineid = strsplit(":", namelink);
--              local name = strsub(link, 8);
                if ( name and (strlen(name) > 0) ) then
                        if ( IsShiftKeyDown() ) then
                                 AKA_LinkedName = name;
                                
                                        --ShowWhoTooltip(name);
                                --AKA_LinkedName=""; -- tip has been shown. move along
                        end
                end
        end
        -- if (AKA_LinkedName=="") then
                originalSetItemRef(link, text, button); -- always pass through
--      end
        
end


    
    
    
    


    

-- GLOBAL FUNCTIONS
--  __     _   _              _           _ ___ ___  _        __ 
-- /__ |  / \ |_)  /\  |     |_ | | |\ | /   |   |  / \ |\ | (_  
-- \_| |_ \_/ |_) /--\ |_    |  |_| | \| \_  |  _|_ \_/ | \| __) 
--

function AKA_ChatModder(this, event, arg1, arg2, ...)
local arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11 = ...;

-- arg1 = event
-- arg2 = speaker (usually)
 local killEvent=false;
         AKA_LASTEVENT=event;
         if ((event == "CHAT_MSG_CHANNEL") or (event == "CHAT_MSG_GUILD")  or (event == "CHAT_MSG_RAID") or (event == "CHAT_MSG_PARTY")) then
                if ((arg1 ~= nil)  and (arg2 ~= nil))then
                        if (strsub(arg1, 1, 5) == CHANNEL_PREFIX) then
                                killEvent=true; -- toss it
                        else            
                                if (strsub(arg1, 1, 4) ~= "<GEM")  then -- test for non-chat stuff
                                        arg1=GetNickname(arg2)..' '..arg1;      
                                end -- not GEM 
                        end -- toss <AKA messages
                end -- event args not nil
        end -- event
        if (killEvent == true) then
                -- don't pass it along the chain
        else
                originalChatFrame_OnEvent(this, event, arg1, arg2, ...);
        end   
end




function AKA_GathererModder(msg)
                --[[
                --"Received gather of %1 in %2 from %3 (%4)"
function Gatherer.Util.ChatPrint(str)
        if ( DEFAULT_CHAT_FRAME ) then
                DEFAULT_CHAT_FRAME:AddMessage(str, 1.0, 0.5, 0.25)
        end
end
]]--
        local pName=string.gsub(msg,".* from (.-) .*","%1");
        local nickName=GetNickname(pName)
        if (nickName ~= '') then
                local repstring=' from '..pName..' '..nickName..' ';
                local str=string.gsub(msg," from %a+ ",repstring);
                if ( DEFAULT_CHAT_FRAME ) then
                        DEFAULT_CHAT_FRAME:AddMessage(str, 1.0, 0.5, 0.25)
                end
        end
end


        
-- TIMERS
-- ===================
function AKA_OnUpdate(elapsed)
        secondsSinceLastMsg = secondsSinceLastMsg + elapsed;    
        secondsSinceUpdate = secondsSinceUpdate + elapsed;      
        secondsSinceLastScreenDraw = secondsSinceLastScreenDraw + elapsed; 
        if (secondsSinceUpdate > HEARTBEAT_INTERVAL) then -- time to do stuff!
        
        
--              local p=" ("..secondsSinceLastMsg..")";
--              if (tcount(pendingRequests)>0) then -- there are any elements in the pendingRequests array
--              DEFAULT_CHAT_FRAME:AddMessage("pending requests: "..tcount(pendingRequests), 1, .2, .2, 1); 
--                      p=p.." pendingRequests ";
--              end
--              if (pendingSingleAnnounce) then
--                      p=p.." pendingSingleAnnounce ";
--              end
                

-- DEFAULT_CHAT_FRAME:AddMessage("pending requests: "..p, 1, .2, .2, 1); 
-- local pendingRequests = false;
-- local secondsUntilMyRequest = 0;
                local k,v;
                for k,v in pairs(pendingRequests) do
                -- DEFAULT_CHAT_FRAME:AddMessage("AKA_OnUpdate sending to: "..k, 1, .2, .2, 1); 
                if (v==true) then               
                        if ((k=="GUILD") or (k=="PARTY") or (k=="RAID")) then
                                        local chanType=k;
                                        if ((k=="PARTY") and (UnitInRaid("player")==1)) then
                                                chanType="RAID";
                                        end
                                        if (secondsSinceLastMsg>NOISE_THRESHHOLD) then
                                                -- channel is clear
                                                TransmitMyData(chanType);
                                                -- pendingRequests{k}=false; -- no longer needede since we now wipe the queue whe we're done
                                        end
                        else
                                        -- whisper
                                        if (secondsSinceLastMsg>NOISE_THRESHHOLD) then
                                                -- channel is clear
                                                TransmitMyData(k);
                                                -- pendingRequests{k}=false; -- no longer needede since we now wipe the queue whe we're done
                                        end
                        end -- whisper
                end

                
                        
                end -- loop through pending requests
                pendingRequests={}; -- assume all requests have been handled
        
--              if (secondsSinceLastMsg>NOISE_THRESHHOLD) then
--                      -- channel is clear
--                      TransmitMyData();
--              end
                        

                if (needHello) then
                        UpdateMyData();
                        AKA_RequestSync();
                        needHello=false;
                end
                
                if ((pendingSingleAnnounce==true) and (secondsSinceLastMsg>NOISE_THRESHHOLD)) then
                        -- AKA_TransmitOneToon(myPlayerID);
                        TransmitMyData(); -- go with the overkill model for now
                        pendingSingleAnnounce=false;
                end

                
                
                -- test to see if we have hooked the chat window yet.
                if (hasHookedChat == false) then
                        if (ChatFrame_OnEvent ~= AKA_ChatModder) then
                                originalChatFrame_OnEvent = ChatFrame_OnEvent; --hooked
                                ChatFrame_OnEvent=AKA_ChatModder;
                        end
                hasHookedChat=true;
                end
                
                
                -- test to see if we have hooked the chat link yet.
                if (hasHookedChatLink == false) then
                        if (SetItemRef ~= nil) then
                                if (SetItemRef ~= AKA_SetItemRef) then
                                        originalSetItemRef = SetItemRef; --hooked
                                        SetItemRef=AKA_SetItemRef;
                                        hasHookedChatLink=true;
                                        --DEFAULT_CHAT_FRAME:AddMessage("who hooked", 1.0, 0.5, 0.25)
                                else
                                --      DEFAULT_CHAT_FRAME:AddMessage("who good", 1.0, 0.5, 0.25)
                                end
                        else
                                --DEFAULT_CHAT_FRAME:AddMessage("who not avail", 1.0, 0.5, 0.25)
                        end
                        
                end
                secondsSinceUpdate = 0;
                
                
                
                -- test to see if we have hooked Gatherer yet.
                if (hasHookedGatherer == false) then -- add preference check here eventually
                        if (Gatherer) then
                        -- check for older Gatherer:
                                if (Gatherer.Util ~= nil) then
                                        if (Gatherer.Util.ChatPrint ~= AKA_GathererModder) then
                                
                                                originalGathererChat = Gatherer.Util.ChatPrint; --hooked
                                                Gatherer.Util.ChatPrint=AKA_GathererModder;
                                        end
                                end -- Gatherer.Util
                        end -- is Gatherer installed?
                        hasHookedGatherer=true;
                end
                
                
--[[
                -- test to see if we have hooked the calendar yet.
                

                if (hasHookedCalendar == false) then
                        if (IsAddOnLoaded("Blizzard_Calendar")) then
                                if (CalendarDayButton_OnEnter ~= AKA_CalendarDayButton_OnEnter) then
                                        original_CalendarDayButton_OnEnter = CalendarDayButton_OnEnter; --hooked
                                        CalendarDayButton_OnEnter=AKA_CalendarDayButton_OnEnter;
                                        --DEFAULT_CHAT_FRAME:AddMessage("calendar hooked", 1.0, 0.5, 0.25)
                                        hasHookedCalendar=true;
                                end
                        
                        end
                        
                end     
]]--            
                
                -- check if we need to whisper anyone
                -- AKA_SessionList[arg2]['status']='unknown';
                local now = GetTime();
                for k, v in pairs (AKA_SessionList) do
                        local thisStatus=v['status'];
                        if (thisStatus == 'na') then
                        -- short circuit out. maybe put in an hourly test eventually
                        elseif (thisStatus == 'unknown') then
                                -- send a whisper to this person
                                AKA_SendMsg(REQ_TOKEN,k);
                                AKA_SessionList[k]['status']='pending';
                                AKA_SessionList[k]['lastcontact']=GetTime(); -- mark when we sent the whisper
                        elseif (thisStatus == 'pending') then
                                -- check for the timeout
                                if (now-v['lastcontact']>45) then
                                AKA_SessionList[k]['status']='na';
                                end
                        end
                        
                        -- AKA_ProfessionIndex[v] = k;
--[[AKA_SessionList[arg2]['status']='unknown';  -- 'unknown' when first seen, 'pending' if request has been sent, 'na' if request has timed out, 'available' if AKA request has been answered
        AKA_SessionList[arg2]['lastcontact']=GetTime(); -- seconds
        AKA_SessionList[arg2]['channelList']={};
        AKA_SessionList[arg2]['bestchannel']='';
        ]]--
        
        
                end -- loop through AKA_SessionList






                
                
        end -- heartbeat

        if (secondsSinceLastScreenDraw > 10.0) then
                if ((AKA_ToonListDirty == true) and (getglobal("AKAUsersPanel"):IsVisible())) then
                        AKA_ScrollBar_Update(); -- redraw scoll list contents
                end
        end

end -- function



function AKA_TransmitOneToon(toonName)
        
        local fieldCount=0;
        local myNickname=AKA_SavedVars["MyNickname"];
        local outStr="";
        v=AKA_SavedVars["MyToons"][toonName]
        
        
        AKA_ErrorMsg("AKA_TransmitOneToon("..toonName..") myNickname="..myNickname);
        for fieldCount = 1, table.getn(messageFields) do
        -- AKA_ErrorMsg(fieldCount.."->"..messageFields[fieldCount]);
                fieldName=messageFields[fieldCount];
                local fieldValue=v[fieldName];
                if (fieldName == "nickname") then
                        fieldValue=myNickname;
                end
                if (fieldName == "race") then
                        if (v["race_sex"] ~= nil) then
                                fieldValue=v["race_sex"]; 
                        end
                end
                if (fieldName == "profession1") then
                        if (v["prof1num"] ~= nil) then
                                fieldValue=v["prof1num"]..Dec2BASE64(v["prof1skill"]);
                        else    
                                if (v["prof1name"] == nil) then
                                        fieldValue="";
                                else
                                        fieldValue=AKA_ProfessionIndex[v["prof1name"]]..Dec2BASE64(v["prof1skill"]);
                                        AKA_ErrorMsg("profession1->"..fieldValue);
                                end
                        end
                end
                if (fieldName == "profession2") then
                        if (v["prof2num"] ~= nil) then
                                fieldValue=v["prof2num"]..Dec2BASE64(v["prof2skill"]);
                        else
                                if (v["prof2name"] == nil) then
                                        fieldValue="";
                                else
                                        fieldValue=AKA_ProfessionIndex[v["prof2name"]]..Dec2BASE64(v["prof2skill"]);
                                        AKA_ErrorMsg("profession2->"..fieldValue);
                                end
                        end
                end
                if (fieldName == "userid") then
                        fieldValue=AKA_USERID;
                end
                
                if (fieldValue==nil) then
                        outStr=outStr..MSG_DELIMITER;
                else
                        outStr=outStr.. fieldValue..MSG_DELIMITER;
                end
        end -- for fieldCount
        AKA_SendMsg(outStr);
        AKA_SendVersion();
end


    
function AKA_EnterNewNickname()
        local newNickname=getglobal("AKA_PrefsMyNickname"):GetText();

        if (newNickname ~= "" and newNickname ~= nil) then
                AKA_SavedVars["MyNickname"]=newNickname;
        end
        if (AKA_SavedVars["MyNickname"]=="") then
                AKA_SavedVars["MyNickname"]=myPlayerName;       -- use current name if no default
        end
        AKA_CurrentNickname:SetText("Current nickname: "..AKA_SavedVars["MyNickname"]);
        UpdateMyData();
        pendingSingleAnnounce=true;
end



function AKA_RequestSync()

        AKA_SendMsg(REQ_TOKEN);
        -- DEFAULT_CHAT_FRAME:AddMessage("AKA-REQUESTING SYNC:", 0.5, 1.0, 0.5, 3);
        needHello=false; -- we wil be responding to a sync request anyway
        
end


function AKA_SendMsg(msg, targetPlayer)
        -- send a message using the appropriate channel
        local rChanNum,rChanName, r2, channelInfo;
        if (targetPlayer ~= nil) then
                local dashOffset=string.find(targetPlayer, "-");
                if (dashOffset ~= nil) then
                        -- DEFAULT_CHAT_FRAME:AddMessage("AKA_SendMsg(targetPlayer:"..targetPlayer..")", 0.5, 1.0, 0.5, 3);
                        targetPlayer = "PARTY";
                        if (UnitInRaid("player")==1) then
                                targetPlayer = "RAID";
                        end
                end
        end
        channelInfo=AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]; -- make a shorter reference
        if ((targetPlayer == nil) or (targetPlayer == "")) then
        -- regular broadcasts:
                
                if (channelInfo == nil) then
                        UpdateMyData();
                        channelInfo=AKA_SavedVars["MyToons"][myPlayerID]["com_channels"];
                end
                AKAg=channelInfo; -- make a global for testing dbc
                
                -- guild traffic:
                if (IsInGuild() and (channelInfo["Guild"]["active"] == "yes")) then -- only send on guild channel if in a guild
                         SendAddonMessage(MSG_PREFIX, MESSAGE_FORMAT..msg, "GUILD");
                         MessagesSentPerChannel["GUILD"]=MessagesSentPerChannel["GUILD"]+1;
                        if (AKA_TRAFFICMONITOR) then
                                DEFAULT_CHAT_FRAME:AddMessage("AKA_TX(Guild):"..MESSAGE_FORMAT..msg, 0.5, 1.0, 0.5, 3);
                        end      
                 end
                
        elseif ( targetPlayer == "GUILD") then
                if (IsInGuild() and (channelInfo["Guild"]["active"] == "yes")) then -- only send on guild channel if in a guild
                        SendAddonMessage(MSG_PREFIX, MESSAGE_FORMAT..msg, "GUILD");
                        MessagesSentPerChannel["GUILD"]=MessagesSentPerChannel["GUILD"]+1;
                        if (AKA_TRAFFICMONITOR) then
                                DEFAULT_CHAT_FRAME:AddMessage("AKA_TX(Guild):"..MESSAGE_FORMAT..msg, 0.5, 1.0, 0.5, 3);
                        end      
                end
        
        
        elseif (targetPlayer == "RAID") then
                if ( (channelInfo["Raid"]["active"] == "yes")) then -- put in test for in-raid eventually
                        SendAddonMessage(MSG_PREFIX, MESSAGE_FORMAT..msg, "RAID");
                        MessagesSentPerChannel["RAID"]=MessagesSentPerChannel["RAID"]+1;
                        if (AKA_TRAFFICMONITOR) then
                                DEFAULT_CHAT_FRAME:AddMessage("AKA_TX(RAID):"..MESSAGE_FORMAT..msg, 0.5, 1.0, 0.5, 3);
                        end      
                end
                
        elseif (targetPlayer == "PARTY") then
                if ( (channelInfo["Raid"]["active"] == "yes")) then -- put in test for in-raid eventually
                        SendAddonMessage(MSG_PREFIX, MESSAGE_FORMAT..msg, "PARTY");
                        MessagesSentPerChannel["PARTY"]=MessagesSentPerChannel["PARTY"]+1;
                        if (AKA_TRAFFICMONITOR) then
                                DEFAULT_CHAT_FRAME:AddMessage("AKA_TX(PARTY):"..MESSAGE_FORMAT..msg, 0.5, 1.0, 0.5, 3);
                        end      
                end
        
        else
        
        --whispers:
                if (AKA_TRAFFICMONITOR) then
                        DEFAULT_CHAT_FRAME:AddMessage("AKA_TX(WHISPER:"..targetPlayer.."):"..MESSAGE_FORMAT..msg, 0.5, 1.0, 0.5, 3);
                end     
                SendAddonMessage(MSG_PREFIX, MESSAGE_FORMAT..msg, "WHISPER", targetPlayer);
                MessagesSentPerChannel["WHISPER"]=MessagesSentPerChannel["WHISPER"]+1;

        end
        




end


function AKA_ErrorMsg(msg)
-- send a message using the appropriate channel
        if (AKA_DEBUG) then
                DEFAULT_CHAT_FRAME:AddMessage("AKA-DEBUG:"..msg, 0.5, 1.0, 0.5, 3);
        end
end



function AKA_TestVersionMsg(msg)
-- Input: is the regular string from the addon channel
-- Returns: true if this is a version test.  false is some other sort of message
-- AKA_VersionNote will be the note for the version we don't have
        if (strsub(msg, 1, 2) == "V:") then -- this is a version message
                local toss, prefix,version,note = string.find(msg,"V:(.*)`(.*)");
                local parsedVersion=tonumber(version)
                if (parsedVersion>AKA_HighestSeenVersion) then
                        AKA_HighestSeenVersion=parsedVersion;
                        if (AKA_HighestSeenVersion>AKA_Version) then
                                DEFAULT_CHAT_FRAME:AddMessage(AKA_TEXT["VERSION_UPDATE"].."(old:"..AKA_Version.." new:"..parsedVersion..") "..note, 0.5, 1.0, 0.5, 3); 
                        end
                end
        
                return true;
        else
                return false;
        end

end


function AKA_SendVersion()
        if  (AKA_Version>AKA_HighestSeenVersion) then
                AKA_HighestSeenVersion=AKA_Version;
                AKA_SendMsg("V:"..AKA_Version.."`"..AKA_TEXT["VERSION_NOTES"]);
        end


end

-- GUI Handlers:
-- =============================


-- Prefs:
-- ------
-- Handle clicks for Prefs
function AKAOptions_OnClick(self)

        local buttonName=self:GetName()
        --DEFAULT_CHAT_FRAME:AddMessage("LookoutOptions_OnClick: OnClick: " .. buttonName );
        AKA_Defaults[buttonName] =getglobal(buttonName):GetChecked();
        AKA_SavedVars[buttonName] =getglobal(buttonName):GetChecked();
end



function AKAOptions_SharingOnClick(shareType)
-- Called by checkbuttons in preferences frame
-- sharetype = one of ["Guild" "Raid "Chat"

        local checkbuttonName = "AKA_PrefsShare"..shareType;
        local currentState=getglobal("AKA_PrefsShare"..shareType):GetChecked();
        local newSetting="no";

        if (currentState) then
                newSetting="yes";
        end
        AKA_SavedVars["MyToons"][myPlayerID]["com_channels"][shareType]["active"]=newSetting;   
end

function AKAOptions_RadioClick(butNum)
        AKA_SavedVars["MyToons"][myPlayerID]["guildnotes"]=butNum+0; -- 0=no, 1=1st word, 2=(), 3=[]
        
        UpdateGuildNotes();
        UpdateRadios();
        
end






function AKA_ListClick(passedFrame)
        local level,race,class,guild,zone;
        local thisToonID=passedFrame.toonID;

        -- DEFAULT_CHAT_FRAME:AddMessage(thisToonID , 0.5, 1.0, 0.5, 3); 


        if (thisToonID ~= nil) then             
                if (AKA_SavedVars["FriendToons"] == nil) then -- repair FriendToons if necessary
                        AKA_FixDefaults();
                end
                if (AKA_SavedVars["FriendToons"][thisToonID]) then -- if there is an entry for this person
                        speakerRec=AKA_SavedVars["FriendToons"][thisToonID];
                        if ((speakerRec["nickname"] ~= "")  and (speakerRec["nickname"] ~= nil)) then -- there is a nickname
                                linkedNickname=speakerRec["nickname"] ;
                        end -- there is a nickname
                                                        
                        -- build a structure of alts
                        local toonList = AKA_SavedVars["FriendToons"];

                        if (toonList == nil) then
                                -- we are done
                                outStr=("No player selected");  
                        else
        
                                outStr="AKA:\"|c9090FFFF"..linkedNickname.."\"|r\n";
                                -- table.foreach(toonList,function(k,v)
                                for k,v in pairs(toonList) do 
                                        if (((v["faction"] == myPlayerFaction) and (v["realm"]==myPlayerRealm)) or (v["faction"] == nil) or (v["realm"] == nil)) then
                                                
                                                AKA_ErrorMsg(k..":"..v["name"]);
                                                if (v["nickname"] == linkedNickname) then
                                                        local thisToonText = "";
                                                        for fieldCount = 1, table.getn(tooltipFields) do -- tooltipDelimiters
                                                                local fieldName=tooltipFields[fieldCount];
                                                                local fieldValue=v[fieldName];
                                                                        if ((fieldValue ~= nil) and (fieldValue ~= "")) then -- if no value, skip
                                                                                thisToonText=thisToonText.. fieldValue..tooltipDelimiters[fieldCount];
                                                                        end     
                                                        end -- for fieldCount
                                                        outStr=outStr..thisToonText.."\n";
                                                end -- nickname matches
                                         end -- meets factio/realm criteria
                                end -- pairs
                
                         end -- toonlist == nil
                        
                        end -- there are alts to check
                        

                getglobal("AKA_DispPlayerNotes"):SetText(outStr);


        end

end -- function




 -- OnShow for prefs
 function AKA_PrefsFrameOnShow()
-- read settings from profile, and change our checkbuttons and slider to represent them
        local currentOptions = getglobal(this:GetName().."Options");
        PlaySound("igCharacterInfoOpen");
        if (not currentOptions) then
                currentOptions=LookoutDefaults;
        end
        UpdateRadios();
        -- draw the current settings:

        if (AKA_SavedVars["AKA_PrefsShowMe"]) then
                getglobal("AKA_PrefsShowMe"):SetChecked(true)
        else
                getglobal("AKA_PrefsShowMe"):SetChecked(false)
        end

        if (AKA_SavedVars["MyNickname"] ~= nil) then
                AKA_CurrentNickname:SetText("Current nickname: "..AKA_SavedVars["MyNickname"]);
        end
        


-- prefill nickname     
        local textValue=AKA_SavedVars["MyNickname"];
        if (textValue == nil) then
                textValue=""
        end
        getglobal("AKA_PrefsMyNickname"):SetText(textValue);

-- draw sharing preferences:

for i,v in ipairs({"Guild","Raid","Chat"}) do 

        if (AKA_SavedVars["MyToons"][myPlayerID]["com_channels"][v]["active"] == "yes") then
                getglobal("AKA_PrefsShare"..v):SetChecked(true)
        else
                getglobal("AKA_PrefsShare"..v):SetChecked(false)
        end
end

        
        
        if ((AKAPrefs_CurrentPanel == nil) or (AKAPrefs_CurrentPanel == 0)) then
                AKAPrefs_CurrentPanel=-1;
                AKA_HidePanel(2);
                -- PanelTemplates_Tab_OnClick(1);
                AKA_ShowPanel(1); -- default to panel 1
        end
 end
 
 


 
function AKA_ShowPanel(whichPanel)

        if (AKAPrefs_CurrentPanel > 0) then
                AKA_HidePanel(AKAPrefs_CurrentPanel);
        end
        getglobal(AKAPrefs_PanelFrames[whichPanel]):Show();
        AKAPrefs_CurrentPanel=whichPanel;

 end


function AKA_HidePanel(whichPanel)
        getglobal(AKAPrefs_PanelFrames[whichPanel]):Hide();
        AKAPrefs_CurrentPanel = 0;

end
 
 
 
 

 
function AKA_ScrollBar_Update(self)
-- Uses the buttons created by AKA_CreateScrollItems and filles in their text and toonID's
  DrawScrollContents(FauxScrollFrame_GetOffset(self));
  --    local scrollTestData = {};
   -- for i=1,50 do
   --   scrollTestData[i] = "Test "..math.random(100);
  --  end
        local totalLines=table.getn(AKA_BIGLIST);
   
  -- FauxScrollFrame_Update(AKA_FrameScrollBar,VISIBLE_MAX,5,16); -- function, max entries, # visible, pixel height of one
  FauxScrollFrame_Update(self,totalLines,VISIBLE_MAX,16); 
  -- DEFAULT_CHAT_FRAME:AddMessage("We're at "..FauxScrollFrame_GetOffset(AKA_FrameScrollBar));
   
   if (AKA_ScrollItem1 == nil) then
           AKA_CreateScrollItems();
   end
        
        local lineCounter, dataLine, buttonName;
        local listText=""; -- temporary simple list version
--      DEFAULT_CHAT_FRAME:AddMessage("top="..FauxScrollFrame_GetOffset(AKA_FrameScrollBar));
        
        for lineCounter=1,VISIBLE_MAX do
                dataLine= lineCounter + FauxScrollFrame_GetOffset(AKA_FrameScrollBar);
                buttonName="AKA_ListLine"..lineCounter;
                if (dataLine <= table.getn(AKA_BIGLIST)) then
                -- DEFAULT_CHAT_FRAME:AddMessage("lineCounter="..lineCounter.."  dataLine="..dataLine.."  "..AKA_BIGLIST[dataLine]);                    
                        getglobal("AKA_ListLine"..lineCounter):SetText(AKA_BIGLIST[dataLine]);
                        getglobal("AKA_ListLine"..lineCounter).toonID=AKA_BIGIDS[dataLine];
                        getglobal("AKA_ListLine"..lineCounter):Show();
                else
                        getglobal("AKA_ListLine"..lineCounter):Hide();
                end
        end -- for
        AKA_ToonListDirty=false;

 end
 
 
 function AKA_CreateScrollItems()
 -- Create the buttons that make up the "faux" scrolling list of toon names
        local i, f, entryName;
         for i = 1, VISIBLE_MAX do
                entryName="AKA_ListLine"..i;
                 if  (getglobal(entryName) == nil) then
                        f = CreateFrame("Button", entryName, AKAUsersPanel,"AKA_ScrollMenuEntryTemplate"); --CreateFrame("frameType", "frameName", parentFrame[, "inheritsFrame"]);
                        --f:SetID(i);
                        f:SetWidth(700);
                        f:SetHeight(19);
                        f:ClearAllPoints();
                        f:SetPoint("TOPLEFT", "AKA_PrefsTitle", "TOPLEFT", 0, -90+(-16*i));
                        f:SetText("Test #"..i);
                        --f:Show();
                end
         end

end
 
 
 
 

 
 -- text changed on prefs panel:
 function AKA_PrefsTextChanged()
-- eventually only show change button if something changes
end



function AKA_EnterNewChannelName(whichChannel)
        -- attempt to leave the old channel is available
        -- save the data, but don't try to join right away - leave that for the transmit fuction
        local oldChanName = AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]["Chan"..whichChannel]["name"];
        if (oldChanName == nil) or (oldChanName == "") then
        -- no old channel to leave
        else
                LeaveChannelByName(oldChanName);
                DEFAULT_CHAT_FRAME:AddMessage("Leaving Channel:"..oldChanName, 1, .2, .2, 1); 
        end
        

        local chanName=getglobal("AKA_PrefsChannel"..whichChannel.."Name"):GetText();
        local chanPW=getglobal("AKA_PrefsChannel"..whichChannel.."PW"):GetText();
        
        if (AKA_SavedVars["MyToons"][myPlayerID]["com_channels"] == nil) then
                AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]=DEFAULT_COM_CHANNELS;
        end
        AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]["Chan"..whichChannel]["name"]=chanName;
        AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]["Chan"..whichChannel]["pw"]=chanPW;
        ALA_DrawChannelPrefsValues(whichChannel); -- update the name in the head if needed
        pendingSingleAnnounce=true; -- announce our presence in the channel
        AKA_RequestSync(); -- ask users in the new channels for information

end







        



--     CheckButton:GetChecked() - Get the status of the checkbox. 
--    CheckButton:SetChecked([state]) - Set the status of the checkbox. 
--    CheckButton:SetCheckedTexture("texture") - Set the texture to use for a checked box. 
--    CheckButton:SetDisabledCheckedTexture("texture") - Set the texture to use for an unchecked box.
    
    

    
    
    
    
-- math lib:

function AKA_TestBase()
local orig=0;
local t64=Dec2BASE64(orig);
local res=BASE642Dec(t64);

        DEFAULT_CHAT_FRAME:AddMessage("orig:"..orig, 0.5, 1.0, 0.5, 3); 
        DEFAULT_CHAT_FRAME:AddMessage("b64 :"..t64, 0.5, 1.0, 0.5, 3); 
        DEFAULT_CHAT_FRAME:AddMessage("dec :"..res, 0.5, 1.0, 0.5, 3); 
local orig=math.random(1,1000);
local t64=Dec2BASE64(orig);
local res=BASE642Dec(t64);

        DEFAULT_CHAT_FRAME:AddMessage("orig:"..orig, 0.5, 1.0, 0.5, 3); 
        DEFAULT_CHAT_FRAME:AddMessage("b64 :"..t64, 0.5, 1.0, 0.5, 3); 
        DEFAULT_CHAT_FRAME:AddMessage("dec :"..res, 0.5, 1.0, 0.5, 3); 



end

-- Event functions
-- Onload:
function AKA_OnLoad(self)
        -- this:RegisterEvent("ADDON_LOADED");

        -- Register the slash command
        -- --------------------------
        SLASH_AKA1 = "/aka";
        SlashCmdList["AKA"] = AKA_ParseCommandLine; -- trying this global - didn't kick in with local
        InitMath();


-- Register the event handlers:
-- =============================        
-- this:RegisterEvent("VARIABLES_LOADED"); -- eventually will call OnEvent      
self:RegisterEvent("CHAT_MSG");

self:RegisterEvent("CHAT_MSG_ADDON");
self:RegisterEvent("CHAT_MSG_SYSTEM"); -- for the /who
self:RegisterEvent("WHO_LIST_UPDATE"); -- for the /who


-- raid command stuff:
-- self:RegisterEvent("CHAT_MSG_RAID");
-- self:RegisterEvent("CHAT_MSG_PARTY");

-- Party/Roster stuff:
self:RegisterEvent("RAID_ROSTER_UPDATE");
self:RegisterEvent("CHAT_MSG_CHANNEL"); -- will update with alias names, will watch for potential peers
self:RegisterEvent("CHAT_MSG_GUILD"); -- will update with alias names
self:RegisterEvent("CHAT_MSG_RAID"); -- will update with alias names
self:RegisterEvent("CHAT_MSG_PARTY"); -- will update with alias names
self:RegisterEvent("VARIABLES_LOADED");
self:RegisterEvent("PLAYER_ENTERING_WORLD"); -- will start a timer for initial syncs
self:RegisterEvent("MINIMAP_ZONE_CHANGED"); -- Update our last known location

self:RegisterEvent("CHAT_MSG_CHANNEL_JOIN"); -- watch for potential peers joining the channel
self:RegisterEvent("GUILD_ROSTER_UPDATE"); -- watch for potential peers joining the channel


        if (not myPlayerName) then
                myPlayerName = UnitName("player");
        end
        
        
        DEFAULT_CHAT_FRAME:AddMessage(AKA_TITLE.." loaded. Type /aka to change settings.",  0.5, 1.0, 0.5, 1);
        tinsert(UISpecialFrames,'AKA_PrefsFrame');

end -- OnLoad





        
function AKA_Event(self, event, ...)
local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11 = ...;
        if (event==nil) then
                -- DEFAULT_CHAT_FRAME:AddMessage("AKA: event="..event .. " arg1="..arg1.." arg2="..arg2,  0.5, 1.0, 0.5, 1);
        end
local eventHandled = false;
local msgText = "";
-- oh to have a case statement!

-- debug
if (AKA_ShowEvent) then
        DEFAULT_CHAT_FRAME:AddMessage("AKA: event "..event,  0.5, 1.0, 0.5, 1);
end



if (event == "GUILD_ROSTER_UPDATE") then
        -- if (arg1 ~= nil) then
                UpdateGuildNotes();
                eventHandled = true;
        -- end 
end






        if (eventHandled == false) then
                if ((event == "CHAT_MSG_SYSTEM") or (event =="WHO_LIST_UPDATE")) then -- looking for the "who" event set earlier by the linky
                        if ((AKA_LinkedName~="") and (AKA_LinkedName~=nil)) then
                                ShowWhoTooltip();
                                AKA_LinkedName=""; -- tip has been shown. move along
                                eventHandled = true;
                        end     
                end -- CHAT_MSG_SYSTEM
        end -- eventHandled
        
        
        
        
        
        
        
-- VARIABLES_LOADED
-- ================

        if ( event == "VARIABLES_LOADED" ) then
        
                -- Reseed the random # generator
                -- supposedly not needed with 3.x+ clients
                -- math.randomseed(math.random(0,2147483647)+(GetTime()*1000));
                if (not AKA_USERID) then
                        AKA_USERID=GenerateUSERID();
                        -- this will be expanded into a larger version to handle
                        -- people playing on multiple machines.
                        -- we will implment a "who am I?" function to try to determine if there is an existing ID.
                end
                -- DEFAULT_CHAT_FRAME:AddMessage("AKA: realm="..myPlayerRealm.. "("..AKA_USERID..")  today="..TODAY,  0.5, 1.0, 0.5, 1);

                
                FixDefaults();
                
                -- Delete old entries:
                for k,v in pairs(AKA_SavedVars["FriendToons"])  do
                        if ((TODAY-v["lastupdate"])>100) then
                                -- table.remove(AKA_SavedVars["FriendToons"],k);
                                AKA_SavedVars["FriendToons"][k]=nil;
                        end
                end
                
                
                -- record that we have been loaded
                AKA_variablesLoaded = true;
                eventHandled = true;


                    

                
        end -- ( event == "VARIABLES_LOADED" )
        
        
        
        
-- Raid update event
-- ===========================
        if (eventHandled == false) then
                if ((event == "RAID_ROSTER_UPDATE") or (event == "PARTY_MEMBERS_CHANGED")) then 
                        -- Lookout_UpdateRaidtable();
                        eventHandled = true;
                end
                
        end
        if (eventHandled == false) then
                if ((event == "ZONE_CHANGED") or (event == "MINIMAP_ZONE_CHANGED") ) then       
                        if (myPlayerZone ~= GetRealZoneText()) then -- GetMinimapZoneText() had too much detail
                                myPlayerZone=GetRealZoneText();
                                UpdateMyData();
                                pendingSingleAnnounce=true;
                        end
                        eventHandled = true;
                end
        end
        
        
        if (eventHandled == false) then
                if (event == "CHAT_MSG_ADDON") then 
                -- process incoming messages
                -- AKA2 supports WHISPER, PARTY and RAID messages as well
                --[[
                Fired when the client receives a message from SendAddonMessage

arg1 
    prefix 
arg2 
    message 
arg3 
    distribution type ("PARTY", "RAID", "GUILD", "BATTLEGROUND" or "WHISPER") 
arg4 
    sender 
    ]]--
                
                
                
                        if (arg1 == MSG_PREFIX) then
                                --if (arg3 == "GUILD") then -- Only use ADDON channel for guild
                                local chanInfo = AKA_SavedVars["MyToons"][myPlayerID]["com_channels"]; -- create a shorter reference
                                if ((arg3=="GUILD") and (chanInfo["Guild"]["active"] =="yes")) 
                                        or ((arg3=="RAID") and (chanInfo["Raid"]["active"] =="yes")) 
                                        or  ((arg3=="PARTY") and (chanInfo["Raid"]["active"] =="yes")) 
                                        or (arg3=="WHISPER")
                                        then
                                        if (arg2 ~= nil) then
                                                secondsSinceLastMsg=0; -- reset the message timer
                                                if (AKA_TRAFFICMONITOR) then
                                                        DEFAULT_CHAT_FRAME:AddMessage("AKA_RX:("..arg3.."):"..arg2, 0.5, 1.0, 0.5, 1);
                                                end
        
        
                                                local msgText=strsub(arg2,2); -- strip off version byte
                                                -- char 1 is the version which we can test later...
                                                if (msgText== REQ_TOKEN)then
                                                                -- DEFAULT_CHAT_FRAME:AddMessage("AKA token recieved:("..msgText.."):"..arg2, 1.0, .6, 0.6, 1);
                        -- determined we're getting at least this far...
                                                        if( arg3=="WHISPER") then
                                                                pendingRequests[arg4]=true;
                                                        else -- GUILD, PARTY, RAID
                                                                pendingRequests[arg3]=true;
                                                        end
                                                        -- pendingRequests is an associative array of player names who have requested data. 
                                                        -- It will also contain the names of channels in which requests have arrived.
                                                        -- i.e. PARTY, RAID, or GUILD
                                                else
                                                        if (AKA_TestVersionMsg(msgText)) then
                                                        -- version test packet
                                                        else
                                                                ParseMessage(msgText,arg4, arg3); -- this is a data packet
                                                                -- arg2 = message text, arg4=sender name
                                                        end
                                                end --  REQ_TOKEN
                                        end
                                end -- checks for preferences 
                                
                                
                                
                        end
                        -- Lookout_UpdateRaidtable();


-- Fired when the client receives a message from SendAddonMessage
-- 
-- arg1     prefix 
-- arg2     message 
-- arg3     distribution type ("PARTY","RAID","GUILD" or "BATTLEGROUND") 
-- arg4     sender 
    
    
                        eventHandled = true;
                end
                
        end
        
        
        
        

        
        
        
        
        
        
-- Raid chat events (incoming)
-- ===========================
        if (event == "CHAT_MSG_RAID" or event == "CHAT_MSG_PARTY" or event =="CHAT_MSG_CHANNEL") then
                -- arg1 = messsage text
                -- arg2 = message sender
                local sendingMember = nil;
                local inStr;
                local msgStr;
                local cmdStr;
                local toss;
                local toss2;
-- General, Trade, and LocalDefense             
                
                -- end -- (string.find( arg1, "::")
-- put in logic here to determine which channels to monitor:
-- record everyone we've seen speak:
 if (AKA_SessionList[arg2]) then
        -- we've seen this person before
 else
        -- add this speaker to our list and check if they are running AKA
        AKA_SessionList[arg2]={};
        AKA_SessionList[arg2]['status']='unknown';      -- 'unknown' when first seen, 'pending' if request has been sent, 'na' if request has timed out, 'available' if AKA request has been answered
        AKA_SessionList[arg2]['lastcontact']=GetTime(); -- seconds
        AKA_SessionList[arg2]['channelList']={};
        AKA_SessionList[arg2]['bestchannel']='';
 end
        end -- event=CHAT_MSG_RAID et. al.
        -- channel monitor end

        



        


        
        
        
        if (eventHandled == false) then
        --      msgText = string.lower(arg1);
        end 


end -- end of function
 


-- command line parameters: (slash command handler)
function AKA_ParseCommandLine(msg)
        cmd=string.lower(msg);

        if ( ( msg=="1") or (msg=="")) then
                AKA_PrefsFrame:Show();
        end


        
        
        if ( cmd =="t") then
                AKA_TestBase();
        end

        if ( cmd =="help") then
                DEFAULT_CHAT_FRAME:AddMessage("/aka reset - restore default values",  0.5, 1.0, 0.5, 1);
                DEFAULT_CHAT_FRAME:AddMessage("/aka debug - toggle display of debug messages",  0.5, 1.0, 0.5, 1);
                DEFAULT_CHAT_FRAME:AddMessage("/aka messages - toggle display of netowork traffic",  0.5, 1.0, 0.5, 1);
                DEFAULT_CHAT_FRAME:AddMessage("/aka updateme - send your data to other AKA clients",  0.5, 1.0, 0.5, 1);

        end
        
        if ( cmd =="reset") then
                DEFAULT_CHAT_FRAME:AddMessage("Setting AKA variables to default values.",  0.5, 1.0, 0.5, 1);

                AKA_SavedVars = {};
                AKA_SavedVars=AKA_Defaults;
                AKA_SavedVars["Version"]=AKA_Version;
                UpdateMyData();
                -- LookoutAlertHandler(" Variables reset ");
        end     
        
        if ( cmd =="messages") then
                AKA_TRAFFICMONITOR= not AKA_TRAFFICMONITOR;
                if (AKA_TRAFFICMONITOR) then
                        DEFAULT_CHAT_FRAME:AddMessage("AKA now diplaying communications traffic",  0.5, 1.0, 0.5, 1);
                else
                        DEFAULT_CHAT_FRAME:AddMessage("AKA message display off",  0.5, 1.0, 0.5, 1);
                end
                
                
                
        end     
        
        if ( cmd =="debug") then
                AKA_DEBUG = not AKA_DEBUG;
                if (AKA_DEBUG) then
                        DEFAULT_CHAT_FRAME:AddMessage("AKA Debug messages enabled.",  0.5, 1.0, 0.5, 1);
                else
                        DEFAULT_CHAT_FRAME:AddMessage("AKA Debug messages off.",  0.5, 1.0, 0.5, 1);
                end
                
        end     
        if ( cmd =="updateme") then
                DEFAULT_CHAT_FRAME:AddMessage("Sending update to other AKA clients.",  0.5, 1.0, 0.5, 1);

                UpdateMyData();
                pendingSingleAnnounce=true;
        end     
        
        
        if ( cmd =="sync") then
                DEFAULT_CHAT_FRAME:AddMessage("Request sync from other AKA clients.",  0.5, 1.0, 0.5, 1);

                AKA_RequestSync();
                --pendingSingleAnnounce=true;
        end     
        
        if ( cmd =="spells") then
                DEFAULT_CHAT_FRAME:AddMessage("Displaying Spellbook...",  0.5, 1.0, 0.5, 1);

                ShowSpells();
                pendingSingleAnnounce=true;
        end     


   if( string.sub(cmd,1,5)=="name ") then
                AKA_LookupName(string.sub(msg,6));
                pendingSingleAnnounce=true;
        end     
end

function AKA_LookupName(whatname)
        local str="";
        DEFAULT_CHAT_FRAME:AddMessage(GetNickname(whatname));

end
function AKA_GetNickname(visibleName, noColor)
--global form for other addons
return GetNickname(visibleName, noColor)
end


function AKA_ExpandNickname(visibleName, noColor)
--global form for other addons

return visibleName..' '..GetNickname(visibleName, noColor);

end

Compare with Previous | Blame