You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
612 lines
20 KiB
612 lines
20 KiB
|
5 years ago
|
local myname, ns = ...
|
||
|
|
|
||
|
|
local core = LibStub("AceAddon-3.0"):GetAddon("SilverDragon")
|
||
|
|
local module = core:NewModule("Announce", "AceTimer-3.0", "LibSink-2.0")
|
||
|
|
local Debug = core.Debug
|
||
|
|
|
||
|
|
local LSM = LibStub("LibSharedMedia-3.0")
|
||
|
|
|
||
|
|
-- Register some media
|
||
|
|
LSM:Register("sound", "Rubber Ducky", 566121)
|
||
|
|
LSM:Register("sound", "Cartoon FX", 566543)
|
||
|
|
LSM:Register("sound", "Explosion", 566982)
|
||
|
|
LSM:Register("sound", "Shing!", 566240)
|
||
|
|
LSM:Register("sound", "Wham!", 566946)
|
||
|
|
LSM:Register("sound", "Simon Chime", 566076)
|
||
|
|
LSM:Register("sound", "War Drums", 567275)--NPC Scan default
|
||
|
|
LSM:Register("sound", "Scourge Horn", 567386)--NPC Scan default
|
||
|
|
LSM:Register("sound", "Pygmy Drums", 566508)
|
||
|
|
LSM:Register("sound", "Cheer", 567283)
|
||
|
|
LSM:Register("sound", "Humm", 569518)
|
||
|
|
LSM:Register("sound", "Short Circuit", 568975)
|
||
|
|
LSM:Register("sound", "Fel Portal", 569215)
|
||
|
|
LSM:Register("sound", "Fel Nova", 568582)
|
||
|
|
LSM:Register("sound", "PVP Flag", 569200)
|
||
|
|
LSM:Register("sound", "Thunder crack", 566202) -- doodad/fx_thundercrack04.ogg
|
||
|
|
LSM:Register("sound", "Algalon: Beware!", 543587)
|
||
|
|
LSM:Register("sound", "Yogg Saron: Laugh", 564859)
|
||
|
|
LSM:Register("sound", "Illidan: Not Prepared", 552503)
|
||
|
|
LSM:Register("sound", "Magtheridon: I am Unleashed", 554554)
|
||
|
|
LSM:Register("sound", "Loatheb: I see you", 554236)
|
||
|
|
LSM:Register("sound", "Ikiss: Trinkets", 561403)
|
||
|
|
LSM:Register("sound", "NPCScan", 567275)--Sound file is actually bogus, this just forces the option NPCScan into menu. We hack it later.
|
||
|
|
|
||
|
|
function module:OnInitialize()
|
||
|
|
self.db = core.db:RegisterNamespace("Announce", {
|
||
|
|
profile = {
|
||
|
|
sink = true,
|
||
|
|
drums = true,
|
||
|
|
sound = true,
|
||
|
|
soundgroup = true,
|
||
|
|
soundguild = false,
|
||
|
|
sound_mount = true,
|
||
|
|
sound_boss = true,
|
||
|
|
sound_loot = true,
|
||
|
|
soundfile = "Loatheb: I see you",
|
||
|
|
soundfile_mount = "Illidan: Not Prepared",
|
||
|
|
soundfile_boss = "Magtheridon: I am Unleashed",
|
||
|
|
soundfile_loot = "Ikiss: Trinkets",
|
||
|
|
sound_loop = 1,
|
||
|
|
sound_mount_loop = 1,
|
||
|
|
sound_boss_loop = 1,
|
||
|
|
sound_loot_loop = 1,
|
||
|
|
flash = true,
|
||
|
|
flash_texture = "Blizzard Low Health",
|
||
|
|
flash_color = {r=1,g=0,b=1,a=1,},
|
||
|
|
flash_mount = true,
|
||
|
|
flash_texture_mount = "Blizzard Low Health",
|
||
|
|
flash_color_mount = {r=0,g=1,b=0,a=1,},
|
||
|
|
flash_boss = false,
|
||
|
|
flash_texture_boss = "Blizzard Low Health",
|
||
|
|
flash_color_boss = {r=1,g=0,b=1,a=1,},
|
||
|
|
instances = false,
|
||
|
|
dead = true,
|
||
|
|
already = false,
|
||
|
|
already_drop = true,
|
||
|
|
already_transmog = false,
|
||
|
|
already_alt = true,
|
||
|
|
sink_opts = {},
|
||
|
|
channel = "Master",
|
||
|
|
unmute = false,
|
||
|
|
background = false,
|
||
|
|
loot = true,
|
||
|
|
},
|
||
|
|
})
|
||
|
|
|
||
|
|
self:SetSinkStorage(self.db.profile.sink_opts)
|
||
|
|
|
||
|
|
if self.db.profile.sink_opts.sink20OutputSink == "Channel" then
|
||
|
|
-- 8.2.5 / Classic removed the ability to output to channels, outside of hardware-driven events
|
||
|
|
self.db.profile.sink_opts.sink20OutputSink = "Default"
|
||
|
|
end
|
||
|
|
|
||
|
|
core.RegisterCallback(self, "Seen")
|
||
|
|
core.RegisterCallback(self, "SeenLoot")
|
||
|
|
|
||
|
|
local config = core:GetModule("Config", true)
|
||
|
|
if config then
|
||
|
|
local toggle = config.toggle
|
||
|
|
local get = function(info) return self.db.profile[info[#info]] end
|
||
|
|
local set = function(info, v) self.db.profile[info[#info]] = v end
|
||
|
|
|
||
|
|
local sink_config = self:GetSinkAce3OptionsDataTable()
|
||
|
|
local sink_args = {}
|
||
|
|
for k,v in pairs(sink_config.args) do
|
||
|
|
if k ~= "Channel" then
|
||
|
|
sink_args[k] = v
|
||
|
|
end
|
||
|
|
end
|
||
|
|
sink_config.args = sink_args
|
||
|
|
sink_config.inline = true
|
||
|
|
sink_config.order = 15
|
||
|
|
sink_config.args.Channel = nil
|
||
|
|
|
||
|
|
local faker = function(id, name, zone, x, y)
|
||
|
|
return {
|
||
|
|
type = "execute", name = name,
|
||
|
|
desc = "Fake seeing " .. name,
|
||
|
|
func = function()
|
||
|
|
-- id, zone, x, y, is_dead, source, unit
|
||
|
|
core.events:Fire("Seen", id, zone, x, y, false, "fake", false)
|
||
|
|
end,
|
||
|
|
}
|
||
|
|
end
|
||
|
|
local soundfile = function(enabled_key, order)
|
||
|
|
return {
|
||
|
|
type = "select", dialogControl = "LSM30_Sound",
|
||
|
|
name = "Sound to Play", desc = "Choose a sound file to play",
|
||
|
|
values = AceGUIWidgetLSMlists.sound,
|
||
|
|
disabled = function() return not self.db.profile[enabled_key] end,
|
||
|
|
order = order,
|
||
|
|
}
|
||
|
|
end
|
||
|
|
local soundrange = function(order)
|
||
|
|
return {
|
||
|
|
type = "range",
|
||
|
|
name = "Repeat...",
|
||
|
|
desc = "How many times to repeat the sound",
|
||
|
|
min = 1, max = 10, step = 1,
|
||
|
|
order = order,
|
||
|
|
}
|
||
|
|
end
|
||
|
|
local colorget = function(info)
|
||
|
|
local color = self.db.profile[info[#info]]
|
||
|
|
return color.r, color.g, color.b, color.a
|
||
|
|
end
|
||
|
|
local colorset = function(info, r, g, b, a)
|
||
|
|
local color = self.db.profile[info[#info]]
|
||
|
|
color.r, color.g, color.b, color.a = r, g, b, a
|
||
|
|
end
|
||
|
|
|
||
|
|
local options = {
|
||
|
|
general = {
|
||
|
|
type = "group", name = "General", inline = true,
|
||
|
|
order = 10,
|
||
|
|
get = get, set = set,
|
||
|
|
args = {
|
||
|
|
already = toggle("Already found", "Announce when we see rares we've already killed / achieved (if known)", 0),
|
||
|
|
already_drop = toggle("Got the loot", "Announce when we see rares which drop a mount / toy / pet you already have", 10),
|
||
|
|
already_transmog = toggle("...include transmog as loot", "Count transmog appearances as knowable loot for the previous option?", 11),
|
||
|
|
already_alt = toggle("Completed by an alt", "Announce when we see rares for an achievement that the current character doesn't have, but an alt has completed already", 20),
|
||
|
|
dead = toggle("Dead rares", "Announce when we see dead rares, if known. Not all scanning methods know whether a rare is dead or not, so this isn't entirely reliable.", 30),
|
||
|
|
instances = toggle("Instances", "Show announcements while in an instance", 50),
|
||
|
|
loot = toggle("Treasures", "Show announcements when treasure appears on the minimap", 60),
|
||
|
|
},
|
||
|
|
},
|
||
|
|
message = {
|
||
|
|
type = "group", name = "Messages",
|
||
|
|
order = 20,
|
||
|
|
get = get, set = set,
|
||
|
|
args = {
|
||
|
|
sink = toggle("Enabled", "Send a message to whatever scrolling text addon you're using.", 10),
|
||
|
|
output = sink_config,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
test = {
|
||
|
|
type = "group", name = "Test it!",
|
||
|
|
inline = true,
|
||
|
|
args = {
|
||
|
|
-- id, name, zone, x, y, is_dead, is_new_location, source, unit
|
||
|
|
time = faker(32491, "Time-Lost Proto Drake (Mount!)", 120, 0.490, 0.362),
|
||
|
|
-- ishak = faker(157134, "Ishak of the Four Winds (Mount!)", 1527, 0.73, 0.83),
|
||
|
|
anger = faker(60491, "Sha of Anger (Boss!)", 809, 0.5, 0.5),
|
||
|
|
vyragosa = faker(32630, "Vyragosa (Boring)", 120, 0.5, 0.5),
|
||
|
|
deathmaw = faker(10077, "Deathmaw (Tame!)", 29, 0.5, 0.5),
|
||
|
|
-- haakun = faker(83008, "Haakun", 946, 0.5, 0.5),
|
||
|
|
yiphrim = faker(157473, "Yiphrim the Will Ravager (Toy!)", 1527, 0.5, 0.786),
|
||
|
|
amalgamation = faker(157593, "Amalgamation of Flesh (Pet!)", 1527, 0.598, 0.724),
|
||
|
|
-- alash = faker(148787, "Alash'anir", 62, 0.598, 0.724),
|
||
|
|
-- burninator = faker(149141, "Burninator Mk V (Pet!)", 62, 0.414, 0.764),
|
||
|
|
worldedge = faker(160821, "Worldedge Gorger (mount)", 1525, 0.5, 0.5),
|
||
|
|
tarahna = faker(126900, "Instructor Tarahna (multi-toy)", 882, 0.5, 0.5),
|
||
|
|
nerissa = faker(162690, "Nerissa Heartless (mount)", 1536, 0.5, 0.5),
|
||
|
|
-- faeflayer = faker(171688, "Faeflayer", 1536, 0.5, 0.5),
|
||
|
|
scrapking = faker(151625, "Scrap King (loot)", 1462, 0.5, 0.5),
|
||
|
|
kash = faker(159105, "Collector Kash (lots of loot)", 1536, 0.5, 0.5),
|
||
|
|
chest = {
|
||
|
|
type = "execute", name = "Waterlogged Chest",
|
||
|
|
desc = "Fake seeing a Waterlogged Chest",
|
||
|
|
func = function()
|
||
|
|
-- id, zone, x, y, is_dead, source, unit
|
||
|
|
core.events:Fire("SeenLoot", "Waterlogged Chest", 3341, 37, 0.318, 0.628)
|
||
|
|
end,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
sound = {
|
||
|
|
type = "group", name = "Sounds",
|
||
|
|
get = get, set = set,
|
||
|
|
order = 10,
|
||
|
|
args = {
|
||
|
|
about = config.desc("Play sounds to announce rare mobs? Can do special things for special mobs. You *really* don't want to miss, say, the Time-Lost Proto Drake, after all...", 0),
|
||
|
|
channel = {
|
||
|
|
type = "select",
|
||
|
|
name = _G.SOUND_CHANNELS,
|
||
|
|
descStyle = "inline",
|
||
|
|
values = {
|
||
|
|
Ambience = _G.AMBIENCE_VOLUME,
|
||
|
|
Master = _G.MASTER,
|
||
|
|
Music = _G.MUSIC_VOLUME,
|
||
|
|
SFX = _G.SOUND_VOLUME,
|
||
|
|
Dialog = _G.DIALOG_VOLUME,
|
||
|
|
},
|
||
|
|
order = 11,
|
||
|
|
},
|
||
|
|
unmute = toggle("Ignore mute", "Play sounds even when muted", 12),
|
||
|
|
background = toggle(_G.ENABLE_BGSOUND, _G.OPTION_TOOLTIP_ENABLE_BGSOUND, 13),
|
||
|
|
drums = toggle("The Sound of Drums", "Underneath it all, the constant drumming", 14),
|
||
|
|
soundgroup = toggle("Group Sync Sounds", "Play sounds from synced mobs from party/raid members", 15),
|
||
|
|
soundguild = toggle("Guild Sync Sounds", "Play sounds from synced mobs from guild members not in group", 16),
|
||
|
|
regular = {type="header", name="", order=20,},
|
||
|
|
sound = toggle("Sounds", "Play sounds for regular mobs", 21),
|
||
|
|
soundfile = soundfile("sound", 22),
|
||
|
|
sound_loop = soundrange(23),
|
||
|
|
mount = {type="header", name="", order=25,},
|
||
|
|
sound_mount = toggle("Mount sounds", "Play a sound for mobs that drop a mount", 26),
|
||
|
|
soundfile_mount = soundfile("sound_mount", 27),
|
||
|
|
sound_mount_loop = soundrange(28),
|
||
|
|
boss = {type="header", name="", order=30,},
|
||
|
|
sound_boss = toggle("Boss sounds", "Play a sound for mobs that require a group", 31),
|
||
|
|
soundfile_boss = soundfile("sound_boss", 35),
|
||
|
|
sound_boss_loop = soundrange(37),
|
||
|
|
loot = {type="header", name="", order=40,},
|
||
|
|
sound_loot = toggle("Loot sounds", "Play a sound for treasures", 41),
|
||
|
|
soundfile_loot = soundfile("sound_loot", 45),
|
||
|
|
sound_loot_loop = soundrange(47),
|
||
|
|
},
|
||
|
|
},
|
||
|
|
flash = {
|
||
|
|
type = "group", name = "Flash",
|
||
|
|
get = get, set = set,
|
||
|
|
order = 15,
|
||
|
|
args = {
|
||
|
|
about = config.desc("Flash the screen when a rare is seen.", 0),
|
||
|
|
flash = toggle("Enabled", "Flash the screen?", 1),
|
||
|
|
flash_color = {
|
||
|
|
name = COLOR,
|
||
|
|
type = "color",
|
||
|
|
hasAlpha = true,
|
||
|
|
descStyle = "inline",
|
||
|
|
get = colorget,
|
||
|
|
set = colorset,
|
||
|
|
order = 2,
|
||
|
|
},
|
||
|
|
flash_texture = {
|
||
|
|
name = TEXTURES_SUBHEADER,
|
||
|
|
type = "select",
|
||
|
|
descStyle = "inline",
|
||
|
|
dialogControl = "LSM30_Background",
|
||
|
|
values = AceGUIWidgetLSMlists.background,
|
||
|
|
order = 3,
|
||
|
|
},
|
||
|
|
preview = {
|
||
|
|
name = PREVIEW,
|
||
|
|
type = "execute",
|
||
|
|
func = function()
|
||
|
|
module:Flash(50065) -- Armagedillo
|
||
|
|
end,
|
||
|
|
order = 4,
|
||
|
|
},
|
||
|
|
mount = {type="header", name="", order=10,},
|
||
|
|
flash_mount = toggle("Mount flash", "Flash the screen differently when we see a mob with a mount?", 11),
|
||
|
|
flash_color_mount = {
|
||
|
|
name = COLOR,
|
||
|
|
type = "color",
|
||
|
|
hasAlpha = true,
|
||
|
|
descStyle = "inline",
|
||
|
|
get = colorget,
|
||
|
|
set = colorset,
|
||
|
|
order = 12,
|
||
|
|
},
|
||
|
|
flash_texture_mount = {
|
||
|
|
name = TEXTURES_SUBHEADER,
|
||
|
|
type = "select",
|
||
|
|
descStyle = "inline",
|
||
|
|
dialogControl = "LSM30_Background",
|
||
|
|
values = AceGUIWidgetLSMlists.background,
|
||
|
|
order = 13,
|
||
|
|
},
|
||
|
|
preview_mount = {
|
||
|
|
name = PREVIEW,
|
||
|
|
type = "execute",
|
||
|
|
func = function()
|
||
|
|
module:Flash(32491) -- time lost
|
||
|
|
end,
|
||
|
|
order = 14,
|
||
|
|
},
|
||
|
|
boss = {type="header", name="", order=20,},
|
||
|
|
flash_boss = toggle("Boss flash", "Flash the screen differently when we see a boss rare?", 21),
|
||
|
|
flash_color_boss = {
|
||
|
|
name = COLOR,
|
||
|
|
type = "color",
|
||
|
|
hasAlpha = true,
|
||
|
|
descStyle = "inline",
|
||
|
|
get = colorget,
|
||
|
|
set = colorset,
|
||
|
|
order = 22,
|
||
|
|
},
|
||
|
|
flash_texture_boss = {
|
||
|
|
name = TEXTURES_SUBHEADER,
|
||
|
|
type = "select",
|
||
|
|
descStyle = "inline",
|
||
|
|
dialogControl = "LSM30_Background",
|
||
|
|
values = AceGUIWidgetLSMlists.background,
|
||
|
|
order = 23,
|
||
|
|
},
|
||
|
|
preview_boss = {
|
||
|
|
name = PREVIEW,
|
||
|
|
type = "execute",
|
||
|
|
func = function()
|
||
|
|
module:Flash(70096) -- War-God Dokah
|
||
|
|
end,
|
||
|
|
order = 24,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
config.options.args.outputs.plugins.announce = options
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function module:Seen(callback, id, zone, x, y, is_dead, source, ...)
|
||
|
|
Debug("Announce:Seen", id, zone, x, y, is_dead, ...)
|
||
|
|
|
||
|
|
if not self.db.profile.instances and IsInInstance() then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
if not self:ShouldAnnounce(id, zone, x, y, is_dead, source, ...) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
core.events:Fire("Announce", id, zone, x, y, is_dead, source, ...)
|
||
|
|
end
|
||
|
|
|
||
|
|
function module:SeenLoot(callback, name, id, zone, x, y, ...)
|
||
|
|
Debug("Announce:SeenLoot", name, id, zone, x, y, ...)
|
||
|
|
|
||
|
|
if not self.db.profile.instances and IsInInstance() then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
if not self.db.profile.loot then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
core.events:Fire("AnnounceLoot", name, id, zone, x, y, ...)
|
||
|
|
end
|
||
|
|
|
||
|
|
function module:ShouldAnnounce(id, zone, x, y, is_dead, source, ...)
|
||
|
|
if is_dead and not self.db.profile.dead then
|
||
|
|
Debug("ShouldAnnounce", false, "dead")
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
if core.db.global.always[id] then
|
||
|
|
-- If you've manually added a mob, bypass any other checks
|
||
|
|
Debug("ShouldAnnounce", true, "always")
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
if not self.db.profile.already_drop and ns.Loot.Status(id, self.db.profile.already_transmog) == true then
|
||
|
|
-- hide mobs which have a mount/pet/toy which you already own
|
||
|
|
-- this means there's knowable loot, and it's all known
|
||
|
|
Debug("ShouldAnnounce", false, "already got loot")
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
if not self.db.profile.already then
|
||
|
|
-- hide already-completed mobs
|
||
|
|
local quest, achievement, by_alt = ns:CompletionStatus(id)
|
||
|
|
if by_alt and not self.db.profile.already_alt then
|
||
|
|
-- an alt has completed the achievement, and we don't want to know about that
|
||
|
|
Debug("ShouldAnnounce", false, "alt got achievement")
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
if source == "vignette" then
|
||
|
|
-- The vignette's presence implies no quest completion
|
||
|
|
Debug("ShouldAnnounce", true, "vignette implies quest")
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
if quest ~= nil then
|
||
|
|
Debug("ShouldAnnounce", not quest, "quest")
|
||
|
|
return not quest
|
||
|
|
end
|
||
|
|
if achievement ~= nil then
|
||
|
|
-- can just fall back on achievement
|
||
|
|
Debug("ShouldAnnounce", not achievement, "achievement")
|
||
|
|
return not achievement
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
Debug("ShouldAnnounce", true, "fallback")
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
core.RegisterCallback("SD Announce Sink", "Announce", function(callback, id, zone, x, y, dead, source)
|
||
|
|
if not module.db.profile.sink then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
Debug("Pouring")
|
||
|
|
if source:match("^sync") then
|
||
|
|
local channel, player = source:match("sync:(.+):(.+)")
|
||
|
|
if channel and player then
|
||
|
|
local localized_zone = core.zone_names[zone] or UNKNOWN
|
||
|
|
source = "by " .. player .. " in your " .. strlower(channel) .. "; " .. localized_zone
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if x and y then
|
||
|
|
if x == 0 and y == 0 then
|
||
|
|
source = source .. " @ unknown location"
|
||
|
|
else
|
||
|
|
source = source .. " @ " .. core.round(x * 100, 1) .. "," .. core.round(y * 100, 1)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
local prefix = "Rare seen: "
|
||
|
|
module:Pour((prefix .. "%s%s (%s)"):format(core:GetMobLabel(id), dead and "... but it's dead" or '', source or ''))
|
||
|
|
end)
|
||
|
|
core.RegisterCallback("SD AnnounceLoot Sink", "AnnounceLoot", function(callback, name, id, zone, x, y)
|
||
|
|
if not module.db.profile.sink then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
|
||
|
|
Debug("Pouring")
|
||
|
|
local location = UNKNOWN
|
||
|
|
if x and y and x > 0 and y > 0 then
|
||
|
|
location = core.round(x * 100, 1) .. "," .. core.round(y * 100, 1)
|
||
|
|
end
|
||
|
|
local prefix = "Treasure seen: "
|
||
|
|
module:Pour((prefix .. "%s (%s)"):format(name, location))
|
||
|
|
end)
|
||
|
|
|
||
|
|
local cvar_overrides
|
||
|
|
local channel_cvars = {
|
||
|
|
Ambience = "Sound_EnableAmbience",
|
||
|
|
Master = "Sound_EnableAllSound",
|
||
|
|
Music = "Sound_EnableMusic",
|
||
|
|
SFX = "Sound_EnableSFX",
|
||
|
|
Dialog = "Sound_EnableDialog",
|
||
|
|
}
|
||
|
|
local delays = {
|
||
|
|
["Ikiss: Trinkets"] = 5.7,
|
||
|
|
}
|
||
|
|
local nowplaying
|
||
|
|
function module:PlaySound(s)
|
||
|
|
-- Arg is a table, to make scheduling the loops easier. I am lazy.
|
||
|
|
Debug("Playing sound", s.soundfile, s.loops)
|
||
|
|
-- boring check:
|
||
|
|
if s and s.handle then
|
||
|
|
StopSound(s.handle)
|
||
|
|
if s.drumshandle then
|
||
|
|
StopSound(s.drumshandle)
|
||
|
|
end
|
||
|
|
s.handle = nil
|
||
|
|
s.drumshandle = nil
|
||
|
|
end
|
||
|
|
if not s.loops or s.loops == 0 then
|
||
|
|
if cvar_overrides and s.cvars then
|
||
|
|
for cvar, value in pairs(s.cvars) do
|
||
|
|
SetCVar(cvar, value)
|
||
|
|
end
|
||
|
|
cvar_overrides = false
|
||
|
|
end
|
||
|
|
nowplaying = false
|
||
|
|
return
|
||
|
|
end
|
||
|
|
if not cvar_overrides then
|
||
|
|
if self.db.profile.background and GetCVar("Sound_EnableSoundWhenGameIsInBG") == "0" then
|
||
|
|
cvar_overrides = true
|
||
|
|
s.cvars = s.cvars or {}
|
||
|
|
s.cvars["Sound_EnableSoundWhenGameIsInBG"] = GetCVar("Sound_EnableSoundWhenGameIsInBG")
|
||
|
|
SetCVar("Sound_EnableSoundWhenGameIsInBG", "1")
|
||
|
|
end
|
||
|
|
if self.db.profile.unmute and GetCVar(channel_cvars[self.db.profile.channel]) == "0" then
|
||
|
|
cvar_overrides = true
|
||
|
|
s.cvars = s.cvars or {}
|
||
|
|
s.cvars[channel_cvars[self.db.profile.channel]] = GetCVar(channel_cvars[self.db.profile.channel])
|
||
|
|
SetCVar(channel_cvars[self.db.profile.channel], "1")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
-- now, noise!
|
||
|
|
local drums = self.db.profile.drums
|
||
|
|
if s.soundfile == "NPCScan" then
|
||
|
|
--Override default behavior and force npcscan behavior of two sounds at once
|
||
|
|
drums = true
|
||
|
|
local _, handle = PlaySoundFile(LSM:Fetch("sound", "Scourge Horn"), self.db.profile.channel)
|
||
|
|
s.handle = handle
|
||
|
|
else
|
||
|
|
--Play whatever sound is set
|
||
|
|
local _, handle = PlaySoundFile(LSM:Fetch("sound", s.soundfile), self.db.profile.channel)
|
||
|
|
s.handle = handle
|
||
|
|
end
|
||
|
|
if drums then
|
||
|
|
local _, handle = PlaySoundFile(LSM:Fetch("sound", "War Drums"), self.db.profile.channel)
|
||
|
|
s.drumshandle = handle
|
||
|
|
end
|
||
|
|
s.loops = s.loops - 1
|
||
|
|
-- we guarantee one callback, in case we need to do cleanup
|
||
|
|
self:ScheduleTimer("PlaySound", delays[s.soundfile] or 4.5, s)
|
||
|
|
nowplaying = true
|
||
|
|
end
|
||
|
|
core.RegisterCallback("SD Announce Sound", "Announce", function(callback, id, zone, x, y, dead, source)
|
||
|
|
if not LSM then return end
|
||
|
|
if nowplaying then return end
|
||
|
|
if source:match("^sync") then
|
||
|
|
local channel, player = source:match("sync:(.+):(.+)")
|
||
|
|
if channel == "GUILD" and not module.db.profile.soundguild or (channel == "PARTY" or channel == "RAID") and not module.db.profile.soundgroup then return end
|
||
|
|
end
|
||
|
|
local soundfile, loops
|
||
|
|
if ns.Loot.HasMounts(id) then
|
||
|
|
if not module.db.profile.sound_mount then return end
|
||
|
|
soundfile = module.db.profile.soundfile_mount
|
||
|
|
loops = module.db.profile.sound_mount_loop
|
||
|
|
elseif ns.mobdb[id] and ns.mobdb[id].boss then
|
||
|
|
if not module.db.profile.sound_boss then return end
|
||
|
|
soundfile = module.db.profile.soundfile_boss
|
||
|
|
loops = module.db.profile.sound_boss_loop
|
||
|
|
else
|
||
|
|
if not module.db.profile.sound then return end
|
||
|
|
soundfile = module.db.profile.soundfile
|
||
|
|
loops = module.db.profile.sound_loop
|
||
|
|
end
|
||
|
|
module:PlaySound{soundfile = soundfile, loops = loops}
|
||
|
|
end)
|
||
|
|
core.RegisterCallback("SD AnnounceLoot Sound", "AnnounceLoot", function(callback, id, zone, x, y, dead, source)
|
||
|
|
if not (module.db.profile.sound_loot and LSM) then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
if nowplaying then return end
|
||
|
|
module:PlaySound{soundfile = module.db.profile.soundfile_loot, loops = module.db.profile.sound_loot_loop}
|
||
|
|
end)
|
||
|
|
|
||
|
|
do
|
||
|
|
local flashframe
|
||
|
|
function module:Flash(id)
|
||
|
|
if not module.db.profile.flash then
|
||
|
|
return
|
||
|
|
end
|
||
|
|
if not flashframe then
|
||
|
|
flashframe = CreateFrame("Frame", nil, WorldFrame)
|
||
|
|
flashframe:SetClampedToScreen(true)
|
||
|
|
flashframe:SetFrameStrata("FULLSCREEN_DIALOG")
|
||
|
|
flashframe:SetToplevel(true)
|
||
|
|
flashframe:SetAllPoints(UIParent)
|
||
|
|
flashframe:Hide()
|
||
|
|
|
||
|
|
-- Use the OutOfControl (blue) and LowHealth (red) textures to get a purple flash
|
||
|
|
local texture = flashframe:CreateTexture(nil, "BACKGROUND")
|
||
|
|
texture:SetBlendMode("ADD")
|
||
|
|
texture:SetDesaturated(true)
|
||
|
|
texture:SetAllPoints()
|
||
|
|
|
||
|
|
local group = flashframe:CreateAnimationGroup()
|
||
|
|
group:SetLooping("BOUNCE")
|
||
|
|
local pulse = group:CreateAnimation("Alpha")
|
||
|
|
pulse:SetFromAlpha(0.3)
|
||
|
|
pulse:SetToAlpha(0.75)
|
||
|
|
pulse:SetDuration(0.5236)
|
||
|
|
|
||
|
|
local loops = 0
|
||
|
|
group:SetScript("OnLoop", function(frame, state)
|
||
|
|
loops = loops + 1
|
||
|
|
if loops == 9 then
|
||
|
|
group:Finish()
|
||
|
|
end
|
||
|
|
end)
|
||
|
|
group:SetScript("OnFinished", function(self)
|
||
|
|
loops = 0
|
||
|
|
flashframe:Hide()
|
||
|
|
end)
|
||
|
|
|
||
|
|
flashframe:SetScript("OnShow", function(self)
|
||
|
|
local background = module.db.profile.flash_texture
|
||
|
|
local color = module.db.profile.flash_color
|
||
|
|
if self.id and ns.mobdb[self.id] then
|
||
|
|
if ns.Loot.HasMounts(self.id) and module.db.profile.flash_mount then
|
||
|
|
background = module.db.profile.flash_texture_mount
|
||
|
|
color = module.db.profile.flash_color_mount
|
||
|
|
elseif ns.mobdb[self.id].boss and module.db.profile.flash_boss then
|
||
|
|
background = module.db.profile.flash_texture_boss
|
||
|
|
color = module.db.profile.flash_color_boss
|
||
|
|
end
|
||
|
|
end
|
||
|
|
texture:SetTexture(LSM:Fetch("background", background))
|
||
|
|
texture:SetVertexColor(color.r, color.g, color.b, color.a)
|
||
|
|
|
||
|
|
group:Play()
|
||
|
|
end)
|
||
|
|
end
|
||
|
|
|
||
|
|
Debug("Flashing")
|
||
|
|
flashframe.id = id
|
||
|
|
flashframe:Hide()
|
||
|
|
flashframe:Show()
|
||
|
|
end
|
||
|
|
|
||
|
|
core.RegisterCallback("SD Announce Flash", "Announce", function(callback, id)
|
||
|
|
module:Flash(id)
|
||
|
|
end)
|
||
|
|
core.RegisterCallback("SD AnnounceLoot Flash", "AnnounceLoot", function(callback, id)
|
||
|
|
module:Flash(id)
|
||
|
|
end)
|
||
|
|
end
|