--[[ The SW Sync Channel ]]-- SW_SyncPassiveMode = false; SW_SyncMsgs = {}; SW_S_DetailsSynced = {}; SW_S_HealedSynced = {}; --1.5 added deathcounter to sync SW_DCSynced = {}; --1.5.1 added decurse count syncing SW_DecurseCSynced = {}; -- holds "lost" mana info SW_ManaAfterDrop = {0,0,0}; SW_SyncSessionID = 1; SW_SyncChanID = 0; -- var that hold info if we are leaving the SyncChannel SW_SyncLeavingChannel = false; -- used to see if the person is still there SW_LITimerDead = 300; -- 1.42 added timeframe in which to accept session id updates without a RE -- (joining a running channel) SW_SessIDTimerThresh = 210 ; -- in this imeframe we will have at least an LI once SW_SessIDTimer = time(); -- 1.5.3 increased val buffer from 3% to 10% SW_ValBuffer = 10 -- % this is used to check if somebody else needs to post info even though this was a self info (user dropped) SW_DecurseBuffer = 3; --same as above but not as % -- time in seconds to assume the person in the channel has "up to date" info -- eg he drops and reconnects checked in SW_SyncSend SW_SyncKeepTime = 300; SW_S_LastManaSent = {0,0,0}; -- 1.5 added, used to stop sending unneeded messages on relogging SW_StartupTime = time(); SW_SyncIgnoreNil = 120; SW_Sync_MsgTrack = {}; --[[ The sync Queue So we dont have to think about timing record length etc only thing to consider is that one single message may not be larger then 255 chars but we use short strings here anyways ]]-- SW_SyncQueue = { first = 1, last = 0, maxBlockLen = 255, sep = '"', sepLen = 1, queue = {}, clearing = false, itemSep = '~', PushSWInfo = function (self, infType, vals) if self.clearing then return false; end if SW_Settings["SYNCLastChan"] == nil then return; end if SW_SyncChanID == 0 then return; end local tmpVal; local outStr = infType.." "; local valLen =0; local ident = SW_SyncPepper[infType]; local sCount=0; local iCount=0; if vals == nil then vals = { math.random(100) }; end valLen = table.getn(vals); for i,v in ipairs(vals) do tmpVal = tonumber(v); if tmpVal == nil then sCount = sCount + 1; else iCount = iCount + 1; ident = ident + tmpVal; end outStr = outStr..v; if i ~= valLen then outStr = outStr..self.itemSep end end tmpVal = math.floor(math.sqrt(ident * string.len(SW_Settings["SYNCLastChan"]))) * 1000; ident = math.floor(1000 * math.sqrt(ident * string.len(SW_Settings["SYNCLastChan"]))); self:PushVal(SW_SyncSessionID.." "..(ident-tmpVal).." "..sCount.." "..iCount.." "..outStr); --self:PushVal(SW_SyncSessionID.." "..outStr); end, PushVal = function (self, val) if string.len(val) > self.maxBlockLen or self.clearing then return false; end local last = self.last + 1; self.last = last; self.queue[last] = val; return true; end, PopStack = function (self) if self.clearing then return nil; end local last = self.last; if self.first > last then return nil; end local val = self.queue[last]; self.queue[last] = nil; self.last = last - 1; return val; end, Pop = function (self) if self.clearing then return nil; end local first = self.first; if first > self.last then return nil; end local val = self.queue[first]; self.queue[first] = nil; self.first = first + 1; return val; end, HasData = function (self) if self.clearing then return false; end return not (self.first > self.last); end, Clear = function (self) self.clearing = true; for i=self.first, self.last do self.queue[i] = nil; self.first = i + 1; end self.clearing = false; end, PopBlock = function (self) if self.clearing then return nil; end local first = self.first; if first > self.last then return nil; end local sepsLen = self.sepLen; local pos = first; local len = string.len(self.queue[first]); while self.queue[pos + 1] and len + string.len(self.queue[pos + 1]) + sepsLen < self.maxBlockLen do pos = pos + 1; sepsLen = sepsLen + self.sepLen; len = len + string.len(self.queue[pos]); end local val = table.concat(self.queue, self.sep, first, pos); for i=first, pos do self.queue[i] = nil; self.first = i + 1; end return val; end, -- to lazy wouldn't work if + is a sep in the queue not using % -- because this goes through chat and the profanity filter could alter the str and add a % EncStr = function (self, str) local sOut = string.gsub(str, "([%"..self.sep.."%"..self.itemSep.."%+%|])", function(c) return string.format ("+%02X", string.byte(c)) end); return sOut; end, DecStr = function (self, str) local sOut = string.gsub (str, "%+(%x%x)", function(h) return string.char(tonumber(h,16)) end); return sOut; end, }; function SW_SyncSend() -- this only happens when logging out and comeing back in or when leaving sync channel if SW_SyncChanID ~= 0 and SW_Settings["SYNCLastAction"] ~= nil and time() - SW_Settings["SYNCLastAction"] > SW_SyncKeepTime then -- are we still in this channel? id, _ = GetChannelName(SW_Settings["SYNCLastChan"]); if id == 0 then SW_SyncChanID = 0; SW_Settings["SYNCLastChan"] = nil; if SW_S_DetailsSynced[SW_SELF_STRING] ~= nil then SW_S_DetailsSynced[SW_SELF_STRING]["LI"] = nil; end return; end -- if we get here we are still in the channel and need a reset SW_printStr("Reset in SyncSend"); SW_SessIDTimer = time(); SW_SyncReset(1); return; end if SW_SyncChanID == 0 and SW_Settings["SYNCLastChan"] ~= nil then SW_SyncChanID, _ = GetChannelName(SW_Settings["SYNCLastChan"]); end local toSend = SW_SyncQueue:PopBlock(); if toSend ~= nil then if SW_SyncChanID ~= 0 then SendChatMessage(toSend, "CHANNEL", nil, SW_SyncChanID); end end if SW_SyncLeavingChannel then SW_SyncLeavingChannel = false; SW_SyncChanID = 0; LeaveChannelByName(SW_Settings["SYNCLastChan"]); SW_Settings["SYNCLastChan"] = nil; SW_Settings["SYNARP"] = nil; SW_BarFrame1_Title_SyncIcon:Hide(); end end -- used to un/compress ints that are being sent -- not sure about WOW but looking at utf im assuming we have only the lower 127 chars available for 1 byte storage -- minus the lower 32 that are special chars - minus " " (space) - '"' (doublequote) which we want to use -- DOH and dont use \ .. escape codes -- DOH what about pipe?? -- taking it out atm its making more problems than doing good --[[ SW_SyncInt = { digits = {}, rev = {}, base = 10; Init = function(self, base) --[[ self.base = base; self.digits = {}; self.rev = {}; for i=0,9 do self.digits[i] = string.char(48+i) end for i=10,71 do self.digits[i] = string.char(55+i) end -- dont add 127 (DEL) for i=72,84 do self.digits[i] = string.char(119-i) end --go back in the table from before "0" and stop before '"' self.digits[85] = "!"; for i=86,92 do self.digits[i] = string.char(150-i) end --]] self.base = base; self.rev = {}; self.digits = {"1","2","3","4","5","6","7","8","9", "A","B","C","D","E","F","G","H","I","J", "K","L","M","N","O","P","Q","R","S","T", "U","V","W","X","Y","Z","a","b","c","d", "e","f","g","h","i","j","k","l","m","n", "o","p","q","r","s","t","u","v","w","x", "y","z","!","#","$","%","&","(",")", "*","+","-",".","/",":",";","<","=",">", "?","@","^","_","{","}", }; --"y","z","!","#","$","%","&","'","(",")", --"?","@","[","]","^","_","{","}","~", self.digits[0] = "0"; for i,v in ipairs(self.digits) do self.rev[v] = i; end self.rev[ self.digits[0] ] = 0; end, Enc = function(self, number) local s = ""; local remainder = 0; repeat remainder = math.mod(number,self.base); s = self.digits[remainder]..s; number = (number-remainder)/self.base; until number==0 return s; end, Dec = function(self, number) local num = 0; local sLen = string.len(number); for i=1,sLen do num = num + (self.rev[string.sub(number,i,i)] * self.base ^ (sLen - i)); end return num; end, }; ]]-- -- reset -- 1.4.2 changed this it will only reset yourself if your A or L -- and others will check if the sender is A or L -- 1.5.beta.1 added a "force self reset" for completion on a reset vote function SW_SyncReset(newSessID, issuedBy, selfForce) if newSessID ~= nil then if issuedBy ~= nil then -- 1.5.3 very ralrely some events don't fire -- if sombody has an A or is L might not be known so added this -- drawback: somebody with A might have started RE, then had A revoked milliseconds after he sent the msg -- oh hell can't catch em all SW_RebuildFriendList(); end if (issuedBy == nil and (time()-SW_SessIDTimer) < SW_SessIDTimerThresh) or (issuedBy ~= nil and SW_Friends[issuedBy] ~= nil and SW_Friends[issuedBy].Rank > 0) then SW_SyncQueue.clearing = true; SW_ResetInfo(); SW_S_DetailsSynced = {}; SW_S_HealedSynced = {}; SW_DCSynced = {}; SW_ManaAfterDrop = {0,0,0}; SW_SyncSessionID = tonumber(newSessID); SW_Settings["SYNCLastAction"] = time(); SW_SyncQueue:Clear(); end else if SW_Friends[SW_SELF_STRING].Rank > 0 or selfForce then SW_SyncQueue.clearing = true; SW_ResetInfo(); SW_S_DetailsSynced = {}; SW_S_HealedSynced = {}; SW_DCSynced = {}; SW_ManaAfterDrop = {0,0,0}; SW_SyncQueue:Clear(); SW_SyncSessionID = SW_SyncSessionID + 1; end if SW_Friends[SW_SELF_STRING].Rank > 0 and (not selfForce) then SW_SyncQueue:PushSWInfo("RE"); end end end --[[ 1.5 added this The old way wouldnt leave the channel and join a new one in the same funccall --]] local SW_PendingJoinInfo = { newChan = nil, isPassive = nil, } --[[ if isPassive == true that person wont send sync msgs but can listen TODO testing 1.5.3 I noticed some messages do get sent - these are sent through "catch" functions when we send data on a recieved data event, because these are so few not sure if a change is needed --]] function SW_SyncJoin(chanName, isPassive) if tonumber(chanName) then return; end local retName; local id; local oldSynarp; if chanName == nil then return; end SW_Timed_Calls:StopJoinChanPending(); SW_Timed_Calls:StopCheckChan(); --Stop the pump sending messages SW_SyncChanID = 0; oldSynarp = SW_Settings["SYNARP"]; SW_Settings["SYNARP"] = nil; if SW_Settings["SYNCLastChan"] ~= nil then if SW_Settings["SYNCLastChan"] == chanName then -- are we still in this channel? id, _ = GetChannelName(chanName); if id ~= 0 then if SW_Settings["SYNCLastAction"] ~= nil and time() - SW_Settings["SYNCLastAction"] < SW_SyncKeepTime then -- if we get here it was just a repost, for new members to join this chan SW_SyncChanID = id; SW_Settings["SYNARP"] = oldSynarp; return else SW_printStr("Reset on Join LA:"..SW_Settings["SYNCLastAction"].." NOW:"..time()); end end else SW_SyncQueue.clearing = true; --SW_DumpResultList(GetChannelList()); LeaveChannelByName(SW_Settings["SYNCLastChan"]); end end --SW_DumpResultList(GetChannelList()); -- 1.5 leaving and joining while already in 10 channels where 1 is swtats didnt work. SW_PendingJoinInfo.newChan = chanName; SW_PendingJoinInfo.isPassive = isPassive; SW_Timed_Calls:StartJoinChanPending(); end function SW_SyncJoinPending() local chanName = SW_PendingJoinInfo.newChan; if chanName == nil then return; end if SW_PendingJoinInfo.isPassive then SW_SyncPassiveMode = isPassive; end SW_SyncQueue.clearing = true; _, retName = JoinChannelByName(chanName); id, _ = GetChannelName(chanName); if id ~= 0 then SW_Settings["SYNCLastChan"] = chanName; SW_SessIDTimer = time(); SW_SyncReset(1); SW_Settings["SYNCLastAction"] = time(); else -- we werent able to join the chan SW_printStr(SW_SYNC_CHAN_FAIL..chanName, 1); SW_Settings["SYNCLastChan"] = nil; end SW_SyncChanID = id; SW_PendingJoinInfo.newChan = nil; SW_PendingJoinInfo.isPassive = nil; SW_Timed_Calls:StartCheckChan(); end function SW_SyncJoinedCheck() local chanName = SW_Settings["SYNCLastChan"]; if chanName == nil then return; end if SW_SyncCheckInChan(chanName) then SW_printStr(SW_SYNC_CHAN_JOIN..chanName, 1); local sf =getglobal("SW_BarSyncFrame"); -- refresh sync frame if sf:IsVisible() then sf:Hide() sf:Show() end -- be sure we arent paused SW_ToggleRunning(true); -- 1.5.3 show the sync icon SW_BarFrame1_Title_SyncIcon:Show(); else SW_printStr(SW_SYNC_CHAN_FAIL..chanName, 1); end end function SW_SyncCheckInChan(chanName) local function Check(...) local i = 1; while arg[i] ~= nil do if arg[i] == chanName then return true; end i = i + 1; end return false; end if Check(GetChannelList()) then return true; else SW_SyncChanID = 0; SW_Settings["SYNCLastChan"] = nil; SW_Settings["SYNARP"] = nil; SW_BarFrame1_Title_SyncIcon:Hide(); if chanName then SW_printStr("SW_SyncCheckInChan:False "..chanName); else SW_printStr("SW_SyncCheckInChan:False Name:NIL"); end --SW_printStr(debugstack()); return false; end end function SW_SyncCheckMsgForChan(msg, who) local chan; _,_,chan = string.find(msg, SW_SYNC_CHAN_REGEX); if chan ~= nil and who~= nil and chan ~= SW_Settings["SYNCLastChan"] then StaticPopupDialogs["SW_JoinCheck"]["SW_toChan"] = chan; StaticPopupDialogs["SW_JoinCheck"]["SW_postedBy"] = who; StaticPopupDialogs["SW_JoinCheck"]["text"] = string.format(SW_SYNC_JOINCHECK_FROM, chan, who).."\n"..SW_SYNC_JOINCHECK_INFO; StaticPopup_Show ("SW_JoinCheck"); end end function SW_SyncSplitMsg(msg) local t = {}; local function helper(line) table.insert(t, line); end helper((string.gsub(msg, "(.-)%"..SW_SyncQueue.sep, helper))) return t end function SW_SyncCheckAlive() local now = time(); for k,v in pairs(SW_S_DetailsSynced) do if v["LI"] ~= nil then if now - v["LI"] > SW_LITimerDead then v["LI"] = nil; end end end if SW_SyncPassiveMode then return; end if SW_S_DetailsSynced[SW_SELF_STRING] == nil or SW_S_DetailsSynced[SW_SELF_STRING]["LI"] == nil or time() - SW_S_DetailsSynced[SW_SELF_STRING]["LI"] > (SW_LITimerDead - 200) then SW_SyncQueue:PushSWInfo("LI"); end end function SW_SyncHandleMsg(msg, from) local pre; --[[ this will inject even more wrong people if sombody is drunk.. (S->Sh) but most of the times people use filters, group, evergroup npc etc so these drop out anyways in the display but a lot of the info is most likely valid also this will suppress most unexpected ident msgs if somebody is drunk --]] if SLURRED_SPEECH ~= nil then _,_,pre = string.find(msg, SW_DrunkRegEx) if pre ~= nil then --SW_printStr(msg.."==>"..pre); msg = pre; end end local msgs = SW_SyncSplitMsg(msg); SW_Settings["SYNCLastAction"] = time(); local v1,vx,vs,vi,v2,v3,vals,ident, tmpInt, iCount, sCount; --handels a single Sync Msg for __,oneLine in ipairs(msgs) do _,_,v1,vx,vs,vi,v2,v3 = string.find(oneLine, "^(%d+) (%d+) (%d+) (%d+) (.-) (.+)"); --_,_,v1,v2,v3 = string.find(oneLine, "^(%d+) (.-) (.+)"); if v1==nil or vx==nil or vs==nil or vi==nil or v2==nil or v3==nil then -- another wierd one that happens very rarely -- hmm this could happen if somebody types normal chat messages into the SyncChannel SW_printStr("SW_SyncHandleMsg NIL value FROM: "..from.." in Msg:"); SW_printStr(oneLine); return; end vx = tonumber(vx); vs = tonumber(vs); vi = tonumber(vi); vals = {}; for info in string.gfind(v3, "[^~]+") do table.insert(vals,info); end if table.getn(vals) ~= vs+vi then SW_printStr("SW_SyncHandleMsg unexpected argument count FROM: "..from.." in Msg:"); SW_printStr(oneLine); return; end ident = SW_SyncPepper[v2]; if ident == nil then SW_printStr("SW_SyncHandleMsg unexpected type FROM: "..from.." in Msg:"); SW_printStr(oneLine); return; end sCount=0; iCount=0; for i,v in ipairs(vals) do tmpInt = tonumber(v); if tmpInt == nil then sCount = sCount+1; else iCount=iCount+1; vals[i] = tmpInt; ident = ident + tmpInt; end end if sCount ~= vs or iCount ~= vi then SW_printStr("SW_SyncHandleMsg type missmatch FROM: "..from.." in Msg:"); SW_printStr(oneLine); return; end -- can happen while leaving channel if SW_Settings["SYNCLastChan"] == nil then return; end tmpInt = math.floor(math.sqrt(ident * string.len(SW_Settings["SYNCLastChan"]))) * 1000; ident = math.floor(1000 * math.sqrt(ident * string.len(SW_Settings["SYNCLastChan"]))); if ident-tmpInt ~= vx then SW_printStr("SW_SyncHandleMsg unexpected ident FROM: "..from.." in Msg:"); SW_printStr(oneLine); return; end -- ignore "old" messages if tonumber(v1) < SW_SyncSessionID then return; end -- 1.4.2 chganged reset logic if tonumber(v1) > SW_SyncSessionID then if v2 == "RE" then SW_SyncReset(v1, from); else SW_SyncReset(v1); end else if SW_S_DetailsSynced[from] == nil then SW_S_DetailsSynced[from] = {}; end SW_S_DetailsSynced[from]["LI"] = time(); if v2 ~= "RE" then -- if == and RE we issued it and already did reset if SW_SyncMsgs[v2] ~= nil then SW_SyncMsgs[v2](vals, from); end end end end end function SW_GetValPair(name, subItem, S) if S == nil then return nil; end if S[name] == nil then --[[SW_printStr("NILCRAP "..name.." "..subItem);--]] return 0,0; end if S[name][subItem] == nil then return 0,0; end return S[name][subItem][1],S[name][subItem][2]; end function SW_SetValPair(name, subItem, S, v1, v2) if S == nil then return nil; end if S[name] == nil then S[name]={}; end if S[name][subItem] == nil then S[name][subItem] = {}; end S[name][subItem][1] = v1; S[name][subItem][2] = v2; end function SW_GetVal(name, subItem, S) if S == nil then return nil; end if S[name] == nil then return 0; end if S[name][subItem] == nil then return 0; end return S[name][subItem]; end function SW_SetVal(name, subItem, S, v) if S == nil then return nil; end if S[name] == nil then S[name]={}; end S[name][subItem] = v; end function SW_SyncDo() if SW_Settings["SYNCLastChan"] == nil and SW_SyncChanID ==0 then return; end if not SW_SyncCheckInChan(SW_Settings["SYNCLastChan"]) then return; end if SW_SyncPassiveMode then return; end SW_SyncDoOne(SW_SELF_STRING, true); SW_SyncDoHeal(SW_SELF_STRING, true); SW_SyncDoMana(); local SW_SyncP = 0; local rnd; local peerCount =0; for k,v in pairs(SW_S_DetailsSynced) do if SW_S_DetailsSynced[k]["LI"] ~= nil then peerCount = peerCount +1; end end --auto% when to sync if peerCount > 5 then SW_SyncP = math.ceil( (100 / peerCount) / 2 ); else -- nonsense to post when alone but i use it for testing SW_SyncP = 10; end for k,v in pairs(SW_S_Details) do rnd = math.random(100); if k ~= SW_SELF_STRING and rnd <= SW_SyncP then if SW_S_DetailsSynced[k] == nil then SW_SyncDoOne(k, false); else if SW_S_DetailsSynced[k]["LI"] == nil then SW_SyncDoOne(k, false); end end end end for k,v in pairs(SW_S_Healed) do rnd = math.random(100); if k ~= SW_SELF_STRING and rnd <= SW_SyncP then if SW_S_HealedSynced[k] == nil then SW_SyncDoHeal(k, false); else -- only tracking "alive" in SW_S_DetailsSynced if SW_S_DetailsSynced[k] == nil or SW_S_DetailsSynced[k]["LI"] == nil then SW_SyncDoHeal(k, false); end end end end for k,v in pairs(SW_PetInfo["PET_OWNER"]) do rnd = math.random(100); if rnd <= SW_SyncP or (v["currentOwners"] and v["currentOwners"][SW_SELF_STRING]) then SW_SyncDoOnePet(k); end end for k,v in pairs(SW_PetInfo["OWNER_PET"]) do rnd = math.random(100); if rnd <= SW_SyncP or k == SW_SELF_STRING then SW_SyncDoOnePetOwner(k); end end for k,v in pairs(SW_S_SpellInfo) do rnd = math.random(100); if rnd <= SW_SyncP or k == SW_SELF_STRING then SW_SyncDoOneDecurseCount(k); end end end -- only do self function SW_SyncDoMana() if SW_S_ManaUsage ~= nil and SW_S_ManaUsage[SW_SELF_STRING] ~= nil then local v = SW_S_ManaUsage[SW_SELF_STRING]; if v[1] > 0 or v[2] > 0 then if SW_S_LastManaSent[1] < v[1] or SW_S_LastManaSent[2] < v[2] or SW_S_LastManaSent[3] < v[3] then SW_S_LastManaSent[1] = v[1]; SW_S_LastManaSent[2] = v[2]; SW_S_LastManaSent[3] = v[3]; SW_SyncQueue:PushSWInfo("MI", {SW_ManaAfterDrop[1] + v[1],SW_ManaAfterDrop[2] + v[2],SW_ManaAfterDrop[3] + v[3]}); end end end end function SW_SyncDoHeal(name, isSelf) local hi = SW_S_Healed[name]; if hi == nil then return; end local hiSync = SW_S_HealedSynced[name]; if hiSync == nil and time() - SW_StartupTime < SW_SyncIgnoreNil then return; end for k,v in hi do if hiSync == nil or hiSync[k] == nil or v > hiSync[k] then if isSelf then SW_SyncQueue:PushSWInfo("HIS", {k, v}); else SW_SyncQueue:PushSWInfo("HIO", {name, k, v}); end end end end function SW_SyncDoOne(name, isSelf) local doneDmg, doneHeal = SW_GetValPair(name, SW_PRINT_ITEM_TOTAL_DONE, SW_S_Details); local gotDmg, gotHeal = SW_GetValPair(name, SW_PRINT_ITEM_RECIEVED, SW_S_Details); local doneDmgS, doneHealS = SW_GetValPair(name, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced); local gotDmgS, gotHealS = SW_GetValPair(name, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced); SW_SyncDoOneDeathCount(name); if doneDmg > doneDmgS or doneHeal > doneHealS or gotDmg > gotDmgS or gotHeal > gotHealS then if isSelf then SW_SyncQueue:PushSWInfo("SI", {doneDmg, doneHeal, gotDmg, gotHeal}); else if time() - SW_StartupTime < SW_SyncIgnoreNil then if doneDmgS == 0 and doneHealS == 0 and gotDmgS == 0 and gotHealS == 0 then return; end end SW_SyncQueue:PushSWInfo("OI", {name, doneDmg, doneHeal, gotDmg, gotHeal}); end end end function SW_SyncDoOneDeathCount(name) local syDeaths = SW_DCSynced[name]; if syDeaths == nil then syDeaths = 0; end if time() - SW_StartupTime < SW_SyncIgnoreNil then if syDeaths == 0 then return; end end local tmpVal = SW_S_Details[name]; if tmpVal ~= nil and tmpVal[SW_PRINT_ITEM_DEATHS] ~= nil then tmpVal = tmpVal[SW_PRINT_ITEM_DEATHS]; if tmpVal > syDeaths then SW_SyncQueue:PushSWInfo("DC", {name, tmpVal, math.random(100)}); end end end function SW_SyncDeathCount(data, from) local name, newDC, id = unpack(data); local syDeaths = SW_DCSynced[name]; if syDeaths == nil or newDC > syDeaths then SW_DCSynced[name] = newDC; end syDeaths = SW_DCSynced[name]; local tmpVal = SW_S_Details[name]; if tmpVal ~= nil then if tmpVal[SW_PRINT_ITEM_DEATHS] == nil or tmpVal[SW_PRINT_ITEM_DEATHS] < syDeaths then tmpVal[SW_PRINT_ITEM_DEATHS] = syDeaths; end end if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("Info from "..from.." for DeathCount of "..name..": "..newDC); end end function SW_SyncDoOneDecurseCount(name) local syDecs = SW_DecurseCSynced[name]; if syDecs == nil then syDecs = 0; end if time() - SW_StartupTime < SW_SyncIgnoreNil then if syDecs == 0 then return; end end local tmpVal = SW_S_SpellInfo[name]; if tmpVal ~= nil and tmpVal[SW_DECURSEDUMMY] ~= nil and tmpVal[SW_DECURSEDUMMY]["total"] ~= nil then tmpVal = tmpVal[SW_DECURSEDUMMY]["total"]; if tmpVal~=nil and tmpVal > syDecs then SW_SyncQueue:PushSWInfo("DCC", {name, tmpVal, math.random(100)}); end end end function SW_SyncDecurseCount(data, from) local name, newDCC, id = unpack(data); local syDecs = SW_DecurseCSynced[name]; if syDecs == nil or newDCC > syDecs then SW_DecurseCSynced[name] = newDCC; end syDecs = SW_DecurseCSynced[name]; local tmpVal; if SW_S_SpellInfo[name] == nil then SW_S_SpellInfo[name] = {}; end if SW_S_SpellInfo[name][SW_DECURSEDUMMY] == nil then SW_S_SpellInfo[name][SW_DECURSEDUMMY] = {}; end tmpVal = SW_S_SpellInfo[name][SW_DECURSEDUMMY]; if tmpVal["total"] == nil then tmpVal["total"] = 0; end if tmpVal["total"] < syDecs then tmpVal["total"] = syDecs; end if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("Info from "..from.." for DecurseCount of "..name..": "..newDCC); end end function SW_SyncDoOnePetOwner(name) local doneDmg, doneHeal = SW_GetValPair(name, SW_PRINT_ITEM_TOTAL_DONE, SW_PetInfo["OWNER_PET"]); local gotDmg, gotHeal = SW_GetValPair(name, SW_PRINT_ITEM_RECIEVED, SW_PetInfo["OWNER_PET"]); local doneDmgS, doneHealS = SW_GetValPair(SW_PETOWNER..name, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced); local gotDmgS, gotHealS = SW_GetValPair(SW_PETOWNER..name, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced); if doneDmg > doneDmgS or doneHeal > doneHealS or gotDmg > gotDmgS or gotHeal > gotHealS then if time() - SW_StartupTime < SW_SyncIgnoreNil then if doneDmgS == 0 and doneHealS == 0 and gotDmgS == 0 and gotHealS == 0 then return; end end SW_SyncQueue:PushSWInfo("PO", {name, doneDmg, doneHeal, gotDmg, gotHeal}); end end function SW_SyncDoOnePet(name) local doneDmg, doneHeal = SW_GetValPair(name, SW_PRINT_ITEM_TOTAL_DONE, SW_PetInfo["PET_OWNER"]); local gotDmg, gotHeal = SW_GetValPair(name, SW_PRINT_ITEM_RECIEVED, SW_PetInfo["PET_OWNER"]); local doneDmgS, doneHealS = SW_GetValPair(SW_PET..name, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced); local gotDmgS, gotHealS = SW_GetValPair(SW_PET..name, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced); if doneDmg > doneDmgS or doneHeal > doneHealS or gotDmg > gotDmgS or gotHeal > gotHealS then if time() - SW_StartupTime < SW_SyncIgnoreNil then if doneDmgS == 0 and doneHealS == 0 and gotDmgS == 0 and gotHealS == 0 then return; end end SW_SyncQueue:PushSWInfo("PI", {name, doneDmg, doneHeal, gotDmg, gotHeal}); end end function SW_SyncPetOwner(data, from) local name, doneDmgS, doneHealS, gotDmgS, gotHealS = unpack(data); local syncName = SW_PETOWNER..name; local doneDmg, doneHeal = SW_GetValPair(name, SW_PRINT_ITEM_TOTAL_DONE, SW_PetInfo["OWNER_PET"]); local gotDmg, gotHeal = SW_GetValPair(name, SW_PRINT_ITEM_RECIEVED, SW_PetInfo["OWNER_PET"]); local doneDmgSync, doneHealSync = SW_GetValPair(syncName, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced); local gotDmgSync, gotHealSync = SW_GetValPair(syncName, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced); if doneDmgS > doneDmgSync or doneHealS > doneHealSync then SW_SetValPair(syncName, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced, doneDmgS, doneHealS); end if gotDmgS > gotDmgSync or gotHealS > gotHealSync then SW_SetValPair(syncName, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced, gotDmgS, gotHealS); end local v1, v2; if doneDmgS > doneDmg then v1 = doneDmgS; else v1 = doneDmg; end if doneHealS > doneHeal then v2 = doneHealS; else v2 = doneHeal; end SW_SetValPair(name, SW_PRINT_ITEM_TOTAL_DONE, SW_PetInfo["OWNER_PET"], v1, v2); if gotDmgS > gotDmg then v1 = gotDmgS; else v1 = gotDmg; end if gotHealS > gotHeal then v2 = gotHealS; else v2 = gotHeal; end SW_SetValPair(name, SW_PRINT_ITEM_RECIEVED, SW_PetInfo["OWNER_PET"], v1, v2); if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("Info from "..from.." for PETOWNER "..name.." "..doneDmgS.." "..doneHealS.." "..gotDmgS.." "..gotHealS); end end function SW_SyncPetInfo(data, from) local name, doneDmgS, doneHealS, gotDmgS, gotHealS = unpack(data); local syncName = SW_PET..name; local doneDmg, doneHeal = SW_GetValPair(name, SW_PRINT_ITEM_TOTAL_DONE, SW_PetInfo["PET_OWNER"]); local gotDmg, gotHeal = SW_GetValPair(name, SW_PRINT_ITEM_RECIEVED, SW_PetInfo["PET_OWNER"]); local doneDmgSync, doneHealSync = SW_GetValPair(syncName, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced); local gotDmgSync, gotHealSync = SW_GetValPair(syncName, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced); if doneDmgS > doneDmgSync or doneHealS > doneHealSync then SW_SetValPair(syncName, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced, doneDmgS, doneHealS); end if gotDmgS > gotDmgSync or gotHealS > gotHealSync then SW_SetValPair(syncName, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced, gotDmgS, gotHealS); end local v1, v2; if doneDmgS > doneDmg then v1 = doneDmgS; else v1 = doneDmg; end if doneHealS > doneHeal then v2 = doneHealS; else v2 = doneHeal; end SW_SetValPair(name, SW_PRINT_ITEM_TOTAL_DONE, SW_PetInfo["PET_OWNER"], v1, v2); if gotDmgS > gotDmg then v1 = gotDmgS; else v1 = gotDmg; end if gotHealS > gotHeal then v2 = gotHealS; else v2 = gotHeal; end SW_SetValPair(name, SW_PRINT_ITEM_RECIEVED, SW_PetInfo["PET_OWNER"], v1, v2); if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("Info from "..from.." for PET "..name.." "..doneDmgS.." "..doneHealS.." "..gotDmgS.." "..gotHealS); end end function SW_SyncBasicInfo(data, from, isSelf) local doneDmgS, doneHealS, gotDmgS, gotHealS = unpack(data); local isSelfStr =""; local buffedDmg, buffedHeal; if from == nil then SW_Event_Channel:AddMessage("From:NIL"); return; end if isSelf then isSelfStr = " IsSelf "; else isSelfStr = " IsOther "; end if doneDmgS == nil then SW_Event_Channel:AddMessage("From:"..from..isSelfStr.."doneDmgS == NIL: "..data); return; elseif doneHealS == nil then SW_Event_Channel:AddMessage("From:"..from..isSelfStr.."doneHealS == NIL: "..data); return; elseif gotDmgS == nil then SW_Event_Channel:AddMessage("From:"..from..isSelfStr.."gotDmgS == NIL: "..data); return; elseif gotHealS == nil then SW_Event_Channel:AddMessage("From:"..from..isSelfStr.."gotHealS == NIL: "..data); return; end local doneDmg, doneHeal = SW_GetValPair(from, SW_PRINT_ITEM_TOTAL_DONE, SW_S_Details); local gotDmg, gotHeal = SW_GetValPair(from, SW_PRINT_ITEM_RECIEVED, SW_S_Details); --check here if somebody came back after a "reset" (he was disconnected to long) if isSelf and from ~= SW_SELF_STRING and (doneDmgS < doneDmg or doneHealS < doneHeal ) then -- this will trigger a message from every player with the addon installed -- maybe find a better way (but this doesnt happen on a regular basis) -- also the first few "ticks" of selfinfo are lost but ist very little compared to total stats -- and maybe somebody else even got those msgs and we ar totally correct --RC5 Changed this.. generated a LOT of chat spam only issue an update like this if its heihger then SW_ValBuffer % -- could happen because of the chat send delay + chat delay, somebody sent info -- that was correct but it arrived 2 seconds later and this would trigger this aswell buffedDmg = ((doneDmgS/100) * SW_ValBuffer) + doneDmgS; buffedHeal = ((doneHealS/100) * SW_ValBuffer) + doneHealS; if buffedDmg < doneDmg or buffedHeal < doneHeal then if not SW_SyncPassiveMode then --1.5.3 after a reset this would generate unneded msgs -- added a delta val buffer depending on the level if SW_Friends[from] ~= nil and SW_Friends[from]["L"] ~= nil and SW_Friends[from]["L"] > 0 then local minVal = SW_Friends[from]["L"] * 100; if ((doneDmgS + minVal) < doneDmg) or ((doneHealS + minVal) < doneHeal) then SW_SyncQueue:PushSWInfo("OI", {from, doneDmg, doneHeal, gotDmg, gotHeal}); end else -- still have this here for sync to work as expected for people that aren't grouped SW_SyncQueue:PushSWInfo("OI", {from, doneDmg, doneHeal, gotDmg, gotHeal}); end end end return; end local doneDmgSync, doneHealSync = SW_GetValPair(from, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced); local gotDmgSync, gotHealSync = SW_GetValPair(from, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced); local topDelta =0; if isSelf and (doneDmgSync > 0) then topDelta = doneDmgS - doneDmgSync; if SW_Sync_MsgTrack[from]["TOPDELTAD"] < topDelta then SW_Sync_MsgTrack[from]["TOPDELTAD"] = topDelta; end end if isSelf and (doneHealSync > 0) then topDelta = doneHealS - doneHealSync; if SW_Sync_MsgTrack[from]["TOPDELTAH"] < topDelta then SW_Sync_MsgTrack[from]["TOPDELTAH"] = topDelta; end end --0.98 no need to update lower info in synced if doneDmgS > doneDmgSync or doneHealS > doneHealSync then SW_SetValPair(from, SW_PRINT_ITEM_TOTAL_DONE, SW_S_DetailsSynced, doneDmgS, doneHealS); end if gotDmgS > gotDmgSync or gotHealS > gotHealSync then SW_SetValPair(from, SW_PRINT_ITEM_RECIEVED, SW_S_DetailsSynced, gotDmgS, gotHealS); end local v1, v2, sIInced=false; if doneDmgS > doneDmg then v1 = doneDmgS; if isSelf then SW_Sync_MsgTrack[from]["SI_WAS_NEEDED"] = SW_Sync_MsgTrack[from]["SI_WAS_NEEDED"] + 1; sIInced=true; end else v1 = doneDmg; end if doneHealS > doneHeal then v2 = doneHealS; if isSelf and (not sIInced) then SW_Sync_MsgTrack[from]["SI_WAS_NEEDED"] = SW_Sync_MsgTrack[from]["SI_WAS_NEEDED"] + 1; sIInced=true; end else v2 = doneHeal; end SW_SetValPair(from, SW_PRINT_ITEM_TOTAL_DONE, SW_S_Details, v1, v2); if gotDmgS > gotDmg then v1 = gotDmgS; else v1 = gotDmg; end if gotHealS > gotHeal then v2 = gotHealS; else v2 = gotHeal; end -- 1.5.3 raid per second -- an SI with dmg is valid if isSelf and (doneDmgS > doneDmg) then SW_RPS:validEvent(); end SW_SetValPair(from, SW_PRINT_ITEM_RECIEVED, SW_S_Details, v1, v2); if SW_Settings["EI_ShowSync"] ~= nil then if isSelf then SW_Event_Channel:AddMessage("SelfInfo for "..from.." "..doneDmgS.." "..doneHealS.." "..gotDmgS.." "..gotHealS); else SW_Event_Channel:AddMessage("Info for "..from.." "..doneDmgS.." "..doneHealS.." "..gotDmgS.." "..gotHealS); end end end function SW_checkSIOI() local vals = {}; for k, v in pairs (SW_Sync_MsgTrack) do if v["OI_UPDATE_SI"] > 0 then table.insert(vals, {k, v["OI_UPDATE_SI"]}); end end table.sort(vals, function(a,b) return a[2] > b[2]; end); return vals; end function SW_checkSINeeded() local vals = {}; for k, v in pairs (SW_Sync_MsgTrack) do if v["SI_WAS_NEEDED"] > 0 then table.insert(vals, {k, v["SI_WAS_NEEDED"]}); end end table.sort(vals, function(a,b) return a[2] > b[2]; end); return vals; end function SW_updateMsgTrack(from, isOI, data) if SW_Sync_MsgTrack[from] == nil then SW_Sync_MsgTrack[from] = {["OI"] = 0, ["SI"] = 0, ["OI_UPDATE_SI"] = 0, ["SI_WAS_NEEDED"] = 0, ["TOPDELTAD"] = 0, ["TOPDELTAH"] = 0}; end if isOI then if SW_S_DetailsSynced[ data[1] ] and SW_S_DetailsSynced[ data[1] ]["LI"] ~= nil then SW_Sync_MsgTrack[from]["OI_UPDATE_SI"] = SW_Sync_MsgTrack[from]["OI_UPDATE_SI"] + 1; else SW_Sync_MsgTrack[from]["OI"] = SW_Sync_MsgTrack[from]["OI"] + 1; end else SW_Sync_MsgTrack[from]["SI"] = SW_Sync_MsgTrack[from]["SI"] + 1; end end function SW_SyncSelfInfo(data, from) SW_updateMsgTrack(from, false, data); SW_SyncBasicInfo(data, from, true); end function SW_SyncOtherInfo(data, from) --local _,_,nameFrom, restData = string.find(data, "^~(.-)~ (.+)"); --SW_SyncBasicInfo(restData, nameFrom, false); SW_updateMsgTrack(from, true, data); local name = data[1]; table.remove(data, 1); SW_SyncBasicInfo(data, name, false); end function SW_SyncSendARP(allow) if UnitInRaid("player") and not (IsRaidLeader() or IsRaidOfficer()) then return; end if allow then SW_SyncQueue:PushSWInfo("ARP", {"true", math.random(100)}); else SW_SyncQueue:PushSWInfo("ARP", {"false", math.random(100)}); end end function SW_SyncAllowReport(data, from) if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("Allow Report "..data[1].." from "..from); end if data[1] == "true" then SW_Settings["SYNARP"] = true; else SW_Settings["SYNARP"] = nil; end end function SW_SyncManaInfo(data, from) if from ~= SW_SELF_STRING then if SW_S_ManaUsage[from] ~= nil then if data[3] < SW_S_ManaUsage[from][3] then --the sender dropped, alt+f4d etc. -- this isn't time critical and we don't want a huge spam when somebody comes back -- so just make it a 20% chance local rnd = math.random(100); if rnd < 20 then local mu = SW_S_ManaUsage[from]; SW_SyncQueue:PushSWInfo("MIO", {from, mu[1], mu[2], mu[3]}); end else SW_S_ManaUsage[from] = {unpack(data)}; end else SW_S_ManaUsage[from] = {unpack(data)}; end end if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("ManaInfo from "..from.." "..data[1].." "..data[2].." "..data[3]); end end function SW_SyncManaInfoOther(data, from) --this happens when we posten a self mana info and somebody in the SyncChannel -- had a higher value stored, we dropped or alt+f4'd etc if data[1] == SW_SELF_STRING then local tp, m1, m2, m3 = unpack(data); local m1o, m2o, m3o = unpack(SW_ManaAfterDrop); if m3 > m3o then SW_ManaAfterDrop = {m1,m2,m3}; end end if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("ManaInfoOther from "..from.." for "..data[1].." "..data[2].." "..data[3].." "..data[4]); end end function SW_SyncAlive(data, from) if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("LI from "..from); end -- nothing really to do here end -- 0.98 heal info details (who healed who) function SW_SyncHealInfo(healer, healTarget, amount, isSelf) healed = SW_GetVal(healer, healTarget, SW_S_Healed); healedSync = SW_GetVal(healer, healTarget, SW_S_HealedSynced); --the person posting self info dropped if isSelf and healer ~= SW_SELF_STRING and amount < healed then --SW_SyncQueue:Push(SW_SyncSessionID.." HIO ~"..healer.."~ ~"..healTarget.."~ "..healed); if ((amount/100) * SW_ValBuffer) + amount < healed then SW_SyncQueue:PushSWInfo("HIO", {healer, healTarget, healed}); end return; end if amount > healedSync then SW_SetVal(healer, healTarget, SW_S_HealedSynced, amount); end if healed < amount then SW_SetVal(healer, healTarget, SW_S_Healed, amount); end if SW_Settings["EI_ShowSync"] ~= nil then if isSelf then SW_Event_Channel:AddMessage("SelfInfo "..healer.." healed "..healTarget.." "..amount); else SW_Event_Channel:AddMessage("Info "..healer.." healed "..healTarget.." "..amount); end end end function SW_SyncSendLeave() if SW_Settings["SYNCLastChan"] ~= nil then SW_SyncQueue:Clear(); SW_SyncQueue:PushSWInfo("LS"); SW_SyncLeavingChannel = true; end end function SW_SyncHealInfoOther(data, from) local nameFrom, nameTo, amount = unpack(data); SW_SyncHealInfo(nameFrom, nameTo, amount, false); end function SW_SyncHealInfoSelf(data, from) local nameTo, amount = unpack(data); SW_SyncHealInfo(from, nameTo, amount, true); end function SW_SyncRequestFullSync() --SW_SyncQueue:Push(SW_SyncSessionID.." FS "..SW_SyncSessionID); SW_SyncQueue:PushSWInfo("FS"); end --0.98b added full sync --1.5 removed the console sommand to acces this -- it's just nbot needed in the current form function SW_SyncFullSync(nop, from) -- A full sync.. never ever do in fight..... if from == SW_SELF_STRING then --this works but not sure if i want it -- idea is that the requestor sends out all his info SW_S_DetailsSynced = {}; SW_S_HealedSynced = {}; end for k,v in pairs(SW_S_Details) do if k == SW_SELF_STRING then SW_SyncDoOne(k, true); else SW_SyncDoOne(k, false); end end for k,v in pairs(SW_S_Healed) do if k == SW_SELF_STRING then SW_SyncDoHeal(k, true); else SW_SyncDoHeal(k, false); end end end function SW_SyncLeave(data, from) if SW_S_DetailsSynced[from] ~= nil then SW_S_DetailsSynced[from]["LI"] = nil; end end function SW_SyncSendRSU(skillName) SW_SyncQueue:PushSWInfo("RSU", {skillName, math.random(100)}); end function SW_SyncRequestSkillUsage(data, from) if SW_S_SpellInfo[SW_SELF_STRING] ~= nil and SW_S_SpellInfo[SW_SELF_STRING][ data[1] ] ~= nil then SW_SyncQueue:PushSWInfo("SU", {data[1], SW_S_SpellInfo[SW_SELF_STRING][ data[1] ][1], math.random(100)}); end if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("Request Skill Usage from "..from.." for Skill "..data[1]); end end function SW_SyncSkillUsage(data, from) SW_printStr("["..date("%X").."] "..LIGHTYELLOW_FONT_COLOR_CODE..from..FONT_COLOR_CODE_CLOSE.." "..data[1]..":"..RED_FONT_COLOR_CODE..data[2]..FONT_COLOR_CODE_CLOSE); if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("Skill Usage "..from.." for Skill "..data[1]..":"..data[2]); end end -- added 1.4 version check stuff function SW_SyncSendRSV() SW_SyncQueue:PushSWInfo("RSV", {math.random(100)}); end function SW_SyncRequestVersionCheck(data, from) SW_SyncQueue:PushSWInfo("SV", {SW_VERSION, GetLocale(), math.random(100)}); if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("Request Version info from "..from); end end function SW_SyncVersionCheck(data, from) if data[2] ~= nil and tonumber(data[2]) then SW_printStr("["..date("%X").."] "..from.." "..RED_FONT_COLOR_CODE..data[1]..FONT_COLOR_CODE_CLOSE); else SW_printStr("["..date("%X").."] "..from.." "..RED_FONT_COLOR_CODE..data[1]..FONT_COLOR_CODE_CLOSE.." ("..data[2]..")"); end if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("V "..from..": "..data[1].." "..data[2]); end end -- added 1.4 kicking people from the sync chan -- usefull if somebody left the raid/group and is still playing function SW_SyncKick(data, from) if SW_Settings["EI_ShowSync"] ~= nil then SW_Event_Channel:AddMessage("KICK from "..from.." for: "..data[1]); end SW_printStr("["..date("%X").."] KICK from "..from.." for:"..RED_FONT_COLOR_CODE..data[1]..FONT_COLOR_CODE_CLOSE); if data[1] == SW_SELF_STRING then SW_SyncSendLeave(); end end function SW_SendSyncKick(who) SW_SyncQueue:PushSWInfo("KI", {who, math.random(100)}); end function SW_SyncGetLIs() local out = {}; local SW_PC = 0; for k,v in pairs(SW_S_DetailsSynced) do if SW_S_DetailsSynced[k]["LI"] ~= nil then SW_PC = SW_PC +1; out[k] = 1; end end out["SW_PC"] = SW_PC; return out; end function SW_SyncInit() -- use "base 89" -- had nil problems usinglower base to see if it fixes that -- turned off compression alltogether for now --SW_SyncInt:Init(84); SW_SyncMsgs ={ ["RE"] = SW_SyncReset, ["OI"] = SW_SyncOtherInfo, ["SI"] = SW_SyncSelfInfo, ["LI"] = SW_SyncAlive, ["HIO"] = SW_SyncHealInfoOther, ["HIS"] = SW_SyncHealInfoSelf, ["FS"] = SW_SyncFullSync, ["LS"] = SW_SyncLeave, ["MI"] = SW_SyncManaInfo, ["MIO"] = SW_SyncManaInfoOther, ["ARP"] = SW_SyncAllowReport, ["RSU"] = SW_SyncRequestSkillUsage, ["SU"] = SW_SyncSkillUsage, ["RSV"] = SW_SyncRequestVersionCheck, ["SV"] = SW_SyncVersionCheck, ["KI"] = SW_SyncKick, ["PI"] = SW_SyncPetInfo, ["PO"] = SW_SyncPetOwner, ["DC"] = SW_SyncDeathCount, ["IV"] = SW_SyncIssuedVote, ["IVA"] = SW_SyncIssuedVoteAnswer, ["VA"] = SW_SyncVoteAnswer, ["DCC"] = SW_SyncDecurseCount, }; SW_SyncPepper ={ ["RE"] = 3985, ["OI"] = 9724, ["SI"] = 9967, ["LI"] = 5391, ["HIO"] = 8549, ["HIS"] = 3941, ["FS"] = 7105, ["LS"] = 6418, ["MI"] = 8256, ["MIO"] = 9601, ["ARP"] = 4215, ["RSU"] = 1098, ["SU"] = 7209, ["RSV"] = 5780, ["SV"] = 3009, ["KI"] = 6105, ["PI"] = 2193, ["PO"] = 6623, ["DC"] = 1043, ["IV"] = 8312, ["IVA"] = 3104, ["VA"] = 8858, ["DCC"] = 5103, }; end