Mercurial > wow > turok
diff Turok/Modules/Timer/Cooldown.lua @ 6:a9b8b0866ece
clear out log jam
author | Nenue |
---|---|
date | Sun, 21 Feb 2016 08:32:53 -0500 |
parents | |
children | 9400a0ff8540 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Turok/Modules/Timer/Cooldown.lua Sun Feb 21 08:32:53 2016 -0500 @@ -0,0 +1,345 @@ + +--- ${PACKAGE_NAME} +-- @file-author@ +-- @project-revision@ @project-hash@ +-- @file-revision@ @file-hash@ +-- Created: 12/25/2015 5:33 AM +--- Spell cooldown tracking resides here. +-- +-- Workflow of cooldown tracking: +-- A tracked spell cast is detected. (UNIT_SPELLCAST_*) +-- That spell ID enters the timer table. +-- The table is read by a handler that fires on the next frame, when cooldown information is available. (COOLDOWN_*) +-- Set() is called on the corresponding timer frame, and frame script takes over. +-- Timer table spells are polled on each COOLDOWN_* event, re-applying Set() when certain conditions are met. +-- The framescript or certain handlers will remove the timer table entry when there are no more positive conditions. +-- +local tostring, tonumber, tinsert = tostring, tonumber, tinsert +local GetTime, GetSpellInfo, GetInventoryItemCooldown, GetSpellCooldown, PlaySoundFile = GetTime, GetSpellInfo, GetInventoryItemCooldown, GetSpellCooldown, PlaySoundFile +local GetSpellCharges, GetSpellCount, GetInventoryItemCount, UnitAura = GetSpellCharges, GetSpellCount, GetInventoryItemCount, UnitAura +local IsUsableItem, IsUsableSpell, GetItemSpell = IsUsableItem, IsUsableSpell, GetItemSpell +local xpcall = xpcall + +local CD_SLOT, CD_ITEM, CD_SPELL = 1, 2, 3 +local HIDDEN, PASSIVE, ACTIVE = 0, 1, 2 +local format, ceil = string.format, math.ceil +local strrep, gsub, pairs = string.rep, string.gsub, pairs +local mod = Turok.modules.TimerControl +local T = Turok +local db +local FADE_TIME = 0.2 +--@debug@ +local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool +local print = function(...) print('Cooldown', ...) end +local function GetPrint (trace) + return trace and print or function() end +end + + +local item_spells = { + ['PvP Trinket'] = 42292, + ['Burning Mirror'] = 184270, +} + +T.defaults.spirit.cooldown = { + + alpha = 1, + alpha_ooc = 0.2, + inverse = false, + persist = false, + desaturated = false, + fill_inverse = true, + size = 24, + counterText = "%p", + subCounterText = "%.p", + chargesText = "%s", + justifyH = 'CENTER', + justifyV = 'TOP', + + iconText = "%p", + leftText = "%p", + rightText = "%n / %d", + passive = { + icon = { + desaturated = false, + color = {1, 1, 1, 1}, + blend = 'BLEND' + } + }, + active = { + icon = { + desaturated = false, + color = {1, 1, 1, .6}, + blend = 'ADD' + } + }, + + --- control displays of aura information in cooldown displays + showAura = false, + cooldownAura = { + icon = { + desaturated = true, + color = {0,1,0,1}, + } + } +} + +local p = mod.prototype.trigger.cooldown +--@end-debug@ +p.class = 'trigger' +p.type = 'cooldown' +p.cvars = { +} +--- Sets initial values before dry Event is fired to check for presence +p.Init = function(self, spellID, caster, tristate, minValue, maxValue) + local print = GetPrint(self.trace) + + self.spellID = spellID and spellID or self.spellID + self.unit = caster and caster or self.unit + self.persist = tristate and tristate or self.persist + self.minValue = minValue and minValue or tonumber(self.minValue) + self.maxValue = maxValue and maxValue or tonumber(self.maxValue) + + --- current and last state values need to be flipped for inverted conditional + --- last state is defined in case it needs to be overridden to ensure proper frame update + print(cWord('Load:'),cNum(self.spellID or self.inventoryID or self.itemID), cText(self.spellName or GetItemSpell('player', self.inventoryID or self.itemID)) ) + print(cWord(' inverse=')..cBool(self.cvars.inverse)) + if self.cvars.inverse then + self.flags = { + active = HIDDEN, + active_prev = ACTIVE, + passive = PASSIVE, + passive_prev = PASSIVE, + hidden = PASSIVE, + hidden_prev = HIDDEN, + } + else + self.flags = { + active = ACTIVE, + active_prev = HIDDEN, + passive = PASSIVE, + passive_prev = HIDDEN, + hidden = HIDDEN, + hidden_prev = PASSIVE + } + end + if not (self.spellID or self.spellName) then + self.debug_info('No valid spell ID or Name') + end +end + +local GetItemCooldown, GetItemInfo = GetItemCooldown, GetItemInfo +p.Query = function(self) + local print = GetPrint(self.trace) + local id = self.inventoryID or self.itemID or self.spellID + local name, usable, start, duration, enabled, charges, maxCharges, chargeStart, chargeDuration, count + + --- checked in order of precedence + if self.inventoryID then + print(cText(' type'), cWord('inventory slot'), cNum(id)) + self.cooldownType = CD_SLOT + start, duration, enabled = GetInventoryItemCooldown('player', id) + charges, maxCharges, chargeStart, chargeDuration = nil, nil, nil, nil + count = GetInventoryItemCount('player', id) + usable = name and true or false + elseif self.itemID then + self.cooldownType = CD_ITEM + + start, duration, enabled = GetItemCooldown(self.itemID) + print(GetItemCooldown(self.itemID)) + print(GetItemInfo(id)) + + elseif self.spellID then + self.cooldownType = CD_SPELL + name = GetSpellInfo(self.spellID) + start, duration, enabled = GetSpellCooldown(self.spellID) + charges, maxCharges, chargeStart, chargeDuration = GetSpellCharges(self.spellID) + count = GetSpellCount(self.spellID) + usable = true -- they still exist even when dead + else + self.unit = 'notaunit' + T:Print('Timer \''..tostring(self.timerName)..'\' doesn\'t have a valid status ID.') + end + + -- may not have been stored for some reason + if charges and not self.maxCharges then + self.maxCharges = maxCharges + end + + print('cooldown.Query(',id,')', name, usable, start, duration, enabled, charges, maxCharges, chargeStart, chargeDuration) + return name, usable, start, duration, enabled, charges, chargeStart, chargeDuration, count +end + +p.Set = function(self, ...) + local print = GetPrint(self.trace) + + --name, usable, start, duration, enabled, charges, maxCharges, chargeStart, chargeDuration, count + local name + name, self.usable, self.start, self.duration, self.enabled, self.charges, self.chargeStart, self.chargeDuration, self.count = ... + if name then + self.spellName = name + end + + if self.duration and self.start then + self.expires = self.start + self.duration + else + self.expires = 0 + end +end + +p.Value = function(self) + return (self.charges and self.charges < self.maxCharges) and ((GetTime() - self.chargeStart) / self.chargeDuration) or ((GetTime() - self.start) / self.duration) +end + +p.SetText = mod.SetText + +--- Assign where meaning won't be amibiguous +local Cooldown_OnCast = function(self) + self.triggerState = true +end + +local Cooldown_OnUpdate = function(self, event) + local print = GetPrint(self.trace) + + if self.triggerState then + print(cWord('Event'), cText(self.timerName)) + if not event then + print(' *', cWord('Poke')) + end + local diff = 'start='..cText(self.start)..' duration='..cText(self.duration)..' charges='.. + cText(self.charges).. ' chargeStart='..cText(self.chargeStart).. ' chargeDuration='..cText(self.chargeDuration) + local name, usable, start, duration, enabled, charges, chargeStart, chargeDuration, count = self:Query() + + -- If we want and can, pull aura data and use that in place of cooldown information + local expires, hasAura, _ + if self.cvars.showAura then + print(cText('UnitAura'), self.unit, self.spellName, nil, 'HELPFUL') + local name, _, _, count, _, auraDuration, auraExpires = UnitAura(self.unit , self.spellName, nil, 'HELPFUL') + if name and (auraDuration ~= self.auraDuration or auraExpires ~= self.auraExpires) then + + print(cText('aura check ='), cBool(name), 's='..cNum(count), 'd='..cNum(auraDuration), 'e='..cNum(auraExpires)) + start = auraExpires - auraDuration + duration = auraDuration + expires = auraExpires + end + end + + -- print(name, usable, start, duration, enabled, charges, maxCharges, chargeStart, chargeDuration, count) + if duration ~= self.duration or + start ~= self.start or + chargeStart ~= self.chargeStart + or charges ~= self.charges then + print('a variable has changed') + local state + + + if duration == 0 and charges == self.maxCharges then + print(cText(' cooldown has reset, drop it from the queue')) + state = self.cvars.persist and self.flags.passive or self.flags.hidden + self.triggerState = nil + print(' ', cText('dropping'), cWord(self.timerName), cText('from spell tracking')) + + + self:Stats(state) + else + if duration ~= 0 then + print(cText(' cooldown has a hard duration')) + if duration > T.GCD and self.displayState ~= self.flags.active then + print(cText(' and its > GCD, update it')) + state = self.flags.active + end + end + + if charges then + print(cText(' cooldown has charges')) + if charges ~= self.charges or chargeStart ~= self.chargeStart then + print(cText(' charges count or starting time has changed')) + state = self.flags.active + end + end + + self:Stats(state) + end + + + -- form ID, id type, displayState, prevState + --T:Dispatch('TK_COOLDOWN_UPDATE', self.spellID, self.cooldownType, state, self.displayState) + if state then + self:Set(name, usable, start, duration, enabled, charges, chargeStart, chargeDuration, count) + self.expires = charges and (self.chargeStart + self.chargeDuration) or (self.start + self.duration) + self:SetState(state) + --print(' ', cText('SetState'), cNum(self.displayState), 'from', cNum(self.prevState), cWord(self.timerName)) + print(' ',diff) + print(' start='..cText(self.start)..' duration='..cText(self.duration)..' charges='.. + cText(self.charges).. ' chargeStart='..cText(self.chargeStart).. ' chargeDuration='..cText(self.chargeDuration)) + end + elseif self.cooldownType == CD_SPELL then + if duration == 0 and charges == self.maxCharges and self.displayState == HIDDEN then + print(cKey(self.timerName), cText('post-framescript clean-up')) + self.triggerState = nil + end + end + end + --self:DumpMessages() + +end + +p.Stats = function(self, state) + print(self.unit, self.spellName) + local auraName, _, _, auraCharges, _, auraDuration, auraExpires = UnitAura(self.unit, self.spellName, nil, 'HELPFUL') + local name, usable, start, duration, enabled, charges, maxCharges, chargeStart, chargeDuration, count = self:Query() + print('# GCD =', T.GCD) + print('# SpellCooldown', 's =', start, 'd =', duration, 's =', charges and (charges..'/'..maxCharges) or 'NA') + print('# Aura', auraName and 'yes' or 'no', auraName and ('d='..cNum(auraDuration)) or '', auraName and ('e='..auraExpires)) + print('# Frame', 'state1 =', self.displayState, 'state2 =', self.previousState, state and ('change to '..cWord(state)) or '') + + +end + +--- Event pointers +p.events = { + ['UNIT_SPELLCAST_SUCCEEDED'] = Cooldown_OnCast, + ['UNIT_SPELLCAST_CHANNEL_START'] = Cooldown_OnCast, + ['BAG_UPDATE_COOLDOWN'] = Cooldown_OnUpdate, + ['SPELL_UPDATE_COOLDOWN'] = Cooldown_OnUpdate, + ['SPELL_UPDATE_USABLE'] = Cooldown_OnUpdate, + ['SPELL_UPDATE_CHARGES'] = Cooldown_OnUpdate, +} + +local unpack, select, debugstack = unpack, select, debugstack +p.Event = function(self, e, ...) + local print = GetPrint(self.trace) + + self.event = e + --- dry event case + if not e then + print('onEvent', self.timerName, e) + self.triggerState = true + Cooldown_OnUpdate(self, e, ...) + else + local unit = select(1,...) + if self.unit and unit ~= self.unit and e ~= 'SPELL_UPDATE_COOLDOWN' then + return + end + local args = {...} + local success, d = xpcall(function() self.events[e](self, e, unpack(args)) end, function(m) print(self.name .."\n".. m .. "\n".. debugstack(3)) end) + + end +end + +p.triggerList = { + ['on_cooldown'] = function(self) + local start, duration, enabled = GetSpellCooldown(self.spellID) + local charges, _, cStart, cDuration = GetSpellCharges(self.spellID) + return (enabled and (duration ~= 0 or start ~= 0 or charges ~= self.maxCharges)), start, duration, enabled, charges, cStart, cDuration + end, + ['not_on_cooldown'] = function(self) + local start, duration, enabled = GetSpellCooldown(self.spellID) + local charges, _, cStart, cDuration = GetSpellCharges(self.spellID) + return (duration == 0 and start == 0 and charges == self.maxCharges), start, duration, enabled, charges, cStart, cDuration + end, + ['buff_active'] = function(self) + local name, rank, icon, count, dispelType, duration, expires, caster, isStealable, shouldConsolidate, spellID, canApplyAura, isBossDebuff, value1, value2, value3 = UnitAura(self.unit, self.spellName, self.filters) + return (name and true or false), expires - duration, duration, true, count, 0, 0 + end +} \ No newline at end of file