local unitscan = CreateFrame'Frame' unitscan:SetScript('OnUpdate', function() unitscan.UPDATE() end) unitscan:SetScript('OnEvent', function() if event == "VARIABLES_LOADED" then unitscan.LOAD() else unitscan.load_zonetargets() end end) unitscan:RegisterEvent'VARIABLES_LOADED' unitscan:RegisterEvent'MINIMAP_ZONE_CHANGED' unitscan:RegisterEvent'PLAYER_ENTERING_WORLD' local BROWN = {.7, .15, .05} local YELLOW = {1, 1, .15} local CHECK_INTERVAL = 1 -- .1 unitscan_targets = {} unitscan_zonetargets = {} do local last_played function unitscan.play_sound() if not last_played or GetTime() - last_played > 10 then -- 8 SetCVar('MasterSoundEffects', 0) SetCVar('MasterSoundEffects', 1) -- PlaySoundFile[[Interface\AddOns\unitscan-turtle\Event_wardrum_ogre.ogg]] -- PlaySoundFile[[Interface\AddOns\unitscan-turtle\scourge_horn.ogg]] PlaySoundFile[[Interface\AddOns\unitscan-turtle\gruntling_horn_bb.ogg]] last_played = GetTime() end end end function unitscan.load_zonetargets() unitscan_zone_targets() unitscan.reloadtimer = nil -- DEFAULT_CHAT_FRAME:AddMessage("DEBUG: unitscan: reloaded zone targets") end function unitscan.check_for_targets() local prevTarget = UnitExists("target") for name, _ in unitscan_targets do if name == unitscan.target(name) then -- DEFAULT_CHAT_FRAME:AddMessage("DEBUG: unitscan check_for_targets: "..name.." was found!") unitscan.toggle_target(name) unitscan.play_sound() unitscan.flash.animation:Play() unitscan.button:set_target() -- store last target unitscan.lastTarget = name -- restore prev target if prevTarget then TargetLastTarget() end end end end function unitscan.check_for_zonetargets() local prevTarget = UnitExists("target") for name, _ in unitscan_zonetargets do if strupper(name) == unitscan.target(name) then -- DEFAULT_CHAT_FRAME:AddMessage("DEBUG: unitscan check_for_zonetargets: "..name.." was found!") unitscan.toggle_zonetarget(name) unitscan.play_sound() unitscan.flash.animation:Play() unitscan.button:set_target() -- store last target unitscan.lastTarget = name -- restore prev target if prevTarget then TargetLastTarget() end end end end do local pass = function() end function unitscan.target(name) local orig = UIErrorsFrame_OnEvent UIErrorsFrame_OnEvent = pass TargetByName(name, true) UIErrorsFrame_OnEvent = orig local target = UnitName'target' -- return target and strupper(target) == name if target then -- always return players, only return neutral or hostile mobs that are alive if UnitIsPlayer'target' then return strupper(target) elseif (UnitReaction("target", "player") <= 4) and (not UnitIsDead'target') then return strupper(target) end else return nil end end end function unitscan.LOAD() do local flash = CreateFrame'Frame' unitscan.flash = flash flash:Show() flash:SetAllPoints() flash:SetAlpha(0) flash:SetFrameStrata'FULLSCREEN_DIALOG' local texture = flash:CreateTexture() texture:SetBlendMode'ADD' texture:SetAllPoints() texture:SetTexture[[Interface\FullScreenTextures\LowHealth]] flash.animation = CreateFrame'Frame' flash.animation:Hide() flash.animation:SetScript('OnUpdate', function() local t = GetTime() - this.t0 if t <= .5 then flash:SetAlpha(t * 2) elseif t <= 1 then flash:SetAlpha(1) elseif t <= 1.5 then flash:SetAlpha(1 - (t - 1) * 2) else flash:SetAlpha(0) this.loops = this.loops - 1 if this.loops == 0 then this.t0 = nil this:Hide() else this.t0 = GetTime() end end end) function flash.animation:Play() if self.t0 then self.loops = 4 else self.t0 = GetTime() self.loops = 3 end self:Show() end end local button = CreateFrame("Button", "unitscan_button", UIParent) button:Hide() unitscan.button = button button:SetPoint('BOTTOM', UIParent, 0, 128) button:SetWidth(150) button:SetHeight(42) button:SetScale(1.25) button:SetMovable(true) button:SetUserPlaced(true) button:SetClampedToScreen(true) button:SetScript('OnMouseDown', function() if IsControlKeyDown() then this:RegisterForClicks() this:StartMoving() end end) button:SetScript('OnMouseUp', function() this:StopMovingOrSizing() this:RegisterForClicks'LeftButtonDown' end) button:SetFrameStrata'FULLSCREEN_DIALOG' -- button:SetNormalTexture[[Interface\AddOns\unitscan-turtle\UI-Achievement-Parchment-Horizontal]] button:SetBackdrop{ tile = true, edgeSize = 16, edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], } button:SetBackdropBorderColor(unpack(BROWN)) button:SetScript('OnEnter', function() this:SetBackdropBorderColor(unpack(YELLOW)) end) button:SetScript('OnLeave', function() this:SetBackdropBorderColor(unpack(BROWN)) end) button:SetScript('OnClick', function() TargetByName(this:GetText(), true) end) function button:set_target() self:SetText(UnitName'target') self.model:reset() self.model:SetUnit'target' self:Show() self.glow.animation:Play() self.shine.animation:Play() end do local background = button:CreateTexture(nil, 'BACKGROUND') background:SetTexture[[Interface\AddOns\unitscan-turtle\UI-Achievement-Parchment-Horizontal]] background:SetPoint('BOTTOMLEFT', 3, 3) background:SetPoint('TOPRIGHT', -3, -3) background:SetTexCoord(0, 1, 0, .25) end do local title_background = button:CreateTexture(nil, 'BORDER') title_background:SetTexture[[Interface\AddOns\unitscan-turtle\UI-Achievement-Title]] title_background:SetPoint('TOPRIGHT', -5, -5) title_background:SetPoint('LEFT', 5, 0) title_background:SetHeight(18) title_background:SetTexCoord(0, .9765625, 0, .3125) title_background:SetAlpha(.8) local title = button:CreateFontString(nil, 'OVERLAY') title:SetFont([[Fonts\FRIZQT__.TTF]], 14) title:SetShadowOffset(1, -1) title:SetPoint('TOPLEFT', title_background, 0, 0) title:SetPoint('RIGHT', title_background) button:SetFontString(title) local subtitle = button:CreateFontString(nil, 'OVERLAY') subtitle:SetFont([[Fonts\FRIZQT__.TTF]], 9) subtitle:SetTextColor(0, 0, 0) subtitle:SetPoint('TOPLEFT', title, 'BOTTOMLEFT', 0, -4) subtitle:SetPoint('RIGHT', title ) subtitle:SetText'Unit Found!' end do local model = CreateFrame('PlayerModel', nil, button) button.model = model model:SetPoint('BOTTOMLEFT', button, 'TOPLEFT', 0, -4) model:SetPoint('RIGHT', 0, 0) model:SetHeight(button:GetWidth() * .6) do local last_update, delay function model:on_update() this:SetFacing(this:GetFacing() + (GetTime() - last_update) * math.pi / 4) last_update = GetTime() end function model:on_update_model() if delay > 0 then delay = delay - 1 return end this:SetScript('OnUpdateModel', nil) this:SetScript('OnUpdate', this.on_update) this:SetModelScale(.75) this:SetAlpha(1) last_update = GetTime() end function model:reset() self:SetAlpha(0) self:SetFacing(0) self:SetModelScale(1) self:ClearModel() self:SetScript('OnUpdate', nil) self:SetScript("OnUpdateModel", self.on_update_model) delay = 10 -- to prevent scaling bugs end end end do local close = CreateFrame('Button', nil, button, 'UIPanelCloseButton') close:SetPoint('TOPRIGHT', 0, 0) close:SetWidth(32) close:SetHeight(32) close:SetScale(.8) close:SetHitRectInsets(8, 8, 8, 8) end do local glow = button.model:CreateTexture(nil, 'OVERLAY') button.glow = glow glow:SetPoint('CENTER', button, 'CENTER') glow:SetWidth(400 / 300 * button:GetWidth()) glow:SetHeight(171 / 70 * button:GetHeight()) glow:SetTexture[[Interface\AddOns\unitscan-turtle\UI-Achievement-Alert-Glow]] glow:SetBlendMode'ADD' glow:SetTexCoord(0, .78125, 0, .66796875) glow:SetAlpha(0) glow.animation = CreateFrame'Frame' glow.animation:Hide() glow.animation:SetScript('OnUpdate', function() local t = GetTime() - this.t0 if t <= .2 then glow:SetAlpha(t * 5) elseif t <= .7 then glow:SetAlpha(1 - (t - .2) * 2) else glow:SetAlpha(0) this:Hide() end end) function glow.animation:Play() self.t0 = GetTime() self:Show() end end do local shine = button:CreateTexture(nil, 'ARTWORK') button.shine = shine shine:SetPoint('TOPLEFT', button, 0, 8) shine:SetWidth(67 / 300 * button:GetWidth()) shine:SetHeight(1.28 * button:GetHeight()) shine:SetTexture[[Interface\AddOns\unitscan-turtle\UI-Achievement-Alert-Glow]] shine:SetBlendMode'ADD' shine:SetTexCoord(.78125, .912109375, 0, .28125) shine:SetAlpha(0) shine.animation = CreateFrame'Frame' shine.animation:Hide() shine.animation:SetScript('OnUpdate', function() local t = GetTime() - this.t0 if t <= .3 then shine:SetPoint('TOPLEFT', button, 0, 8) elseif t <= .7 then shine:SetPoint('TOPLEFT', button, (t - .3) * 2.5 * this.distance, 8) end if t <= .3 then shine:SetAlpha(0) elseif t <= .5 then shine:SetAlpha(1) elseif t <= .7 then shine:SetAlpha(1 - (t - .5) * 5) else shine:SetAlpha(0) this:Hide() end end) function shine.animation:Play() self.t0 = GetTime() self.distance = button:GetWidth() - shine:GetWidth() + 8 self:Show() end end end do unitscan.last_check = GetTime() function unitscan.UPDATE() -- reload targets for zone if unitscan.reloadtimer and (GetTime() > unitscan.reloadtimer) then unitscan.load_zonetargets() end if GetTime() - unitscan.last_check >= CHECK_INTERVAL then unitscan.last_check = GetTime() unitscan.check_for_targets() unitscan.check_for_zonetargets() if prevTarget then end end end end function unitscan.print(msg) if DEFAULT_CHAT_FRAME then DEFAULT_CHAT_FRAME:AddMessage(LIGHTYELLOW_FONT_COLOR_CODE .. ' ' .. msg) end end function unitscan.sorted_targets() local sorted_targets = {} for key in pairs(unitscan_targets) do tinsert(sorted_targets, key) end sort(sorted_targets, function(key1, key2) return key1 < key2 end) return sorted_targets end function unitscan.toggle_target(name) local key = strupper(name) if unitscan_targets[key] then unitscan_targets[key] = nil unitscan.print('- ' .. key) elseif key ~= '' then unitscan_targets[key] = true unitscan.print('+ ' .. key) end end function unitscan.toggle_zonetarget(name) -- DEFAULT_CHAT_FRAME:AddMessage("DEBUG: unitscan: toggle_zonetarget") if unitscan_zonetargets[name] then unitscan_zonetargets[name] = nil unitscan.print(name .. ' was found!') unitscan.reloadtimer = GetTime() + 60 -- trigger reload zone timer end end SLASH_UNITSCAN1 = '/unitscan' function SlashCmdList.UNITSCAN(parameter) local _, _, name = strfind(parameter, '^%s*(.-)%s*$') if name == '' then for _, key in ipairs(unitscan.sorted_targets()) do unitscan.print(key) end else unitscan.toggle_target(name) end end SLASH_UNITSCANTARGET1 = '/unitscantarget' function SlashCmdList.UNITSCANTARGET() if unitscan.lastTarget then TargetByName(unitscan.lastTarget, true) end end