/trunk/NaturCombat
## Interface: 20400 |
## Title: NaturCombat |
## Version: 9.0BETA3 |
## Version: wowi:revision |
## Author: Macca, Beladona |
## Notes: Enemy cast bars for cooldowns, buffs, debuffs and casts for both pvp and pve |
## OptionalDeps: LibStub, LibWombat, GTB-1.0, LibSharedMedia-3.0 |
## OptionalDeps: LibStub, LibWombat, NaturGTB, LibSharedMedia-3.0 |
## SavedVariables: NaturDB |
embed\LibStub\LibStub.lua |
embed\LibSharedMedia-3.0\LibSharedMedia-3.0.lua |
addon\spells.lua |
addon\spells\Druid.lua |
addon\spells\Rogue.lua |
addon\spells\Priest.lua |
addon\spells\Paladin.lua |
addon\spells\Hunter.lua |
addon\spells\Shaman.lua |
addon\spells\Mage.lua |
addon\spells\Warlock.lua |
addon\spells\Warrior.lua |
addon\generator.lua |
addon\parser.lua |
local addon = LibStub:GetLibrary("NaturCombat"); |
assert(addon,"NaturCombat failed to load in 'NaturCombat\addon\generator.lua' on line 1"); |
addon.bar = LibStub:GetLibrary("GTB-1.0"); |
assert(addon.bar,"GTB-1.0 failed to load in 'NaturCombat\addon\generator.lua' on line 3"); |
addon.media = LibStub:GetLibrary("LibSharedMedia-3.0"); |
assert(addon.media, "LibSharedMedia-3.0 failed to load in 'NaturCombat\addon\generator.lua' on line 5"); |
local addon = LibStub("NaturCombat"); -- Our Library |
addon.bar = LibStub("NaturGTB"); -- Bar Library |
addon.media = LibStub("LibSharedMedia-3.0"); -- Textures/Icons |
---------------------------------------------------------------------------------------------------- |
addon.colors = {}; |
addon.colors["HOSTILECAST"] = {r = 1, g = 0, b = 0}; |
addon.colors["FRIENDLYCAST"] = {r = 0, g= 1, b = 0}; |
addon.colors["COOLDOWN"] = {r = 0, g = 0, b = 1}; |
addon.colors["HOSTILEBUFF"] = {r = 0.5, g = 0, b = 0.65}; |
addon.colors["FRIENDLYBUFF"] = {r = 1, g = 0, b = 1}; |
addon.colors["STUN"] = {r = 0.5, g = 0.2, b = 0.1}; |
addon.colors["DOT"] = {r = 0, g = 0.8, b = 0.8}; |
addon.colors["DEBUFF"] = {r = 0.8, g = 0.8, b = 0}; |
addon.colors["GREY"] = { r = 0.8, g = 0.8, b = 0.8}; |
-- DEFAULT VARIABLES |
---------------------------------------------------------------------------------------------------- |
addon.default = { Version=GetAddOnMetadata("NaturCombat", "Version"), Height=20, Width=270, Scale=1, FontSize=15, MaxBars=10, Lock=true, Icon=true, |
Growth="UP", Invert=true, Texture="NaturGlaze", Vertical=0, Cooldowns=true, Diminish=true, Sounds=true, Groups=false, Track=false, TargetFocus=true, Casting=true, |
Colors = { |
["HOSTILECAST"] = {r = 1, g = 0, b = 0}, |
["FRIENDLYCAST"] = {r = 0, g= 1, b = 0}, |
["COOLDOWN"] = {r = 0, g = 0, b = 1}, |
["HOSTILEBUFF"] = {r = 0.5, g = 0, b = 0.65}, |
["FRIENDLYBUFF"] = {r = 1, g = 0, b = 1}, |
["STUN"] = {r = 0.5, g = 0.2, b = 0.1}, |
["DOT"] = {r = 0, g = 0.8, b = 0.8}, |
["DEBUFF"] = {r = 0.8, g = 0.8, b = 0}, |
["GREY"] = { r = 0.8, g = 0.8, b = 0.8}, |
},}; |
NaturDB = NaturDB or addon.default; |
addon.killcounter, addon.killtimer, addon.timers = 0, nil, {}; |
---------------------------------------------------------------------------------------------------- |
-- BAR GROUPS |
---------------------------------------------------------------------------------------------------- |
addon.bargroups = { |
["COOLDOWNS"] = "Cooldowns"; |
["DEBUFFS"] = "Debuffs"; |
["HOSTILEGAIN"] = "Hostile Gains"; |
["FRIENDLYGAIN"] = "Friendly Gains"; |
["HOSTILECAST"] = "Hostile Casts"; |
["FRIENDLYCAST"] = "Friendly Casts"; |
}; |
addon.groups = {}; -- Table for bar anchors |
addon.CDTable = {}; -- Table for cooldowns |
---------------------------------------------------------------------------------------------------- |
-- REGISTER MEDIA FILES |
---------------------------------------------------------------------------------------------------- |
addon.media:Register("statusbar", "NaturGlaze", [[Interface\AddOns\NaturCombat\media\glaze]]); |
addon.media:Register("icon", "Target", [[Interface\AddOns\NaturCombat\media\Target]]); |
addon.media:Register("icon", "Focus", [[Interface\AddOns\NaturCombat\media\Focus]]); |
---------------------------------------------------------------------------------------------------- |
addon.media:Register("sound", "First Blood", [[Interface\AddOns\NaturCombat\media\sounds\firstblood.mp3]]); |
addon.media:Register("sound", "Dominating", [[Interface\AddOns\NaturCombat\media\sounds\dominating.mp3]]); |
addon.media:Register("sound", "Monster Kill", [[Interface\AddOns\NaturCombat\media\sounds\monsterkill.mp3]]); |
addon.media:Register("sound", "Godlike", [[Interface\AddOns\NaturCombat\media\sounds\godlike.mp3]]); |
---------------------------------------------------------------------------------------------------- |
-- This is to deal with realm names from cross realm battlegroups |
function addon:StripName(name) |
name = string.match(name, "[^-]*"); |
return name; |
end |
-- FUNCTIONS |
---------------------------------------------------------------------------------------------------- |
local f = CreateFrame("Frame", nil, InterfaceOptionsFrame) |
function addon:StripName(str) |
return string.match(str, "[^-]*"); |
end; |
---------------------------------------------------------------------------------------------------- |
function addon:CreateBarGroup(name) |
local group = addon.bar:RegisterGroup(name, addon.media:Fetch("statusbar", NaturDB.Texture)); |
group:SetScale(NaturDB.Scale); |
group:SetWidth(NaturDB.Width); |
group:SetHeight(NaturDB.Height); |
group:SetAnchorVisible(NaturDB.Lock); |
group:SetMaxBars(NaturDB.MaxBars); |
group:SetBarGrowth(NaturDB.Growth); |
group:SetInvert(NaturDB.Invert); |
group:SetVerticalSpacing(NaturDB.Vertical); |
group:SetPoint("CENTER"); |
group:RegisterOnFade(addon, "OnFade"); |
return group; |
end; |
---------------------------------------------------------------------------------------------------- |
function addon:OnFade(barID) |
if (addon.CDTable[barID]) then |
addon.CDTable[barID] = nil; |
end |
end; |
---------------------------------------------------------------------------------------------------- |
function addon:GetColor(type) -- USED BY OPTIONS |
if (not NaturDB.Colors[type]) then return; end |
return NaturDB.Colors[type].r, NaturDB.Colors[type].g, NaturDB.Colors[type].b; |
end; |
---------------------------------------------------------------------------------------------------- |
function addon:SetColor(type, ...) -- USED BY OPTIONS |
if (not NaturDB.Colors[type]) then return; end |
NaturDB.Colors[type] = {r = select(1, ...), g = select(2, ...), b = select(3, ...)}; |
end; |
---------------------------------------------------------------------------------------------------- |
-- OPTIONS SLASH COMMAND |
-- /necb, /natur, /nct |
---------------------------------------------------------------------------------------------------- |
local f = CreateFrame("Frame", nil, InterfaceOptionsMenu); |
f:SetScript("OnShow", function(self) LoadAddOn("NaturOptions"); self:SetScript("OnShow", nil) end); |
SlashCmdList["NaturCombat"] = function() |
SlashCmdList["NaturCombat"] = function(cmd) |
if (LoadAddOn("NaturOptions")) then |
InterfaceOptionsFrame_OpenToFrame("NaturCombat"); |
end |
end; |
SLASH_NaturCombat1 = "/necb"; |
SLASH_NaturCombat2 = "/natur"; |
local addon = LibStub:GetLibrary("NaturCombat"); |
assert(addon,"NaturCombatTimers failed to load in 'NaturCombat\addon\parser.lua' on line 1"); |
LibStub:GetLibrary("LibWombat"):NewParser(addon); |
assert(addon.StartParsing,"LibWombat failed to load in 'NaturCombat\addon\parser.lua' on line 3"); |
NaturDB = NaturDB or {Height=20,Width=270,Scale=1,FontSize=15,MaxBars=10,Lock=true,Growth="UP",Invert=true,Texture="NaturGlaze",Cooldowns=true,Diminishing=true,Sounds=true}; |
addon.factor = 1; |
local CPAura, KillCounter, KillTimer = false, 0; |
local expTime, activeDR = {}, {}; |
local CDTable = {}; |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("VARIABLES_LOADED", function() |
addon.group = addon.bar:RegisterGroup("NaturCombat", addon.media:Fetch("statusbar", NaturDB.Texture)); |
addon.group:SetScale(NaturDB.Scale); |
addon.group:SetWidth(NaturDB.Width); |
addon.group:SetHeight(NaturDB.Height); |
addon.group:SetDisplayGroup("NaturCombat"); -- This redirects every bar to this certain group. |
addon.group:SetAnchorVisible(NaturDB.Lock); |
addon.group:SetGroupFontSize(NaturDB.FontSize); |
addon.group:SetMaxBars(NaturDB.MaxBars); |
addon.group:SetBarGrowth(NaturDB.Growth); |
addon.group:SetInvert(NaturDB.Invert); |
addon.group:SetPoint("CENTER"); |
addon.group:RegisterOnFade(addon, "OnFade"); |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("PLAYER_ENTERING_WORLD", function() |
local _, z = IsInInstance(); |
if (z == "arena") then -- Player is in an arena, clean bars |
addon.group:UnregisterAllBars(); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("SPELL_AURA_APPLIED", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local spell = addon:GetSpellData(...); |
if (dstGUID == UnitGUID("target") or dstGUID == UnitGUID("focus")) and (dstGUID ~= UnitGUID("player")) then |
if (spell) and (spell.duration) then |
-- Talents? |
if (spell.talent) then |
if (spell.talent[5] == select(2,UnitClass("player"))) then |
local _, _, _, _, rank = GetTalentInfo(spell.talent[1], spell.talent[2]); |
if (rank) and (rank > 0) then |
spell.duration = spell.talent[3] + rank * spell.talent[4]; |
end |
end |
end |
-- Set Bar Color |
local color = addon.colors["GREY"]; |
if (spell.type == "BUFF") then |
if (CombatLog_Object_IsA(dstFlags, COMBATLOG_FILTER_HOSTILE_PLAYERS)) then |
color = addon.colors["HOSTILEBUFF"]; |
elseif (CombatLog_Object_IsA(dstFlags, COMBATLOG_FILTER_FRIENDLY_UNITS)) then |
color = addon.colors["FRIENDLYBUFF"]; |
end |
elseif (spell.type == "DEBUFF") then |
if (spell.stun) then |
color = addon.colors["STUN"]; |
elseif (spell.dot) then |
color = addon.colors["DOT"]; |
else |
color = addon.colors["DEBUFF"]; |
end |
end |
-- PVP Duration? |
local duration = 1; |
local guid = strsub(dstGUID, 1 ,5); |
if (spell.pvpdur) and (bit.band(guid, 0x00F) == 0) then -- Player? |
duration = spell.pvpdur; |
else |
duration = spell.duration; |
end |
-- DR? only on target. |
if (dstGUID == UnitGUID("target")) and (spell.drcat) and (NaturDB.Diminishing) then |
addon:ApplyDiminish(spell.id, dstName, dstGUID); |
duration = duration * addon.factor; |
end |
-- Combo? |
if (spell.combo) then CPAura = true; end |
local text = spell.name .. " - " .. addon:StripName(dstName); |
addon.group:RegisterBar(dstGUID..spell.id, text, duration, nil, spell.icon, color.r, color.g, color.b); |
end |
end |
end); |
---------------------------------------------------------------------------------------------------- |
-- Deal with cooldowns and instant casts |
-- Add cooldown to the CDTable so we can remove/show on target change |
addon:StartParsing("SPELL_CAST_SUCCESS", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local spell = addon:GetSpellData(...); |
--Quick fix for refreshing spells until 2.4.3 SPELL_AURA_REFRESH |
if (spell) and (spell.duration) then |
if (dstGUID == UnitGUID("target") or dstGUID == UnitGUID("focus")) and (dstGUID ~= UnitGUID("player")) then |
addon.group:SetTime(dstGUID..spell.id, spell.duration); |
end |
end |
----------- |
if (spell.special) and (srcGUID == UnitGUID("player")) then -- show this even tho the player casted it. |
local color = addon.colors["FRIENDLYBUFF"]; |
local text = spell.name .. " - " .. srcName; |
addon.group:RegisterBar(srcGUID..spell.id, text, spell.duration, nil, spell.icon, color.r, color.g, color.b); |
end |
if (srcGUID == UnitGUID("player")) then return; end |
if (srcGUID == UnitGUID("target")) then --We don't want to show cooldowns for our focus.. maybe change this if someone requests it. |
if (spell) and (spell.cooldown) then |
if (spell.type == "CAST") and (spell.instant) then |
if (spell.duration) then |
local color; |
if (CombatLog_Object_IsA(srcFlags, COMBATLOG_FILTER_HOSTILE_PLAYERS)) then |
color = addon.colors["HOSTILEBUFF"]; |
elseif (CombatLog_Object_IsA(srcFlags, COMBATLOG_FILTER_FRIENDLY_UNITS)) then |
color = addon.colors["FRIENDLYBUFF"]; |
end |
local text = spell.name .. " - " .. addon:StripName(srcName); |
addon.group:RegisterBar(srcGUID..spell.id, text, spell.duration, nil, spell.icon, color.r, color.g, color.b); |
end |
if (NaturDB.Cooldowns) then |
local color = addon.colors["COOLDOWN"]; |
local text = spell.name .. " [CD] - " .. addon:StripName(srcName); |
addon.group:RegisterBar(srcGUID..spell.id.."CD", text, spell.cooldown, nil, spell.icon, color.r, color.g, color.b); |
--Add to CDTable |
CDTable[srcGUID..spell.id.."CD"] = {srcGUID,spell.cooldown}; |
end |
elseif (spell.type == "BUFF") then |
if (NaturDB.Cooldowns) then |
local color = addon.colors["COOLDOWN"]; |
local text = spell.name .. " [CD] - " .. addon:StripName(srcName); |
addon.group:RegisterBar(srcGUID..spell.id.."CD", text, spell.cooldown, nil, spell.icon, color.r, color.g, color.b); |
-- Add to DB |
CDTable[srcGUID..spell.id.."CD"] = {srcGUID,spell.cooldown}; |
end |
end |
end |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("SPELL_AURA_REMOVED", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local spell = addon:GetSpellData(...); |
if (spell) and (spell.duration) then |
if (spell.combo) then CPAura = false; end |
if (spell.drcat) then |
addon:RemoveDiminish(spell.id, dstName, dstGUID); |
end |
addon.group:UnregisterBar(dstGUID..spell.id); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("SPELL_AURA_DISPELLED", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local spell = addon:GetSpellData(select(12, ...)); |
if (spell) and (spell.duration) then |
addon.group:UnregisterBar(dstGUID..spell.id); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("SPELL_INTERRUPT", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local spell = addon:GetSpellData(select(12, ...)); |
if (spell) and (spell.duration) then |
addon.group:UnregisterBar(dstGUID..spell.id); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("SPELL_MISSED", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local spell = addon:GetSpellData(...); |
if (spell) and (spell.duration) then |
addon.group:UnregisterBar(dstGUID..spell.id); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("SPELL_AURA_APPLIED_DOSE", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local spell = addon:GetSpellData(...); |
local stack = select(5, ...); |
if (dstGUID == UnitGUID("player")) then return; end |
if (dstGUID == UnitGUID("target")) or (dstGUID == UnitGUID("focus")) then |
if (spell) and (spell.stacks) and (spell.duration) then |
local text = "(" .. stack .. ") " .. spell.name .. " - " .. addon:StripName(dstName); |
addon.group:SetBarText(dstGUID..spell.id, text); |
addon.group:SetTime(dstGUID..spell.id, spell.duration); |
end |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("SPELL_AURA_REMOVED_DOSE", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local spell = addon:GetSpellData(...); |
local stack = select(5, ...); |
if (dstGUID == UnitGUID("player")) then return; end |
if (dstGUID == UnitGUID("target")) or (dstGUID == UnitGUID("focus")) then |
if (spell) and (spell.stacks) and (spell.duration) then |
local text = "(" .. stack .. ") " .. spell.name .. " - " .. addon:StripName(dstName); |
addon.group:SetBarText(dstGUID..spell.id, text); |
end |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("UNIT_DIED", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
if (dstGUID == UnitGUID("player")) then return; end |
for k, v in pairs(addon.spelldata) do |
addon.group:UnregisterBar(dstGUID..k); |
addon.group:UnregisterBar(dstGUID..k.."CD"); |
if (addon.spelldata[k].drcat) then |
addon.group:UnregisterBar(dstGUID..addon.spelldata[k].drcat); |
end |
CDTable[dstGUID..k.."CD"] = nil; |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("UNIT_SPELLCAST_START", function(unitid, spell, ...) |
if (UnitGUID(unitid) == UnitGUID("player")) then return; end |
if (unitid == "target" and spell) or (unitid == "focus" and spell) then |
local color; |
if (UnitReaction(unitid, "player") < 4) then -- Hostile |
color = addon.colors["HOSTILECAST"]; |
else |
color = addon.colors["FRIENDLYCAST"]; |
end |
local icon, sTime, eTime = select(4, UnitCastingInfo(unitid)); |
local text = spell .. " - " .. addon:StripName(UnitName(unitid)); |
sTime, eTime = sTime/1000, eTime/1000; |
addon.group:RegisterBar(UnitGUID(unitid).."cast", text, eTime - sTime, nil, icon, color.r, color.g, color.b); |
end |
end); |
addon:StartParsing("UNIT_SPELLCAST_STOP", function(unitid, ...) -- This is suppose to return the spellname yet fails to do so.. |
if (UnitGUID(unitid) == UnitGUID("player")) then return; end |
if (unitid == "target") or (unitid == "focus") then |
addon.group:UnregisterBar(UnitGUID(unitid).."cast"); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("UNIT_SPELLCAST_CHANNEL_START", function(unitid, spell, ...) |
if (UnitGUID(unitid) == UnitGUID("player")) then return; end |
if (unitid == "target" and spell) or (unitid == "focus" and spell) then |
local color; |
if (UnitReaction(unitid, "player") < 4) then -- Hostile |
color = addon.colors["HOSTILECAST"]; |
else |
color = addon.colors["FRIENDLYCAST"]; |
end |
local icon, sTime, eTime = select(4, UnitChannelInfo(unitid)); |
local text = spell .. " - " .. addon:StripName(UnitName(unitid)); |
sTime, eTime = sTime/1000, eTime/1000; |
addon.group:RegisterBar(UnitGUID(unitid).."channel", text, eTime - sTime, nil, icon, color.r, color.g, color.b); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("UNIT_SPELLCAST_CHANNEL_STOP", function(unitid, spell, ...) |
if (UnitGUID(unitid) == UnitGUID("player")) then return; end |
if (unitid == "target") or (unitid == "focus") then |
addon.group:UnregisterBar(UnitGUID(unitid).."channel"); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
-- NOTE: There has to be a better way to deal with combo point abilites :/ |
addon:StartParsing("UNIT_AURA", function(unitid) |
if (UnitGUID(unitid) == UnitGUID("player")) then return; end |
if (unitid == "target") or (unitid == "focus") then |
local name, duration; |
if (not CPAura) then return; end |
local id = 0; |
while (true) do |
id = id + 1; |
name, _, _, _, _, duration = UnitDebuff(unitid, id); |
if (not name) then break; end |
if (addon.spellkeys[name]) then |
if (addon.spelldata[addon.spellkeys[name]].combo) and (addon.spelldata[addon.spellkeys[name]].duration) then |
local text = name .. " - " .. addon:StripName(UnitName(unitid)); |
if (not duration) then |
duration = addon.spelldata[addon.spellkeys[name]].duration; |
end |
addon.group:SetTime(UnitGUID(unitid)..addon.spelldata[addon.spellkeys[name]].id, duration); |
CPAura = false; |
end |
end |
end |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("PLAYER_TARGET_CHANGED", function() |
-- Remove CD's from old target |
for id, cooldown in pairs(CDTable) do |
if (UnitGUID("target") ~= cooldown[1]) then |
addon.group:HideBar(id); |
else |
addon.group:ShowBar(id, cooldown[2]); |
end |
end |
end); |
---------------------------------------------------------------------------------------------------- |
addon:StartParsing("PARTY_KILL", function(when,what,srcGUID,srcName,srcFlags,dstGUID,dstName,dstFlags,...) |
local guid = strsub(dstGUID, 1, 5); |
if (srcGUID == UnitGUID("player")) and (bit.band(guid, 0x00F) == 0) and (NaturDB.Sounds) then |
if (not KillTimer) or (GetTime() - KillTimer > 60) then |
PlaySoundFile(addon.media:Fetch("sound", "First Blood")); |
KillCounter = 0; |
elseif (GetTime() - KillTimer <= 60) then |
KillCounter = KillCounter + 1 |
if (KillCounter == 1) then |
PlaySoundFile(addon.media:Fetch("sound", "Dominating")); |
elseif (KillCounter == 2) then |
PlaySoundFile(addon.media:Fetch("sound", "Killing Spree")); |
elseif (KillCounter == 3) then |
PlaySoundFile(addon.media:Fetch("sound", "Unstoppable")); |
elseif (KillCounter == 4) then |
PlaySoundFile(addon.media:Fetch("sound", "Monster Kill")); |
elseif (KillCounter > 4) then |
PlaySoundFile(addon.media:Fetch("sound", "Godlike")); |
end |
end |
KillTimer = GetTime(); |
end |
end); |
---------------------------------------------------------------------------------------------------- |
-- TODO: Look over DR code and improve it. |
-- Massive thanks to Shadowd the author of DR Tracker. |
function addon:ApplyDiminish(spellID, dstName, dstGUID) |
local spell = addon:GetSpellData(spellID); |
local id = dstGUID .. spell.drcat; |
local time = GetTime(); |
local diminished = 100; |
if (expTime[id] and expTime[id] >= time) then |
diminished = self:GetDR(activeDR[id]); |
addon.factor = select(3, self:GetDR(activeDR[id])); |
activeDR[id] = diminished; |
expTime[id] = GetTime() + 15; |
addon.group:UnregisterBar(id); |
elseif (not expTime[id] or expTime[id] <= time) then |
activeDR[id] = diminished; |
addon.factor = 1; |
expTime[id] = GetTime() + 15; |
end |
end; |
---------------------------------------------------------------------------------------------------- |
function addon:RemoveDiminish(spellId, dstName, dstGUID) |
local spell = addon:GetSpellData(spellId); |
local id = dstGUID .. spell.drcat; |
if (activeDR[id]) then |
local text = spell.name .. " [".. spell.drcat .." |cffff2020DR " .. select(2,addon:GetDR(activeDR[id])) .. "/3|r] - " .. addon:StripName(dstName); |
local color = addon.colors["COOLDOWN"]; |
addon.group:RegisterBar(id, text, 15, nil, spell.icon, color.r, color.g, color.b); |
end |
expTime[id] = GetTime() + 15; |
end; |
---------------------------------------------------------------------------------------------------- |
function addon:GetDR(dr) |
if (dr == 100) then |
return 50, 1, 0.5; |
elseif (dr == 50) then |
return 25, 2, 0.25; |
elseif (dr == 25) then |
return 0, "Immune! 3", 0; |
end |
end; |
---------------------------------------------------------------------------------------------------- |
function addon:OnFade(barid) |
if (CDTable[barid]) then |
CDTable[barid] = nil; |
end |
end; |
local addon = LibStub:NewLibrary("NaturCombat",20080514); |
assert(addon,"NaturCombatTimers failed to load in 'NaturCombatTimers\addon\spells.lua' on line 1"); |
local addon = LibStub:NewLibrary("NaturCombat", 20080716); |
---------------------------------------------------------------------------------------------------- |
addon.spelldata = {}; -- lookup table used for data storage, stored by spellid |
addon.spellkeys = {}; -- lookup table used for spell names that default to a spellid |
addon.spellmeta = {}; |
addon.spellmeta.__newindex = function(tbl,key,value) |
addon.spelldata = {}; -- Lookup table for data, stored by spellid |
addon.spellkeys = {}; -- Lookup table for spell names that default to a spellid |
addon.spellmeta = {}; -- Metatable |
addon.spellmeta.__newindex = function(tbl, key, value) |
local name = GetSpellInfo(key); |
if (not addon.spelldata[key]) then addon.spelldata[key] = value; end |
if (not addon.spellkeys[name]) then addon.spellkeys[name] = key; end |
end; |
addon.spellmeta.__index = function(tbl,key) |
local name,rank,icon,_,_,_,castTime = GetSpellInfo(key); |
addon.spellmeta.__index = function(tbl, key) |
local name, rank, icon, _, _, _, castTime = GetSpellInfo(key); |
if (not addon.spelldata[key]) then key = addon.spellkeys[name]; end |
local data = addon.spelldata[key] or {}; |
data.id, data.name, data.rank, data.icon, data.castTime = key, name, rank, icon, castTime/1000; |
data.id, data.name, data.rank, data.icon, data.castTime = key, name, rank, icon, castTime / 1000; |
return data; |
end; |
addon.spells = setmetatable({},addon.spellmeta); |
local spells = setmetatable({}, addon.spellmeta); |
function addon:GetSpellData(id) |
if (id) then return addon.spells[id]; end |
end; |
if (id) then return spells[id]; end |
end |
---------------------------------------------------------------------------------------------------- |
-- RACIALS |
addon.spells[20600] = {duration=20,cooldown=180,type="BUFF"}; -- Perception |
addon.spells[7744] = {duration=5,cooldown=120,type="BUFF"}; -- Will of the Forsaken |
addon.spells[20594] = {duration=8,cooldown=180,type="BUFF"}; -- Stoneform |
addon.spells[26297] = {duration=10,cooldown=180,type="BUFF"}; -- Berseking |
addon.spells[28880] = {duration=15,cooldown=180,type="BUFF"}; -- Gift of the Naaru |
addon.spells[20549] = {duration=2,type="DEBUFF"}; -- War Stomp |
addon.spells[25467] = {duration=24,dot=true,type="DEBUFF"}; -- Devouring Plague |
addon.spells[25446] = {duration=15,dot=true,type="DEBUFF"}; -- Starshards |
-- Misc. |
addon.spells[5530] = {duration=3,stun=true,type="DEBUFF"}; -- Mace Stun |
watcher:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP"); |
watcher:RegisterEvent("UNIT_AURA"); |
watcher:RegisterEvent("PLAYER_TARGET_CHANGED"); |
watcher:RegisterEvent("PLAYER_FOCUS_CHANGED"); |
-- |
wombat.parser = wombat.parser or {}; |
local CleanParser = function() |
local major = "GTB-1.0" |
local major = "NaturGTB" |
local minor = tonumber(string.match("$Revision: 752 $", "(%d+)") or 1) |
assert(LibStub, string.format("%s requires LibStub.", major)) |
["MUST_CALL"] = "You must call '%s' from a registered GTB object.", |
["GROUP_EXISTS"] = "The group '%s' already exists.", |
["BAD_FUNC"] = "You must pass an actual handler and function to '%s'.", |
["ALT_DRAG"] = "ALT + Drag to move the frame anchor.", |
["ALT_DRAG"] = "Drag to move the frame anchor.", |
} |
-- Validation for passed arguments |
local framePool = GTB.framePool |
local groups = GTB.groups |
local methods = {"RegisterOnMove", "SetAnchorVisible", "GetReversed", "GetGrowth", "GetMaxBars", "GetScale", "GetFontSize", "GetWidth", "GetHeight", "SetMaxBars", "SetBaseColor", "EnableGradient", "SetPoint", "SetScale", "SetWidth", "SetHeight", "SetTexture", "SetBarGrowth", "SetIconPosition", "SetTextColor", "HideBar", "ShowBar", "SortBars", |
"SetTimerColor", "SetFadeTime", "RegisterOnFade", "RegisterOnClick", "SetGroupFontSize", "SetInvert", "SetDisplayGroup", "GetDisplayGroup", "RegisterBar", "UnregisterBar", "SetRepeatingTimer", "UnregisterAllBars", "SetBarIcon", "SetTime", "SetBarText"} |
local methods = {"RegisterOnMove", "SetAnchorVisible", "SetAlpha", "GetAlpha", "SetFlashTime", "GetFlashTime", "GetReversed", "GetGrowth", "GetMaxBars", "GetScale", "GetFontSize", "GetWidth", "GetHeight", "SetMaxBars", "SetBaseColor", "EnableGradient", "SetPoint", "SetScale", "SetWidth", "SetHeight", "SetTexture", "SetBarGrowth", "SetIconPosition", "SetTextColor", "HideBar", "ShowBar", "SortBars", |
"SetTimerColor", "SetFadeTime", "RegisterOnFade", "RegisterOnClick", "GetVertical", "SetVerticalSpacing", "SetGroupFontSize", "SetInvert", "SetDisplayGroup", "GetDisplayGroup", "RegisterBar", "UnregisterBar", "SetRepeatingTimer", "UnregisterAllBars", "SetBarIcon", "SetTime", "SetBarText"} |
-- Internal functions for managing bars |
local function getFrame() |
-- Create icon |
frame.icon = frame:CreateTexture(nil, "ARTWORK") |
-- Create Focus/Target Icon |
frame.ticon = frame:CreateTexture(nil, "ARTWORK") |
-- Sparky |
frame.spark = frame:CreateTexture(nil, "OVERLAY") |
frame.spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark") |
end |
end |
-- Fadeout OnUpdate |
local function fadeOnUpdate(self, elapsed) |
local time = GetTime() |
-- Reposition the group |
-- edited for NaturCombat |
local function sortBars(a, b) |
local group = groups["NaturCombat"] |
for id, bar in pairs(group.bars) do |
if (not bar:IsShown()) then -- this specific bar exists.. but it's hidden |
return false |
else |
return a.endTime < b.endTime |
end |
end |
return a.endTime < b.endTime |
end |
local function repositionFrames(group) |
if( i > 1 ) then |
if( group.barGrowth == "DOWN" ) then |
bar:SetPoint("TOPLEFT", group.usedBars[i - 1], "BOTTOMLEFT", 0, 0) |
bar:SetPoint("TOPLEFT", group.usedBars[i - 1], "BOTTOMLEFT", 0, group.vertical) |
else |
bar:SetPoint("BOTTOMLEFT", group.usedBars[i - 1], "TOPLEFT", 0, 0) |
bar:SetPoint("BOTTOMLEFT", group.usedBars[i - 1], "TOPLEFT", 0, group.vertical) |
end |
elseif( group.barGrowth == "UP" ) then |
bar:SetPoint("BOTTOMLEFT", group.frame, "TOPLEFT", offset, 0) |
fadeoutBar(self) |
return |
end |
--flashTime = 5 |
self:SetAlpha(NaturDB.Alpha) |
-- Timer text, need to see if this can be optimized a bit later |
local hour = floor(self.secondsLeft / 3600) |
local minutes = self.secondsLeft - (hour * 3600) |
-- Dragging functions |
local function OnDragStart(self) |
if( IsAltKeyDown() ) then |
self.isMoving = true |
self:StartMoving() |
end |
self.isMoving = true |
self:StartMoving() |
end |
local function OnDragStop(self) |
GameTooltip:Hide() |
end |
function GTB:UnregisterAllBarGroups() |
for a, _ in pairs(groups) do |
groups[a] = nil; |
end |
end |
function GTB:UnregisterGroup(name) |
if groups[name] then |
groups[name] = nil; |
end |
end |
function GTB:RegisterGroup(name, texture) |
argcheck(name, 1, "string") |
argcheck(texture, 2, "string") |
assert(3, not groups[name], string.format(L["GROUP_EXISTS"], name)) |
local obj = {name = name, frame = CreateFrame("Frame", name, UIParent), fontSize = 11, height = 16, obj = obj, bars = {}, usedBars = {}, reversed = false} |
local obj = {name = name, frame = CreateFrame("Frame", name, UIParent), fontSize = 11, height = 16, obj = obj, bars = {}, usedBars = {}, vertical = 0} |
-- Inject our methods |
for _, func in pairs(methods) do |
obj:SetScale(1.0) |
obj:SetWidth(200) |
obj:SetFadeTime(0.25) |
--obj:SetFlashTime(5) |
obj:SetMaxBars(20) |
obj:EnableGradient(true) |
obj:SetAnchorVisible(true) |
--Edit the timer value of a bar |
function GTB.SetTime(group, id, value) |
if( group.redirectTo and groups[group.redirectTo] ) then |
group = groups[group.redirectTo] |
end |
if not group.bars[id] then return end |
group.bars[id].timer:SetText(value) |
group.bars[id].secondsLeft = value |
-- Edit the text on an active bar |
local origBarID = {} |
function GTB.SetBarText(group, id, text) |
if( group.redirectTo and groups[group.redirectTo] ) then |
group = groups[group.redirectTo] |
end |
if not group.bars[id] then return end |
group.bars[id].text:SetText(text) |
group.bars[id].barText = text |
end |
function GTB.HideBar(group, id) |
if( group.redirectTo and groups[group.redirectTo] ) then |
group = groups[group.redirectTo] |
end |
if not group.bars[id] then return end |
--Keep record of this timer |
origBarID[id] = {update=group.bars[id].lastUpdate,text=group.bars[id].barText,timer=group.bars[id].secondsLeft,icon=group.bars[id].iconPath,color={r=group.bars[id].r,g=group.bars[id].g,b=group.bars[id].b}} |
origBarID[id] = {update=group.bars[id].lastUpdate,text=group.bars[id].barText,timer=group.bars[id].secondsLeft,icon=group.bars[id].iconPath,ticon=group.bars[id].ticonPath,color={r=group.bars[id].r,g=group.bars[id].g,b=group.bars[id].b}} |
GTB.UnregisterBar(group, id) |
end |
function GTB.ShowBar(group, id, timer) |
if( group.redirectTo and groups[group.redirectTo] ) then |
group = groups[group.redirectTo] |
end |
if not origBarID[id] then return end |
local time = origBarID[id].timer - (GetTime() - origBarID[id].update) |
-- group, id, text, 60, 54, icon, r, g, b |
GTB.RegisterBar(group, id, origBarID[id].text, time, timer, origBarID[id].icon, origBarID[id].color.r, origBarID[id].color.g, origBarID[id].color.b) |
GTB.RegisterBar(group, id, origBarID[id].text, time, timer, origBarID[id].icon, origBarID[id].ticon, origBarID[id].color.r, origBarID[id].color.g, origBarID[id].color.b) |
end |
function GTB.SetInvert(group, value) |
if( group.redirectTo and groups[group.redirectTo] ) then |
group = groups[group.redirectTo] |
end |
group.reversed = value |
end |
function GTB.GetReversed(group) |
function GTB.GetScale(group) |
return group.scale |
end |
function GTB.GetFontSize(group) |
return group.fontSize |
end |
function GTB.GetMaxBars(group) |
return group.maxBars |
end |
function GTB.GetGrowth(group) |
return group.barGrowth |
end |
function GTB.SetVerticalSpacing(group, val) |
if( group.redirectTo and groups[group.redirectTo] ) then |
group = groups[group.redirectTo] |
end |
group.vertical = val |
end |
function GTB.GetVertical(group) |
return group.vertical |
end |
function GTB.SetAlpha(group, val) |
if( group.redirectTo and groups[group.redirectTo] ) then |
group = groups[group.redirectTo] |
end |
for k, v in pairs(group.bars) do |
group.bars[k]:SetAlpha(val); |
end |
end |
-- Change the font size of the group |
function GTB.SetGroupFontSize(group, size) |
if( group.redirectTo and groups[group.redirectTo] ) then |
group = groups[group.redirectTo] |
end |
group.fontSize = size |
end |
group.fadeTime = seconds |
end |
-- When should we start flashing the bar |
function GTB.SetFlashTime(group, seconds) |
argcheck(seconds, 2, "number") |
assert(3, group.name and groups[group.name], string.format(L["MUST_CALL"], "SetFadeTime")) |
group.flasherTime = seconds |
end |
function GTB.GetFlashTime(group) |
return group.flasherTime |
end |
-- Redirect everything to the specified group |
function GTB.SetDisplayGroup(group, name) |
argcheck(name, 2, "string", "nil") |
-------------------- |
-- Register |
function GTB.RegisterBar(group, id, text, seconds, startSeconds, icon, r, g, b) |
function GTB.RegisterBar(group, id, text, seconds, startSeconds, icon, ticon, r, g, b) |
argcheck(id, 2, "string", "number") |
argcheck(text, 3, "string") |
argcheck(seconds, 4, "number") |
argcheck(icon, 5, "string", "nil") |
argcheck(r, 6, "number", "nil") |
argcheck(g, 7, "number", "nil") |
argcheck(b, 8, "number", "nil") |
argcheck(icon, 5, "string", "number", "nil") |
argcheck(ticon, 6, "string", "nil") |
argcheck(r, 7, "number", "nil") |
argcheck(g, 8, "number", "nil") |
argcheck(b, 9, "number", "nil") |
assert(3, group.name and groups[group.name], string.format(L["MUST_CALL"], "RegisterBar")) |
local originalOwner = group.name |
-- Update icon |
if( icon ) then |
if (type(icon) == "number") then |
icon = select(3, GetSpellInfo(icon)); |
end |
frame.icon:SetTexture(icon) |
if( frame.icon:GetTexture() ) then |
frame.icon:Hide() |
end |
-- Update Target/Focus Icon |
if ( ticon ~= type("string") ) then |
frame.ticon:SetTexture(ticon) |
if (frame.ticon:GetTexture()) then |
frame.ticon:SetWidth(group.height) |
frame.ticon:SetHeight(group.height) |
frame.ticon:SetTexCoord(0.07, 0.93, 0.07, 0.93) |
frame.ticon:SetPoint("TOPLEFT", frame, "TOPRIGHT", offset, 0) |
frame.ticon:Show() |
else |
frame.ticon:Hide() |
end |
end |
-- Set info the bar needs to know |
frame.r = r or group.baseColor.r |
frame.g = g or group.baseColor.g |
frame.gradients = group.gradients |
frame.groupName = group.name |
frame.iconPath = icon |
frame.ticonPath = ticon |
frame.barText = text |
frame.barID = id |
frame.group = group |
frame.reversed = group.reversed |
frame.vertical = group.vertical |
-- Setup background |
frame.bg:SetStatusBarTexture(group.texture) |
frame.bg:SetStatusBarColor(0.0, 0.5, 0.5, 0.5) |
-- Start it up |
frame:SetStatusBarTexture(group.texture) |
frame:SetStatusBarColor(frame.r, frame.g, frame.b) |
frame:SetStatusBarColor(r, g, b) |
frame:SetWidth(group.width) |
frame:SetHeight(group.height) |
frame:SetScale(group.scale) |
frame:SetScript("OnUpdate", barOnUpdate) |
--[[frame.button:SetScript("OnClick", function(self, button) |
frame.button:SetScript("OnClick", function(self, button) |
if (button == "RightButton") then |
-- delete bar |
GTB.UnregisterBar(group, id) |
end |
end)]] |
end) |
-- Reposition this group |
repositionFrames(group) |