initial commit
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+521
@@ -0,0 +1,521 @@
|
||||
local version = '1.0'
|
||||
local author = 'shirsig'
|
||||
|
||||
local BROWN = { .7, .15, .05 }
|
||||
local YELLOW = { 1, 1, .15 }
|
||||
local CHECK_INTERVAL = .5
|
||||
|
||||
npcscan_targets = {}
|
||||
|
||||
npcscan = {}
|
||||
|
||||
|
||||
function npcscan.without_errors(f)
|
||||
local orig = UIErrorsFrame.AddMessage
|
||||
UIErrorsFrame.AddMessage = Aux.util.pass
|
||||
f()
|
||||
UIErrorsFrame.AddMessage = orig
|
||||
end
|
||||
|
||||
do
|
||||
local last_played
|
||||
|
||||
function npcscan.play_sound()
|
||||
if not last_played or GetTime() - last_played > 10 then -- 8
|
||||
PlaySoundFile('Interface\\AddOns\\npcscan\\Event_wardrum_ogre.ogg', 'Master')
|
||||
PlaySoundFile('Interface\\AddOns\\npcscan\\scourge_horn.ogg', 'Master')
|
||||
last_played = GetTime()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function npcscan.check_for_targets()
|
||||
for name, _ in pairs(npcscan_targets) do
|
||||
-- local original_target = UnitName('target')
|
||||
if npcscan.target(name) then
|
||||
-- if UnitPlayerControlled('target') then
|
||||
-- if original_target then
|
||||
-- TargetByName(original_target, true)
|
||||
-- end
|
||||
-- else
|
||||
npcscan.remove_target(UnitName('target'))
|
||||
npcscan.play_sound()
|
||||
if npcscan.flash.animation:playing() then
|
||||
npcscan.flash.animation:stop_after(3)
|
||||
else
|
||||
npcscan.flash:reset()
|
||||
npcscan.flash.animation:play()
|
||||
end
|
||||
npcscan.button:set_target()
|
||||
-- end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function npcscan.target(name)
|
||||
TargetByName(name, true)
|
||||
return UnitName('target') and strupper(UnitName('target')) == name
|
||||
end
|
||||
|
||||
function npcscan.on_event()
|
||||
if event == 'VARIABLES_LOADED' then
|
||||
do
|
||||
local flash = CreateFrame('Frame')
|
||||
npcscan.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]])
|
||||
|
||||
function flash:reset()
|
||||
self:SetAlpha(0)
|
||||
end
|
||||
|
||||
local screen_flash_in = npcscan.alpha_animation(flash, 1, .5)
|
||||
local screen_flash_out = npcscan.alpha_animation(flash, -1, .5)
|
||||
local screen_flash_delay = npcscan.delay(.5)
|
||||
|
||||
flash.animation = (screen_flash_in..screen_flash_delay..screen_flash_out) * 3
|
||||
end
|
||||
|
||||
local button = CreateFrame('Button', 'npcscan_button', UIParent)
|
||||
button:Hide()
|
||||
npcscan.button = button
|
||||
button:SetPoint('BOTTOM', UIParent, 0, 128)
|
||||
button:SetWidth(150)
|
||||
button:SetHeight(42)
|
||||
button:SetScale(1.25)
|
||||
button:SetFrameStrata('FULLSCREEN_DIALOG')
|
||||
button:SetNormalTexture([[Interface\AddOns\npcscan\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:stop()
|
||||
self.shine.animation:stop()
|
||||
self.glow:reset()
|
||||
self.shine:reset()
|
||||
self.glow.animation:play()
|
||||
self.shine.animation:play()
|
||||
end
|
||||
|
||||
do
|
||||
local background = button:GetNormalTexture()
|
||||
background:SetDrawLayer('BACKGROUND')
|
||||
background:ClearAllPoints()
|
||||
background:SetPoint('BOTTOMLEFT', 3, 3)
|
||||
background:SetPoint('TOPRIGHT', -3, -3)
|
||||
background:SetTexCoord(0, 1, 0, 0.25)
|
||||
end
|
||||
|
||||
do
|
||||
local title_background = button:CreateTexture(nil, 'BORDER')
|
||||
title_background:SetTexture([[Interface\AddOns\npcscan\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', 'GameFontHighlightMedium')
|
||||
title:SetPoint('TOPLEFT', title_background, 0, 0)
|
||||
title:SetPoint('RIGHT', title_background)
|
||||
button:SetFontString(title)
|
||||
|
||||
local subtitle = button:CreateFontString(nil, 'OVERLAY', 'GameFontBlackTiny')
|
||||
subtitle:SetPoint('TOPLEFT', title, 'BOTTOMLEFT', 0, -4)
|
||||
subtitle:SetPoint('RIGHT', title )
|
||||
subtitle:SetText('NPC 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: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\npcscan\UI-Achievement-Alert-Glow]])
|
||||
glow:SetBlendMode('ADD')
|
||||
glow:SetTexCoord(0, .78125, 0, .66796875)
|
||||
glow:SetAlpha(0)
|
||||
|
||||
function glow:reset()
|
||||
self:SetAlpha(0)
|
||||
end
|
||||
|
||||
local glow_in = npcscan.alpha_animation(glow, 1, .2)
|
||||
local glow_out = npcscan.alpha_animation(glow, -1, .5)
|
||||
|
||||
glow.animation = glow_in..glow_out
|
||||
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\npcscan\UI-Achievement-Alert-Glow]])
|
||||
shine:SetBlendMode('ADD')
|
||||
shine:SetTexCoord(.78125, .912109375, 0, .28125)
|
||||
shine:SetAlpha(0)
|
||||
|
||||
function shine:reset()
|
||||
self:SetAlpha(0)
|
||||
self:SetPoint('TOPLEFT', button, 0, 8)
|
||||
end
|
||||
|
||||
local shine_delay1 = npcscan.delay(.3)
|
||||
local shine_in = npcscan.alpha_animation(shine, 1, 0)
|
||||
local shine_delay2 = npcscan.delay(.2)
|
||||
local shine_move = npcscan.translation_animation(shine, button:GetWidth() - shine:GetWidth() + 8, 0, .4)
|
||||
local shine_out = npcscan.alpha_animation(shine, -1, .2)
|
||||
|
||||
shine.animation = (shine_delay1..shine_in)..(shine_move + (shine_delay2..shine_out))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
do
|
||||
npcscan.last_check = GetTime()
|
||||
function npcscan.on_update()
|
||||
if GetTime() - npcscan.last_check >= CHECK_INTERVAL then
|
||||
npcscan.last_check = GetTime()
|
||||
npcscan.without_errors(npcscan.check_for_targets)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function npcscan.log(msg)
|
||||
if DEFAULT_CHAT_FRAME then
|
||||
DEFAULT_CHAT_FRAME:AddMessage('[npcscan]: '..msg, 1, 1, 0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Slash commands
|
||||
|
||||
function npcscan.sorted_targets()
|
||||
local sorted_targets = {}
|
||||
for key, _ in pairs(npcscan_targets) do
|
||||
tinsert(sorted_targets, key)
|
||||
end
|
||||
sort(sorted_targets, function(key1, key2) return key1 < key2 end)
|
||||
return sorted_targets
|
||||
end
|
||||
|
||||
function npcscan.add_target(name)
|
||||
local key = strupper(name)
|
||||
if key ~= '' and not npcscan_targets[key] then
|
||||
npcscan_targets[key] = true
|
||||
npcscan.log(key..' (added)')
|
||||
end
|
||||
end
|
||||
|
||||
function npcscan.remove_target(name)
|
||||
local key = strupper(name)
|
||||
if npcscan_targets[key] then
|
||||
npcscan_targets[key] = nil
|
||||
npcscan.log(key..' (removed)')
|
||||
end
|
||||
end
|
||||
|
||||
SLASH_NPCSCAN1 = '/npcscan'
|
||||
function SlashCmdList.NPCSCAN(parameter)
|
||||
local _, _, command, name = strfind(parameter, '%s*(%a*)%s*(.*)')
|
||||
|
||||
if command == '' then
|
||||
for _, key in ipairs(npcscan.sorted_targets()) do
|
||||
npcscan.log(key)
|
||||
end
|
||||
elseif command == 'add' then
|
||||
npcscan.add_target(name)
|
||||
elseif command == 'rem' then
|
||||
npcscan.remove_target(name)
|
||||
end
|
||||
end
|
||||
|
||||
-- Animation framework
|
||||
|
||||
function npcscan.translation_animation(target, x_change, y_change, duration)
|
||||
return npcscan.animation(
|
||||
{x_change, y_change},
|
||||
duration,
|
||||
function()
|
||||
local _, _, _, original_x, original_y = target:GetPoint()
|
||||
return original_x, original_y
|
||||
end,
|
||||
function(x, y)
|
||||
local point, relative_to, relative_point = target:GetPoint()
|
||||
target:SetPoint(
|
||||
point,
|
||||
relative_to,
|
||||
relative_point,
|
||||
x,
|
||||
y
|
||||
)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function npcscan.alpha_animation(target, change, duration)
|
||||
return npcscan.animation(
|
||||
{change},
|
||||
duration,
|
||||
function()
|
||||
return target:GetAlpha()
|
||||
end,
|
||||
function(alpha)
|
||||
target:SetAlpha(alpha)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
function npcscan.delay(t)
|
||||
return npcscan.animation({}, t, function() end, function() end)
|
||||
end
|
||||
|
||||
do
|
||||
local animation_metamethods = {}
|
||||
|
||||
local mul_mt = { __index = {} }
|
||||
local add_mt = { __index = {} }
|
||||
local concat_mt = { __index = {} }
|
||||
local animation_mt = { __index = {} }
|
||||
|
||||
|
||||
function animation_metamethods.__mul(animation, repetitions)
|
||||
local self = {
|
||||
_frame = CreateFrame('Frame'),
|
||||
_repetitions_left = 0,
|
||||
_repetitions = repetitions,
|
||||
_animation = animation,
|
||||
}
|
||||
setmetatable(self, mul_mt)
|
||||
|
||||
self._frame:SetScript('OnUpdate', function()
|
||||
self:_on_update()
|
||||
end)
|
||||
|
||||
return self
|
||||
end
|
||||
function animation_metamethods.__add(lhs, rhs)
|
||||
local self = {}
|
||||
setmetatable(self, add_mt)
|
||||
|
||||
self._animations = {lhs, rhs}
|
||||
|
||||
return self
|
||||
end
|
||||
function animation_metamethods.__concat(lhs, rhs)
|
||||
local self = { _frame = CreateFrame('Frame') }
|
||||
setmetatable(self, concat_mt)
|
||||
|
||||
self._animations = {lhs, rhs}
|
||||
|
||||
self._frame:SetScript('OnUpdate', function()
|
||||
self:_on_update()
|
||||
end)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
for _, mt in ipairs({ mul_mt, add_mt, concat_mt, animation_mt }) do
|
||||
for key, metamethod in pairs(animation_metamethods) do
|
||||
mt[key] = metamethod
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function mul_mt.__index:play()
|
||||
self._repetitions_left = self._repetitions
|
||||
end
|
||||
function mul_mt.__index:playing()
|
||||
return self._repetitions_left > 0
|
||||
end
|
||||
function mul_mt.__index:stop()
|
||||
self._repetitions_left = 0
|
||||
end
|
||||
function mul_mt.__index:stop_after(repetitions)
|
||||
self._repetitions_left = self._repetitions
|
||||
end
|
||||
function mul_mt.__index:_on_update()
|
||||
if self._repetitions_left > 0 then
|
||||
if not self._animation_started then
|
||||
self._animation:play()
|
||||
self._animation_started = true
|
||||
elseif not self._animation:playing() then
|
||||
self._repetitions_left = self._repetitions_left - 1
|
||||
self._animation_started = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function add_mt.__index:play()
|
||||
for _, animation in ipairs(self._animations) do
|
||||
animation:play()
|
||||
end
|
||||
end
|
||||
function add_mt.__index:playing()
|
||||
for _, animation in ipairs(self._animations) do
|
||||
if animation:playing() then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
function add_mt.__index:stop()
|
||||
for _, animation in ipairs(self._animations) do
|
||||
animation:stop()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function concat_mt.__index:play()
|
||||
self._index = 1
|
||||
end
|
||||
function concat_mt.__index:playing()
|
||||
return self._index ~= nil
|
||||
end
|
||||
function concat_mt.__index:stop()
|
||||
if self._index and self._animations[self._index] then
|
||||
self._animations[self._index]:stop()
|
||||
end
|
||||
self._index = nil
|
||||
end
|
||||
function concat_mt.__index:_on_update()
|
||||
if self._index then
|
||||
if not self._animations[self._index] then
|
||||
self._index = nil
|
||||
elseif not self._animation_started then
|
||||
self._animations[self._index]:play()
|
||||
self._animation_started = true
|
||||
elseif not self._animations[self._index]:playing() then
|
||||
self._index = self._index + 1
|
||||
self._animation_started = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function animation_mt.__index:play()
|
||||
self._t0 = GetTime()
|
||||
self._original_values = { self._getter() }
|
||||
end
|
||||
function animation_mt.__index:stop()
|
||||
self._t0 = nil
|
||||
end
|
||||
function animation_mt.__index:playing()
|
||||
return self._t0 ~= nil
|
||||
end
|
||||
function animation_mt.__index:_current_changes(factor)
|
||||
local values = {}
|
||||
for i, change in ipairs(self._changes) do
|
||||
tinsert(values, self._original_values[i] + change * factor)
|
||||
end
|
||||
return unpack(values)
|
||||
end
|
||||
function animation_mt.__index:_on_update(factor)
|
||||
if self._t0 then
|
||||
local progress = GetTime() - self._t0
|
||||
if progress >= self._duration then
|
||||
self._callback(self:_current_changes(1))
|
||||
self._t0 = nil
|
||||
else
|
||||
self._callback(self:_current_changes(progress / self._duration))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function npcscan.animation(changes, duration, getter, callback)
|
||||
|
||||
local self = {
|
||||
_frame = CreateFrame('Frame'),
|
||||
_changes = changes,
|
||||
_duration = duration,
|
||||
_getter = getter,
|
||||
_callback = callback,
|
||||
}
|
||||
setmetatable(self, animation_mt)
|
||||
|
||||
self._frame:SetScript('OnUpdate', function()
|
||||
self:_on_update()
|
||||
end)
|
||||
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
-- building the frame structure
|
||||
@@ -0,0 +1,4 @@
|
||||
## Interface: 11200
|
||||
## Title: npcscan
|
||||
## SavedVariables: npcscan_targets
|
||||
npcscan.xml
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
<Ui xsi:schemaLocation='http://www.blizzard.com/wow/ui/'>
|
||||
<Script file='npcscan.lua'/>
|
||||
|
||||
<Frame>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
this:RegisterEvent('VARIABLES_LOADED')
|
||||
</OnLoad>
|
||||
<OnEvent>
|
||||
npcscan.on_event()
|
||||
</OnEvent>
|
||||
<OnUpdate>
|
||||
npcscan.on_update()
|
||||
</OnUpdate>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
|
||||
<FontString name="GameFontBlackTiny" font="Fonts\FRIZQT__.TTF" virtual="true">
|
||||
<FontHeight>
|
||||
<AbsValue val="9"/>
|
||||
</FontHeight>
|
||||
<Color r="0" g="0" b="0"/>
|
||||
</FontString>
|
||||
<FontString name="GameFontHighlightMedium" font="Fonts\FRIZQT__.TTF" virtual="true">
|
||||
<FontHeight>
|
||||
<AbsValue val="14"/>
|
||||
</FontHeight>
|
||||
<Shadow>
|
||||
<Offset>
|
||||
<AbsDimension x="1" y="-1"/>
|
||||
</Offset>
|
||||
<Color r="0" g="0" b="0"/>
|
||||
</Shadow>
|
||||
<Color r="1" g="1" b="1"/>
|
||||
</FontString>
|
||||
</Ui>
|
||||
Binary file not shown.
Reference in New Issue
Block a user