---------------------------------------------- -- Global variables ---------------------------------------------- KarmaData = {}; -- Karma data is stored in the following tree: (v10) -- KarmaData = {}; -- REALMS = {}; -- ["Proudmoore"] = {} -- FACTIONLIST = {}; -- ["Alliance"] = {} -- CHARACTERLIST = {}; -- ["Amadea"] = {} -- ... -- CHARACTER_IDS = {}; -- [1] = "Amadea", -- ... -- MEMBERBUCKETS = {[A] = {} ... [Z] = {}}; -- (20400.x ) ALTGROUPS = { -- [1] = { ID = 1, AL = { "Foo", "Baz", "Bar" } }, -- [2] = { ID = 2, AL = { "Tick", "Trick", "Track" } }, -- ... -- } -- QUESTNAMES = {}; -- REALM_IDS = {}; -- [1] = "Proudmoore", -- [2] = "...", -- ... -- COMMON = {}; -- REGIONNAMES = {}; -- ZONENAMES = {}; -- FACTIONLIST = {}; -- <Faction> = {}; -- QUESTNAMES = {}; -- QUESTINFOS = {}; -- <LOCALE> -- TALENTS = {} -- Karma data is stored in the following tree: (v11) -- KarmaAvEnK<Faction> = {}; -- REALMS = {}; -- ["Proudmoore"] = {} -- ... (like above) -- -- The switch is so that all faction data can easily be pushed to/pulled from the LOD modules -- v12: moved XFACTIONHOLD to KarmaData, so the XFaction-DB doesn't need to be loaded on XFaction info -- v13: added indirect keys, so MEMBERBUCKETS can account cross-realm at all local KarmaObj = KarmaAvEnK; local KOH = KarmaObj.Helpers; ----------------------------------------- -- Low Level Functions ----------------------------------------- function Karma_NilToEmptyString(Input) if (Input ~= nil) then return Input; else return ""; end end function Karma_NilToString(value) if (value == nil) then return "<nil>"; end return value; end function Karma_NilToZero(Input) -- KarmaChatDefault("N20: " .. Karma_NilToEmptyString(Input)); if (Input ~= nil) then return Input; else return 0; end end function Karma_CopyTable(table) local copyoftable = {}; local index, value; for index, value in pairs(table) do if (type(value) ~= "table") then copyoftable[index] = value; else copyoftable[index] = Karma_CopyTable(value); end end return copyoftable; end function Karma_TableMerge2Into1(table1, table2) -- degenerated cases: no first table if (#table1 == 0) then return Karma_CopyTable(table2); end -- first table not empty, second is: if (#table2 == 0) then return Karma_CopyTable(table1); end local index, value; -- depending on size of the tables, walk one and insert into other -- special case: very short table2 if (#table2 < 3) then -- get the three values local i = 1; local val1, val2, val3; for index, value in pairs(table2) do if (i == 1) then val1 = value; end if (i == 2) then val2 = value; end if (i == 3) then val3 = value; end i = i + 1; end -- check if already contained for index, value in pairs(table1) do if (value == val1) then val1 = nil; end if (value == val2) then val2 = nil; end if (value == val3) then val3 = nil; end end -- if not contained, insert if (val1 ~= nil) then table.insert(table1, val1); end if (val2 ~= nil) then table.insert(table1, val2); end if (val3 ~= nil) then table.insert(table1, val3); end return Karma_CopyTable(table1); end -- now to the ugly part... -- sure this would be helluva lot nicer, if we had them sorted... not today. :D local tablelarge, tablesmall; if (#table1 >= #table2) then tablelarge = table1; tablesmall = table2; else tablelarge = table2; tablesmall = table1; end -- walk the large table, and check for each value, if it's in the small, otherwise insert local table3 = {}; for index, value in pairs(tablesmall) do local key = "K"..index; table3[key] = {}; table3[key].ix = index; table3[key].val = value; table3[key].found = 0; end local index1, index2, value1, value2; for index1, value1 in pairs(tablelarge) do -- check if value1 also in tablesmall, if yes, remove for index2, value2 in pairs(tablesmall) do if (value1 == value2) then local key = "K"..index2; table3[key].found = 1; break; end end end -- now tablesmall should only contain values that are not in tablelarge -- just throw them in for index, value in pairs(table3) do if (value.found == 0) then table.insert(tablelarge, value.val); end end return Karma_CopyTable(tablelarge); end local Stacks = {}; function Karma_FieldInitialize(dict, field, initialvalue, bSilent, bCopy) KarmaObj.ProfileStart("Karma_FieldInitialize"); if (dict == nil) or (field == nil) or (type(dict) ~= "table") then if (type(initialvalue) ~= "table") then KarmaChatDebugFallbackSecondary(KARMA_MSG_FIELDINIT_ERROR_VALUE .. initialvalue); else KarmaChatDebugFallbackSecondary(KARMA_MSG_FIELDINIT_ERROR_VALUE .. KARMA_MSG_FIELDINIT_ERROR_TABLE); end local backtrace = debugstack(); KarmaChatDebugFallbackSecondary("CB: " .. backtrace); elseif (dict[field] == nil) then if (bCopy and (type(initialvalue) == "table")) then dict[field] = Karma_CopyTable(initialvalue); else dict[field] = initialvalue; end if (not bSilent) then if (type(initialvalue) ~= "table") then local valstr = initialvalue; if (valstr == true) then valstr = "true"; elseif (valstr == false) then valstr = "false"; elseif (valstr == nil) then valstr = "nil"; end KarmaChatDebug("FI: " .. field .. " -> default: " .. valstr); else KarmaChatDebug("FI: " .. field .. " -> default: <table>"); end end elseif ((initialvalue ~= nil) and (type(initialvalue) == "table") and KOH.TableIsEmpty(initialvalue)) then local backtrace = debugstack(); local iCount, bFound, i = #Stacks, false; for i = 1, iCount do if (Stacks[i] == backtrace) then bFound = true; break; end end if (not bFound) then tinsert(Stacks, backtrace); KarmaChatDebugFallbackSecondary("Empty table initializer (" .. tostring(iCount + 1) .. "): " .. backtrace); end end KarmaObj.ProfileStop("Karma_FieldInitialize"); end function Karma_FieldDeinitialize(dict, field, initialvalue, bSilent) KarmaObj.ProfileStart("Karma_FieldDeinitialize"); if (dict == nil) or (field == nil) or (type(dict) ~= "table") then if (type(initialvalue) ~= "table") then KarmaChatDebugFallbackSecondary(KARMA_MSG_FIELDINIT_ERROR_VALUE .. initialvalue); else KarmaChatDebugFallbackSecondary(KARMA_MSG_FIELDINIT_ERROR_VALUE .. KARMA_MSG_FIELDINIT_ERROR_TABLE); end local backtrace = debugstack(); KarmaChatDebugFallbackSecondary("CB: " .. backtrace); elseif (dict[field] == initialvalue) then dict[field] = nil; KarmaChatDebug("FI: " .. field .. " -> default: " .. tostring(initialvalue)); end KarmaObj.ProfileStop("Karma_FieldDeinitialize"); end ---------------------------------------------- -- CONSTS ---------------------------------------------- local KARMA_SUPPORTEDDATABASEVERSION = 14; ---------------------------------------------- -- LOCALS ---------------------------------------------- local KDBC = { -- empty initalizers so we keep track of what we use and how we name it... Realm = nil, -- current realm name PlayerFaction = nil, -- player faction PlayerName = nil, -- player name CommonFactionObject = nil, -- COMMON::FACTION object FactionObjectCache = nil, -- SERVER::FACTION object }; ---------------------------------------------- -- DB KEYS ---------------------------------------------- --------- TOP LEVEL -------------------------- -- TOP LEVEL FIELDS local KARMA_DB_L1 = { VERSION = "VERSION", COMMONLIST = "COMMON", REALMLIST = "REALMS", REALM_IDS = "REALM_IDS", -- added in v13, reverse ID to realm info REALMGROUPS = "REALMGRPS", -- added in v13, timestamp cross-server links XFACTIONHOLD = "XFACTIONHOLD", -- moved to here in version 12 RELOCATIONS = "RELOCATIONS", }; --------- COMMON LEVEL -------------------------- -- COMMON LEVEL FIELDS: -> DB_L2_C local KARMA_DB_L2_C = { REGIONNAMES = "REGIONNAMES", ZONENAMES = "ZONENAMES", FACTION = "FACTIONLIST", -- unused after version 11 LOCALE = "LOCALE_", -- gets concatenated with current Locale }; -- COMMON/REGIONNAMES LEVEL FIELDS: DB_L3_CR local KARMA_DB_L3_CR = { ZONEIDS = "ZONEIDS", ISPVPZONE = "PVPZONE", ZONETYPE = "ZONETYPE" }; -- COMMON/LOCALE_* LEVEL FIELDS: TALENTS local KARMA_DB_L3_CL = { TALENTS = "TALENTS", REGIONS = "REGIONS", }; -- COMMON/FACTION LEVEL FIELDS: DB_L3_CF local KARMA_DB_L3_CF_QUESTNAMES = "QUESTNAMES"; local KARMA_DB_L3_CF_QUESTINFOS = "QUESTINFOS"; local KARMA_DB_L3_CF_RECENTLY_JOINED = "JOIN_MRU"; -- new in version 11 --------- REALM LEVEL -------------------------- -- REALM LEVEL FIELDS: DB_L3_RR local KARMA_DB_L3_RR_FACTION = "FACTIONLIST"; -- REALM/FACTION/<FACTION> LEVEL FIELDS: DB_L4_RRFF local KARMA_DB_L4_RRFF = { SERVER_ID = "SVR_ID", -- added in v13 CHARACTERLIST = "CHARACTERLIST", CHARACTER_IDS = "CHAR_IDS", -- added in v13 QUESTNAMES = "QUESTNAMES", ZONENAMES = "ZONENAMES", IGNORE24 = "IGNTMP", MEMBERLIST = "MEMBERLIST", -- No longer used after version 3 of the database MEMBERBUCKETS = "MEMBERBUCKETS", ALTGROUPS = "ALTGROUPS", XFACTIONHOLD = "XFACTIONHOLD", -- moved from here in version 12 HISTORY_MOVED = "HIST_MOVED", HISTORY_SEEN = "HIST_SEEN", }; -- REALM/FACTION/<FACTION>/CHARACTERLIST OBJECT FIELDS: DB_L5_RRFFC local KARMA_DB_L5_RRFFC = { NAME = "NAME", GUID = "GUID", -- added in v13 (server ID) KARMA_ID = "K_ID", -- added in v13 (internal ID) XPTOTAL = "XPTOTAL", XPLAST = "XPLAST", XPMAX = "XPMAX", PLAYED = "PLAYED", PLAYEDLAST = "PLAYEDLAST", CONFIGPERCHAR = "CHARCONFIG", XPLVLSUM = "XPLVLSUM", }; -- REALM/FACTION/<FACTION>/IGNORE24 OBJECT FIELDS: DB_L5_RRFFI local KARMA_DB_L5_RRFFI = { GUID = "GUID", ACTIONS = "ACTIONS", IGNORE = "IGN", TIMEOUT = "TIMEOUT", }; -- Waawaa, "local" limit: 200 -- TODO: more KARMA_DB_??_*_* -> KARMA_DB_??_*.* -- REALM/FACTION/<FACTION>/MEMBERLIST OBJECT FIELDS: DB_L5_RRFFM local KARMA_DB_L5_RRFFM = { LASTCHANGED_TIME = "TOUCH_TIME", LASTCHANGED_FIELD = "TOUCH_FIELD", LASTSEEN = "LASTSEEN", GUID = "GUID", NAME = "NAME", ALTGROUP = "ALTID", GUILD = "GUILD", LEVEL = "LEVEL", GENDER = "GENDER", RACE = "RACE", CLASS = "CLASS", CLASS_ID = "CLSID", ADDED_IN = "ADD_Z", RACE_EN = "RACEEN", CLASS_EN = "CLASSEN", }; -- #### -- local KARMA_DB_L5_RRFFM_CONFLICT = "CONFLICT"; local KARMA_DB_L5_RRFFM_TALENT = "TALENT"; local KARMA_DB_L5_RRFFM_TALENTTREE = "TALENTTREE"; local KARMA_DB_L5_RRFFM_KARMA = "KARMA"; local KARMA_DB_L5_RRFFM_NOTES = "NOTES"; local KARMA_DB_L5_RRFFM_PUBLIC_NOTES = "PUBLIC_NOTES"; -- stores imported total sum local KARMA_DB_L5_RRFFM_KARMA_IMPORTED = "K_IMP"; -- modifier for "time"-Karma: -1 = use default, 0 = off, 1 = on local KARMA_DB_L5_RRFFM_KARMA_TIME = "K_TIME"; -- old concept... dropped. -- it's impossible to add "-3 underperforming" to "+3 nice" and get a sensible result... -- must remain a while to clean out intermediate versions local KARMA_DB_L5_RRFFM_KARMA_MODSOC = "K_SOC"; local KARMA_DB_L5_RRFFM_KARMA_MODSKILL = "K_SKILL"; -- TODO: three new values to filter on... local KARMA_DB_L5_RRFFM_SKILL = "SKILL"; local KARMA_DB_L5_RRFFM_GEAR_PVP = "GEAR_PVP"; local KARMA_DB_L5_RRFFM_GEAR_PVE = "GEAR_PVE"; local KARMA_DB_L5_RRFFM_TIMESTAMP = "TIMESTAMP"; local KARMA_DB_L5_RRFFM_TIMESTAMP_TRY = "TRY"; local KARMA_DB_L5_RRFFM_TIMESTAMP_SUCCESS = "SUCCESS"; local KARMA_DB_L5_RRFFM_JOINEDLAST_TIME = "JOINEDLAST"; local KARMA_DB_L5_RRFFM_JOINEDLAST_CHAR = "JOINEDWITH"; local KARMA_DB_L5_RRFFM_KARMA_TRUST = "K_TRUST"; -- REALM/FACTION/<FACTION>/MEMBERLIST/<Bucket>/<Member>/CHARACTERS/<Character> OBJECT FIELDS: DB_L6_RRFFMCC -- character specific data -- container local KARMA_DB_L5_RRFFM_CHARACTERS = "CHARACTERSPECIFIC"; local KARMA_DB_L6_RRFFMCC_KARMA_ID = "K_IDREF"; -- data local KARMA_DB_L6_RRFFMCC_QUESTIDLIST = "QUESTIDLIST"; local KARMA_DB_L6_RRFFMCC_QUESTEXLIST = "QUESTEXLIST"; local KARMA_DB_L6_RRFFMCC_ZONEIDLIST = "ZONEIDLIST"; local KARMA_DB_L6_RRFFMCC_XP = "XP"; local KARMA_DB_L6_RRFFMCC_XPLAST = "XPLAST"; local KARMA_DB_L6_RRFFMCC_XPMAX = "XPMAX"; local KARMA_DB_L6_RRFFMCC_XPLVL = "XPLVL"; local KARMA_DB_L6_RRFFMCC_PLAYED = "PLAYED"; local KARMA_DB_L6_RRFFMCC_PLAYEDPVP = "PLAYEDPVP"; local KARMA_DB_L6_RRFFMCC_PLAYEDLAST = "PLAYEDLAST"; local KARMA_DB_L6_RRFFMCC_JOINEDLAST = "JOINEDLAST"; local KARMA_DB_L6_RRFFMCC_ACHIEVED = "ACHIEVED"; -- ../CHARACTERS/<Character>/REGIONLIST OBJECT FIELDS: DB_L7_RRFFMCCR -- region tracking: which when how long... -- container local KARMA_DB_L6_RRFFMCC_REGIONLIST = "REG_L"; -- list of -- data -- KARMA_DB_L7_RRFFMCCRR_ -> KARMA_DB_L7_RRFFMCCRR_ local KARMA_DB_L7_RRFFMCCRR_KEY = "RL_REGKEY"; -- an ID (RegionID + Difficulty!) local KARMA_DB_L7_RRFFMCCRR_ID = "RL_REGID"; -- a RegionID local KARMA_DB_L7_RRFFMCCRR_DIFF = "RL_REGDIFF"; -- a difficulty local KARMA_DB_L7_RRFFMCCRR_PLAYEDTOTAL = "REG_TOTAL"; -- summed time -- another container local KARMA_DB_L7_RRFFMCCRR_PLAYEDDAYS = "REG_DAYS"; -- list of -- and another dataset local KARMA_DB_L8_RRFFMCCRRD_KEY = "REG_DAYKEY"; -- an ID local KARMA_DB_L8_RRFFMCCRRD_START = "RD_FROM"; -- start (datetime) local KARMA_DB_L8_RRFFMCCRRD_END = "RD_TILL"; -- end (datetime) -- REALM/FACTION/<FACTION>/XFACTIONHOLD OBJECT FIELDS: additional field besides DB_L5_RRFFM local KARMA_DB_L5_RRFFX_SOURCE = "SOURCE"; local KARMA_DB_L5_RRFFX_FACTION = "FACTION"; local KARMA_ALPHACHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; -- -- Legacy broken version -- local function Karma_AccentedToPlain(thechar) if (strlen(thechar) == 1) then KarmaChatDebug("FIXME: AccentedToPlain only got initial ~ " .. debugstack()); end thechar = strsub(thechar, 1, 1); local asccode = string.byte(thechar); -- if (asccode < 127) then -- A..Z => return same if (asccode >= string.byte("A")) and (asccode <= string.byte("Z")) then return thechar; end -- a..z => return A..Z - version if (asccode >= string.byte("a")) and (asccode <= string.byte("z")) then return string.upper(thechar); end -- replace via table - broken variant :D local index, value, i; for index, value in pairs(KARMA_ALPHACHARS_ACCENT) do for i = 1, getn(value) do if value[i] == asccode then return index; end end end -- now, this might be *anything*... better throw it into a bucket we know exists --return thechar; -- choose a bucket, that is probably rarely used, but *does* exist: return "Y"; end -- --- teh new order -- local function DB_Server_ID_Init(oRealms, oRealmIDs, sRealm) local oServerFaction = oRealms[sRealm]; local iServerID = oServerFaction[KARMA_DB_L4_RRFF.SERVER_ID]; if (iServerID == nil) then local i, sServer, oServer = 0; for sServer, oServer in pairs(oRealms) do i = math.max(i, oServer[KARMA_DB_L4_RRFF.SERVER_ID] or 0); end iServerID = i + 1; oServerFaction[KARMA_DB_L4_RRFF.SERVER_ID] = iServerID; oRealmIDs[iServerID] = sRealm; end return iServerID; end local function DB_Char_ID_Init(iServerID, oCharacters, oCharIDs, sCharacter) iServerID = bit.lshift(iServerID, 16); local oCharacter = oCharacters[sCharacter]; local iCharID = oCharacter[KARMA_DB_L5_RRFFC.KARMA_ID]; if (iCharID == nil) then local i, sChar, oChar = iServerID; for sChar, oChar in pairs(oCharacters) do i = math.max(i, oChar[KARMA_DB_L5_RRFFC.KARMA_ID] or iServerID); end oCharacter[KARMA_DB_L5_RRFFC.KARMA_ID] = i + 1; oCharIDs[i + 1] = sCharacter; end end function KarmaObj.DB.ServerExists(sRealm) return (type(sRealm) == "string") and (type(KDBC.Faction[KARMA_DB_L1.REALMGROUPS][sRealm]) == "table"); end function KarmaObj.DB.ServerCreate(oFactionDB, sRealm, bPartial) if ((type(oFactionDB) ~= "table") or (type(sRealm) ~= "string")) then KarmaChatDebug("Improper args to ServerCreate: " .. tostring(oFactionDB) .. " / " .. tostring(sRealm)); return end if (strlen(sRealm) < 5) then KarmaChatDebug("Improper arg to ServerCreate: <" .. sRealm .. ">"); return end -- <FACTIONDB> = {}; -- REALMS = {}; -- <REALMNAME> = {}; -- <FACTIONDB>/REALMS KOH.TableInit(oFactionDB, KARMA_DB_L1.REALMGROUPS); if (type(oFactionDB[KARMA_DB_L1.REALMGROUPS][sRealm]) ~= "table") then KarmaChatSecondary("Adding new container for server <" .. sRealm .. ">..."); end KOH.TableInit(oFactionDB[KARMA_DB_L1.REALMGROUPS], sRealm); -- <FACTIONDB>/REALMS["realmName"] KOH.TableInit(oFactionDB, KARMA_DB_L1.REALMLIST); KOH.TableInit(oFactionDB[KARMA_DB_L1.REALMLIST], sRealm); local oServerFaction = oFactionDB[KARMA_DB_L1.REALMLIST][sRealm]; KOH.TableInit(oFactionDB, KARMA_DB_L1.REALM_IDS); local iServerID = DB_Server_ID_Init(oFactionDB[KARMA_DB_L1.REALMLIST], oFactionDB[KARMA_DB_L1.REALM_IDS], sRealm); ------------------------------------------------------------------------ -- ROOT/REALMS["realmName"]/FACTIONS["factionname]/MEMBERBUCKETS KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.MEMBERBUCKETS); local buckets, i = {}; for i = 1, strlen(KARMA_ALPHACHARS) do local sBucketName = strsub(KARMA_ALPHACHARS, i, i); KOH.TableInit(oServerFaction[KARMA_DB_L4_RRFF.MEMBERBUCKETS], sBucketName); end ------------------------------------------------------------------------ -- ROOT/REALMS["realmName"]/FACTIONS["factionname]/ALTGROUPS KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.ALTGROUPS); ------------------------------------------------------------------------ if (not bPartial) then KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.CHARACTERLIST); KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.CHARACTER_IDS); -- KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.QUESTNAMES); -- KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.ZONENAMES); KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.IGNORE24); KarmaObj.DB.I24.Clean(oServerFaction); end return iServerID, oServerFaction; end function KarmaObj.DB.Create() local sRealm; if (GetRealmName ~= nil) then -- 5.4: realmname is no longer a global variable sRealm = GetRealmName(); else sRealm = GetCVar("realmName"); end local sPlayerFaction = UnitFactionGroup("player"); if ((sRealm == nil) or (sPlayerFaction == nil)) then local s = ""; if (sRealm == nil) then s = s .. "/realm name"; end if (sPlayerFaction == nil) then s = s .. "/character faction"; end DEFAULT_CHAT_FRAME:AddMessage("Karma: |cFFFF8080Fatal initialization error! Couldn't determine your " .. strsub(s, 2) .. "!! DB remains uninitialized.|r"); return -1 end local oFactionDB = _G["KarmaAvEnK" .. sPlayerFaction]; if (type(oFactionDB) ~= "table") then DEFAULT_CHAT_FRAME:AddMessage("Karma: |cFFFF8080Fatal initialization error! Couldn't initialize the load-on demand module for your faction (" .. sPlayerFaction .. ")!! DB remains uninitialized.|r (Make sure the module KarmaDB" .. sPlayerFaction .. " is enabled.)"); return -1 end local sPlayername = UnitName("player"); KDBC.Faction = oFactionDB; KDBC.Realm = sRealm; KDBC.PlayerFaction = sPlayerFaction; KDBC.PlayerName = sPlayername; KDBC.Locale = GetLocale(); -- This creates fields in the database as we need them. Thus it is perfectly -- safe to call this function over and over again, as it only adds fields as they -- are required. -- At the end of this function, we will have an empty skeleton database setup. ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- ROOT if (type(KarmaData) ~= "table") then KarmaData = {}; end Karma_FieldInitialize(KarmaData, KARMA_DB_L1.VERSION, KARMA_SUPPORTEDDATABASEVERSION); ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- Questlists, Zonelists, and Subzonelists NEED NOT be per server! -- ROOT/COMMON KOH.TableInit(KarmaData, KARMA_DB_L1.COMMONLIST); local oGlobalCommon = KarmaData[KARMA_DB_L1.COMMONLIST]; KOH.TableInit(oFactionDB, KARMA_DB_L1.COMMONLIST); local oFactionCommon = oFactionDB[KARMA_DB_L1.COMMONLIST]; -- ROOT/COMMON/REGIONNAMES KOH.TableInit(oGlobalCommon, KARMA_DB_L2_C.REGIONNAMES); local CommonZoneList = oGlobalCommon[KARMA_DB_L2_C.REGIONNAMES]; for k, v in pairs(CommonZoneList) do if (type(v) ~= "table") then KOH.TableInit(CommonZoneList, k); KOH.TableInit(CommonZoneList[k], KARMA_DB_L3_CR.ZONEIDS); end end -- ROOT/COMMON/ZONENAMES KOH.TableInit(oGlobalCommon, KARMA_DB_L2_C.ZONENAMES); -- ROOT/COMMON: /LOCALE_*/TALENTS local sLocale = KARMA_DB_L2_C.LOCALE .. KDBC.Locale; KOH.TableInit(oGlobalCommon, sLocale); local oGlobalCommonLocale = oGlobalCommon[sLocale]; KOH.TableInit(oGlobalCommonLocale, KARMA_DB_L3_CL.TALENTS); ------------------------------------------------------------------------ --[[ -- ROOT = {}; -- COMMON = {}; -- FACTIONLIST = {}; -- <Faction> = {}; -- QUESTNAMES = {}; -- ROOT/COMMON/FACTIONLIST KOH.TableInit(oGlobalCommon, KARMA_DB_L2_C.FACTION); -- ROOT/COMMON/FACTIONLIST[<Faction>] local oCommonFactionList = oGlobalCommon[KARMA_DB_L2_C.FACTION]; KOH.TableInit(oCommonFactionList, sPlayerFaction); -- ROOT/COMMON/FACTIONLIST[<Faction>]/QUESTNAMES local oGlobalCommonFaction = oCommonFactionList[sPlayerFaction]; KOH.TableInit(oGlobalCommonFaction, KARMA_DB_L3_CF_QUESTNAMES); KOH.TableInit(oGlobalCommonFaction, KARMA_DB_L3_CF_QUESTINFOS); KDBC.CommonFactionObject = oGlobalCommonFaction; ]]-- ------------------------------------------------------------------------ -- <FACTIONDB> = {}; -- COMMON = {}; -- QUESTNAMES = {}; -- QUESTINFOS = {}; KOH.TableInit(oFactionCommon, KARMA_DB_L3_CF_QUESTNAMES); KOH.TableInit(oFactionCommon, KARMA_DB_L3_CF_QUESTINFOS); KOH.TableInit(oFactionCommon, KARMA_DB_L3_CF_RECENTLY_JOINED); KOH.TableInit(oFactionCommon[KARMA_DB_L3_CF_RECENTLY_JOINED], sRealm); KDBC.CommonFactionObject = oFactionCommon; ------------------------------------------------------------------------ ------------------------------------------------------------------------ ------------------------------------------------------------------------ -- relocation records: store if and which data is stored in LOD modules -- ROOT/RELOCATIONS KOH.TableInit(KarmaData, KARMA_DB_L1.RELOCATIONS); -- ROOT/XFACTIONHOLD (moved up in v12 to avoid loading XFaction DBs) KOH.TableInit(KarmaData, KARMA_DB_L1.XFACTIONHOLD); ------------------------------------------------------------------------ local iServerID, oServerFaction = KarmaObj.DB.ServerCreate(oFactionDB, sRealm); ------------------------------------------------------------------------ -- ROOT/REALMS["realmName"]/FACTIONS["factionname]/CHARACTERLIST local oCharacters = oServerFaction[KARMA_DB_L4_RRFF.CHARACTERLIST]; KOH.TableInit(oCharacters, sPlayername); local oCharIDs = oServerFaction[KARMA_DB_L4_RRFF.CHARACTER_IDS]; DB_Char_ID_Init(iServerID, oCharacters, oCharIDs, sPlayername); -- ROOT/REALMS["realmName"]/FACTIONS["factionname]/CHARACTERLIST["player"] local oCharacter = oCharacters[sPlayername]; Karma_FieldInitialize(oCharacter, KARMA_DB_L5_RRFFC.NAME, sPlayername); Karma_FieldInitialize(oCharacter, KARMA_DB_L5_RRFFC.GUID, UnitGUID("player")); Karma_FieldInitialize(oCharacter, KARMA_DB_L5_RRFFC.XPTOTAL, 0); Karma_FieldInitialize(oCharacter, KARMA_DB_L5_RRFFC.XPLAST, UnitXP("player")); Karma_FieldInitialize(oCharacter, KARMA_DB_L5_RRFFC.XPMAX, UnitXPMax("player")); Karma_FieldInitialize(oCharacter, KARMA_DB_L5_RRFFC.XPLVLSUM, 0); KOH.TableInit(oCharacter, KARMA_DB_L5_RRFFC.CONFIGPERCHAR); ------------------------------------------------------------------------ KDBC.FactionObjectCache = nil; ------------------------------------------------------------------------ -- ROOT/REALMS["realmName"]/FACTIONS["factionname]/HISTORY -- this is a list of { ["name"] = timestamp } and describes old entries which were moved out to KarmaTrans/KarmaHistory KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.HISTORY_MOVED); -- this is a list of { ["name"] = timestamp } and describes entries which should be pulled back as the player is back KOH.TableInit(oServerFaction, KARMA_DB_L4_RRFF.HISTORY_SEEN); return 1; end function KarmaObj.DB.Upgrade() --DEFAULT_CHAT_FRAME:AddMessage("DBU: " .. KarmaData[KARMA_DB_L1.VERSION] .. " -> " .. KARMA_SUPPORTEDDATABASEVERSION); if (KarmaData[KARMA_DB_L1.VERSION] == KARMA_SUPPORTEDDATABASEVERSION) then --DEFAULT_CHAT_FRAME:AddMessage("DBU: nothing to do."); return end if (KarmaData[KARMA_DB_L1.VERSION] > KARMA_SUPPORTEDDATABASEVERSION) then DEFAULT_CHAT_FRAME:AddMessage("Karma: |cFFFF8080You downgraded Karma to a previous version. Will NOT touch database with unknown changes in format.|r"); return -1 end --DEFAULT_CHAT_FRAME:AddMessage("DBU: precheck of DB..."); local bLoadOk = true; if (not IsAddOnLoaded("KarmaDBAlliance")) then local iLoaded, sWhyNot = LoadAddOn("KarmaDBAlliance"); if (not iLoaded) then bLoadOk = false; KarmaChatDebug("DB Alliance: " .. sWhyNot); end end if (not IsAddOnLoaded("KarmaDBHorde")) then local iLoaded, sWhyNot = LoadAddOn("KarmaDBHorde"); if (not iLoaded) then bLoadOk = false; KarmaChatDebug("DB Horde: " .. sWhyNot); end end if (not bLoadOk or (type(KarmaAvEnKAlliance) ~= "table") or (type(KarmaAvEnKHorde) ~= "table")) then DEFAULT_CHAT_FRAME:AddMessage("Karma: |cFFFF8080Update of database required, but could not load the load-on-demand modules for both factions successfully.|r"); return -1 end if (KarmaData[KARMA_DB_L1.VERSION] <= 10) then local realmlist, realmname, realmdata; local factionlist, factionname, factiondata; -- check for missing outer tables outside the loop: realmlist = KarmaData[KARMA_DB_L1.REALMLIST]; if (type(realmlist) ~= "table") then -- something has to go wrong in a very weird way for this return -1 end for realmname, realmdata in pairs(realmlist) do if (type(realmdata) ~= "table") then -- Hm. Giving up. return -1 end factionlist = realmdata[KARMA_DB_L3_RR_FACTION]; if (type(factionlist) ~= "table") then if (factionlist ~= nil) then -- Hm. Giving up. return -1 else -- create the missing table realmdata[KARMA_DB_L3_RR_FACTION] = {}; factionlist = realmdata[KARMA_DB_L3_RR_FACTION]; end end for factionname, factiondata in pairs(factionlist) do if (type(factiondata) ~= "table") then -- Hm. Giving up. return -1 end end end end --DEFAULT_CHAT_FRAME:AddMessage("DBU: upgrade in progress..."); -- force reinit, if it already happened KDBC.FactionObjectCache = nil; -- Loop until the database has been upgraded all the iterations of the formats between. -- (it actually is NOT a loop, as every next version upgrade is following after the previous in the first pass) if (KarmaData[KARMA_DB_L1.VERSION] ~= KARMA_SUPPORTEDDATABASEVERSION) then local iVersion = KarmaData[KARMA_DB_L1.VERSION] or 2; KarmaChatDefault("Upgrading DB version from " .. iVersion .. " to " .. (iVersion + 1) .. "..."); --- --- Upgrade from version 2 --> version 3 --- if (KarmaData[KARMA_DB_L1.VERSION] == 2) then local realmlist, realmname, realmdata = KarmaData[KARMA_DB_L1.REALMLIST]; for realmname, realmdata in pairs(realmlist) do -- Update to the version 3 database. -- Changes are only mandatory field additions to the -- Characterlist entries -- Memberlist Entries local factionlist, factionname, factiondata = realmdata[KARMA_DB_L3_RR_FACTION]; for factionname, factiondata in pairs(factionlist) do local ckey, cvalue; for ckey, cvalue in pairs(factiondata[KARMA_DB_L4_RRFF.CHARACTERLIST]) do if (cvalue ~= nil) then cvalue[KARMA_DB_L5_RRFFC.PLAYED] = 0; cvalue[KARMA_DB_L5_RRFFC.PLAYEDLAST] = 0; end end local mkey, mvalue; for mkey, mvalue in pairs(factiondata[KARMA_DB_L4_RRFF.MEMBERLIST]) do if (mvalue ~= nil) then KOH.TableInit(mvalue, KARMA_DB_L5_RRFFM_CHARACTERS); local key, value; for key, value in pairs(mvalue[KARMA_DB_L5_RRFFM_CHARACTERS]) do if (value ~= nil) then cspecificobject = value; cspecificobject[KARMA_DB_L6_RRFFMCC_PLAYED] = 0; cspecificobject[KARMA_DB_L6_RRFFMCC_PLAYEDLAST] = 0; end end end end end end KarmaData[KARMA_DB_L1.VERSION] = 3; end --- --- End upgrade version 2 --> version 3 --- --- --- Upgrade from version 3 --> version 4 --- if (KarmaData[KARMA_DB_L1.VERSION] == 3) then local realmlist, realmname, realmdata = KarmaData[KARMA_DB_L1.REALMLIST]; for realmname, realmdata in pairs(realmlist) do -- put lMembers into buckets for quicker sorting, and accessing. local factionlist, factionname, factiondata = realmdata[KARMA_DB_L3_RR_FACTION]; for factionname, factiondata in pairs(factionlist) do local buckets = {}; local i = 0; local sBucketName; for i = 1, strlen(KARMA_ALPHACHARS) do sBucketName = strsub(KARMA_ALPHACHARS, i, i); buckets[sBucketName] = {}; end factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS] = buckets; local mkey, mvalue; for mkey, mvalue in pairs(factiondata[KARMA_DB_L4_RRFF.MEMBERLIST]) do if (mvalue ~= nil) then sBucketName = Karma_AccentedToPlain(mkey); factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS][sBucketName][mkey] = mvalue; end end factiondata[KARMA_DB_L4_RRFF.MEMBERLIST] = nil; -- no longer used get rid of the extra data end end KarmaData[KARMA_DB_L1.VERSION] = 4; end --- --- End upgrade version 3 --> version 4; --- local realmlist, realmname, realmdata; local factionlist, factionname, factiondata; local bkey, bvalue, ckey, cvalue, mkey, mvalue, key, value; local cspecificobject; --- --- Upgrade from version 4 --> version 5 --- if (KarmaData[KARMA_DB_L1.VERSION] == 4) then realmlist = KarmaData[KARMA_DB_L1.REALMLIST]; for realmname, realmdata in pairs(realmlist) do -- add container for zone tracking factionlist = realmdata[KARMA_DB_L3_RR_FACTION]; for factionname, factiondata in pairs(factionlist) do if (factionname ~= nil) then for bkey, bvalue in pairs(factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do for mkey, mvalue in pairs(bvalue) do if (mvalue~= nil) then for ckey, cvalue in pairs(mvalue[KARMA_DB_L5_RRFFM_CHARACTERS]) do cvalue[KARMA_DB_L6_RRFFMCC_ZONEIDLIST] = {}; end end end end end end end KarmaData[KARMA_DB_L1.VERSION] = 5; end --- --- End upgrade version 4 --> version 5; --- --- --- Upgrade from version 5 --> version 6 --- if (KarmaData[KARMA_DB_L1.VERSION] == 5) then realmlist = KarmaData[KARMA_DB_L1.REALMLIST] or {}; for realmname, realmdata in pairs(realmlist) do -- put lMembers into buckets for quicker sorting, and accessing. factionlist = realmdata[KARMA_DB_L3_RR_FACTION] or {}; for factionname, factiondata in pairs(factionlist) do if (factionname ~= nil) then for bkey, bvalue in pairs(factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do for mkey, mvalue in pairs(bvalue) do if (mvalue~= nil) then for ckey, cvalue in pairs(factiondata[KARMA_DB_L4_RRFF.CHARACTERLIST]) do if (ckey~= nil and ckey~= "") then Karma_MemberList_Add(mkey, factiondata); end end end end end end end end KarmaData[KARMA_DB_L1.VERSION] = 6; end --- --- End upgrade version 5 --> version 6; --- --- --- Upgrade from version 6 --> version 7 --- if (KarmaData[KARMA_DB_L1.VERSION] == 6) then realmlist = KarmaData[KARMA_DB_L1.REALMLIST] or {}; for realmname, realmdata in pairs(realmlist) do -- put lMembers into buckets for quicker sorting, and accessing. factionlist = realmdata[KARMA_DB_L3_RR_FACTION] or {}; for factionname, factiondata in pairs(factionlist) do if (factionname ~= nil) then for bkey, bvalue in pairs(factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do for mkey, mvalue in pairs(bvalue) do if (mvalue~= nil) then mvalue[KARMA_DB_L5_RRFFM.GENDER] = -1; end end end end end end KarmaData[KARMA_DB_L1.VERSION] = 7; end --- --- End upgrade version 6 --> version 7; --- --- --- Upgrade from version 7 --> version 8 --- if (KarmaData[KARMA_DB_L1.VERSION] == 7) then realmlist = KarmaData[KARMA_DB_L1.REALMLIST]; for realmname, realmdata in pairs(realmlist) do factionlist = realmdata[KARMA_DB_L3_RR_FACTION]; for factionname, factiondata in pairs(factionlist) do if (factionname ~= nil) then -- move zonelists and questlists to global local factionzonelist = factiondata[KARMA_DB_L4_RRFF.ZONENAMES]; local zonetranslationlist = {}; local zkey, zvalue; for zkey, zvalue in pairs(factionzonelist) do zonetranslationlist[zkey] = CommonRegionZoneAdd(nil, zvalue, nil, nil); end local factionquestlist = factiondata[KARMA_DB_L4_RRFF.QUESTNAMES]; local questtranslationlist = {}; local qkey, qvalue; for qkey, qvalue in pairs(factionquestlist) do local qix = KarmaObj.DB.CF.QuestListAdd(qvalue, factionname); if (qix) then questtranslationlist[qkey] = qix; else return -1; end end local bkey, bvalue; for bkey, bvalue in pairs(factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do for mkey, mvalue in pairs(bvalue) do if (mvalue~= nil) then local charspecificlist = mvalue[KARMA_DB_L5_RRFFM_CHARACTERS]; for ckey, cvalue in pairs(charspecificlist) do local charzonelist = cvalue[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]; for zkey, zvalue in pairs(charzonelist) do if (zvalue > 0) then local tmpzvalue = zonetranslationlist[zvalue]; local newzvalue; if (tmpzvalue == nil) then KarmaChatDebug(mkey.."::"..ckey..": ["..zkey.."] = "..zvalue.." => nil!"); newzvalue = 0; else newzvalue = -tmpzvalue; end charzonelist[zkey] = newzvalue; end end local charquestlist = cvalue[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]; for qkey, qvalue in pairs(charquestlist) do if (qvalue > 0) then local tmpqvalue = questtranslationlist[qvalue]; local newqvalue; if (tmpqvalue == nil) then KarmaChatDebug(mkey.."::"..ckey..": ["..qkey.."] = "..qvalue.." => nil!"); newqvalue = 0; else newqvalue = -tmpqvalue; end charquestlist[qkey] = newqvalue; end end end end end end end end end for realmname, realmdata in pairs(realmlist) do factionlist = realmdata[KARMA_DB_L3_RR_FACTION] or {}; for factionname, factiondata in pairs(factionlist) do if (factionname ~= nil) then -- remove local zonelists and questlists factiondata[KARMA_DB_L4_RRFF.QUESTNAMES] = nil; factiondata[KARMA_DB_L4_RRFF.ZONENAMES] = nil; end end end KarmaData[KARMA_DB_L1.VERSION] = 8; end --- --- End upgrade version 7 --> version 8 --- --- --- Upgrade from version 8 --> version 9 --- if (KarmaData[KARMA_DB_L1.VERSION] == 8) then realmlist = KarmaData[KARMA_DB_L1.REALMLIST] or {}; for realmname, realmdata in pairs(realmlist) do factionlist = realmdata[KARMA_DB_L3_RR_FACTION] or {}; for factionname, factiondata in pairs(factionlist) do if (factionname ~= nil) then for bkey, bvalue in pairs(factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do for mkey, mvalue in pairs(bvalue) do if (mvalue~= nil) then local charspecificlist = mvalue[KARMA_DB_L5_RRFFM_CHARACTERS]; for ckey, cvalue in pairs(charspecificlist) do local charquestexlist = cvalue[KARMA_DB_L6_RRFFMCC_QUESTEXLIST]; if (type(charquestexlist) == "table") then for qid, qexl in pairs(charquestexlist) do local qexlnew = {}; for qkey, qvalue in pairs(qexl) do if (type(qkey) == "number") then qexlnew["O." .. qkey] = qvalue; else qexlnew[qkey] = qvalue; end end charquestexlist[qid] = qexlnew; end end end end end end end end end KarmaData[KARMA_DB_L1.VERSION] = 9; end --- --- End upgrade version 8 --> version 9 --- --- --- Upgrade from version 9 --> version 10 --- if (KarmaData[KARMA_DB_L1.VERSION] == 9) then realmlist = KarmaData[KARMA_DB_L1.REALMLIST] or {}; for realmname, realmdata in pairs(realmlist) do factionlist = realmdata[KARMA_DB_L3_RR_FACTION] or {}; local sBucketOld, sBucketNew; for factionname, factiondata in pairs(factionlist) do for bkey, bvalue in pairs(factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do for mkey, mvalue in pairs(bvalue) do sBucketOld = Karma_AccentedToPlain(mkey); sBucketNew = KarmaObj.NameToBucket(mkey); if (sBucketOld ~= sBucketNew) then factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS][sBucketNew][mkey] = mvalue; factiondata[KARMA_DB_L4_RRFF.MEMBERBUCKETS][sBucketOld][mkey] = nil; KarmaChatDebug("DBUpdate(9->10): Moved <" .. mkey .. "> from Bucket " .. sBucketOld .. " to " .. sBucketNew .. "."); end end end end end KarmaData[KARMA_DB_L1.VERSION] = 10; end --- --- End upgrade version 9 --> version 10 --- --- --- Upgrade from version 10 --> version 11 --- if (KarmaData[KARMA_DB_L1.VERSION] == 10) then local oCommonFactionList, sFaction, oFactionGlobalDB = KarmaData[KARMA_DB_L1.COMMONLIST][KARMA_DB_L2_C.FACTION]; for sFaction, oFactionGlobalDB in pairs(oCommonFactionList) do local oFactionLocalDB = _G["KarmaAvEnK" .. sFaction][KARMA_DB_L1.COMMONLIST]; if (type(oFactionLocalDB) ~= "table") then _G["KarmaAvEnK" .. sFaction][KARMA_DB_L1.COMMONLIST] = {}; oFactionLocalDB = _G["KarmaAvEnK" .. sFaction][KARMA_DB_L1.COMMONLIST]; end local oFields, iQuest, sQuest = { KARMA_DB_L3_CF_QUESTNAMES, KARMA_DB_L3_CF_QUESTINFOS }; for iQuest, sQuest in pairs(oFields) do if ((type(oFactionGlobalDB[sQuest]) == "table") and not KOH.TableIsEmpty(oFactionGlobalDB[sQuest])) then oFactionLocalDB[sQuest] = oFactionGlobalDB[sQuest]; end oFactionGlobalDB[sQuest] = nil; end end KarmaData[KARMA_DB_L1.COMMONLIST][KARMA_DB_L2_C.FACTION] = nil; KDBC.CommonFactionObject = oFactionCommon; KOH.TableInit(KarmaAvEnKAlliance, KARMA_DB_L1.REALMLIST); KOH.TableInit(KarmaAvEnKHorde, KARMA_DB_L1.REALMLIST); realmlist = KarmaData[KARMA_DB_L1.REALMLIST] or {}; for realmname, realmdata in pairs(realmlist) do factionlist = realmdata[KARMA_DB_L3_RR_FACTION] or {}; for factionname, factiondata in pairs(factionlist) do local oFactionDB = _G["KarmaAvEnK" .. factionname]; oFactionDB[KARMA_DB_L1.REALMLIST][realmname] = factiondata; end end KarmaData[KARMA_DB_L1.REALMLIST] = nil; KarmaData[KARMA_DB_L1.VERSION] = 11; end --- --- End upgrade version 10 --> version 11 --- --- --- Upgrade from version 11 --> version 12 --- if (KarmaData[KARMA_DB_L1.VERSION] == 11) then local oFactionDBs, sFaction, oFactionDB = { ["Alliance"] = KarmaAvEnKAlliance, ["Horde"] = KarmaAvEnKHorde }; for sFaction, oFactionDB in pairs(oFactionDBs) do realmlist = oFactionDB[KARMA_DB_L1.REALMLIST] or {}; for realmname, realmdata in pairs(realmlist) do if realmdata[KARMA_DB_L4_RRFF.XFACTIONHOLD] then local oXFactionHold = KarmaData[KARMA_DB_L1.XFACTIONHOLD]; KOH.TableInit(oXFactionHold, realmname); oXFactionHold[sFaction] = realmdata[KARMA_DB_L4_RRFF.XFACTIONHOLD]; end end end KarmaData[KARMA_DB_L1.VERSION] = 12; end --- --- End upgrade version 11 --> version 12 --- --- --- Upgrade from version 12 --> version 13 --- if (KarmaData[KARMA_DB_L1.VERSION] == 12) then local oFactionDBs, sFaction, oFactionDB = { ["Alliance"] = KarmaAvEnKAlliance, ["Horde"] = KarmaAvEnKHorde }; for sFaction, oFactionDB in pairs(oFactionDBs) do realmlist = oFactionDB[KARMA_DB_L1.REALMLIST]; if (type(realmlist) == "table") then KOH.TableInit(oFactionDB, KARMA_DB_L1.REALM_IDS); local oRealmIDs = oFactionDB[KARMA_DB_L1.REALM_IDS]; -- initialize all the IDs we require for realmname, realmdata in pairs(realmlist) do local iServerID = DB_Server_ID_Init(realmlist, oRealmIDs, realmname); local oCharacters = realmdata[KARMA_DB_L4_RRFF.CHARACTERLIST]; if (type(oCharacters) == "table") then KOH.TableInit(realmdata, KARMA_DB_L4_RRFF.CHARACTER_IDS); local oCharIDs = realmdata[KARMA_DB_L4_RRFF.CHARACTER_IDS]; for ckey, cvalue in pairs(oCharacters) do DB_Char_ID_Init(iServerID, oCharacters, oCharIDs, ckey); end end end else realmlist = {}; end -- insert the IDs in all the right places for realmname, realmdata in pairs(realmlist) do local iServerID = realmdata[KARMA_DB_L4_RRFF.SERVER_ID]; for bkey, bvalue in pairs(realmdata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do for mkey, mvalue in pairs(bvalue) do local oCharsOld = mvalue[KARMA_DB_L5_RRFFM_CHARACTERS]; if (type(oCharsOld) == "table") then local oCharsNew = {}; for ckey, cvalue in pairs(oCharsOld) do local sCombined = ckey .. '@' .. realmname; local iID = KarmaObj.DB.MC.NameToID(sCombined, oFactionDB); if (iID == nil) then KarmaChatDebugStack("Failed to resolve [" .. sCombined .. "]", nil, true); return -1; end cvalue[KARMA_DB_L6_RRFFMCC_KARMA_ID] = iID; tinsert(oCharsNew, cvalue); end mvalue[KARMA_DB_L5_RRFFM_CHARACTERS] = oCharsNew; end end end end end KarmaData[KARMA_DB_L1.VERSION] = 13; end --- --- End upgrade version 12 --> version 13 --- --- --- Upgrade from version 13 --> version 14 --- if (KarmaData[KARMA_DB_L1.VERSION] == 13) then local oFactionDBs, sFaction, oFactionDB = { ["Alliance"] = KarmaAvEnKAlliance, ["Horde"] = KarmaAvEnKHorde }; for sFaction, oFactionDB in pairs(oFactionDBs) do realmlist = oFactionDB[KARMA_DB_L1.REALMLIST] or {}; local oServers = {}; local oMovables = {}; for realmname, realmdata in pairs(realmlist) do for bkey, bvalue in pairs(realmdata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do for mkey, mvalue in pairs(bvalue) do if (strfind(mvalue[KARMA_DB_L5_RRFFM.NAME], '@', 1, true)) then local sName, sServer = strsplit('@', mvalue[KARMA_DB_L5_RRFFM.NAME]); oServers[sServer] = true; mvalue[KARMA_DB_L5_RRFFM.NAME] = sName; tinsert(oMovables, { Bucket = bkey, Name = sName, Server = sServer, Data = mvalue } ); bvalue[mkey] = nil; end end end end local iCnt, i = #oMovables; for realmname, realmdata in pairs(oServers) do local _, oServerFaction = KarmaObj.DB.ServerCreate(oFactionDB, realmname, true); local oBuckets = oServerFaction[KARMA_DB_L4_RRFF.MEMBERBUCKETS]; local iMoveCnt = 0; local iMergeCnt = 0; for i = 1, iCnt do if (oMovables[i].Server == realmname) then local oMove = oMovables[i]; if (oBuckets[oMove.Bucket][oMove.Name] == nil) then iMoveCnt = iMoveCnt + 1; oBuckets[oMove.Bucket][oMove.Name] = oMove.Data; else iMergeCnt = iMergeCnt + 1; KarmaObj.DB.MergeChar(oBuckets[oMove.Bucket][oMove.Name], oMove.Data); end end end KarmaChatDebug("DB upgrade: XServer moves to <" .. realmname .. ">: " .. iMoveCnt .. " moves, " .. iMergeCnt .. " merges."); end end KarmaData[KARMA_DB_L1.VERSION] = 14; end --- --- End upgrade version 13 --> version 14 --- end KarmaChatDefault("DB upgrade complete."); KarmaChatDebugStack("DB upgrade via"); end function KarmaObj.DB.TankByClass() local iRealmCnt, iMemberCnt, iRegLCnt, iRegDaysCnt = 0, 0, 0, 0; local oTank, iDateFrom, iDateTo = { DEATHKNIGHT = {}, DRUID = {}, PALADIN = {}, WARRIOR = {} }; local oFactionDBs, sFaction, oFactionDB = { ["Alliance"] = KarmaAvEnKAlliance, ["Horde"] = KarmaAvEnKHorde }; for sFaction, oFactionDB in pairs(oFactionDBs) do local realmlist, realmname, realmdata; realmlist = oFactionDB[KARMA_DB_L1.REALMLIST] or {}; local oServers = {}; local oMovables = {}; for realmname, realmdata in pairs(realmlist) do iRealmCnt = iRealmCnt + 1; local bkey, bvalue; for bkey, bvalue in pairs(realmdata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do local mkey, mvalue; for mkey, mvalue in pairs(bvalue) do iMemberCnt = iMemberCnt + 1; local sClass, oRegL = mvalue["CLASSEN"]; if (sClass and mvalue["CHARACTERSPECIFIC"]) then local oCharKey, oCharValue; for oCharKey, oCharValue in pairs(mvalue["CHARACTERSPECIFIC"]) do oRegL = oCharValue["REG_L"]; if (oRegL) then iRegLCnt = iRegLCnt + 1; local rgkey, rgvalue, rdkey, rdvalue; for rgkey, rgvalue in pairs(oRegL) do if (rgvalue["REG_DAYS"]) then iRegDaysCnt = iRegDaysCnt + 1; local iDiff = rgvalue["RL_REGDIFF"]; for rdkey, rdvalue in pairs(rgvalue["REG_DAYS"]) do if (rdvalue["RD_ROLE"] == 1) then local iDate = rdvalue["REG_DAYKEY"]; if (not iDateFrom or iDate < iDateFrom) then iDateFrom = iDate; end if (not iDateTo or iDate > iDateTo) then iDateTo = iDate; end if (mvalue["LEVEL"] < 36) then oTank[sClass][iDiff + 10] = (oTank[sClass][iDiff + 10] or 0) + 1; else oTank[sClass][iDiff] = (oTank[sClass][iDiff] or 0) + 1; end end end end end end end end end end end end -- KarmaChatDefault("Across " .. iRealmCnt .. " servers, " .. iMemberCnt .. " players, " .. iRegLCnt .. " groupage sections, " .. iRegDaysCnt .. " groups:"); KarmaChatDefault("Between " .. date("%Y-%m-%d", iDateFrom) .. " and " .. date("%Y-%m-%d", iDateTo) .. ": (class, total, normal, heroic)"); local sClass, iCounts; for sClass, iCounts in pairs(oTank) do KarmaChatDefault(sClass .. ": " .. ((iCounts[1] or 0) + (iCounts[2] or 0)) .. " (" .. (iCounts[1] or "") .. " | " .. (iCounts[2] or "") .. ", " .. (iCounts[11] or 0) .. ")"); end -- KarmaChatDefault("---"); end --############################################################################################### --############################################################################################### --############################################################################################### ----------------------------------------- -- Global Lists ----------------------------------------- function KarmaObj.DB.ServerName() return KDBC.Realm; end --############################################################################################### --############################################################################################### --############################################################################################### ----------------------------------------- -- Common/Global ----------------------------------------- function KarmaObj.DB.CG.RegionListGet() KarmaObj.ProfileStart("DB.CG.RegionListGet"); local CommonRegionList = KarmaData[KARMA_DB_L1.COMMONLIST][KARMA_DB_L2_C.REGIONNAMES]; KarmaObj.ProfileStop("DB.CG.RegionListGet"); return CommonRegionList; end function KarmaObj.DB.CG.ZoneListGet() KarmaObj.ProfileStart("DB.CG.ZoneListGet"); local CommonZoneList = KarmaData[KARMA_DB_L1.COMMONLIST][KARMA_DB_L2_C.ZONENAMES]; KarmaObj.ProfileStop("DB.CG.ZoneListGet"); return CommonZoneList; end function KarmaObj.DB.CG.LocaleTalentGet(iSpecID, sClassEN) KarmaObj.ProfileStart("DB.CG.LocaleTalentGet"); local oGlobalCommon = KarmaData[KARMA_DB_L1.COMMONLIST]; local sLocale = KARMA_DB_L2_C.LOCALE .. KDBC.Locale; local oGlobalCommonLocale = oGlobalCommon[sLocale]; local LocaleTalents = oGlobalCommonLocale[KARMA_DB_L3_CL.TALENTS]; if (type(LocaleTalents[iSpecID]) ~= "table") then local sRole = GetSpecializationRoleByID(iSpecID); if (sRole) then -- extra request for role plus check seems like a detour, -- as the Info also contains the role at pos #6 local _, sName, sDescription, sIcon = GetSpecializationInfoByID(iSpecID); if (sName) then if (sClassEN == nil) then local sClassLowercase = select(2, strsplit("_", sIcon)); sClassEN = strupper(KarmaObj.UTF8.SubInChars(sClassLowercase, 1, 1)) .. KarmaObj.UTF8.SubInChars(sClassLowercase, 2); end LocaleTalents[iSpecID] = { Name = sName, ClassEN = sClassEN, Desc = sDescription, Role = sRole }; end end end KarmaObj.ProfileStop("DB.CG.LocaleTalentGet"); return LocaleTalents[iSpecID]; end -- -- -- local oRegion2AreaID; function KarmaObj.DB.CG.LocaleRegions(iAreaID, iContinent, iZone, sName) KarmaObj.ProfileStart("DB.CG.LocaleRegions"); local oGlobalCommon = KarmaData[KARMA_DB_L1.COMMONLIST]; local sLocale = KARMA_DB_L2_C.LOCALE .. KDBC.Locale; local oGlobalCommonLocale = oGlobalCommon[sLocale]; if (iAreaID == 312312312) then oGlobalCommonLocale[KARMA_DB_L3_CL.REGIONS] = nil; end local LocaleRegions = oGlobalCommonLocale[KARMA_DB_L3_CL.REGIONS]; if (type(LocaleRegions) ~= "table") then oGlobalCommonLocale[KARMA_DB_L3_CL.REGIONS] = { NAMES = {}, CONTZONE = {} }; LocaleRegions = oGlobalCommonLocale[KARMA_DB_L3_CL.REGIONS]; end if (type(iAreaID) == "number") then if (iAreaID < 0) then LocaleRegions.FETCHCTR = math.max(LocaleRegions.FETCHCTR or 0, - iAreaID); elseif (type(sName) == "string") then oRegion2AreaID = nil; LocaleRegions.NAMES[iAreaID] = sName; if ((type(iContinent) == "number") and (type(iZone) == "number")) then LocaleRegions.CONTZONE[iAreaID] = iContinent * 1000 + iZone; end end end KarmaObj.ProfileStop("DB.CG.LocaleRegions"); if (type(iAreaID) == "number") then return LocaleRegions.NAMES[iAreaID], LocaleRegions.CONTZONE[iAreaID]; else return LocaleRegions, LocaleRegions.FETCHCTR; end end local oRegion2AreaID; function KarmaObj.DB.CG.LocaleRegion2AreaID(sName) if (type(oRegion2AreaID) == "table") then return oRegion2AreaID[sName]; end oRegion2AreaID = {}; local oRegions, k, v = KarmaObj.DB.CG.LocaleRegions(); for k, v in pairs(oRegions.NAMES) do oRegion2AreaID[v] = k; end return oRegion2AreaID[sName]; end function KarmaObj.DB.CG.RegionListMarkPVP(oRegionsBGsAndArenas) KarmaObj.ProfileStart("DB.CG.RegionListMarkPVP"); local RL, k, v = KarmaObj.DB.CG.RegionListGet(); if (next(oRegionsBGsAndArenas) ~= nil) then for k, v in pairs(RL) do if (oRegionsBGsAndArenas[v.Name]) then KarmaChatDebug("<" .. v.Name .. ">: will be/is marked as pvp-region."); if (v[KARMA_DB_L3_CR.ISPVPZONE] ~= 1) then KarmaChatDefault("<" .. v.Name .. "> " .. KARMA_MSG_DBCLEAN_PVPREGIONMARKED); v[KARMA_DB_L3_CR.ISPVPZONE] = 1; end elseif (v[KARMA_DB_L3_CR.ISPVPZONE] == 1) then KarmaChatDebug("<" .. v.Name .. ">: marked as pvp-region, but shouldn't be?"); end end else for k, v in pairs(RL) do if (v.Name == KARMA_PVPZONE_WSG) or (v.Name == KARMA_PVPZONE_AB) or (v.Name == KARMA_PVPZONE_AV) or (v.Name == KARMA_PVPZONE_ES) or (v.Name == KARMA_PVPZONE_SA) or (v.Name == KARMA_PVPZONE_IOC) or (v.Name == KARMA_PVPZONE_WG) or (v.Name == KARMA_PVPZONE_BFG) or (v.Name == KARMA_PVPZONE_TP) or (v.Name == KARMA_PVPZONE_TB) then KarmaChatDebug("<" .. v.Name .. ">: will be/is marked as pvp-region."); if (v[KARMA_DB_L3_CR.ISPVPZONE] ~= 1) then KarmaChatDefault("<" .. v.Name .. "> " .. KARMA_MSG_DBCLEAN_PVPREGIONMARKED); v[KARMA_DB_L3_CR.ISPVPZONE] = 1; end end end end KarmaObj.ProfileStop("DB.CG.RegionListMarkPVP"); end --############################################################################################### --############################################################################################### --############################################################################################### ----------------------------------------- -- Common/PerFaction (but not per server) ----------------------------------------- -- CommonQuestListGet function KarmaObj.DB.CF.QuestNameListGet() KarmaObj.ProfileStart("DB.CF.QuestNameListGet"); local oCF, CommonQuestList = KDBC.CommonFactionObject; if (oCF ~= nil) then CommonQuestList = oCF[KARMA_DB_L3_CF_QUESTNAMES]; end KarmaObj.ProfileStop("DB.CF.QuestNameListGet"); return CommonQuestList; end -- CommonQuestInfoListGet function KarmaObj.DB.CF.QuestInfosListGet() KarmaObj.ProfileStart("DB.CF.QuestInfosListGet"); local oCF, CommonQuestInfoList = KDBC.CommonFactionObject; if (oCF ~= nil) then CommonQuestInfoList = oCF[KARMA_DB_L3_CF_QUESTINFOS]; end KarmaObj.ProfileStop("DB.CF.QuestInfosListGet"); return CommonQuestInfoList; end -- CommonQuestAdd function KarmaObj.DB.CF.QuestListAdd(Quest, Faction, ExtID) local Index, PerfectIndex; if ((ExtID == nil) and (Faction == nil)) then KarmaChatDebug("DB.CF.QuestListAdd: ExtID == nil! " .. debugstack()); end local oCommonFaction = KDBC.CommonFactionObject; if (FactionKey and (FactionKey ~= KDBC.PlayerFaction)) then --[[ if (KarmaData[KARMA_DB_L1.COMMONLIST][KARMA_DB_L2_C.FACTION][FactionKey] == nil) then -- happens at database conversion for the faction the current char is NOT on KOH.TableInit(KarmaData[KARMA_DB_L1.COMMONLIST][KARMA_DB_L2_C.FACTION], FactionKey); KOH.TableInit(KarmaData[KARMA_DB_L1.COMMONLIST][KARMA_DB_L2_C.FACTION][FactionKey], KARMA_DB_L3_CF_QUESTNAMES); KOH.TableInit(KarmaData[KARMA_DB_L1.COMMONLIST][KARMA_DB_L2_C.FACTION][FactionKey], KARMA_DB_L3_CF_QUESTINFOS); end ]]-- if (not IsAddOnLoaded("KarmaDB" .. FactionKey)) then local iLoaded, sWhyNot = LoadAddOn("KarmaDB" .. FactionKey); if (not iLoaded) then KarmaChatDefault("Cannot access database for faction " .. FactionKey .. ": Failed to load load-on-demand module. (" .. sWhyNot .. ")"); KarmaChatDebug(debugstack()); return end end local xFactionDB = _G["KarmaAvEnK" .. FactionKey]; if (type(xFactionDB) ~= "table") then KarmaChatDefault("Cannot access database for faction " .. FactionKey .. ": Failed to initialize load-on-demand module properly."); KarmaChatDebug(debugstack()); return end oCommonFaction = xFactionDB[KARMA_DB_L1.COMMONLIST]; if (oCommonFaction == nil) then -- happens at database conversion for the faction the current char is NOT on KOH.TableInit(xFactionDB, KARMA_DB_L1.COMMONLIST); KOH.TableInit(xFactionDB[KARMA_DB_L1.COMMONLIST], KARMA_DB_L3_CF_QUESTNAMES); KOH.TableInit(xFactionDB[KARMA_DB_L1.COMMONLIST], KARMA_DB_L3_CF_QUESTINFOS); oCommonFaction = xFactionDB[KARMA_DB_L1.COMMONLIST]; end end local CommonQuestNamesList = oCommonFaction[KARMA_DB_L3_CF_QUESTNAMES]; local CommonQuestInfosList = oCommonFaction[KARMA_DB_L3_CF_QUESTINFOS]; if (CommonQuestNamesList) then local Count = 0; for k, v in pairs(CommonQuestNamesList) do Count = Count + 1; if (v == Quest) then if (ExtID) then local VExtID; if (CommonQuestInfosList[k]) then VExtID = CommonQuestInfosList[k].ExtID; end if (VExtID) then if (ExtID == VExtID) then PerfectIndex = k; Index = k; end else Index = k; end else Index = k; end end end -- if the perfect Index was before a non-perfect one, Index got overridden, restore from PerfectIndex if (PerfectIndex) then Index = PerfectIndex; end if (Index == nil) then Index = 1 + Count; CommonQuestNamesList[Index] = Quest; end if (ExtID) then if (CommonQuestInfosList[Index] == nil) then CommonQuestInfosList[Index] = {}; end CommonQuestInfosList[Index].ExtID = ExtID; end end return Index; end --############################################################################################### function KarmaObj.DB.CF.QuestInfoCleanup() local oCommonFaction = KDBC.CommonFactionObject; local oRealmlist = KDBC.Faction[KARMA_DB_L1.REALMLIST]; local oStore = {}; local realmname, realmdata; for realmname, realmdata in pairs(oRealmlist) do local bkey, bvalue; for bkey, bvalue in pairs(realmdata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do local mkey, mvalue; for mkey, mvalue in pairs(bvalue) do local charspecificlist, ckey, cvalue = mvalue[KARMA_DB_L5_RRFFM_CHARACTERS]; for ckey, cvalue in pairs(charspecificlist) do local charquestlist, qkey, qvalue = cvalue[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]; if (charquestlist) then for qkey, qvalue in pairs(charquestlist) do if (qvalue > 0) then KarmaChatDebug("Positive QuestID in database, upgrade error, can't cleanup QuestInfo/-Ex"); return end oStore[- qvalue] = (oStore[- qvalue] or 0) + 1; end end local charquestexlist = cvalue[KARMA_DB_L6_RRFFMCC_QUESTEXLIST]; if (charquestexlist) then for qkey, qvalue in pairs(charquestexlist) do if (qkey > 0) then KarmaChatDebug("Positive QuestID in database, upgrade error, can't cleanup QuestInfo/-Ex"); return end oStore[- qkey] = (oStore[- qkey] or 0) + 1; end end end end end end -- -- local CommonQuestNamesList = oCommonFaction[KARMA_DB_L3_CF_QUESTNAMES]; local CommonQuestInfosList = oCommonFaction[KARMA_DB_L3_CF_QUESTINFOS]; local oQuestNamesNew = {}; local oQuestInfosNew = {}; local oMap = {}; local qidnew, qkey, qvalue = 1; for qkey, qvalue in pairs(oStore) do oMap[qkey] = qidnew; oQuestNamesNew[qidnew] = CommonQuestNamesList[qkey]; oQuestInfosNew[qidnew] = CommonQuestInfosList[qkey]; qidnew = qidnew + 1; end oCommonFaction[KARMA_DB_L3_CF_QUESTNAMES] = oQuestNamesNew; oCommonFaction[KARMA_DB_L3_CF_QUESTINFOS] = oQuestInfosNew; -- -- local realmname, realmdata; for realmname, realmdata in pairs(oRealmlist) do local bkey, bvalue; for bkey, bvalue in pairs(realmdata[KARMA_DB_L4_RRFF.MEMBERBUCKETS]) do local mkey, mvalue; for mkey, mvalue in pairs(bvalue) do local charspecificlist, ckey, cvalue = mvalue[KARMA_DB_L5_RRFFM_CHARACTERS]; for ckey, cvalue in pairs(charspecificlist) do local charquestlist, qkey, qvalue = cvalue[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]; if (charquestlist) then local oNew = {}; for qkey, qvalue in pairs(charquestlist) do tinsert(oNew, - oMap[- qvalue]); end cvalue[KARMA_DB_L6_RRFFMCC_QUESTIDLIST] = oNew; end local charquestexlist = cvalue[KARMA_DB_L6_RRFFMCC_QUESTEXLIST]; if (charquestexlist) then local oNew = {}; for qkey, qvalue in pairs(charquestexlist) do oNew[ - oMap[- qkey]] = qvalue; end cvalue[KARMA_DB_L6_RRFFMCC_QUESTEXLIST] = oNew; end end end end end end --############################################################################################### --############################################################################################### --############################################################################################### ----------------------------------------- -- Server/Faction Object ----------------------------------------- function KarmaObj.DB.FactionCacheInit(bInit) local bSet = KDBC.FactionObjectCache == nil; if (KDBC.Realm and KDBC.PlayerFaction) then local oFactionDB = _G["KarmaAvEnK" .. KDBC.PlayerFaction]; if (type(oFactionDB) == "table") then KDBC.FactionObjectCache = oFactionDB[KARMA_DB_L1.REALMLIST][KDBC.Realm]; end end if (bSet) then if (KDBC.FactionObjectCache == nil) then if (bInit) then DEFAULT_CHAT_FRAME:AddMessage("Karma: |cFFFF6060Initialization error! <" .. (KDBC.Realm or "???") .. "; " .. (KDBC.PlayerFaction or "???") .. ">|r Cannot use database, cannot store or load information."); end else DEFAULT_CHAT_FRAME:AddMessage("Karma: Loaded database for <" .. (KDBC.Realm or "???") .. "; " .. (KDBC.PlayerFaction or "???") .. ">."); end end return KDBC.FactionObjectCache ~= nil; end -- Karma_Faction_GetFactionObject -> KarmaObj.DB.FactionCacheGet KarmaObj.DB.FactionCacheError = {}; function KarmaObj.DB.FactionCacheGet(bNoInit) KarmaObj.ProfileStart("DB.FactionCacheGet"); if (KDBC.FactionObjectCache == nil) then if (not bNoInit) then KarmaObj.DB.FactionCacheInit(); end tinsert(KarmaObj.DB.FactionCacheError, debugstack()); DEFAULT_CHAT_FRAME:AddMessage(debugstack()); end KarmaObj.ProfileStop("DB.FactionCacheGet"); return KDBC.FactionObjectCache; end KarmaObj.DB.FSGError = {}; function KarmaObj.DB.FactionServerGet(sServer) if (not sServer) then local sData = debugstack(); KarmaObj.DB.FSGError[sData] = (KarmaObj.DB.FSGError[sData] or 0) + 1; return KarmaObj.DB.FactionCacheGet(); elseif (sServer == KDBC.Realm) then return KarmaObj.DB.FactionCacheGet(); else local iServerID, oServerFaction = KarmaObj.DB.ServerCreate(KDBC.Faction, sServer, true); return oServerFaction; end end -- cross-faction FactionObject (no caching) function KarmaObj.DB.FactionOtherGet() KarmaObj.ProfileStart("DB.FactionOtherGet"); local xFaction; if (KDBC.PlayerFaction == "Horde") then xFaction = "Alliance"; elseif (KDBC.PlayerFaction == "Alliance") then xFaction = "Horde"; end local oXFaction; if (KDBC.Realm and xFaction) then local xFactionDB = _G["KarmaAvEnK" .. xFaction]; if (type(xFactionDB) == "table") then oXFaction = xFactionDB[KARMA_DB_L1.REALMLIST][KDBC.Realm]; end end KarmaObj.ProfileStop("DB.FactionOtherGet"); return oXFaction; end function KarmaObj.DB.FactionXHoldCreate(sFaction) local oServer = KarmaData[KARMA_DB_L1.XFACTIONHOLD][KDBC.Realm]; if (type(oServer) ~= "table") then KarmaData[KARMA_DB_L1.XFACTIONHOLD][KDBC.Realm] = {}; oServer = KarmaData[KARMA_DB_L1.XFACTIONHOLD][KDBC.Realm]; end if (sFaction == nil) then sFaction = KDBC.PlayerFaction; end local oFaction = oServer[sFaction]; if (type(oFaction) ~= "table") then oServer[sFaction] = {}; oFaction = oServer[sFaction]; end end function KarmaObj.DB.FactionXHoldGet(sFaction) local oServer = KarmaData[KARMA_DB_L1.XFACTIONHOLD][KDBC.Realm]; if (type(oServer) == "table") then if (sFaction == nil) then sFaction = KDBC.PlayerFaction; end local oFaction = oServer[sFaction]; if (type(oFaction) == "table") then return oFaction; end end end function KarmaObj.DB.ServerListGet(bAll) local oNames, k, v = {}; for k, v in pairs(KDBC.Faction[KARMA_DB_L1.REALMLIST]) do if ((k ~= KDBC.Realm) or bAll) then tinsert(oNames, k); end end table.sort(oNames); return oNames; end -- -- -- local function NameToNameServer(sMemberName, sMemberServer) if (sMemberName == nil) or (sMemberName == "") then return nil; end if (strfind(sMemberName, '@', 1, true)) then sMemberName, sMemberServer = strsplit('@', sMemberName); else if (sMemberServer == "") then sMemberServer = nil; end sMemberServer = sMemberServer or KDBC.Realm; end return sMemberName, sMemberServer; end function Karma_MemberList_GetObject(sMemberName, sMemberServer, lMembers, sMembersServer, bAdd) sMemberName, sMemberServer = NameToNameServer(sMemberName, sMemberServer); if (sMemberName == nil) then return nil; end if ((sMembersServer == nil) or (sMembersServer ~= sMemberServer)) then lMembers = KarmaObj.DB.SF.MemberListGet(sMemberServer or KDBC.Realm); end if (lMembers == nil) then KarmaChatDebugStack("lMembers nil: " .. (sMemberServer or "??") .. ", " .. (sMembersServer or "??") .. " - " .. (sMemberServer or KDBC.Realm or "??")); end local sBucketName = KarmaObj.NameToBucket(sMemberName); local oMember = lMembers[sBucketName][sMemberName]; if ((oMember == nil) and bAdd) then oMember = {}; lMembers[sBucketName][sMemberName] = oMember; end return oMember; end function Karma_MemberList_Remove(sMemberName, sMemberServer) sMemberName, sMemberServer = NameToNameServer(sMemberName, sMemberServer); local lMembers = KarmaObj.DB.SF.MemberListGet(sMemberServer or KDBC.Realm); local sBucketName = KarmaObj.NameToBucket(sMemberName); local oMember = lMembers[sBucketName][sMemberName]; if (oMember) then lMembers[sBucketName][sMemberName] = nil; end KarmaWindow_Update(); end -- --- accessors -- -- old per s/f logic function KarmaObj.DB.SF.QuestListGet() KarmaObj.ProfileStart("Karma_Faction_GetQuestList"); local oFaction = KarmaObj.DB.FactionCacheGet(); local lQuests = oFaction[KARMA_DB_L4_RRFF.QUESTNAMES]; KarmaObj.ProfileStop("Karma_Faction_GetQuestList"); return lQuests; end -- old per s/f logic function KarmaObj.DB.SF.ZoneListGet() KarmaObj.ProfileStart("Karma_Faction_GetZoneList"); local oFaction = KarmaObj.DB.FactionCacheGet(); local lZones = oFaction[KARMA_DB_L4_RRFF.ZONENAMES]; KarmaObj.ProfileStop("Karma_Faction_GetZoneList"); return lZones; end function KarmaObj.DB.SF.CharacterListGet() KarmaObj.ProfileStart("KarmaOjb.DB.SF.CharacterListGet"); local oFaction = KarmaObj.DB.FactionCacheGet(); local lCharacters = oFaction[KARMA_DB_L4_RRFF.CHARACTERLIST]; KarmaObj.ProfileStop("KarmaOjb.DB.SF.CharacterListGet"); return lCharacters; end function KarmaObj.DB.SF.MemberListGet(sServer) KarmaObj.ProfileStart("KarmaObj.DB.SF.MemberListGet"); local oFaction = KarmaObj.DB.FactionServerGet(sServer); local lMembers = oFaction[KARMA_DB_L4_RRFF.MEMBERBUCKETS]; KarmaObj.ProfileStop("KarmaObj.DB.SF.MemberListGet"); return lMembers; end function KarmaObj.DB.SF.RecentlyJoinedInit() local oData = KDBC.CommonFactionObject[KARMA_DB_L3_CF_RECENTLY_JOINED][KDBC.Realm]; if (#oData > 0) then return end local oMembers = KarmaObj.DB.SF.MemberListGet(KDBC.Realm); local sBucketName, oBucketValues; for sBucketName, BucketValue in pairs(oMembers) do -- Loop through each bucket local sMemberName, oMember; for sMemberName, oMember in pairs(BucketValue) do -- Loop through contents of bucket local iAt = oMember[KARMA_DB_L5_RRFFM.LASTSEEN] or 0; if (strfind(sMemberName, '@')) then local sPlayer, sServer = strsplit('@', sMemberName); oData[1 + #oData] = { sPlayer = sPlayer, sServerFrom = sServer, iAt = iAt }; else oData[1 + #oData] = { sPlayer = sMemberName, sServerFrom = KDBC.Realm, iAt = iAt }; end end end end function KarmaObj.DB.SF.RecentlyJoinedWipe() table.wipe(KDBC.CommonFactionObject[KARMA_DB_L3_CF_RECENTLY_JOINED]); end function KarmaObj.DB.SF.RecentlyJoinedGet() return Karma_CopyTable(KDBC.CommonFactionObject[KARMA_DB_L3_CF_RECENTLY_JOINED][KDBC.Realm]); end function KarmaObj.DB.SF.RecentlyJoinedUpdate(oParty) local oData, iCnt, i = KDBC.CommonFactionObject[KARMA_DB_L3_CF_RECENTLY_JOINED][KDBC.Realm]; local oReverse, bResort = {}; -- first, run over the whole list and re-fetch the timestamps iCnt = #oData; for i = 1, iCnt do local sCombined = oData[i].sPlayer .. "@" .. oData[i].sServerFrom; if (oReverse[sCombined]) then -- duplicate?! oData[oReverse[sCombined]].iAt = 0; end oReverse[sCombined] = i; local oMember; if (oData[i].sServerFrom ~= KDBC.Realm) then oMember = Karma_MemberList_GetObject(oData[i].sPlayer, oData[i].sServerFrom); else oMember = Karma_MemberList_GetObject(oData[i].sPlayer); end if (oMember == nil) then -- deleted: set timestamp to 0 oData[i].iAt = 0; bResort = true; elseif (oData[i].iAt ~= oMember[KARMA_DB_L5_RRFFM.LASTSEEN]) then -- updated: refresh timestamp to most recent iCnt = #oData + 1; oData[iCnt] = Karma_CopyTable(oData[i]); oData[i].iAt = 0; oData[iCnt].iAt = oMember[KARMA_DB_L5_RRFFM.LASTSEEN]; oReverse[sCombined] = iCnt; bResort = true; end end -- second, add the players from oParty and dump those above the 250th entry local oRealmGrp, sCombined, oCombined = KDBC.Faction[KARMA_DB_L1.REALMGROUPS][KDBC.Realm]; for sCombined, oCombined in pairs(oParty) do if (not strfind(sCombined, '@')) then sCombined = sCombined .. "@" .. KDBC.Realm; end local iOld = oReverse[sCombined]; if (iOld == nil) then local sPlayer, sServer = strsplit('@', sCombined); local iAt = oCombined[KARMA_DB_L5_RRFFM.LASTSEEN] or 1; oRealmGrp[sServer] = math.max(iAt, oRealmGrp[sServer] or 1); KarmaChatDebug("MRU list: adding player " .. sCombined); oData[1 + #oData] = { sPlayer = sPlayer, sServerFrom = sServer, iAt = iAt }; elseif (oData[iOld].iAt ~= oCombined[KARMA_DB_L5_RRFFM.LASTSEEN]) then iCnt = #oData + 1; oData[iCnt] = Karma_CopyTable(oData[iOld]); oData[iOld].iAt = 0; oData[iCnt].iAt = oCombined[KARMA_DB_L5_RRFFM.LASTSEEN]; oReverse[sCombined] = iCnt; bResort = true; end end if (bResort) then -- keep the newest 250 or more: -- first, dump all 0ed out entries local oDataNew = {}; iCnt = #oData; for i = 1, iCnt do if (oData[i].iAt ~= 0) then oDataNew[1 + #oDataNew] = oData[i]; end end if (#oDataNew > 300) then local iExtra = #oDataNew; iCnt = math.min(#oDataNew, 250); for i = 1, iCnt do oDataNew[i] = oDataNew[i + 50]; end for i = iCnt + 1, iExtra do oDataNew[i] = nil; end end KarmaChatDebug("MRU list: updating from " .. #KDBC.CommonFactionObject[KARMA_DB_L3_CF_RECENTLY_JOINED][KDBC.Realm] .. " to " .. #oDataNew .. " entries."); KDBC.CommonFactionObject[KARMA_DB_L3_CF_RECENTLY_JOINED][KDBC.Realm] = oDataNew; end end function KarmaObj.DB.SF.RecentlyJoinedFixup() local oData, iCnt, i = KDBC.CommonFactionObject[KARMA_DB_L3_CF_RECENTLY_JOINED][KDBC.Realm]; local oReverse, bResort = {}; -- first, run over the whole list and re-fetch the timestamps iCnt = #oData; for i = 1, iCnt do local sCombined = oData[i].sPlayer .. "@" .. oData[i].sServerFrom; if (oReverse[sCombined]) then -- duplicate?! oData[oReverse[sCombined]].iAt = 0; bResort = true; end oReverse[sCombined] = i; end if (bResort) then -- keep the newest 250 or more: -- first, dump all 0ed out entries local oDataNew = {}; iCnt = #oData; for i = 1, iCnt do if (oData[i].iAt ~= 0) then oDataNew[1 + #oDataNew] = oData[i]; end end if (#oDataNew > 300) then iCnt = math.min(#oDataNew, 250); for i = 1, iCnt do oDataNew[i] = oDataNew[i + 50]; end end oData = oDataNew; KDBC.CommonFactionObject[KARMA_DB_L3_CF_RECENTLY_JOINED][KDBC.Realm] = oData; end iCnt = #oData; for i = 1, iCnt - 1 do local j; for j = i + 1, iCnt do if (oData[j].iAt < oData[i].iAt) then local oSwap = oData[j]; oData[j] = oData[i]; oData[i] = oSwap; end end end end --############################################################################################### local fSparseTestOrDelete = function(sName, oMember, bExecute) local iCount = 0; if (oMember) then local oMemPerChar = oMember[KARMA_DB_L5_RRFFM_CHARACTERS]; if (type(oMemPerChar) == "table") then for sChar, oChar in pairs(oMemPerChar) do --[[ -- minimal pointless data: ["XP"] = 0, ["XPLVL"] = 0, ["XPLAST"] = 0, ["XPMAX"] = 0, ["PLAYED"] = 0, ["PLAYEDLAST"] = <any value>, ["ZONEIDLIST"] = {}, ["QUESTIDLIST"] = {}, ["QUESTEXLIST"] = {}, ["ACHIEVED"] = {}, ["REG_L"] = {}, -- related field names KARMA_DB_L6_RRFFMCC_XP = "XP"; KARMA_DB_L6_RRFFMCC_XPLAST = "XPLAST"; KARMA_DB_L6_RRFFMCC_XPMAX = "XPMAX"; KARMA_DB_L6_RRFFMCC_XPLVL = "XPLVL"; KARMA_DB_L6_RRFFMCC_PLAYED = "PLAYED"; KARMA_DB_L6_RRFFMCC_PLAYEDLAST = "PLAYEDLAST"; KARMA_DB_L6_RRFFMCC_JOINEDLAST = "JOINEDLAST"; KARMA_DB_L6_RRFFMCC_ZONEIDLIST = "ZONEIDLIST"; KARMA_DB_L6_RRFFMCC_QUESTIDLIST = "QUESTIDLIST"; KARMA_DB_L6_RRFFMCC_QUESTEXLIST = "QUESTEXLIST"; KARMA_DB_L6_RRFFMCC_ACHIEVED = "ACHIEVED"; KARMA_DB_L6_RRFFMCC_REGIONLIST = "REG_L"; ]]-- local iXP = oChar[KARMA_DB_L6_RRFFMCC_XP]; local iPlayed = oChar[KARMA_DB_L6_RRFFMCC_PLAYED]; local iJoined = oChar[KARMA_DB_L6_RRFFMCC_JOINEDLAST]; if (((iXP == nil) or (iXP == 0)) and ((iPlayed == nil) or (iPlayed == 0)) and ((iJoined == nil) or (iJoined == 0))) then local sAnything = ""; local sKey, oData; for sKey, oData in pairs(oChar) do if ((sKey == KARMA_DB_L6_RRFFMCC_KARMA_ID) or (sKey == KARMA_DB_L6_RRFFMCC_XP) or (sKey == KARMA_DB_L6_RRFFMCC_XPLAST) or (sKey == KARMA_DB_L6_RRFFMCC_XPMAX) or (sKey == KARMA_DB_L6_RRFFMCC_XPLVL) or (sKey == KARMA_DB_L6_RRFFMCC_PLAYED) or (sKey == KARMA_DB_L6_RRFFMCC_PLAYEDLAST)) then -- nothing to do: already pre-tested or not relevant elseif ((sKey == KARMA_DB_L6_RRFFMCC_ZONEIDLIST) or (sKey == KARMA_DB_L6_RRFFMCC_QUESTIDLIST) or (sKey == KARMA_DB_L6_RRFFMCC_QUESTEXLIST) or (sKey == KARMA_DB_L6_RRFFMCC_REGIONLIST) or (sKey == KARMA_DB_L6_RRFFMCC_ACHIEVED)) then if (not KOH.TableIsEmpty(oData)) then local iCnt, sSub, oSub = 0; for sSub, oSub in pairs(oData) do iCnt = iCnt + 1; end sAnything = sAnything .. " " .. sKey .. "[" .. iCnt .. "]"; end else -- leaves JOINEDLAST sAnything = sAnything .. " " .. sKey; end end if (sAnything ~= "") then KarmaChatSecondary(sName .. "::" .. sChar .. " - " .. sAnything); else if (bExecute) then oMemPerChar[sChar] = nil; KarmaChatSecondary(sName .. "::" .. sChar .. " - DROPPED!"); else KarmaChatSecondary(sName .. "::" .. sChar .. " - could drop!"); end iCount = iCount + 1; end else local sOutput = ""; if (iXP and (iXP > 0)) then if (sOutput ~= "") then sOutput = sOutput .. " or"; end sOutput = sOutput .. " xp > 0: " .. Karma_NilToString(iXP); end if (iPlayed and (iPlayed > 0)) then if (sOutput ~= "") then sOutput = sOutput .. " or"; end sOutput = sOutput .. " played > 0: " .. Karma_NilToString(iPlayed); end if (iJoined and (iJoined > 0)) then if (sOutput ~= "") then sOutput = sOutput .. " or"; end sOutput = sOutput .. " joined > 0: " .. Karma_NilToString(iJoined); end KarmaChatSecondary(sName .. "::" .. sChar .. " -" .. sOutput); end end end end return iCount; end -- operating on whole memberlist function KarmaObj.DB.SF.Sparsify(sPattern, bDrop) local iDropped = 0; if (strsub(sPattern, strlen(sPattern)) == "*") then local iLen = strlen(sPattern) - 1; local sPat = strsub(sPattern, 1, iLen); local lMembers = KarmaObj.DB.SF.MemberListGet(KDBC.Realm); local sBucketName, oBucketValues; for sBucketName, BucketValue in pairs(lMembers) do -- Loop through each bucket local sMemberName, oMember; for sMemberName, oMember in pairs(BucketValue) do -- Loop through contents of bucket if (strsub(sMemberName, 1, iLen) == sPat) then iDropped = iDropped + fSparseTestOrDelete(sMemberName, oMember, bDrop); end end end else local oMember = Karma_MemberList_GetObject(sPattern); iDropped = fSparseTestOrDelete(sPattern, oMember, bDrop); end return iDropped; end function KarmaObj.DB.SF.NameToID(sServer, oFactionDB) if (oFactionDB == nil) then oFactionDB = _G["KarmaAvEnK" .. KDBC.PlayerFaction]; end if (type(oFactionDB) ~= "table") then return end local oServerlist = oFactionDB[KARMA_DB_L1.REALMLIST]; if (type(oServerlist) ~= "table") then return end local oServerFaction = oServerlist[sServer]; if (type(oServerFaction) ~= "table") then return end return oServerFaction[KARMA_DB_L4_RRFF.SERVER_ID], oServerFaction; end function KarmaObj.DB.SF.IDToName(iServerID) local oFactionDB = _G["KarmaAvEnK" .. KDBC.PlayerFaction]; if (type(oFactionDB) ~= "table") then return end local oServerIDs = oFactionDB[KARMA_DB_L1.REALM_IDS]; if (type(oServerIDs) ~= "table") then return end local sServer = oServerIDs[iServerID]; if (sServer == nil) then return end local oServerlist = oFactionDB[KARMA_DB_L1.REALMLIST]; if (type(oServerlist) ~= "table") then return end local oServerFaction = oServerlist[sServer]; if (type(oServerFaction) ~= "table") then return end return sServer, oServerFaction; end --############################################################################################### --############################################################################################### --############################################################################################### ----------------------------------------- -- Character Object ----------------------------------------- function KarmaObj.DB.CharacterConfigObjectGet() local lCharacters = KarmaObj.DB.SF.CharacterListGet(); local CharConfig = lCharacters[KDBC.PlayerName][KARMA_DB_L5_RRFFC.CONFIGPERCHAR]; return CharConfig; end --############################################################################################### --############################################################################################### --############################################################################################### ----------------------------------------- -- History pointer data ----------------------------------------- function KarmaObj.DB.HistorySeen(sName, iNow) if (KDBC.FactionObjectCache) then if (KDBC.FactionObjectCache[KARMA_DB_L4_RRFF.HISTORY_MOVED][sName]) then KarmaChatDebug("Flagging member <" .. sName .. "> as recently-seen in history reference."); KDBC.FactionObjectCache[KARMA_DB_L4_RRFF.HISTORY_SEEN][sName] = iNow; end end end ----------------------------------------- -- Member Object ----------------------------------------- function KarmaObj.DB.M.AddedZoneSet(oMember, oMemberChar, iZoneID, bTrack) if (type(oMember) == "table") then if (oMember[KARMA_DB_L5_RRFFM.ADDED_IN] == nil) then local sOut = "Setting initial zone to <" .. iZoneID .. ">"; if (not bTrack) then sOut = sOut .. " (pvp)"; end KarmaChatDebug(sOut); oMember[KARMA_DB_L5_RRFFM.ADDED_IN] = iZoneID; end if (not bTrack) then return end local oZones, index, value = oMemberChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]; for index, value in pairs(oZones) do if (value == iZoneID) then return end end oZones[#oZones + 1] = iZoneID; end end function KarmaObj.DB.M.AddedZoneGet(oMember) if (type(oMember) == "table") then return oMember[KARMA_DB_L5_RRFFM.ADDED_IN]; end end function KarmaObj.DB.M.Modified(oMember, sField) if (type(oMember) == "table") then oMember[KARMA_DB_L5_RRFFM.LASTCHANGED_TIME] = time(); oMember[KARMA_DB_L5_RRFFM.LASTCHANGED_FIELD] = sField; end end -- regular contents -- function KarmaObj.DB.M.KarmaGet(oMember) local iKarma = 50; if (type(oMember) == "table") then iKarma = oMember[KARMA_DB_L5_RRFFM_KARMA] or iKarma; end return iKarma; end function KarmaObj.DB.M.KarmaSet(oMember, iKarma) if (type(oMember) == "table") then local iOld = oMember[KARMA_DB_L5_RRFFM_KARMA] or 50; if (iOld ~= iKarma) then KarmaObj.DB.M.Modified(oMember, "Karma value"); if (iKarma == 50) then oMember[KARMA_DB_L5_RRFFM_KARMA] = nil; else oMember[KARMA_DB_L5_RRFFM_KARMA] = iKarma; end end end end ----------------------------------------- -- Member/Char Object ----------------------------------------- function KarmaObj.DB.MC.AchievementAdd(oMember, sChar, iAchievementID, iCriteriaIndex, iCritNum) if (type(oMember) == "table") then local charobj = Karma_MemberObject_GetCharacterObject(oMember, sChar); if (charobj) then local sAKey = "A" .. iAchievementID; -- working key (LUA is not good with numeric keys in tables) KOH.TableInit(charobj, KARMA_DB_L6_RRFFMCC_ACHIEVED); KOH.TableInit(charobj[KARMA_DB_L6_RRFFMCC_ACHIEVED], sAKey); local oAch = charobj[KARMA_DB_L6_RRFFMCC_ACHIEVED][sAKey]; oAch.At = time(); -- singular criteria if (iCriteriaIndex) then local sCKey = "C" .. iCriteriaIndex; oAch[sCKey] = time(); end if (iCritNum) then oAch["CMAX"] = iCritNum; end KarmaObj.DB.M.Modified(oMember, "Achievement"); end end end function KarmaObj.DB.MC.AchievementListGet(oMember, sChar) if (type(oMember) == "table") then local charobj = Karma_MemberObject_GetCharacterObject(oMember, sChar); if (type(charobj) == "table") then local lAchievements = charobj[KARMA_DB_L6_RRFFMCC_ACHIEVED]; if (type(lAchievements) == "table") then local lResult, sAKey, oValues, sSubKey, oSubVal = {}; for sAKey, oValues in pairs(lAchievements) do lResult[sAKey] = {}; for sSubKey, oSubVal in pairs(oValues) do lResult[sAKey][sSubKey] = oSubVal; end end return lResult; end end end return nil; end --############################################################################################### local function KarmaAvEnK_DB_MC_AccessByID(oChars, iID) if (type(oChars) ~= "table") then return end local k, v; for k, v in pairs(oChars) do if (iID == v[KARMA_DB_L6_RRFFMCC_KARMA_ID]) then return v; end end end function KarmaObj.DB.MC.NameToID(sCombined, oFactionDB) local sName, sServer = sCombined; if (strfind(sCombined, '@')) then sName, sServer = strsplit('@', sCombined); else sServer = KDBC.Realm; end local iServerID, oServerFaction = KarmaObj.DB.SF.NameToID(sServer, oFactionDB) if (type(oServerFaction) ~= "table") then return end local oChar = oServerFaction[KARMA_DB_L4_RRFF.CHARACTERLIST][sName]; if (type(oChar) ~= "table") then return end return oChar[KARMA_DB_L5_RRFFC.KARMA_ID]; end function KarmaObj.DB.MC.IDToName(iID) local oFactionDB = _G["KarmaAvEnK" .. KDBC.PlayerFaction]; if (type(oFactionDB) ~= "table") then KarmaChatDebug("MC.!IDToName(" .. tostring(iID) .. "): !oFactionDB"); return end local iServerID, sServer, oServer = bit.rshift(iID, 16); if (iServerID ~= 0) then sServer, oServer = KarmaObj.DB.SF.IDToName(iServerID); end if (type(oServer) ~= "table") then KarmaChatDebug("MC.!IDToName(" .. tostring(iID) .. "): !oServer (ID = " .. tostring(iServerID) .. ")"); return end local oChars = oServer[KARMA_DB_L4_RRFF.CHARACTER_IDS]; if (type(oChars) ~= "table") then KarmaChatDebug("MC.!IDToName(" .. tostring(iID) .. "): !oChars"); return end local sName = oChars[iID]; if (sName) then return sName, sServer; else KarmaChatDebug("MC.!IDToName(" .. tostring(iID) .. "): !oChars[iID]"); end end local function KarmaAvEnK_DB_MC_Access(oChars, xCombined) local iID = xCombined; if (type(xCombined) == "string") then iID = KarmaObj.DB.MC.NameToID(xCombined); end return KarmaAvEnK_DB_MC_AccessByID(oChars, iID); end local function KarmaAvEnK_DB_MC_InitCore(oMember, sCombined) if ((type(oMember) ~= "table") or (type(sCombined) ~= "string")) then return false; end KOH.TableInit(oMember, KARMA_DB_L5_RRFFM_CHARACTERS); local iID = KarmaObj.DB.MC.NameToID(sCombined); if (iID == nil) then return false; end local oChar = KarmaAvEnK_DB_MC_AccessByID(oMember[KARMA_DB_L5_RRFFM_CHARACTERS], iID); local bCreated = oChar == nil; if (bCreated) then oChar = {}; tinsert(oMember[KARMA_DB_L5_RRFFM_CHARACTERS], oChar); end Karma_FieldInitialize(oChar, KARMA_DB_L6_RRFFMCC_KARMA_ID, iID, true); return bCreated, oChar; end function KarmaObj.DB.MC.InitMinimum(oMember, sCombined) local bCreated = KarmaAvEnK_DB_MC_InitCore(oMember, sCombined); return bCreated; end function KarmaObj.DB.MC.InitMinimumPlayer(oMember) local bCreated = KarmaObj.DB.MC.InitMinimum(oMember, KDBC.PlayerName); return bCreated; end function KarmaObj.DB.MC.InitFull(oMember, sCombined) local bCreated, oTableChar = KarmaAvEnK_DB_MC_InitCore(oMember, sCombined); if (oTableChar) then Karma_FieldInitialize(oTableChar, KARMA_DB_L6_RRFFMCC_PLAYED, 0, true); Karma_FieldInitialize(oTableChar, KARMA_DB_L6_RRFFMCC_PLAYEDPVP, 0, true); Karma_FieldInitialize(oTableChar, KARMA_DB_L6_RRFFMCC_PLAYEDLAST, 0, true); Karma_FieldInitialize(oTableChar, KARMA_DB_L6_RRFFMCC_XP, 0, true); Karma_FieldInitialize(oTableChar, KARMA_DB_L6_RRFFMCC_XPLVL, 0, true); -- Karma_FieldInitialize(oTableChar, KARMA_DB_L6_RRFFMCC_XPLAST, 0, true); -- Karma_FieldInitialize(oTableChar, KARMA_DB_L6_RRFFMCC_XPMAX, 0, true); KOH.TableInit(oTableChar, KARMA_DB_L6_RRFFMCC_QUESTIDLIST); KOH.TableInit(oTableChar, KARMA_DB_L6_RRFFMCC_QUESTEXLIST); KOH.TableInit(oTableChar, KARMA_DB_L6_RRFFMCC_ZONEIDLIST); KOH.TableInit(oTableChar, KARMA_DB_L6_RRFFMCC_ACHIEVED); KOH.TableInit(oTableChar, KARMA_DB_L6_RRFFMCC_REGIONLIST); return bCreated end return false; end function KarmaObj.DB.MC.InitFullPlayer(oMember) KarmaObj.DB.MC.InitFull(oMember, KDBC.PlayerName); end function KarmaObj.DB.MC.Exists(oMember, sCombined) if ((type(oMember) ~= "table") or (type(sCombined) ~= "string")) then -- KarmaChatDebug("MC:!Exists(" .. tostring(oMember) .. ", " .. tostring(sCombined) .. "): Arg type invalid."); return false; end if (type(oMember[KARMA_DB_L5_RRFFM_CHARACTERS]) ~= "table") then -- KarmaChatDebug("MC:!Exists(" .. tostring(oMember) .. ", " .. tostring(sCombined) .. "): No char data at all."); return false; end local oChar = KarmaAvEnK_DB_MC_Access(oMember[KARMA_DB_L5_RRFFM_CHARACTERS], sCombined); if (type(oChar) ~= "table") then -- KarmaChatDebug("MC:!Exists(" .. tostring(oMember) .. ", " .. tostring(sCombined) .. "): No char data for req. char."); return false; end return true; end function KarmaObj.DB.MC.Get(oMember, sCombined) if (KarmaObj.DB.MC.Exists(oMember, sCombined)) then return KarmaAvEnK_DB_MC_Access(oMember[KARMA_DB_L5_RRFFM_CHARACTERS], sCombined); end end function KarmaObj.DB.MC.GetPlayer(oMember) return KarmaObj.DB.MC.Get(oMember, KDBC.PlayerName); end --############################################################################################### function KarmaObj.DB.JoinedInInstance(oMember, sChar, sInstance) if (type(oMember) ~= "table") or (type(sChar) ~= "string") or (type(sInstance) ~= "string") then return false; end local charobj = Karma_MemberObject_GetCharacterObject(oMember, sChar); if (charobj and charobj[KARMA_DB_L6_RRFFMCC_REGIONLIST]) then local oRegions = charobj[KARMA_DB_L6_RRFFMCC_REGIONLIST]; if (oRegions) then local CommonRegionList = KarmaObj.DB.CG.RegionListGet(); local k, v; for k, v in pairs(oRegions) do local iRegionID = v[KARMA_DB_L7_RRFFMCCRR_ID]; local sRegion = CommonRegionList[iRegionID].Name; if (string.find(sRegion, sInstance)) then return true; end end end end return false; end --############################################################################################### --############################################################################################### --############################################################################################### function KarmaObj.DB.FixupAchCMAX() -- CMAX wasn't stored properly at first, this fixes that local lMembers = KarmaObj.DB.SF.MemberListGet(KDBC.Realm); local sBucketName, oBucketValues; for sBucketName, BucketValue in pairs(lMembers) do -- Loop through each bucket local sMemberName, oMember; for sMemberName, oMember in pairs(BucketValue) do -- Loop through contents of bucket local oMemPerChar = oMember[KARMA_DB_L5_RRFFM_CHARACTERS]; if (type(oMemPerChar) == "table") then for sChar, oChar in pairs(oMemPerChar) do if (type(oChar[KARMA_DB_L6_RRFFMCC_ACHIEVED]) == "table") then local sAKey, oAch; for sAKey, oAch in pairs(oChar[KARMA_DB_L6_RRFFMCC_ACHIEVED]) do if (oAch.CMAX == nil) then local iAch = tonumber(strsub(sAKey, 2)); oAch.CMAX = GetAchievementNumCriteria(iAch); if (oAch.CMAX ~= nil) then local _, sAchievementName = GetAchievementInfo(iAch); KarmaChatDebug("Fixup(CMAX): nil -> " .. oAch.CMAX .. " for " .. sMemberName .. " in data relating to " .. sChar); end end end end end end end end end --############################################################################################### --############################################################################################### --############################################################################################### --[[ local KARMA_DB_L5_RRFFI = { GUID = "GUID", ACTIONS = "ACTIONS", IGNORE = "IGN", TIMEOUT = "TIMEOUT", }; ]]-- function KarmaObj.DB.I24.Clean(oFaction) local oIgn24 = oFaction[KARMA_DB_L4_RRFF.IGNORE24]; if (next(oIgn24)) then local iNow = time() - 86400; local oDrop, k, v = {}; for k, v in pairs(oIgn24) do if (v[KARMA_DB_L5_RRFFI.TIMEOUT] < iNow) then tinsert(oDrop, k); end end local iCnt, i = #oDrop; for i = 1, iCnt do oIgn24[oDrop[i]] = nil; end end end function KarmaObj.DB.I24.Add(sName, sGUID, sEvent, sAction, bIgnore) local oFaction = KarmaObj.DB.FactionCacheGet(); local oIgn24 = oFaction[KARMA_DB_L4_RRFF.IGNORE24]; if (oIgn24[sName] == nil) then oIgn24[sName] = { [ KARMA_DB_L5_RRFFI.ACTIONS ] = {} }; end local oData = oIgn24[sName]; local iNow = time(); oData[KARMA_DB_L5_RRFFI.TIMEOUT] = iNow; if (sGUID) then oData[KARMA_DB_L5_RRFFI.GUID] = sGUID; end if (bIgnore ~= nil) then oData[KARMA_DB_L5_RRFFI.IGNORE] = bIgnore; end local oActions = oData[KARMA_DB_L5_RRFFI.ACTIONS]; if (#oActions > 0) then local oPrevious = oActions[#oActions]; if ((oPrevious.iTime == iNow) and (oPrevious.sEvent == sEvent) and (oPrevious.sAction == sAction)) then -- CHAT_MSG_* is sent once per chat window it appears in, only log once return end end oActions[#oActions + 1] = { iTime = iNow, sEvent = sEvent, sAction = sAction }; end function KarmaObj.DB.I24.Check(sName) local oFaction = KarmaObj.DB.FactionCacheGet(); local oIgn24 = oFaction[KARMA_DB_L4_RRFF.IGNORE24]; if (oIgn24[sName] ~= nil) then local oData = oIgn24[sName]; return oData[KARMA_DB_L5_RRFFI.IGNORE]; end return false; end -- --- Import/Export -- function KarmaObj.DB.ExportOne(Member) -- do global export of current server/faction if no name? local sBucketName = KarmaObj.NameToBucket(Member); local lMembers = Karma_Faction_GetMemberList(oFaction); local tMember = lMembers[sBucketName][Member]; if (tMember == nil) then KarmaChatDefault("Can't export " .. args[2] .. KARMA_WINEL_FRAG_COLONSPACE .. KARMA_MSG_COMMAND_NOTMEMBER); return; end -- to export, we need: -- (1) the Questnames to ID mapping -- (2) the Zones to ID mapping -- (3) the player data local KarmaTransRoot = nil; if (KARMATRANS_AVAILABLE ~= nil) then KarmaTransRoot = KarmaExp; else KarmaTransRoot = KarmaData["_EXP_"]; end if (KarmaTransRoot == nil) then KarmaTransRoot = {}; KarmaTransRoot["CSV"] = {}; KarmaTransRoot["LUA"] = {}; KarmaTransRoot["LUA"]["_M"] = {}; KarmaTransRoot["LUA"]["_Q"] = {}; KarmaTransRoot["LUA"]["_Z"] = {}; KarmaTransRoot["LUA"]["_R"] = {}; KarmaTransRoot["SFD"] = {}; KarmaTransRoot["SFD"]["SERVER"] = GetRealmName(); KarmaTransRoot["SFD"]["FACTION"] = KDBC.PlayerFaction; KarmaTransRoot["SFD"]["DBVERSION"] = KARMA_SUPPORTEDDATABASEVERSION; -- assign back if (KARMATRANS_AVAILABLE ~= nil) then KarmaExp = KarmaTransRoot; else KarmaData["_EXP_"] = KarmaTransRoot; end end -- for our import: just everything in Blizzard format -- must not add anything to this, as LUA also adds it into tMember... KarmaTransRoot["LUA"]["_M"][Member] = tMember; -- shortcuts local ExportRootLUA = KarmaTransRoot["LUA"]; local ExportRootCSV = KarmaTransRoot["CSV"]; ExportRootCSV[Member] = {}; -- for import in a spreadsheet -- °: just a char noone uses in notes (hopefully) - any better ideas for a delimiter? local CSVText = "###P;" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM.NAME]) .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM_KARMA]) .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM.LEVEL]) .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM.CLASS]) .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM.CLASS_ID]) .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM.GENDER]) .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM.GUILD]) .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM.RACE]) .. ";°" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM_NOTES]) .. "°"; if (tMember[KARMA_DB_L5_RRFFM_TIMESTAMP] ~= nil) then CSVText = CSVText .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM_TIMESTAMP][KARMA_DB_L5_RRFFM_TIMESTAMP_TRY]) .. ";" .. Karma_NilToEmptyString(tMember[KARMA_DB_L5_RRFFM_TIMESTAMP][KARMA_DB_L5_RRFFM_TIMESTAMP_SUCCESS]); end ExportRootCSV[Member]["_G"] = CSVText; -- let all the IDs make sense... local CQL = CommonQuestListGet(); local CQIL = CommonQuestInfoListGet(); local CZL = CommonZoneListGet(); local RegionListToAdd = {}; for mychar, infos in pairs(tMember[KARMA_DB_L5_RRFFM_CHARACTERS]) do -- convert general CHARACTERS data into CSV format ExportRootCSV[Member][mychar] = {}; ExportRootCSV[Member][mychar]["_X"] = "###PC;" .. Member .. ";" .. mychar .. ";" .. Karma_NilToEmptyString(infos[KARMA_DB_L6_RRFFMCC_XPLAST]) .. ";" .. Karma_NilToEmptyString(infos[KARMA_DB_L6_RRFFMCC_XPMAX]) .. ";" .. Karma_NilToEmptyString(infos[KARMA_DB_L6_RRFFMCC_XP]) .. ";" .. Karma_NilToEmptyString(infos[KARMA_DB_L6_RRFFMCC_PLAYEDLAST]) .. ";" .. Karma_NilToEmptyString(infos[KARMA_DB_L6_RRFFMCC_PLAYED]); ExportRootCSV[Member][mychar]["_Q"] = {}; for index, QID in pairs(infos[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]) do local QIDKey = "Q"..QID; local QIDPos = - QID; if (ExportRootLUA["_Q"][QIDKey] == nil) then if (CQL[QIDPos] ~= nil) then ExportRootLUA["_Q"][QIDKey] = {}; ExportRootLUA["_Q"][QIDKey]["ID"] = QID; ExportRootLUA["_Q"][QIDKey]["NAME"] = CQL[QIDPos]; ExportRootLUA["_Q"][QIDKey]["INFOS"] = CQIL[QIDPos]; local QName = CQL[QIDPos]; if (QName == nil) then QName = "NIL"; end ExportRootCSV[QIDKey] = "###Q2N;" .. QID .. ";" .. QName; -- currently only region ID, wanted originally also QObjectives saved... local QRegionID; if (CQIL[QIDPos] ~= nil) then QRegionID = CQIL[QIDPos].RegionID; end if (QRegionID ~= nil) then ExportRootCSV[QIDKey] = ExportRootCSV[QIDKey] .. ";" .. QRegionID; table.insert(RegionListToAdd, QRegionID); end end end -- last ";" to add completion infos, if available ExportRootCSV[Member][mychar]["_Q"][QIDKey] = "###Q2C;" .. QID .. ";" .. Member .. ";" .. mychar .. ";"; end -- QUESTEXLIST is currently fucked up, thanks to a LUA change of maximum stupidity -- have to change the DB format again to force it to save the Objective-Nr. explicitly -- same for QUESTNAMES. *grmbls* => no action in DB v8 ExportRootCSV[Member][mychar]["_Z"] = {}; for index, ZID in pairs(infos[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]) do local ZIDKey = "Z"..ZID; local ZIDPos = - ZID; if (ExportRootLUA["_Z"][ZIDKey] == nil) then ExportRootLUA["_Z"][ZIDKey] = {}; ExportRootLUA["_Z"][ZIDKey]["ID"] = ZID; if (CZL[ZIDPos] ~= nil) then ExportRootLUA["_Z"][ZIDKey]["NAME"] = CZL[ZIDPos].Name; ExportRootLUA["_Z"][ZIDKey]["RID"] = CZL[ZIDPos].RegionID; local ZName = CZL[ZIDPos].Name; if (ZName == nil) then ZName = "NIL"; end ExportRootCSV[ZIDKey] = "###Z2N;" .. ZID .. ";" .. ZName; local ZRegionID = CZL[ZIDPos].RegionID if (ZRegionID ~= nil) then ExportRootCSV[ZIDKey] = ExportRootCSV[ZIDKey] .. ";" .. ZRegionID; table.insert(RegionListToAdd, ZRegionID); end end end ExportRootCSV[Member][mychar]["_Z"][ZIDKey] = "###Z2C;" .. ZID .. ";" .. Member .. ";" .. mychar .. ";"; end end if (#RegionListToAdd > 0) then local CRL = CommonRegionListGet(); for index, RID in pairs(RegionListToAdd) do if (RID ~= 0) then local RIDKey = "R"..RID; if (ExportRootLUA["_R"][RIDKey] == nil) then ExportRootLUA["_R"][RIDKey] = {}; ExportRootLUA["_R"][RIDKey]["ID"] = RID; ExportRootLUA["_R"][RIDKey]["NAME"] = CRL[RID].Name; local RName = CRL[RID].Name; if (RName == nil) then RName = "NIL"; end ExportRootCSV[RIDKey] = "###R;" .. RID .. ";" .. RName; end end end end end function KarmaObj.DB.Import(args) local KarmaTransRoot = nil; if (KARMATRANS_AVAILABLE ~= nil) then KarmaTransRoot = KarmaImp; else KarmaTransRoot = KarmaData["_IMP_"]; end if (type(KarmaTransRoot) ~= "table") then -- no *sensible* data KarmaChatDefault("No data to import at all."); return; end if KarmaTransRoot == {} then -- empty data KarmaChatDefault("Import data set empty (1)."); return; end if (type(KarmaTransRoot["LUA"]) ~= "table") then -- *still* no sensible data KarmaChatDefault("Import data set empty (2)."); return; end if KarmaTransRoot["LUA"] == {} then -- *still* empty data KarmaChatDefault("Import data set empty (3)."); return; end if (type(KarmaTransRoot["SFD"]) ~= "table") then -- unverifyable source KarmaChatDefault("Import data set incomplete."); return; end local Server = KarmaTransRoot["SFD"]["SERVER"]; local Faction = KarmaTransRoot["SFD"]["FACTION"]; if (GetRealmName() ~= Server) or (KDBC.PlayerFaction ~= Faction) then KarmaChatDefault("Import entries' source does not match. Data set is from server "..Karma_NilToString(Server)..", faction "..Karma_NilToString(Faction)..". Import aborted."); return; end local DBVersion = KarmaTransRoot["SFD"]["DBVERSION"]; if (DBVersion ~= KARMA_SUPPORTEDDATABASEVERSION) then KarmaChatDefault("Import entries were exported from an incompatible version (v"..Karma_NilToString(DBVersion)..")."); KarmaChatDefault("You will have to re-export the data with the current Karma version. Import aborted."); return; end if (args[2] ~= nil) then KarmaChatDefault("Trying to only import " .. args[2] .. KARMA_WINEL_FRAG_TRIDOTS); else KarmaChatDefault("Importing entries" .. KARMA_WINEL_FRAG_TRIDOTS); end KarmaChatSecondary("Starting import" .. KARMA_WINEL_FRAG_TRIDOTS); -- localize local ImportMember, ImportData; -- we only go from the LUA data, CSV is being ignored. -- shortcuts local ImportRootLUA = KarmaTransRoot["LUA"]; -- TODO much later: insert the region info... (i.e. Zone <-> Region mappings) -- first get a mapping of the IDs in the data to our current IDs. local QIDImp2QIDIntern = {}; local ImportQID; for ImportQID, ImportData in pairs(ImportRootLUA["_Q"]) do InternQID = Karma_QuestList_AddQuest(ImportData["NAME"]); QIDImp2QIDIntern[ImportQID] = {}; QIDImp2QIDIntern[ImportQID].ID = InternQID; end local ZIDImp2ZIDIntern = {}; local ImportZID; for ImportZID, ImportData in pairs(ImportRootLUA["_Z"]) do if (ImportData["NAME"] ~= nil) then InternZID = Karma_ZoneList_AddZone(ImportData["NAME"]); ZIDImp2ZIDIntern[ImportZID] = {}; ZIDImp2ZIDIntern[ImportZID].ID = InternZID; end end -- now import the list data local ImportCount = 0; local lMembers = Karma_Faction_GetMemberList(oFaction); for ImportMember, ImportData in pairs(ImportRootLUA["_M"]) do local DoIt = true; if (args[2] ~= nil) then if (args[2] ~= ImportMember) then DoIt = false; else KarmaChatSecondary(args[2] .. " found, importing" .. KARMA_WINEL_FRAG_TRIDOTS); end end if (DoIt) then ImportCount = ImportCount + 1; local sBucketName = KarmaObj.NameToBucket(ImportMember); if (lMembers[sBucketName][ImportMember] == nil) then Karma_MemberList_Add(ImportMember); KarmaChatSecondary("Added "..ImportMember.." to Karma's list" .. KARMA_WINEL_FRAG_TRIDOTS); end local tMember = lMembers[sBucketName][ImportMember]; -- now, don't *lose* data here, that would really be the opposite of why the whole export/import is done... -- Karma value... tricky one. take max. to allow multiple imports of the same data local DeltaImp = KarmaObj.DB.M.KarmaGet(ImportData) - 50; local DeltaIntern = KarmaObj.DB.M.KarmaGet(tMember) - 50; local ImpKarmaNew; if (DeltaIntern == 0) then ImpKarmaNew = 50 + DeltaImp; elseif (DeltaImp == 0) then ImpKarmaNew = 50 + DeltaIntern; elseif (DeltaImp > 0) and (DeltaIntern > 0) then ImpKarmaNew = 50 + max(DeltaImp, DeltaIntern); else ImpKarmaNew = 50 + min(DeltaImp, DeltaIntern); end if (ImpKarmaNew < 0) then ImpKarmaNew = 0; elseif (ImpKarmaNew > 100) then ImpKarmaNew = 100; end KarmaObj.DB.M.KarmaSet(tMember, ImpKarmaNew); if (tMember[KARMA_DB_L5_RRFFM.LEVEL] == 0) and (ImportData[KARMA_DB_L5_RRFFM.LEVEL] > 0) then tMember[KARMA_DB_L5_RRFFM.LEVEL] = ImportData[KARMA_DB_L5_RRFFM.LEVEL]; end if (tMember[KARMA_DB_L5_RRFFM.CLASS] == "") and (strlen(Karma_NilToEmptyString(ImportData[KARMA_DB_L5_RRFFM.CLASS])) > 0) then tMember[KARMA_DB_L5_RRFFM.CLASS] = ImportData[KARMA_DB_L5_RRFFM.CLASS]; end if (tMember[KARMA_DB_L5_RRFFM.GENDER] == "") and (type(ImportData[KARMA_DB_L5_RRFFM.GENDER]) == "number") then tMember[KARMA_DB_L5_RRFFM.GENDER] = ImportData[KARMA_DB_L5_RRFFM.GENDER]; end if (tMember[KARMA_DB_L5_RRFFM.GUILD] == "") and (ImportData[KARMA_DB_L5_RRFFM.GUILD] ~= "") then tMember[KARMA_DB_L5_RRFFM.GUILD] = ImportData[KARMA_DB_L5_RRFFM.GUILD]; end if (tMember[KARMA_DB_L5_RRFFM.RACE] == "") and (ImportData[KARMA_DB_L5_RRFFM.RACE] ~= "") then tMember[KARMA_DB_L5_RRFFM.RACE] = ImportData[KARMA_DB_L5_RRFFM.RACE]; end -- Notes... same problem as above. add if missing to allow multiple imports of the same data -- this could backfire, if multiple different subsets of notes are added multiple times in different order -- I'd call that user error ;) /Kärbär if (string.find(tMember[KARMA_DB_L5_RRFFM_NOTES], ImportData[KARMA_DB_L5_RRFFM_NOTES], 1, true) == nil) then tMember[KARMA_DB_L5_RRFFM_NOTES] = tMember[KARMA_DB_L5_RRFFM_NOTES] .. ImportData[KARMA_DB_L5_RRFFM_NOTES]; end for mychar, infos in pairs(ImportData[KARMA_DB_L5_RRFFM_CHARACTERS]) do local MemChar = tMember[KARMA_DB_L5_RRFFM_CHARACTERS][mychar]; if (MemChar ~= nil) then if (args[2] ~= nil) then KarmaChatDebug("K: "..ImportMember.."::"..mychar.." started."); end -- XPLAST, XPMAX: -- most recent update of the player to our current (XPLAST) and level max (XPMAX) exp -- XP: -- accumulation of grouped exp with the player -- therefore: -- the value with the larger XPMAX or if same, larger XPLAST, wins local MemXPMax = Karma_NilToZero(MemChar[KARMA_DB_L6_RRFFMCC_XPMAX]); local ImpXPMax = Karma_NilToZero(infos[KARMA_DB_L6_RRFFMCC_XPMAX]); if (MemXPMax < ImpXPMax) or ((MemXPMax == ImpXPMax) and (Karma_NilToZero(MemChar[KARMA_DB_L6_RRFFMCC_XPLAST]) <= Karma_NilToZero(infos[KARMA_DB_L6_RRFFMCC_XPLAST]))) then MemChar[KARMA_DB_L6_RRFFMCC_XPLAST] = infos[KARMA_DB_L6_RRFFMCC_XPLAST]; MemChar[KARMA_DB_L6_RRFFMCC_XPMAX] = infos[KARMA_DB_L6_RRFFMCC_XPMAX]; end if (Karma_NilToZero(MemChar[KARMA_DB_L6_RRFFMCC_XP]) < Karma_NilToZero(infos[KARMA_DB_L6_RRFFMCC_XP])) then MemChar[KARMA_DB_L6_RRFFMCC_XP] = infos[KARMA_DB_L6_RRFFMCC_XP]; end -- PLAYEDLAST: timestamp of most recent update to PLAYED -- PLAYED: summed playtime -- therefore: take larger PLAYED, reset PLAYEDLAST MemChar[KARMA_DB_L6_RRFFMCC_PLAYEDLAST] = 0; if (Karma_NilToZero(MemChar[KARMA_DB_L6_RRFFMCC_PLAYED]) < Karma_NilToZero(infos[KARMA_DB_L6_RRFFMCC_PLAYED])) then MemChar[KARMA_DB_L6_RRFFMCC_PLAYED] = infos[KARMA_DB_L6_RRFFMCC_PLAYED]; end local QIDIntern = {}; for index, QID in pairs(infos[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]) do local QIDKey = "Q"..QID; if (QIDImp2QIDIntern[QIDKey] ~= nil) then table.insert(QIDIntern, QIDImp2QIDIntern[QIDKey].ID); end end local S1, S2, S3; S1 = #MemChar[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]; S2 = #QIDIntern; MemChar[KARMA_DB_L6_RRFFMCC_QUESTIDLIST] = Karma_TableMerge2Into1(MemChar[KARMA_DB_L6_RRFFMCC_QUESTIDLIST], QIDIntern); S3 = #MemChar[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]; if (args[2] ~= nil) and (S2 > 0) then KarmaChatDebug("K: "..ImportMember.."::"..mychar..": Q "..S1.."+"..S2.."="..S3); end if (infos[KARMA_DB_L6_RRFFMCC_QUESTEXLIST] ~= nil) then for index, QIDEx in pairs(infos[KARMA_DB_L6_RRFFMCC_QUESTEXLIST]) do -- currently (v8) not really feasible :/ end end local ZIDIntern = {}; for index, ZID in pairs(infos[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]) do local ZIDKey = "Z"..ZID; if (ZIDImp2ZIDIntern[ZIDKey] ~= nil) then table.insert(ZIDIntern, ZIDImp2ZIDIntern[ZIDKey].ID); end end S1 = #MemChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]; S2 = #ZIDIntern; MemChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST] = Karma_TableMerge2Into1(MemChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST], ZIDIntern); S3 = #MemChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]; if (args[2] ~= nil) and (S2 > 0) then KarmaChatDebug("K: "..ImportMember.."::"..mychar..": Q "..S1.."+"..S2.."="..S3); end if (args[2] ~= nil) then KarmaChatDebug("K: "..ImportMember.."::"..mychar.." ended."); end end end end end KarmaChatSecondary("Import complete."); KarmaChatDefault("Import complete, "..ImportCount.." entries transmogrified."); end function KarmaObj.DB.ImpExpCleanup() if (KARMATRANS_AVAILABLE ~= nil) then KarmaExp = nil; KarmaImp = nil; else KarmaData["_EXP_"] = nil; KarmaData["_IMP_"] = nil; end end function KarmaObj.DB.MergeChar(oCharA, oCharB) local tMember = oCharA; local ImportData = oCharB; -- Karma value... tricky one. take max. to allow multiple imports of the same data local DeltaImp = KarmaObj.DB.M.KarmaGet(ImportData) - 50; local DeltaIntern = KarmaObj.DB.M.KarmaGet(tMember) - 50; local ImpKarmaNew; if (DeltaIntern == 0) then ImpKarmaNew = 50 + DeltaImp; elseif (DeltaImp == 0) then ImpKarmaNew = 50 + DeltaIntern; elseif (DeltaImp > 0) and (DeltaIntern > 0) then ImpKarmaNew = 50 + max(DeltaImp, DeltaIntern); else ImpKarmaNew = 50 + min(DeltaImp, DeltaIntern); end if (ImpKarmaNew < 0) then ImpKarmaNew = 0; elseif (ImpKarmaNew > 100) then ImpKarmaNew = 100; end KarmaObj.DB.M.KarmaSet(tMember, ImpKarmaNew); if (tMember[KARMA_DB_L5_RRFFM.LEVEL] == 0) and (ImportData[KARMA_DB_L5_RRFFM.LEVEL] > 0) then tMember[KARMA_DB_L5_RRFFM.LEVEL] = ImportData[KARMA_DB_L5_RRFFM.LEVEL]; end if (tMember[KARMA_DB_L5_RRFFM.CLASS] == "") and (strlen(Karma_NilToEmptyString(ImportData[KARMA_DB_L5_RRFFM.CLASS])) > 0) then tMember[KARMA_DB_L5_RRFFM.CLASS] = ImportData[KARMA_DB_L5_RRFFM.CLASS]; end if (tMember[KARMA_DB_L5_RRFFM.GENDER] == "") and (type(ImportData[KARMA_DB_L5_RRFFM.GENDER]) == "number") then tMember[KARMA_DB_L5_RRFFM.GENDER] = ImportData[KARMA_DB_L5_RRFFM.GENDER]; end if (tMember[KARMA_DB_L5_RRFFM.GUILD] == "") and (ImportData[KARMA_DB_L5_RRFFM.GUILD] ~= "") then tMember[KARMA_DB_L5_RRFFM.GUILD] = ImportData[KARMA_DB_L5_RRFFM.GUILD]; end if (tMember[KARMA_DB_L5_RRFFM.RACE] == "") and (ImportData[KARMA_DB_L5_RRFFM.RACE] ~= "") then tMember[KARMA_DB_L5_RRFFM.RACE] = ImportData[KARMA_DB_L5_RRFFM.RACE]; end -- Notes... same problem as above. add if missing to allow multiple imports of the same data -- this could backfire, if multiple different subsets of notes are added multiple times in different order -- I'd call that user error ;) /Kärbär if (ImportData[KARMA_DB_L5_RRFFM_NOTES]) then local sNotesA = tMember[KARMA_DB_L5_RRFFM_NOTES] or ""; local sNotesB = ImportData[KARMA_DB_L5_RRFFM_NOTES] or ""; if (string.find(sNotesA, sNotesB, 1, true) == nil) then tMember[KARMA_DB_L5_RRFFM_NOTES] = (tMember[KARMA_DB_L5_RRFFM_NOTES] or "") .. ImportData[KARMA_DB_L5_RRFFM_NOTES]; end if (tMember[KARMA_DB_L5_RRFFM_NOTES] == "") then tMember[KARMA_DB_L5_RRFFM_NOTES] = nil; end end local iImpIx, infos; for iImpIx, infos in pairs(ImportData[KARMA_DB_L5_RRFFM_CHARACTERS]) do local MemChar, iMemIx, oMemData for iMemIx, oMemData in pairs(tMember[KARMA_DB_L5_RRFFM_CHARACTERS]) do if (oMemData[KARMA_DB_L6_RRFFMCC_KARMA_ID] == infos[KARMA_DB_L6_RRFFMCC_KARMA_ID]) then MemChar = oMemData; break end end if (MemChar ~= nil) then if (args[2] ~= nil) then KarmaChatDebug("K: "..ImportMember.."::"..iImpIx.." started."); end -- XPLAST, XPMAX: -- most recent update of the player to our current (XPLAST) and level max (XPMAX) exp -- XP: -- accumulation of grouped exp with the player -- therefore: -- the value with the larger XPMAX or if same, larger XPLAST, wins local MemXPMax = Karma_NilToZero(MemChar[KARMA_DB_L6_RRFFMCC_XPMAX]); local ImpXPMax = Karma_NilToZero(infos[KARMA_DB_L6_RRFFMCC_XPMAX]); if (MemXPMax < ImpXPMax) or ((MemXPMax == ImpXPMax) and (Karma_NilToZero(MemChar[KARMA_DB_L6_RRFFMCC_XPLAST]) <= Karma_NilToZero(infos[KARMA_DB_L6_RRFFMCC_XPLAST]))) then MemChar[KARMA_DB_L6_RRFFMCC_XPLAST] = infos[KARMA_DB_L6_RRFFMCC_XPLAST]; MemChar[KARMA_DB_L6_RRFFMCC_XPMAX] = infos[KARMA_DB_L6_RRFFMCC_XPMAX]; end if (Karma_NilToZero(MemChar[KARMA_DB_L6_RRFFMCC_XP]) < Karma_NilToZero(infos[KARMA_DB_L6_RRFFMCC_XP])) then MemChar[KARMA_DB_L6_RRFFMCC_XP] = infos[KARMA_DB_L6_RRFFMCC_XP]; end -- PLAYEDLAST: timestamp of most recent update to PLAYED -- PLAYED: summed playtime -- therefore: take larger PLAYED, reset PLAYEDLAST MemChar[KARMA_DB_L6_RRFFMCC_PLAYEDLAST] = 0; if (Karma_NilToZero(MemChar[KARMA_DB_L6_RRFFMCC_PLAYED]) < Karma_NilToZero(infos[KARMA_DB_L6_RRFFMCC_PLAYED])) then MemChar[KARMA_DB_L6_RRFFMCC_PLAYED] = infos[KARMA_DB_L6_RRFFMCC_PLAYED]; end local QIDIntern = {}; for index, QID in pairs(infos[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]) do local QIDKey = "Q"..QID; if (QIDImp2QIDIntern[QIDKey] ~= nil) then table.insert(QIDIntern, QIDImp2QIDIntern[QIDKey].ID); end end local S1, S2, S3; S1 = #MemChar[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]; S2 = #QIDIntern; MemChar[KARMA_DB_L6_RRFFMCC_QUESTIDLIST] = Karma_TableMerge2Into1(MemChar[KARMA_DB_L6_RRFFMCC_QUESTIDLIST], QIDIntern); S3 = #MemChar[KARMA_DB_L6_RRFFMCC_QUESTIDLIST]; if (args[2] ~= nil) and (S2 > 0) then KarmaChatDebug("K: "..ImportMember.."::"..iImpIx..": Q "..S1.."+"..S2.."="..S3); end local ZIDIntern = {}; for index, ZID in pairs(infos[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]) do local ZIDKey = "Z"..ZID; if (ZIDImp2ZIDIntern[ZIDKey] ~= nil) then table.insert(ZIDIntern, ZIDImp2ZIDIntern[ZIDKey].ID); end end S1 = #MemChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]; S2 = #ZIDIntern; MemChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST] = Karma_TableMerge2Into1(MemChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST], ZIDIntern); S3 = #MemChar[KARMA_DB_L6_RRFFMCC_ZONEIDLIST]; if (args[2] ~= nil) and (S2 > 0) then KarmaChatDebug("K: "..ImportMember.."::"..iImpIx..": Q "..S1.."+"..S2.."="..S3); end local iQEx, oQEx; for iQEx, oQEx in pairs(infos[KARMA_DB_L6_RRFFMCC_QUESTEXLIST]) do if (MemChar[KARMA_DB_L6_RRFFMCC_QUESTEXLIST][iQEx] == nil) then MemChar[KARMA_DB_L6_RRFFMCC_QUESTEXLIST][iQEx] = oQEx; end end local iDungeon, oDungeon; for iDungeon, oDungeon in pairs(infos[KARMA_DB_L6_RRFFMCC_REGIONLIST]) do tinsert(MemChar[KARMA_DB_L6_RRFFMCC_REGIONLIST], oDungeon); end local iAch, oAch; for iAch, oAch in pairs(infos[KARMA_DB_L6_RRFFMCC_ACHIEVED]) do if (MemChar[KARMA_DB_L6_RRFFMCC_ACHIEVED][iAch] == nil) then MemChar[KARMA_DB_L6_RRFFMCC_ACHIEVED][iAch] = oAch; end end if (args[2] ~= nil) then KarmaChatDebug("K: "..ImportMember.."::"..iImpIx.." ended."); end end end end