/
-- mikma, 10/2014 |
-- debugprint works only if debug.EnemyScanner2 is set. |
local function debugprint(chatframe,text,r,g,b) |
if debug.EnemyScanner2 then |
_G["ChatFrame"..chatframe]:AddMessage(text,r,g,b) |
end |
end |
-- Let's create some locals. |
local db |
local _ |
local updating |
local total = 0 |
local anchor = CreateFrame("Button", nil, UIParent) |
ES2timer = CreateFrame("Frame") |
ES2messages = {} |
local ES2timer = CreateFrame("Frame") |
local ES2messages = {} |
local rows = {} |
ES2temptable = {} |
local ES2temptable = {} |
local pvpmatch |
if not EnemyScanner2DB then EnemyScanner2DB = {["position"] = {point = "RIGHT", x = -70, y = 0}, ["expire"] = 10,} end |
-- If SavedVariables database does not exist, create it and add some default values for anchor, expiration time and temporary PvP table. |
if not EnemyScanner2DB then EnemyScanner2DB = {["position"] = {point = "RIGHT", x = -70, y = 0}, ["expire"] = 10, ["PvP"] = {},} end |
local function debugprint(chatframe,text,r,g,b) |
if debug.EnemyScanner2 then |
_G["ChatFrame"..chatframe]:AddMessage(text,r,g,b) |
end |
end |
-- bit.band the sourceflag to check the following: |
-- bit.band the flag to check the following: |
-- Type: COMBATLOG_OBJECT_TYPE_PLAYER 0x00000400 |
-- Controller: COMBATLOG_OBJECT_CONTROL_PLAYER 0x00000100 |
-- Reaction: COMBATLOG_OBJECT_REACTION_HOSTILE 0x00000040 |
-- Controller affiliation: COMBATLOG_OBJECT_AFFILIATION_OUTSIDER 0X00000008 |
-- PLAYER controlled by PLAYER which is REACTION HOSTILE and is OUTSIDER (not in raid or party with you) |
-- PLAYER controlled by PLAYER which is REACTION HOSTILE and is OUTSIDER (not in raid or party with you). |
local function isTargetHostile(flag) |
local HOSTILEUNITFLAG = 0x548 |
if bit.band(flag,HOSTILEUNITFLAG) == HOSTILEUNITFLAG then |
-- Yeap! |
return true |
end |
end |
-- Converts R,G,B into hexcolor. Example: RAID_CLASS_COLORS['SHAMAN'] (r,g,b) 0,0.44,0,87 turns into '|cff0070dd' |
-- Converts R,G,B into hexcolor. Example: RAID_CLASS_COLORS['SHAMAN'] (r,g,b) 0,0.44,0,87 turns into '|cff0070dd'. |
local function DecimalToHex(r,g,b) |
return string.format("|cff%02x%02x%02x", r*255, g*255, b*255) |
if self[event] then return self[event](self, event, ...) end |
end) |
EnemyScanner2:RegisterEvent("PLAYER_ENTERING_WORLD") |
-- Register all the needed events. |
function EnemyScanner2:Enable() |
EnemyScanner2:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") |
EnemyScanner2:RegisterEvent("PLAYER_LOGIN") |
EnemyScanner2:RegisterEvent("UPDATE_MOUSEOVER_UNIT") |
EnemyScanner2:RegisterEvent("PLAYER_TARGET_CHANGED") |
EnemyScanner2:RegisterEvent("ZONE_CHANGED_NEW_AREA") |
end |
-- Realm name is available only after PEW |
function EnemyScanner2:PLAYER_ENTERING_WORLD() |
-- Unregister all events except ZONE_CHANGED_NEW_AREA, which is used to enable the addon once again. |
function EnemyScanner2:Disable() |
EnemyScanner2:UnregisterAllEvents() |
EnemyScanner2:RegisterEvent("ZONE_CHANGED_NEW_AREA") |
updating = ES2timer:GetScript("OnUpdate") |
-- Clear the messages and disable onUpdate timer |
if updating then |
EnemyScanner2:Clear() |
ES2timer:SetScript("OnUpdate",nil) |
end |
end |
-- We use this to enable/disable the addon when player enter instance. |
function EnemyScanner2:ZONE_CHANGED_NEW_AREA() |
local instancetype = select(2,GetInstanceInfo()) |
if instancetype == "pvp" then |
table.wipe(EnemyScanner2DB["PvP"]) |
EnemyScanner:Enable() |
pvpmatch = true |
-- Change temptable to PvP. |
temptable = EnemyScanner2DB["PvP"] |
EnemyScanner2DB.expire = 10 |
EnemyScanner2:Clear() |
debugprint(3,"EnemyScanner2 PvP",0,0,1) |
elseif instancetype == "party" or instancetype == "raid" or instancetype == "arena" then |
EnemyScanner2:Disable() |
debugprint(3,"EnemyScanner2 Disabled",1,0,0) |
else |
-- Change temptable to realmName. |
temptable = EnemyScanner2DB[realmName] |
EnemyScanner2DB.expire = 30 |
EnemyScanner2:Enable() |
if pvpmatch then |
EnemyScanner2:Clear() |
pvpmatch = nil |
end |
debugprint(3,"EnemyScanner2 Enabled",0,1,0) |
end |
end |
-- realmName is available after login. |
function EnemyScanner2:PLAYER_LOGIN() |
local realmName = GetCVar("realmName") |
if not EnemyScanner2DB[realmName] then EnemyScanner2DB[realmName] = {} end |
db = EnemyScanner2DB[realmName] |
EnemyScanner2:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED") |
EnemyScanner2:RegisterEvent("UPDATE_MOUSEOVER_UNIT") |
EnemyScanner2:RegisterEvent("PLAYER_TARGET_CHANGED") |
EnemyScanner2:UnregisterEvent("PLAYER_ENTERING_WORLD") |
EnemyScanner2:Initialize() |
EnemyScanner2:ZONE_CHANGED_NEW_AREA() |
end |
local function GetStats(unit) |
local level = UnitLevel(unit) |
local name = UnitName(unit) |
local classFilename = select(2,UnitClass(unit)) |
-- In case game haven't had the time to cache the player's name yet |
-- In case game haven't had the time to cache the player's name yet. |
if name == "Unknown" then |
debugprint(4,"Mouseover: "..guidsource.." has no name yet?",1,0,0) |
return |
debugprint(4,"Mouseover: "..name.." added and level set to: "..level) |
end |
-- Player exists in the database but level is greater than the one stored, upgrade it |
-- Player exists in the database but level is greater than the one stored, upgrade it. |
if level > db[guidsource] then |
db[guidsource] = level |
debugprint(4,"Mouseover: "..name.." upgraded level to: "..level) |
end |
end |
-- Get stats of unit (mouseover) |
-- Get stats of unit (mouseover). |
function EnemyScanner2:UPDATE_MOUSEOVER_UNIT() |
GetStats("mouseover") |
end |
-- Get stats of unit (tab-target) |
-- Get stats of unit (tab-target). |
function EnemyScanner2:PLAYER_TARGET_CHANGED() |
GetStats("target") |
end |
-- Remember to make this local. |
tooltiptable = {} |
-- We use this to store the guid of the players if they are at max level so they won't be scanned again. |
local tooltiptable = {} |
-- SEMI-Working? What will happen to the 'Level ??' players? |
-- Let's create a simple tooltip what we use to scan the players. - Thanks Semlar! |
local tooltip = CreateFrame("GameTooltip") |
local toolText2 = tooltip:CreateFontString() |
local toolText3 = tooltip:CreateFontString() |
-- We only care about the Line2 left text (person's level without guild) and Line3 left text (person's level in a guild). |
tooltip:AddFontStrings(tooltip:CreateFontString(),tooltip:CreateFontString()) |
tooltip:AddFontStrings(toolText2, tooltip:CreateFontString()) |
tooltip:AddFontStrings(toolText3, tooltip:CreateFontString()) |
tooltip:SetOwner(UIParent, "ANCHOR_NONE") |
-- Working! |
local function tooltipScanner(guid) |
local tooltip = ES2ScanTooltip or CreateFrame("GameTooltip","ES2ScanTooltip",UIParent,"GameTooltipTemplate") |
tooltip:SetOwner(UIParent, "ANCHOR_NONE") |
tooltip:SetPoint("BOTTOMRIGHT",UIParent,"BOTTOMRIGHT") |
local tooltip = tooltip |
tooltip:ClearLines() |
tooltip:SetHyperlink('unit:' .. guid) |
if not tooltiptable[guid] then tooltiptable[guid] = true end |
tooltip:Show() |
local close = CreateFrame("Button", nil, tooltip, "UIPanelCloseButton") |
close:SetPoint("TOPRIGHT",tooltip,"TOPLEFT",5,5) |
close:SetScript("OnClick", function() |
tooltip:Hide() |
end) |
local printline |
local lines = tooltip:NumLines() |
local maxlevel = GetMaxPlayerLevel() |
local maxplayerlevel = MAX_PLAYER_LEVEL_TABLE[GetAccountExpansionLevel()] |
local maxclientlevel = MAX_PLAYER_LEVEL_TABLE[GetExpansionLevel()] |
local lines = tooltip:NumLines() |
-- debugprint required stuff, can be deleted later. |
local class, classFilename, race, raceFilename, sex, name, realm = GetPlayerInfoByGUID(guid) |
if lines > 0 then |
for i=1,lines do |
if string.match(_G["ES2ScanTooltipTextLeft"..i]:GetText(), "Level %d+") then |
printline = string.match(_G["ES2ScanTooltipTextLeft"..i]:GetText(), "%d+") |
if name then |
tooltip:Hide() |
else |
debugprint(4,"Tooltip: name not cached yet!",1,0,0) |
return |
end |
debugprint(4,"Tooltip: scanning "..guid..": "..name..", "..printline) |
return tonumber(printline) |
elseif string.match(_G["ES2ScanTooltipTextLeft"..i]:GetText(), "Level ??") then |
debugprint(4,"Tooltip: scanning "..guid..": "..name..", ??") |
return "??" |
if string.match(toolText2:GetText(), "Level %d+") then |
printline = string.match(toolText2:GetText(), "%d+") |
if not name then debugprint(4,"Tooltip: name not cached yet!",1,0,0); return; end |
debugprint(4,"Tooltip: scanning "..guid..": "..name..", "..printline) |
return tonumber(printline) |
elseif string.match(toolText3:GetText(), "Level %d+") then |
printline = string.match(toolText3:GetText(), "%d+") |
if not name then debugprint(4,"Tooltip: name not cached yet!",1,0,0); return; end |
debugprint(4,"Tooltip: scanning "..guid..": "..name..", "..printline) |
return tonumber(printline) |
elseif string.match(toolText2:GetText(), "Level ??") then |
debugprint(4,"Tooltip: scanning "..guid..": "..name..", ??") |
if UnitLevel("player") <= MAX_PLAYER_LEVEL_TABLE[GetAccountExpansionLevel()] - 10 then |
return UnitLevel("player")+10 |
else |
return 0 |
end |
end |
elseif string.match(toolText3:GetText(), "Level ??") then |
debugprint(4,"Tooltip: scanning "..guid..": "..name..", ??") |
if UnitLevel("player") <= MAX_PLAYER_LEVEL_TABLE[GetAccountExpansionLevel()] - 10 then |
return UnitLevel("player")+10 |
else |
return 0 |
end |
end |
end |
end |
-- Working! |
end |
end |
-- Working! |
function EnemyScanner2:COMBAT_LOG_EVENT_UNFILTERED(_, _, minievent, _, guidsource, source, sourceflags, sourceflagsraid, guidtarget, target, targetflags, targetflagsraid, ...) |
if isTargetHostile(sourceflags) then --and not UnitIsPVPSanctuary("player") then |
if guidsource == '' then |
} |
-- Spell alert will show messages only once, after spell has been applied. |
-- Might need to find a better way of printing the alerts on screen. |
if minievent == "SPELL_AURA_APPLIED" then |
if spellwatch[spellID] then |
local classFilename = select(2,GetPlayerInfoByGUID(guidsource)) |
end |
end |
-- Catch if action is melee |
-- Catch if action is melee. |
if minievent:match("[^_]+") == "SWING" then |
-- Turn ie. "SWING_MISS" text into "Swing Miss" |
-- Turn ie. "SWING_MISS" text into "Swing Miss". |
spellName = minievent:gsub('_',' '):lower() |
spellName = spellName:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end) |
end |
-- Check if action is spell |
-- Check if action is spell. |
if minievent:match("[^_]+") ~= "SWING" and tonumber(spellID) then |
level = GetSpellLevelLearned(spellID) |
spellName = GetSpellLink(spellID) |
end |
-- GUID does not exist in database, add as level 0 |
-- GUID does not exist in database, add as level 0. |
if not db[guidsource] then |
db[guidsource] = 0 |
end |
-- If spell is greater than the one stored in database, upgrade it in the database |
-- If spell is greater than the one stored in database, upgrade it in the database. |
if level and (db[guidsource] < level) then |
-- If spell level is greater than current max level in player's expansion, don't upgrade |
-- If spell level is greater than current max level in player's expansion, don't upgrade. |
if level > MAX_PLAYER_LEVEL_TABLE[GetAccountExpansionLevel()] then |
level = MAX_PLAYER_LEVEL_TABLE[GetAccountExpansionLevel()] |
else |
db[guidsource] = level |
end |
-- Let's do some tooltip magics! |
-- Let's do some tooltip scanning! |
local tooltiplevel |
if guidsource ~= '' and not tooltiptable[guidsource] and db[guidsource] < 90 then |
tooltiplevel = tooltipScanner(guidsource) |
-- The next following line will propably result in ERROR with 'Level ??'! |
if (tooltiplevel and level) and (tooltiplevel > level) then |
db[guidsource] = tooltiplevel |
end |
end |
-- Working! |
-- Initialize the anchor where rows are SetPoint'd |
-- Initialize the anchor where rows are SetPoint'd. |
function EnemyScanner2:Initialize() |
anchor:SetFrameStrata("MEDIUM") |
anchor:SetHeight(30) |
-- Working! |
-- Make sure nothing gets added if name is not found! |
-- Adds a message to the alert frame, returns a uid |
-- Adds a message to the alert frame, returns a uid. |
function EnemyScanner2:AddMessage(name, level, spotted, class) |
if not name then debugprint(4,"AddMessage: Name not found!",1,0,0) return end |
if name == "Unknown" then debugprint(4,"AddMessage: Name not cached!",1,0,0) return end |
-- Working! |
-- Edits a message if it already exists and is being displayed in alert frame |
-- Edits a message if it already exists and is being displayed in alert frame. |
function EnemyScanner2:EditMessage(uid,level,spotted) |
for i=1,#ES2messages do |
if ES2messages[i] == uid then |
end |
-- Working! |
-- Removes a message from the alert frame |
-- Removes a message from the alert frame. |
function EnemyScanner2:DelMessage(uid) |
for i=1,#ES2messages do |
if ES2messages[i] == uid then |
end |
-- Working! |
-- Clears all messages from alert frame |
-- Clears all messages from alert frame. |
function EnemyScanner2:Clear() |
table.wipe(ES2messages) |
EnemyScanner2:Update() |
end |
-- Working! |
-- Updates the frame to display |
-- Updates the frame to display. |
function EnemyScanner2:Update() |
-- Create enough frames, if necessary |
-- Create enough frames, if necessary. |
for i=#rows + 1, #ES2messages, 1 do |
row = CreateFrame("Button", nil, UIParent) |
row:SetFrameStrata("MEDIUM") |
row.text:SetJustifyH("RIGHT") |
rows[i] = row |
end |
-- Anchor the frames in order |
-- Anchor the frames in order. |
for idx,entry in ipairs(ES2messages) do |
local row = rows[idx] |
if idx == 1 then |
row.text:SetTextColor(raidclass.r, raidclass.g, raidclass.b, 1) |
row:Show() |
end |
-- Hide any extra frames |
-- Hide any extra frames. |
for i=#rows, #ES2messages + 1, -1 do |
rows[i]:Hide() |
end |
end |