Mercurial > wow > turok
view Turok/Modules/Timer/Cooldown.lua @ 9:9400a0ff8540
Ugh
Timer:
- container update directionality
- talent update iterates over a non-volatile table to carry out updates
- index management steps organized
- talentRow status implemented, returns the spell associated with the talent chosen from that row
CombatLog:
- sort out font controls and unbork arguments
author | Nenue |
---|---|
date | Sun, 21 Feb 2016 13:08:30 -0500 |
parents | a9b8b0866ece |
children |
line wrap: on
line source
--- ${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(...) if _G.Devian and _G.DevianDB.workspace ~= 1 then _G.print('Cooldown', ...) end 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 = "%i", subCounterText = "%.p", chargesText = "%s", justifyH = 'CENTER', justifyV = 'TOP', iconText = "%p", leftText = "%p", rightText = "%n / %d", passive = { icon = { desaturated = false, color = {1, 1, 1, 1}, } }, active = { icon = { desaturated = true, color = {1, 1, 1, .6}, } }, --- control displays of aura information in cooldown displays overrideAura = false, overrideDuration = false, override = { 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) self.start = 0 self.duration = 0 self.expires = 0 self.charges = nil self.charges_max = 0 self.charge_start = 0 self.charge_duration = 0 self.charge_expires = 0 self.override = false self.override_start = 0 self.override_duration = 0 self.override_expires = 0 --- 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 = nil, false, 0, 0, nil, nil, nil, 0, 0 local override, overrideStart, overrideDuration = false, 0, 0 --- 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 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) 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 if self.spellName and self.cvars.overrideAura then local name, _, _, _, _, d, e = UnitAura(self.unit , self.spellName, nil, 'HELPFUL') if name then override = true overrideDuration = d overrideStart = e - d end end if self.overrideDuration and start > 0 then override = true overrideDuration = self.overrideDuration overrideStart = start end print('cooldown.Query(',id,')', 'name:'..cText(name), 'usable:'..cBool(usable), 'start:'..cNum(start), 'duration:'..cNum(duration), 'enabled:'..cWord(enabled), 'charges:'.. cNum(charges), 'charge_start:'.. cNum(chargeStart), 'charge_duration:'.. cNum(chargeDuration), 'override:' .. cBool(override), 'override_start'..cNum(overrideStart), 'override_duration:'.. cNum(overrideDuration)) return name, usable, start, duration, enabled, charges, maxCharges, chargeStart, chargeDuration, override, overrideStart, overrideDuration 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.charges_max, self.charge_start, self.charge_duration, self.override, self.override_start, self.override_duration = ... 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 if self.charges then self.charge_expires = self.charge_start + self.charge_duration end if self.override then self.override_expires = self.override_start + self.override_duration 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, maxCharges, chargeStart, chargeDuration, override, overrideStart, overrideDuration = self:Query() -- print(name, usable, start, duration, enabled, charges, maxCharges, chargeStart, chargeDuration, count) if duration ~= self.duration or start ~= self.start or chargeStart ~= self.charge_start or charges ~= self.charges or override ~= self.override 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 if state then self:Set(name, usable, start, duration, enabled, charges, maxCharges, chargeStart, chargeDuration, override, overrideStart, overrideDuration) self.expires = charges and (self.chargeStart + self.chargeDuration) or (self.start + self.duration) self:SetState(state) print(' ',diff) print(' start='..cText(self.start)..' duration='..cText(self.duration)..' charges='.. cText(self.charges).. ' chargeStart='..cText(self.chargeStart).. ' chargeDuration='..cText(self.chargeDuration)) end else if 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 end end p.Stats = function(self, state) print(self.unit, self.spellName) if self.spellName then local auraName, _, _, auraCharges, _, auraDuration, auraExpires = UnitAura(self.unit, self.spellName, nil, 'HELPFUL') print(' # Aura', auraName and 'yes' or 'no', auraName and ('d='..cNum(auraDuration)) or '', auraName and ('e='..auraExpires)) end 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(' # 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 }