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.
757 lines
27 KiB
757 lines
27 KiB
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")
|
|
|
|
-- testing snippet:
|
|
-- /script C_Timer.After(2, function() SilverDragon:GetModule("Announce"):Seen("_", 32491, 120, 0.490, 0.362, false, "fake") end)
|
|
|
|
-- 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", "Dwarf Horn", 566064)
|
|
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", "PvP Flag Horde", 568165) -- PVPFlagTakenHorde
|
|
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.
|
|
LSM:Register("sound", "PvP Alliance", 568320) -- PVPWarningAllianceLong
|
|
LSM:Register("sound", "PvP Horde", 569112) -- PVPWarningHordeLong
|
|
LSM:Register("sound", "Grimrail Train Horn", 1023633)
|
|
LSM:Register("sound", "Squire Horn", 598079)
|
|
LSM:Register("sound", "Gruntling Horn", 598196)
|
|
|
|
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,},
|
|
vibrate = true,
|
|
vibrate_type = "High",
|
|
vibrate_intensity = 1,
|
|
vibrate_mount = true,
|
|
vibrate_type_mount = "Low",
|
|
vibrate_intensity_mount = 1,
|
|
vibrate_boss = true,
|
|
vibrate_type_boss = "High",
|
|
vibrate_intensity_boss = 1,
|
|
vibrate_loot = true,
|
|
vibrate_type_loot = "High",
|
|
vibrate_intensity_loot = 0.8,
|
|
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,
|
|
known_mounts = 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 fake_args = {
|
|
-- this is a vanilla mob
|
|
deathmaw = faker(10077, "Deathmaw (Tame!)", 29, 0.5, 0.5),
|
|
}
|
|
if LE_EXPANSION_LEVEL_CURRENT >= (LE_EXPANSION_WRATH_OF_THE_LICH_KING or 999) then
|
|
fake_args.time = faker(32491, "Time-Lost Proto Drake (Mount!)", 120, 0.490, 0.362)
|
|
fake_args.vyragosa = faker(32630, "Vyragosa (Boring)", 120, 0.5, 0.5)
|
|
end
|
|
if not ns.CLASSIC then
|
|
-- id, name, zone, x, y, is_dead, is_new_location, source, unit
|
|
-- ishak = faker(157134, "Ishak of the Four Winds (Mount!)", 1527, 0.73, 0.83)
|
|
fake_args.anger = faker(60491, "Sha of Anger (Boss!)", 809, 0.5, 0.5)
|
|
-- haakun = faker(83008, "Haakun", 946, 0.5, 0.5)
|
|
fake_args.yiphrim = faker(157473, "Yiphrim the Will Ravager (Toy!)", 1527, 0.5, 0.786)
|
|
fake_args.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)
|
|
fake_args.worldedge = faker(160821, "Worldedge Gorger (mount)", 1525, 0.5, 0.5)
|
|
fake_args.tarahna = faker(126900, "Instructor Tarahna (multi-toy)", 882, 0.5, 0.5)
|
|
fake_args.nerissa = faker(162690, "Nerissa Heartless (mount)", 1536, 0.5, 0.5)
|
|
-- faeflayer = faker(171688, "Faeflayer", 1536, 0.5, 0.5)
|
|
fake_args.scrapking = faker(151625, "Scrap King (loot)", 1462, 0.5, 0.5)
|
|
fake_args.kash = faker(159105, "Collector Kash (lots of loot)", 1536, 0.5, 0.5)
|
|
-- worldcracker = faker(180032, "Wild Worldcracker", 1961, 0.5, 0.5)
|
|
-- blanchy = faker(173468, "Dead Blanchy", 1525, 0.5, 0.5)
|
|
fake_args.chest = {
|
|
type = "execute", name = "Waterlogged Chest",
|
|
desc = "Fake seeing a Waterlogged Chest",
|
|
func = function()
|
|
-- id, zone, x, y, instanceid
|
|
core.events:Fire("SeenLoot", "Waterlogged Chest", 3341, 37, 0.318, 0.628)
|
|
end
|
|
}
|
|
fake_args.mount_chest = {
|
|
type = "execute", name = "Mawsworn Supply Chest (mount)",
|
|
desc = "Fake seeing a Mawsworn Supply Chest, which contains a mount",
|
|
func = function()
|
|
-- id, zone, x, y, instanceid
|
|
core.events:Fire("SeenLoot", "Mawsworn Supply Chest", 4969, 1970, 0.318, 0.628)
|
|
end
|
|
}
|
|
end
|
|
|
|
local options = {
|
|
general = {
|
|
type = "group", name = "Announcements", 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", "Still 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", 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),
|
|
known_mounts = toggle("Known mounts are boring", "Treat mount-dropping rares whose mount you already know as if they're regular rares (unless the mount is BoE)", 25),
|
|
dead = toggle("Dead rares", "Announce when we see dead rares, if known. Not all scanning methods know whether a rare is dead or not", 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 = fake_args,
|
|
},
|
|
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 or _G.AUDIO_CHANNELS, -- dragonflight
|
|
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,
|
|
},
|
|
},
|
|
},
|
|
controller = {
|
|
type = "group", name = "Controller",
|
|
get = get, set = set,
|
|
disabled = function(info) return info[#info] ~= "controller" and not C_GamePad.IsEnabled() end,
|
|
order = 15,
|
|
args = {
|
|
about = config.desc("Vibrate a connected controller when a rare is seen. Only works if controller support is enabled. You can turn it on by typing `/console GamePadEnable 1` in the chat box.", 0),
|
|
},
|
|
},
|
|
}
|
|
|
|
local function vibrate_section(t, key, order, heading)
|
|
key = key and ("_"..key) or ""
|
|
if heading then
|
|
t["vibrate_heading" .. key] = {type="header", name="", order=order,}
|
|
end
|
|
t["vibrate" .. key] = toggle(heading or "Vibrate", "Vibrate the controller?", order + 1)
|
|
t["vibrate_type" .. key] = {
|
|
type = "select", name = "Type",
|
|
desc = "What type of vibration to use",
|
|
values = {
|
|
Low = "Low",
|
|
High = "High",
|
|
LTrigger = "LTrigger (PS5 only)",
|
|
RTrigger = "RTrigger (PS5 only)",
|
|
},
|
|
order = order + 2,
|
|
}
|
|
t["vibrate_intensity" .. key] = {
|
|
type = "range", name = "Intensity",
|
|
desc = "How strong the vibration should be",
|
|
min = 0, max = 1, step = 0.1,
|
|
order = order + 3,
|
|
}
|
|
t["preview" .. key] = {
|
|
type = "execute", name = PREVIEW,
|
|
func = function(info)
|
|
C_GamePad.SetVibration(self.db.profile["vibrate_type" .. key], self.db.profile["vibrate_intensity" .. key])
|
|
end,
|
|
order = order + 4,
|
|
}
|
|
return order + 5
|
|
end
|
|
local order = 1
|
|
order = vibrate_section(options.controller.args, nil, 1)
|
|
order = vibrate_section(options.controller.args, "mount", order, "Vibrate for mounts")
|
|
order = vibrate_section(options.controller.args, "boss", order, "Vibrate for bosses")
|
|
order = vibrate_section(options.controller.args, "loot", order, "Vibrate for loot")
|
|
|
|
config.options.args.general.plugins.announce = options
|
|
end
|
|
end
|
|
|
|
function module:HasInterestingMounts(id, isloot)
|
|
if not module.db.profile.known_mounts then
|
|
return ns.Loot.HasMounts(id, nil, nil, isloot)
|
|
end
|
|
return ns.Loot.HasInterestingMounts(id, isloot)
|
|
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 and not ns.Loot.HasMounts(id, true, true) then
|
|
-- hide mobs which have a mount/pet/toy which you already own... apart from BoE mounts
|
|
-- this means there's knowable loot, and it's all known
|
|
Debug("ShouldAnnounce", false, "already got loot")
|
|
return false
|
|
end
|
|
if ns.mobdb[id] and (
|
|
(ns.mobdb[id].requires and not ns.conditions.check(ns.mobdb[id].requires)) or
|
|
(ns.mobdb[id].active and not ns.conditions.check(ns.mobdb[id].active))
|
|
) then
|
|
Debug("ShouldAnnounce", false, "requirements not met")
|
|
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" or source == "point-of-interest" 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
|
|
local pin = ""
|
|
if x and y then
|
|
if x == 0 and y == 0 then
|
|
source = source .. " @ unknown location"
|
|
else
|
|
source = source .. (" @ %.1f, %.1f"):format(x * 100, y * 100)
|
|
if module.db.profile.sink_opts.sink20OutputSink == "ChatFrame" and MAP_PIN_HYPERLINK then
|
|
pin = (" |cffffff00|Hworldmap:%d:%d:%d|h[%s]|h|r"):format(
|
|
zone, x * 10000, y * 10000, MAP_PIN_HYPERLINK
|
|
)
|
|
end
|
|
end
|
|
end
|
|
module:Pour(("Rare seen: %s%s (%s)%s"):format(core:GetMobLabel(id), dead and "... but it's dead" or '', source or '', pin))
|
|
end)
|
|
core.RegisterCallback("SD AnnounceLoot Sink", "AnnounceLoot", function(callback, name, id, zone, x, y, instanceid)
|
|
if not module.db.profile.sink then
|
|
return
|
|
end
|
|
|
|
Debug("Pouring")
|
|
local pin = ""
|
|
local location = UNKNOWN
|
|
if x and y and x > 0 and y > 0 then
|
|
location = ("%.1f, %.1f"):format(x * 100, y * 100)
|
|
if module.db.profile.sink_opts.sink20OutputSink == "ChatFrame" and MAP_PIN_HYPERLINK then
|
|
pin = (" |cffffff00|Hworldmap:%d:%d:%d|h[%s]|h|r"):format(
|
|
zone, x * 10000, y * 10000, MAP_PIN_HYPERLINK
|
|
)
|
|
end
|
|
end
|
|
module:Pour(("Treasure seen: %s (%s)%s"):format(name, location, pin))
|
|
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 module:HasInterestingMounts(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, name, id, zone, x, y, instanceid)
|
|
if not (module.db.profile.sound_loot and LSM) then
|
|
return
|
|
end
|
|
if nowplaying then return end
|
|
local soundfile, loops
|
|
if module:HasInterestingMounts(id, true) then
|
|
if not module.db.profile.sound_mount then return end
|
|
soundfile = module.db.profile.soundfile_mount
|
|
loops = module.db.profile.sound_mount_loop
|
|
else
|
|
soundfile = module.db.profile.soundfile_loot
|
|
loops = module.db.profile.sound_loot_loop
|
|
end
|
|
module:PlaySound{soundfile = soundfile, loops = loops}
|
|
end)
|
|
|
|
do
|
|
local flashframe
|
|
function module:Flash(id, isloot)
|
|
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 module.db.profile.flash_mount and module:HasInterestingMounts(id, isloot) 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, name, id)
|
|
module:Flash(id, true)
|
|
end)
|
|
end
|
|
|
|
core.RegisterCallback("SD Announce Controller", "Announce", function(callback, id, zone, x, y, dead, source)
|
|
local vibrate_type, vibrate_intensity
|
|
if module:HasInterestingMounts(id) then
|
|
if not module.db.profile.vibrate_mount then return end
|
|
vibrate_type = module.db.profile.vibrate_type_mount
|
|
vibrate_intensity = module.db.profile.vibrate_intensity_mount
|
|
elseif ns.mobdb[id] and ns.mobdb[id].boss then
|
|
if not module.db.profile.vibrate_boss then return end
|
|
vibrate_type = module.db.profile.vibrate_type_boss
|
|
vibrate_intensity = module.db.profile.vibrate_intensity_boss
|
|
else
|
|
if not module.db.profile.vibrate then return end
|
|
vibrate_type = module.db.profile.vibrate_type
|
|
vibrate_intensity = module.db.profile.vibrate_intensity
|
|
end
|
|
C_GamePad.SetVibration(vibrate_type, vibrate_intensity)
|
|
end)
|
|
core.RegisterCallback("SD AnnounceLoot Controller", "AnnounceLoot", function(callback, name, id, zone, x, y, instanceid)
|
|
if not module.db.profile.vibrate_loot then
|
|
return
|
|
end
|
|
C_GamePad.SetVibration(module.db.profile.vibrate_type_loot, module.db.profile.vibrate_intensity_loot)
|
|
end)
|
|
|
|
|