IMBA_Tracker_Enabled=false; IMBA_Tracker_UpdateTime=0; IMBA_Tracker_StopTimeGuild=0; IMBA_Tracker_StopTimeRaid=0; IMBA_Tracker_LastPos={x=0;y=0}; IMBA_Tracker_PingDelta={x=0;y=0}; IMBA_Tracker_Calibration={} IMBA_TRACKER_UPDATE_RATE = 0.5 local minimapPlayerModel; IMBA_Minimap_Zoom={}; IMBA_Minimap_Zoom[0]={} IMBA_Minimap_Zoom[1]={} --For Outside of WMO's IMBA_Minimap_Zoom[0][0]=1; IMBA_Minimap_Zoom[0][1]=6/7; IMBA_Minimap_Zoom[0][2]=5/7; IMBA_Minimap_Zoom[0][3]=4/7; IMBA_Minimap_Zoom[0][4]=3/7; IMBA_Minimap_Zoom[0][5]=2/7; --For Inside of WMO's IMBA_Minimap_Zoom[1][0]=1*0.643; IMBA_Minimap_Zoom[1][1]=4/5*0.643; IMBA_Minimap_Zoom[1][2]=3/5*0.643; IMBA_Minimap_Zoom[1][3]=2/5*0.643; IMBA_Minimap_Zoom[1][4]=4/15*0.643; IMBA_Minimap_Zoom[1][5]=1/6*0.643; IMBA_Tracker_Preset=false function IMBA_Tracker_OnLoad() DEFAULT_CHAT_FRAME:AddMessage("Tracker Loaded"); this:RegisterEvent("MINIMAP_PING"); this:RegisterEvent("CHAT_MSG_ADDON"); this:RegisterEvent("RAID_ROSTER_UPDATE"); this:RegisterEvent("PLAYER_LOGIN"); -- Create a table of all the Minimap's children objectSimpleCompass_Saved. local children = {Minimap:GetChildren()}; for i=getn(children), 1, -1 do -- Iterate over them all, starting from the end of the list to see if the object reference is a model. -- If it is, and it has no name (in case some addon attached a model to it), it's probably the right one. if children[i]:IsObjectType("Model") and not children[i]:GetName() and not minimapPlayerModel then -- Found, setting as the addon's local to keep the reference. minimapPlayerModel = children[i]; return; end end end function IMBA_Tracker_OnEvent(event) if event=="MINIMAP_PING" then local x,y=Minimap:GetPingPosition(); local zoom = IMBA_Minimap_Zoom[IMBA_isMinimapInsideWMO()][Minimap:GetZoom()]; IMBA_Tracker_PingDelta.x=IMBA_Tracker_PingDelta.x+IMBA_Tracker_LastPos.x-x*zoom; IMBA_Tracker_PingDelta.y=IMBA_Tracker_PingDelta.y+IMBA_Tracker_LastPos.y-y*zoom; IMBA_Tracker_LastPos.x=x; IMBA_Tracker_LastPos.y=y; if not IMBA_TrackerData then IMBA_TrackerData={}; end if IMBA_Tracker_Calibrating then IMBA_Tracker_CalibratePing.x=IMBA_Tracker_CalibratePing.x+IMBA_Tracker_LastPos.x-x*zoom; IMBA_Tracker_CalibratePing.y=IMBA_Tracker_CalibratePing.y+IMBA_Tracker_LastPos.y-y*zoom; end IMBA_TrackerData.Delta=IMBA_Tracker_PingDelta elseif event=="CHAT_MSG_ADDON" then if arg1=="IMBA_TRACKER_UPDATE" then if arg2=="TRANSMIT" then if arg3=="RAID" then IMBA_Tracker_EnabledRaid=true; IMBA_Tracker_StopTimeRaid=GetTime()+15; elseif arg3=="GUILD" then IMBA_Tracker_EnabledGuild=true; IMBA_Tracker_StopTimeGuild=GetTime()+15; end elseif arg2=="CALIBRATE" then local score=2 if IMBA_Tracker_ValidatePos then score=1 IMBA_Tracker_ValidateTime=GetTime()+60; IMBA_Tracker_Calibrating=true IMBA_Tracker_CountTime=GetTime()+10; IMBA_Tracker_CalibratePing={x=0;y=0} end --DEFAULT_CHAT_FRAME:AddMessage("Calibration Request Received") SendAddonMessage("IMBA_TRACKER_UPDATE","CALIBRATION "..score.." "..IMBA_Tracker_PingDelta.x.." "..IMBA_Tracker_PingDelta.y,"RAID"); IMBA_Tracker_Calibration={} elseif string.find(arg2,"CALIBRATION") and IMBA_Tracker_ValidatePos then local score, deltax, deltay _,_,score, deltax, deltay =string.find(arg2,"CALIBRATION (%d+) (-?%d+.?%d*) (-?%d+.?%d*)") score=tonumber(score) deltax=tonumber(deltax) deltay=tonumber(deltay) --DEFAULT_CHAT_FRAME:AddMessage("Received Calibration Vote "..score.." Delta "..deltax.." "..deltay); for k,v in IMBA_Tracker_Calibration do if IMBA_Tracker_CompareNumber(v.x,deltax) and IMBA_Tracker_CompareNumber(v.y,deltay) then v.totalx=v.totalx+score*deltax; v.totaly=v.totaly+score*deltay; v.score=v.score+score; v.x=v.totalx/v.score v.y=v.totaly/v.score return end end tinsert(IMBA_Tracker_Calibration,{x=deltax;y=deltay;totalx=deltax*score;totaly=deltay*score;score=score}) end end elseif event=="RAID_ROSTER_UPDATE" then if IMBA_Tracker_EnabledRaid and GetNumRaidMembers()==0 then IMBA_Tracker_EnabledRaid=false; end elseif event=="PLAYER_LOGIN" then IMBA_Tracker_Loaded=true IMBA_Tracker_ValidatePos=true; IMBA_Tracker_ValidateTime=GetTime()+0.2; --DEFAULT_CHAT_FRAME:AddMessage("Validating Coords"); if IMBA_SavedVariables.LastPlayerPos then local curX,curY; local oldX,oldY; curX, curY = IMBA_Tracker_GetPostion() oldX=IMBA_SavedVariables.LastPlayerPos.x; oldY=IMBA_SavedVariables.LastPlayerPos.y; if (not IMBA_Tracker_CompareNumber(curX,oldX)) or (not IMBA_Tracker_CompareNumber(curY,oldY)) then if IMBA_TrackerData then --DEFAULT_CHAT_FRAME:AddMessage("Incorrect - Testing with saved Delta's") curX=curX+IMBA_TrackerData.Delta.x curY=curY+IMBA_TrackerData.Delta.y if IMBA_Tracker_CompareNumber(curX,oldX) and IMBA_Tracker_CompareNumber(curY,oldY) then --DEFAULT_CHAT_FRAME:AddMessage("Correct Delta and Set") IMBA_Tracker_PingDelta=IMBA_TrackerData.Delta end end end end end end function IMBA_Tracker_CompareNumber(v1,v2) return math.abs(v1-v2)<0.015; end function IMBA_Tracker_GetPostion() local x,y = Minimap:GetPingPosition(); local zoom = IMBA_Minimap_Zoom[IMBA_isMinimapInsideWMO()][Minimap:GetZoom()]; x=x*zoom+IMBA_Tracker_PingDelta.x; y=y*zoom+IMBA_Tracker_PingDelta.y; return x, y end --The various equations to convert map coordinates to Ping coordinates --Linear equations fitted via linear least squares of a decent sampling of numbers ~25 --Introduces error on the order of +/-0.005 of ping coordinates IMBA_MapEquations={} IMBA_MapEquations[2]={mx=-75.42874908;bx=34.2859094;my=50.2865016;by=-16.00008308} IMBA_MapEquations[1]={mx=-78.85670491;bx=36.57127371;my=52.57102443;by=-27.42828408} function IMBA_Tracker_GetPostion_ViaMap() SetMapToCurrentZone() local continent=GetCurrentMapContinent(); SetMapZoom(continent) local x, y = GetPlayerMapPosition("player"); local equ=IMBA_MapEquations[continent] if not equ then equ={mx=1;bx=0;my=1;by=0} end x=x*equ.mx+equ.bx y=y*equ.my+equ.by return x, y end function IMBA_Tracker_Calibration_Sort(v1,v2) return v1.score>v2.score end function IMBA_Tracker_OnUpdate() local x,y = Minimap:GetPingPosition(); local zoom = IMBA_Minimap_Zoom[IMBA_isMinimapInsideWMO()][Minimap:GetZoom()]; IMBA_Tracker_LastPos.x=x*zoom IMBA_Tracker_LastPos.y=y*zoom --Position Validation if IMBA_Tracker_ValidatePos and IMBA_Tracker_ValidateTime0 then if not IMBA_Tracker_Preset then --DEFAULT_CHAT_FRAME:AddMessage("Preset Map") SetMapZoom(GetCurrentMapContinent()) IMBA_Tracker_ValidateTime=GetTime()+0.1 IMBA_Tracker_Preset=true; else --DEFAULT_CHAT_FRAME:AddMessage("Correcting Map") local wrongX,wrongY=IMBA_Tracker_GetPostion(); local rightX,rightY=IMBA_Tracker_GetPostion_ViaMap(); if (not IMBA_Tracker_CompareNumber(wrongX,rightX)) or (not IMBA_Tracker_CompareNumber(wrongY,rightY)) then IMBA_Tracker_PingDelta.x=IMBA_Tracker_PingDelta.x+(rightX-wrongX); IMBA_Tracker_PingDelta.y=IMBA_Tracker_PingDelta.y+(rightY-wrongY); end IMBA_Tracker_ValidatePos=false; end elseif GetNumRaidMembers()>0 then --Lets try to calibrate if we can with other raid members if not IMBA_Tracker_PrePinged then Minimap:PingLocation(0,0); --Send a ping that we can all agree on IMBA_Tracker_ValidateTime=GetTime()+0.5; IMBA_Tracker_PrePinged=true else SendAddonMessage("IMBA_TRACKER_UPDATE","CALIBRATE","RAID"); --DEFAULT_CHAT_FRAME:AddMessage("Requesting Calibration") IMBA_Tracker_ValidateTime=GetTime()+60; IMBA_Tracker_PrePinged=false; end end end if IMBA_Tracker_Calibrating and IMBA_Tracker_CountTime1.5 then IMBA_Tracker_PingDelta.x=IMBA_Tracker_Calibration[1].x+IMBA_Tracker_CalibratePing.x IMBA_Tracker_PingDelta.y=IMBA_Tracker_Calibration[1].y+IMBA_Tracker_CalibratePing.y IMBA_Tracker_ValidatePos=false; end IMBA_Tracker_Calibrating=false end x=x*zoom+IMBA_Tracker_PingDelta.x; y=y*zoom+IMBA_Tracker_PingDelta.y; if IMBA_Tracker_Loaded then IMBA_SavedVariables.LastPlayerPos={x=x;y=y} end if not IMBA_Tracker_ValidatePos and (IMBA_Tracker_EnabledRaid or IMBA_Tracker_EnabledGuild) and IMBA_Tracker_UpdateTime