# HG changeset patch
# User Nenue
# Date 1456061573 18000
# Node ID a9b8b0866ece1d6599d325fa0edeca3a16c721fd
# Parent 8a9a6637f082072ed720509197ca99b2ca988013
clear out log jam
diff -r 8a9a6637f082 -r a9b8b0866ece .pkgmeta
--- a/.pkgmeta Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-externals:
- Libs/LibStub:
- url: svn://svn.wowace.com/wow/libstub/mainline/trunk
- tag: latest
- Libs/CallbackHandler-1.0:
- url: svn://svn.wowace.com/wow/callbackhandler/mainline/trunk/CallbackHandler-1.0
- tag: latest
- Libs/AceAddon-3.0:
- url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0
- tag: latest
-
-
-ignore:
- - Debug.lua
- - Turok.iml
- - .idea
-
-enable-nolib-creation: no
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Equip.lua
--- a/Equip.lua Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
--- User: Krakyn
--- Created: 12/4/2015 11:20 PM
--- Equipment, spec, etc.
-local T = LibStub("AceAddon-3.0"):GetAddon("Turok")
-local mod = T:NewModule("Equip", "AceEvent-3.0")
---setprinthandler(function (...) T:debug('Equip', nil, ...) end)
-
-local t18_slots = {
- [INVSLOT_HEAD] = 124296, -- head
- [INVSLOT_SHOULDER] = 124307, -- shoulders
- [INVSLOT_CHEST] = 124284, -- chest
- [INVSLOT_LEGS] = 124301, -- legs
- [INVSLOT_HAND] = 124292, -- hands
-}
-
-
-local use_slots = {
- [INVSLOT_FINGER1] = 1,
- [INVSLOT_FINGER2] = 2,
- [INVSLOT_TRINKET1] = 3,
- [INVSLOT_TRINKET2] = 4,
-
-}
-function mod:OnEnable()
- self.equipped = {}
- self:RegisterEvent('COMBAT_RATING_UPDATE', 'UpdateCombatRatings')
- self:RegisterEvent('PLAYER_EQUIPMENT_CHANGED', 'UpdateEquipment')
- self:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED', 'UpdateSpec')
-end
-
-function mod:UpdateEquipment (_, slot, hasItem)
- -- ratings event will handle the rest
- if not t18_slots[slot] or use_slots[slot] then
- return
- end
- -- debug
- local link = GetInventoryItemID('player', slot)
- print('|cFF00FFFFequipment ', slot, hasItem, link)
- -- /debug
-
- if t18_slots[slot] then
- t18_count = 0
- for slot, itemID in pairs(t18_slots) do
- if GetInventoryItemID(slot) == itemID then
- t18_count = t18_count + 1
- end
- end
- if t18 >= 4 then
- T.stats.aimedshot = s.gcd
- else
- T.stats.aimedshot = 2 * T.stats.castingmod
- end
- T.statstext =string.format('%.2f', s.aimedshot)
- end
-
- if use_slots[slot] then
- if hasItem then
- local itemID = GetInventoryItemID('player', slot)
- self.equipped[slot] = itemID
- T:GetModule("Spirit").item_watch[itemID] = {GetInventoryItemCooldown('player', slot) }
- else
- if self.equipped[slot] then
- self.equipped[slot] = nil
- end
-
- end
- end
-
-end
-
-
-function mod:UpdateCombatRatings()
- local s = T.stats
- s.haste = UnitSpellHaste('player')
- s.focusregen = 4 * (1 + s.haste/100)
- s.castingmod = 1+ s.haste/1000
- s.gcd = 1.5 * s.castingmod
- T.statstext = {
- haste = string.format('%.2f', s.haste),
- focusregen = string.format('%.2f', s.focusregen),
- castingmod = string.format('%.2f', s.castingmod),
- }
- local t = T.statstext
-
- print('|cFF00FFFFCOMBAT_RATING_UPDATE:|r', 'haste:', t.haste, 'regen:', t.focusregen)
-end
-
-function mod:UpdateSpec (e, unit)
- if unit ~= 'player' then
- return
- end
-
- T.stats.focusmax = UnitPowerMax('player')
-end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Fog.lua
--- a/Fog.lua Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,325 +0,0 @@
--- User: Krakyn
--- Created: 12/4/2015 11:13 PM
---[[
--- Core tools, mostly frame handling business. It's an interface script after all.
--- Types:
--- StatusFrame
--- Primary container for status data, carries primary value information by default
--- FIELDS
--- value = exact primary value represented by frame
--- min = exact minimum for primary value
--- max = exact maximum for primary value
--- percent = value / max
--- alpha = base frame alpha level, set when a fade animation has completed
--- fadeTo = when set, the frame will begin fading to this level
--- fadeDuration = set with fadeTo when the transition needs to be time-adjusted for unpredictable alpha states
--- fadeTime = set with fadeTo when the transition has an explicit desired timing
--- throttle_rate = animation frame delay
---
--- METHODS
--- Update() = Runs the frame's Update script, and calls UpdateText()
--- UpdateText() = Iterates over frame children and calls Update() if it is a StatusText frame
---
--- StatusText
--- Sub-container for individual text elements, carries string output values, controlled by from Update(). By default
--- these are derived from the parent's primary value data, but is mostly overridden in module code.
--- FIELDS
--- text = WoW FontString object housing text data
--- format = a format string for expressing complex data (timer bars, etc.)
--- METHODS
--- SetText() = shortcut for text:SetText(...)
--- SetJustifyH() = shortcut for text:SetJustifyH(...)
--- Implements:
--- frame = CreateBar(name, config root)
--- Creates and displays a generic bar frame with progress textures and default updater, based on the variables from
--- the smart config table. Seeded with methods Update() and UpdateText().
--- Update() will refresh the entire frame and tail call UpdateText()
--- UpdateText() will iterate over the contents of frame:GetChildren() and call Update()
--- NEVER CREATE A CHILD FRAME WITHOUT Update() DEFINED
--- NEVER INVOKE METHODS FROM A GetParent() RETURN
---
--- Bar_SetUpdateHandler(frame, function)
--- Takes the desired OnUpdate script and wraps it inside frame throttling logic, then does SetScript
---
--- frame = AddLabel(frame, config root, name)
--- Constructs a text display and adds it to the frame's list of internal text objects. Contains method Update(), which
--- refreshed text.
---
--- HANDLERS
--- Bar_Update([value, min/duration, max/end])
--- Default handler for any non-timed bar (where isTimer = false in config vars. Invoked by frame:Update()
-]]
-local T = LibStub("AceAddon-3.0"):GetAddon("Turok")
-local LSM = LibStub("LibSharedMedia-3.0")
-local TL = 'Fog'
-local print = function(...)
- _G.print(TL, ...)
-end
---setprinthandler(function (...) T:debug('Fog', nil, ...) end)
-local FADE_OUT_TIME = 1 -- duration per 1-0 alpha transition
-local FADE_IN_TIME = 0.4 -- duration per 0-1 alpha transition
-
-local inset_factor = {
- ['TOPLEFT'] = {-1, 1},
- ['TOP'] = {0, 1},
- ['TOPRIGHT'] = {1, 1},
- ['RIGHT'] = {1, 0},
- ['BOTTOMRIGHT'] = {1, -1},
- ['BOTTOM'] = {0, -1},
- ['BOTTOMLEFT'] = {-1,-1},
- ['LEFT'] = {-1, 0}
-}
-
-T.anchor_inverse = { ['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['UP'] = 'DOWN', ['DOWN'] = 'UP' } -- directional inverse
-T.direction_coord = { ['LEFT'] = {1, 0}, ['RIGHT'] = {-1,0}, ['UP'] = {0, -1}, ['DOWN'] = {0, 1 } } -- directional derivatives
-T.anchor_direction = { ['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['UP'] = 'BOTTOM', ['DOWN'] = 'TOP'} -- directional anchors
-
-function T:CreateBar(name, config)
- local parent = type(config.parent) == 'string' and _G[config.parent] or parent
- if not parent then
- parent = CreateFrame('Frame', config.parent, UIParent)
- print('creating dry frame |cFFDDDDDD' .. config.parent .. '|r for |cFFFFFF00' .. name .. '|r')
- end
-
- local f
- if _G[name] and _G[name].GetFrameType and _G[name].GetFrameType() == 'Frame' then
- f = _G[name]
- print('found existing table |cFFFFFF00' .. name .. '|r')
- else
- print('creating statusbar '.. name, config.anchor, parent:GetName(), config.anchorTo, config.posX, config.posY)
- end
-
-
- f = CreateFrame('Frame', name, UIParent)
- f.db = config
-
- -- state vars
- f.combat = InCombatLockdown()
- f.min = 0
- f.max = 1
- f.value = 0
- f.percent = 0
- f.alpha = f.combat and config.alpha or config.alpha_ooc
- f:SetAlpha(f.combat and config.alpha or config.alpha_ooc)
- f:SetPoint(config.anchor, config.parent, config.anchorTo, config.posX, config.posY)
- f:SetSize(config.width, config.height)
- f:SetFrameStrata(config.strata)
- self:CreateStatusTextures(f, config)
-
- f.throttle_rate = 0.0166666666 -- ~60fps
- f.throttle_point = GetTime()
-
- -- default handler
- f.Update = T.Bar_Update
- f.UpdateText = T.Bar_UpdateText
- T:Bar_SetUpdateHandler(f, T.Bar_Update)
-
- return f
-end
-
-function T:CreateStatusTextures(region, c)
- c = c and c or region.db
- print('STATUSTEX_make', region:GetName(), c.background_texture, c.background_color, c.foreground_texture, c.foreground_color)
- region.background = region:CreateTexture('background', 'BACKGROUND')
- region.background:SetAllPoints(region)
- if c.background_texture then
- region.background:SetTexture(LSM:Fetch('statusbar', c.background_texture))
- region.background:SetVertexColor(unpack(c.background_color))
- else
- region.background:SetTexture(unpack(c.background_color))
- end
- region.background:SetBlendMode(c.background_blend)
-
- region.foreground = region:CreateTexture('foreground', 'ARTWORK')
- region.foreground:SetPoint('TOPLEFT', region, 'TOPLEFT', 0-c.foreground_inset, c.foreground_inset)
- region.foreground:SetPoint('BOTTOMRIGHT', region, 'BOTTOMRIGHT', c.foreground_inset, 0-c.foreground_inset)
- if c.foreground_texture then
- region.foreground:SetTexture(LSM:Fetch('statusbar', c.foreground_texture))
- region.foreground:SetVertexColor(unpack(c.foreground_color))
- else
- region.foreground:SetTexture(unpack(c.foreground_color))
- end
- region.foreground:SetBlendMode(c.foreground_blend)
-end
-
-function T:CreateStatusIcon(region, c)
- local file = type(c) == 'string' and c or region.icon
- if type(c) ~= 'table' then
- c = region.db
- end
- print('STATUSICON', region:GetName(), file, c.icon_show)
-
-end
-
--- Sets the OnUpdate handler within a timing scheme
-function T:Bar_SetUpdateHandler(bar, func)
- bar:SetScript('OnUpdate', function(bar)
- if GetTime() < bar.throttle_point then
- return
- end
-
- bar.throttle_point = bar.throttle_point + bar.throttle_rate
- if type(func) == 'string' then
- if type(bar[func]) ~= 'function' then
- error('TurokBar:SetUpdateScript(); string "' ..func.. '" is not a valid method name')
- return
- end
- elseif type(func) ~= 'function' then
- error('TurokBar:SetUpdateScript(function or string); got '.. type(func) .. 'instead')
- return
- end
-
- func(bar)
- end)
-end
-
--- Default update loop
-function T:Bar_Update (value, min, max)
-
- if value ~= nil then -- could be 0
- self.value = value
- end
- if (min ~= nil and max ~= nil) then
- if self.isTimer then
- self.duration = min
- self.endTime = max
- else
- self.min = min
- self.max = max
- self.duration = max
- end
- end
-
- if self.combat ~= InCombatLockdown() then
- self.combat = InCombatLockdown()
- if self.combat then
- self.fadeTo = self.db.alpha
- self.fadeDuration = FADE_IN_TIME
- else
- self.fadeTo = self.db.alpha_ooc
- self.fadeDuration = FADE_OUT_TIME
- end
- end
-
- -- we need the time for something
- if self.isTimer or self.fadeTo ~= nil then
- local time = GetTime()
-
- -- start doing fade animation things
- if self.fadeTo ~= nil then
-
- if not self.fadeFrom then
- self.fadeFrom = self:GetAlpha()
- end
-
- -- fadeDuration missing, fill it in
- if not self.fadeDuration then
- self.fadeDuration = self.fadeFrom > self.fadeTo and FADE_OUT_TIME or FADE_IN_TIME
- end
-
- -- fadeTime missing,
- if not self.fadeTime then
- local fadeRatio = 1
- if self.fadeFrom ~= self.alpha then
- fadeRatio = (self.fadeTo - self.fadeFrom) / (self.fadeTo - self.alpha) -- target delta
- end
- --print(fadeRatio, self.fadeDuration)
- self.fadeTime = time + fadeRatio * self.fadeDuration -- fixed rate of change
- end
-
- -- are we done?
- if time >= self.fadeTime then
- self:SetAlpha(self.fadeTo)
- self.alpha = self.fadeTo
- self.fadeTo = nil
- self.fadeFrom = nil
- self.fadeDuration = nil
- self.fadeTime = nil
- else --nope
- local remaining = (self.fadeTime - time) / self.fadeDuration
- local fadeTotal = (self.fadeTo - self.fadeFrom)
- --print(self.fadeTo - (fadeTotal * remaining), fadeTotal * remaining)
- self:SetAlpha(self.fadeTo - (fadeTotal * remaining))
- end
- end
-
- -- termination check
- if self.isTimer then
- if time >= self.endTime and self.fadeTo == nil then
- self:Hide()
- return
- else
- self.percent = (self.endTime - time) / self.duration
- end
- end
-
- else
- self.percent = (self.value - self.min) / (self.max - self.min)
- end
-
- self:UpdateText()
- self.foreground:SetPoint('BOTTOMRIGHT', self, 'BOTTOMLEFT', self.db.width * self.percent + self.db.foreground_inset, 0-self.db.foreground_inset)
-end
-
-function T:Bar_UpdateText()
- local c = {self:GetChildren()}
- for _, rl in ipairs(c) do
- if rl.text then
- rl.format = self.db.label_string
- rl:Update()
- end
- end
-end
-
--- addon:AddLabel
--- Constructs a text display and adds it to that region
---
-function T:AddLabel (region, config, labelname)
- assert(region:IsObjectType('Frame'), "T:CreateLabel(table, table [, string])")
- labelname = (labelname or string.format('%x', GetTime() % 1000000))
- print('assigning frame for text object |cFFFF9922'..labelname..'|r to '..region:GetName())
-
- local lf = CreateFrame('Frame', region:GetName()..'_'..labelname, region)
- local ft = lf:CreateFontString(labelname, 'OVERLAY')
- local lx, ly, lp = 0,0, config.label_point
- if config.label_inset ~= 0 and lp ~= 'CENTER' then
- lx = config.label_inset * inset_factor[lp][1]
- ly = config.label_inset * inset_factor[lp][2]
- end
-
- lf:SetPoint(lp, region, lp, lx, ly)
- lf:SetSize(region:GetWidth(), region:GetHeight())
- lf:SetFrameStrata(config.label_strata)
-
- ft:SetFont(LSM:Fetch('font', config.label_font), config.label_size, config.label_outline)
- ft:SetAllPoints(lf)
- ft:SetJustifyH(config.label_justifyH or (config.label_point:find('LEFT') and 'LEFT' or (config.label_point:find('RIGHT') and 'RIGHT' or 'CENTER')))
- ft:SetJustifyV(config.label_justifyV or (config.label_point:find('TOP') and 'TOP' or (config.label_point:find('BOTTOM') and 'BOTTOM' or 'MIDDLE')))
- ft:SetTextColor(1, 1, 1)
- ft:SetText('SET ME!')
-
- lf.Update = region.isTimer and T.Label_UpdateFormat or T.Label_Update
- lf.SetJustifyH = function(self, justify) ft:SetJustifyH(justify) end
- lf.SetText = function(self, text) ft:SetText(text) end
-
- lf.text = ft
- region[labelname] = lf
- return lf
-end
-
--- one of two possible assignments for label:Update()
-function T:Label_UpdateFormat()
- local region = self:GetParent()
- if self.format then
- self.value = string.gsub(self.format, '%%p', string.format('%.1f', region.value))
- self.value = string.gsub(self.value, '%%d', region.duration)
- if region.name then
- self.value = string.gsub(self.value, '%%n', region.name)
- end
- end
- self.text:SetText(self.value)
-end
-function T:Label_Update()
- self.text:SetText(self:GetParent().value)
-end
-
diff -r 8a9a6637f082 -r a9b8b0866ece Lost.lua
--- a/Lost.lua Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
--- User: Krakyn
--- Created: 12/14/2015 3:03 PM
-local T = LibStub("AceAddon-3.0"):GetAddon("Turok")
-local TL = 'Lost'
-local print = function(...) _G.print(TL, ...) end
-local LSM = LibStub("LibSharedMedia-3.0")
-local mod = T:NewModule(TL, "AceTimer-3.0")
-local time = _G.ct
-local spell_trunc = {}
-local inv = T.anchor_inverse
-local d = T.direction_coord
-local a = T.anchor_direction
-
-mod.encounter_start = {
- ['Aspect'] = {
- type = 'buff',
-
- Test = function()
- local res = UnitBuff('player', 'Aspect of the Pack', nil, 'PLAYER')
- return (res ~= nil)
- end,
- sound = LSM:Fetch('sound', 'Wilhelm Scream'),
- },
- ['Rune'] = {
- Test = function()
- local res = UnitBuff('player', 'Hyper Augmentation', nil, 'PLAYER')
- return (res ~= nil)
- end
- }
-}
-
-function mod:OnEnable()
- self.raidbuffs_active = {} -- active raid buffs
- self.raidbuffs_text = {} -- raid buff text
- self.raidbuffs_avail = {} -- availability info
- self.raidbuffs_display = {} -- buff list ordering info
- self.unit_cache = {} -- remember GUIDs we've seen before
- self.raidbuffs_shown = NUM_LE_RAID_BUFF_TYPES
-
-
- local db = _G.TurokData
- db.raidbuff = {
- parent = 'UIParent',
- anchor = 'BOTTOMRIGHT', anchorTo = 'BOTTOMRIGHT',
- posX = -300, posY = 300,
- height = 24*9, width = 72,
- raidbuff_width = 72,
- raidbuff_height = 24,
- label_size = 11,
- label_font = 'ArchivoNarrow-Bold',
- }
-
-
-
- local rw = CreateFrame('Frame', 'TkRaidWatch', UIParent)
- local c = db.raidbuff
- self.raidbuffs_frame = rw
- rw:SetPoint(c.anchor, c.parent, c.anchorTo, c.posX, c.posY)
- rw:SetSize(c.width, c.height)
- rw:SetMovable(true)
- local bd = rw:CreateTexture()
- bd:SetTexture(1,1,1,1)
- bd:SetGradient('VERTICAL', 0,0,0,1,1,1)
- bd:SetBlendMode('MOD')
- bd:SetPoint('TOPLEFT',rw,'TOPLEFT', -2, 2)
- bd:SetPoint('BOTTOMRIGHT',rw,'BOTTOMRIGHT', 2, -2)
-
- -- seed raid buff analyzer assets
- self.num_raidbuff_columns = math.floor(c.width / c.raidbuff_width)
- for i = 1, 9 do
- local icon = rw:CreateTexture('TkRaidWatchButton'..i, 'ARTWORK')
- icon:SetSize(c.raidbuff_width,c.raidbuff_height)
- icon:SetTexCoord(0.15, 0.85, 0.15, 0.85)
-
-
- self.raidbuffs_active[i] = icon
- rw:EnableMouse(true)
- rw:SetScript('OnMouseDown', function(self) self:StartMoving() end)
- rw:SetScript('OnMouseUp', function(self) self:StopMovingOrSizing() end)
-
- local text = rw:CreateFontString('TkRaidWatchText'.. i, 'OVERLAY')
- text:SetPoint('CENTER', icon, 'CENTER')
- text:SetFont(LSM:Fetch('font', c.label_font), c.label_size, 'OUTLINE')
- text:SetText(i)
- self.raidbuffs_text[i] = text
- end
-
- db.raidevent = {}
-
-
- self:RegisterEvent('PARTY_MEMBERS_CHANGED')
- self:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
- self:RegisterEvent('ENCOUNTER_START')
- self:RegisterEvent('INSPECT_READY')
- self:RegisterEvent('UNIT_AURA', 'RaidBuffScan')
-
- self:RaidBuffScan()
- self:RosterScan()
-end
-function mod:PLAYER_REGEN_ENABLED(e,...) end
-function mod:PLAYER_REGEN_DISABLED(e, ...) end
-
-function mod:INSPECT_READY()
-end
-function mod:PLAYER_SPECIALIZATION_CHANGED(e,unit)
- local specID
- print(e, unit)
- if unit == 'player' then
- specID = GetSpecializationInfo(GetSpecialization())
- else
- --NotifyInspect(unit)
- specID = GetInspectSpecialization()
- end
-
- print(GetSpecializationInfoByID(specID))
- self:RosterScan()
-end
-
-function mod:PARTY_MEMBERS_CHANGED(e, ...)
- if IsInRaid() or IsInGroup() then
- self.raidbuffs_frame:Show()
- self:RaidBuffScan()
- end
-end
-
-function mod:ENCOUNTER_START(e,...)
- for k, v in pairs(self.encounter_start) do
- local test, info = v.Test()
- if test == true then
- print(v.type, k, 'doing a thing')
- else
- print(v.type, k, info)
- end
- end
-end
-
--- Updates available raid/party buffs
-function mod:RaidBuffScan(unit)
- if self.hiding then
- return
- end
- local c = T.db.raidbuff
-
- -- search for unit data
- -- update raidbuffs
-
- -- set our number of things to track
-
- local k = 1
- for i = 1, NUM_LE_RAID_BUFF_TYPES do
- local rb = self.raidbuffs_active[i]
- local rt = self.raidbuffs_text[i]
- local name, rank, texture, duration, expiration, spellId, slot = GetRaidBuffTrayAuraInfo(i)
- if name then
- rb:Hide()
- rt:Hide()
- self.raidbuffs_display[i] = nil
- else
- rb:Show()
- rt:Show()
- if self.raidbuffs_avail[i] then
- rb:SetTexture(0.5,0.5,0.5,0.1)
- rb:SetBlendMode('MOD')
- else
- rb:SetTexture(1,0.2,0,0.5)
- rb:SetBlendMode('ADD')
- end
- self.raidbuffs_text[i]:SetText(string.sub(_G['RAID_BUFF_'..i],0,2))
-
- if not self.raidbuffs_display[i] or self.raidbuffs_display[i] ~= k then
- self.raidbuffs_display[i] = k
- local pn = k-1 -- need (n-1) for lua grid math
- local py = math.floor(pn / self.num_raidbuff_columns) * c.raidbuff_height
- local px = (pn * c.raidbuff_width) % c.width -- x-offset
- print('buff slot '..i..' (draw slot '..k..')', pn, py, px)
- rb:SetPoint('BOTTOMLEFT', TkRaidWatch, 'BOTTOMLEFT', px, py)
- end
-
- k = k + 1
- end
- end
-end
-
-function mod:RosterScan()
- local lim = 1
- if IsInRaid() then
- lim = 40
- elseif IsInGroup() then
- lim = 5
- end
-
- for i = 1, lim do
- local name, rank, subgroup, level, class, fileName, zone, online, isDead, role, isML = GetRaidRosterInfo(i)
- local realm
- if name then
- if string.find(name,'-') then
- name, realm = string.match(name, "(.+)-(.+)")
- else
- realm = GetRealmName()
- end
-
- local GUID = UnitGUID('raid' .. i)
- if not self.unit_cache[GUID] then
- self.unit_cache[GUID] = {
- name = name,
- realm = realm,
- }
- end
-
- pl = self.unit_cache[GUID]
-
-
- print(i, name, class, role)
- end
-
- end
-
-end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Spirit.lua
--- a/Spirit.lua Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
--- User: Krakyn
--- Created: 12/8/2015 7:30 PM
-local T = LibStub("AceAddon-3.0"):GetAddon("Turok")
-local TL = 'Spirit'
-local print = function(...) _G.print(TL, ...) end
-local LSM = LibStub("LibSharedMedia-3.0")
-local mod = T:NewModule("Spirit", "AceTimer-3.0")
-local time = _G.ct
-local auras = {
- 168811, -- sniper training
- 168809, -- sniper training: recently moved
- 13159, -- aspect of the pack,
- 187615, -- Maalus
-}
-local spells = {
- 3045, -- rapid fire,
- 26297, -- berserking,
- 121818, -- stampede,
-
-}
-local FRAME_PREFIX = 'TkSpirit'
-local FADE_TIME = 0.5
--- local repetitive tasks
-local function FindSpirit(id)
- local db = T.db
- local c = db.spirit
- local isIcon = false
- if db.spirit.progressbar[id] then
- c = db.spirit.progressbar[id]
- elseif db.spirit.icon[id] then
- c = db.spirit.icon[id]
- isIcon = true
- end
- local name, rank, icon, castingTime, minRange, maxRange, spellID = GetSpellInfo(id)
- local s = {
- name = name,
- rank = rank,
- icon = icon,
- castingTime = castingTime,
- minRange = minRange,
- maxRange = maxRange,
- spellID = spellID
- }
-
- return s, c, isIcon
-end
-
-function mod:OnEnable()
- local db = _G.TurokData
- self.aura_watch = {}
- self.cooldown_watch = {}
- self.item_watch = {}
- self.myGUID = UnitGUID('player')
-
-
- db.spirit = {
- foreground_color = {1, 1, 1, 0.7},
- foreground_texture = 'Cilo',
- foreground_blend = 'BLEND',
- foreground_inset = -1,
- background_color = {0, 0, 0, 0.7},
- background_blend = 'BLEND',
- background_texture = 'Cilo',
- icon_show = true,
- width = 250, height = 20,
- anchor = 'CENTER', parent = 'UIParent', anchorTo = 'CENTER',
- posX = 0, posY = -150,
- label_color = {1, 1, 1, 1},
- label_font = 'turok',
- label_size = 14,
- label_inset = -2,
- label_point = 'LEFT',
- label_outline = 'OUTLINE',
- label_string = '%n %p',
- label_strata = 'HIGH',
- expire_sound = LSM:Fetch('sound'),
- strata = 'LOW',
- icon = {
- [13159] = { -- Aspect of the Pack
- posX = 20, posY = 20, width = 140, height = 140,
- },
- [3045] = {
- parent = 13159, anchor = 'RIGHT', anchorTo = 'LEFT',
- posx = 0, posY = 0, width = 64, height = 64,
- }
- },
- progressbar = {
- [168811] = { -- Sniper Training (duration)
- background_color = {0,0,0,0},
- foreground_color = {1,0,0,1},
- anchor = 'BOTTOMLEFT', parent = 'TkFocusBar', anchorTo = 'TOPLEFT',
- posX = 0, posY = 0, height = 16, width = 250,
- label_string = '',
- label_point = 'TOPLEFT',
- strata = 'LOW',
- attach = {{
- width_relative = 0.5,
- height_relative = 1,
- background_color = {1,0,0,1},
- foreground_color = {1,1,0.5, 1},
- background_blend = 'ADD',
- foreground_blend = 'ADD',
-
- anchor = 'LEFT',
- anchorTo = 'LEFT',
- strata = 'MEDIUM',
- }}
- },
- [168809] = { -- Sniper Training: Recently Moved
- background_color = {0,0,0,0 },
- foreground_color = {1,1,1,1},
- foreground_blend = 'ADD',
- anchor = 'BOTTOMLEFT', parent = 'TkFocusBar', anchorTo = 'TOPLEFT',
- strata = 'HIGH',
- posX = 0, posY = 0, height = 16, width = 125,
- icon_show = false,
- label_string = '',
- exceptions = {
- function(aura)
- return (mod.aura_watch[168811].expires < aura.expires)
- end
- },
- },
- },
- }
-
- for _, id in pairs(auras) do
- -- store spellinfo fetch
- self.aura_watch[id] = self:CreateSpiritFrame(id)
- self.aura_watch[id].count = 0
- self.aura_watch[id].duration = 0
- self.aura_watch[id].expires = 0
- self.aura_watch[id].caster = 0
- print('AURA', id, self.aura_watch[id].name)
- end
-
- for _, id in ipairs(spells) do
- self.cooldown_watch[id] = self:CreateSpiritFrame(id)
- print('COOLDOWN', id, self.cooldown_watch[id].name)
- end
-
- self:SpiritScan()
- self:RegisterEvent('UNIT_AURA')
- self:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED')
- self:RegisterEvent('PLAYER_REGEN_DISABLED')
- self:RegisterEvent('PLAYER_REGEN_ENABLED')
-end
-
--- StatusBar factory
-function mod:CreateSpiritFrame(id)
- local s, c, isIcon = FindSpirit(id)
-
- -- how much frame do we need?
- local f
- if isIcon then
- f = CreateFrame('Frame', FRAME_PREFIX..id, UIParent)
- f.db = c
- function f:Update() end
- else
- f = T:CreateBar('TkAuraBar'..id, c)
- f.isTimer = true
- if (c.label_string ~= '') then
- print('has label, add it', id)
- T:AddLabel(f, c)
- end
- end
- f:Hide()
-
- -- general display
- f:SetPoint(c.anchor, c.parent, c.anchorTo, c.posX, c.posY)
- f:SetSize(c.width, c.height)
- f:SetFrameStrata(c.strata)
-
- -- icon?
- f.icon = s.icon
- T:CreateStatusIcon(f)
-
- -- attachment frames?
- if c.attach then
- for i, e in ipairs(c.attach) do
- local ef = CreateFrame('Frame', 'TkExtra'..id, f)
- f[i] = ef
- ef:SetPoint(e.anchor, f, e.anchorTo)
- ef:SetSize(c.width * e.width_relative or e.width, c.height * e.height_relative or e.height)
- ef:SetFrameStrata(e.strata or c.strata)
- T:CreateStatusTextures(ef, e)
- end
- end
-
- -- setup suppression checking
- if c.exceptions then
- function s:ExceptionCheck ()
- for i, func in ipairs(c.exceptions) do
- if not func(self) then
- return false, i
- end
- end
- return true
- end
- else
- function s:ExceptionCheck () return true end
- end
-
- -- access linkage
- f.format = c.label_string
- f.spirit = s
- f.name = s.name
- s.frame = f
- return s
-end
-
-function mod:UNIT_AURA(e, unit)
- if unit == 'player' then
- self:SpiritScan()
- end
-end
-
--- Updates aura watches
-function mod:SpiritScan()
- local db = _G.TurokData
- for id, aura in pairs(self.aura_watch) do
- local c = aura.conf
- local f = aura.frame
-
- local name, _, _, count, _, duration, expires, caster = UnitAura('player', aura.name)
-
- if name then
- aura.duration = duration
- aura.expires = expires
- aura.caster = caster
- aura.count = count
- local test, i = aura:ExceptionCheck()
- print(name, duration, expires)
- if not test then
- print('suppressing '..aura.name..' (failed test #'..i..')')
- else
- f.name = name
- f:Update(nil, duration, expires)
- f:Show()
- end
- end
- end
-end
-
-function mod:PLAYER_REGEN_ENABLED()
- for id, aura in pairs(self.aura_watch) do
- print('non-combat alpha for #', id, aura.name, 'is', aura.frame.db.alpha_ooc)
- aura.frame.fadeTo = aura.frame.db.alpha_ooc
- aura.frame.fadeDuration = FADE_TIME
- end
-end
-
-function mod:PLAYER_REGEN_DISABLED()
- for id, aura in pairs(self.aura_watch) do
- print('combat alpha for #', id, aura.name, 'is', aura.frame.db.alpha)
- aura.frame.fadeTo = aura.frame.db.alpha
- aura.frame.fadeDuration = FADE_TIME
- end
-end
-
--- This is the most reliable way of catching item and spell uses, other events are delayed or too vague to be useful
-function mod:COMBAT_LOG_EVENT_UNFILTERED(e, ...)
- local timestamp, combatEvent, hideCaster, sourceGUID, sourceName, sourceFlags, sourceRaidFlags, destGUID, destName, destFlags, destRaidFlags =
- ...; -- Those arguments appear for all combat event variants.
- local eventPrefix, eventSuffix = combatEvent:match("^(.-)_?([^_]*)$");
- if eventPrefix ~= 'SPELL_' or sourceGUID ~= self.myGUID then
- return
- end
-
- local spellid, name, count, type = select(13, select('#', ...), ...)
- local kc = ''
- for i=1,4 do
- kc = kc .. string.format('%X',((string.byte(eventSuffix,i) % 8) + 8))
- end
- print('|cFFFF'..kc..eventSuffix..'|r', sourceName, destName, spellid, name)
-end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Tek.lua
--- a/Tek.lua Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,404 +0,0 @@
-addon, T_ = ...
--- User: Krakyn
--- Created: 12/4/2015 11:17 PM
-local T = LibStub("AceAddon-3.0"):GetAddon("Turok")
-local db = T.db
-local TL = 'Tek'
-local mod = T:NewModule("Tek")
-local print = function(...)
- _G.print('Tek', ...)
-end
-local time = _G.ct
-
--- events & units
-local TRACKED_UNITS = {'player', 'target', 'focus', 'pet'}
-local TRACKED_EVENTS = {'UNIT_SPELLCAST_START', 'UNIT_SPELLCAST_DELAYED', 'UNIT_SPELLCAST_STOP', 'UNIT_SPELLCAST_FAILED', 'UNIT_SPELLCAST_FAILED_QUIET',
- 'UNIT_SPELLCAST_INTERRUPTED', 'UNIT_SPELLCAST_SUCCEEDED', 'UNIT_SPELLCAST_CHANNEL_START', 'UNIT_SPELLCAST_CHANNEL_STOP', 'UNIT_SPELLCAST_CHANNEL_UPDATE' }
-
--- animations are a little different here
-local FADE_OUT_TIME, FADE_IN_TIME = 1000, 200
-
--- values MUST be in chronological order
-local CHANNEL_START, CAST_START, CAST_INTERRUPTED, CAST_SUCCEEDED, CAST_STOPPED, CAST_FAILED, CHANNEL_STOPPED = 1, 2, 3, 4, 5, 6, 7
-local TEXTURE_SUFFIX = {
- [CHANNEL_START] = '_channeling',
- [CAST_START] = '_casting',
- [CAST_INTERRUPTED] = '_interrupted',
- [CAST_SUCCEEDED] = '_finished',
- [CAST_STOPPED] = '_failed',
- [CAST_FAILED] = '_failed',
- [CHANNEL_STOPPED] = ''
-}
-
--- defaults
-db.castbar = {
- --T.defaults.castbar = {
- width = 300, height = 24,
- anchor = 'CENTER', parent = 'UIParent', anchorTo = 'CENTER',
- posX = 0, posY = 0,
- foreground_casting = {0.80784313725, 0.87843137254, 0.0156862745, 1},
- background_casting = {0,0,0,0.4},
- background_interrupted = {1,0,0,1},
- background_failed = {0.60784313725, 0.87843137254, 0.0156862745, 1},
- foreground_interrupted = {1, 0.5, 0, 1},
- foreground_failed = {0,0,0,1},
- foreground_finished = {0.60784313725, 0.87843137254, 0.0156862745, 1},
- background_finished = {0.60784313725, 0.87843137254, 0.0156862745, 1},
- foreground_inset = -1,
- fill_direction = 'RIGHT',
- fill_inverse = false,
- glow_texture = "Tooltip-BigBorder",
- glow_size = 2,
- spark_texture = "Tooltip-BigBorder",
- spark_size = 2,
- ['player'] = {
- width = 400, height = 36,
- anchor = 'TOP', parent = 'TkFocusBar', anchorTo = 'BOTTOM',
- posX = 0, posY = 2,
- },
- ['target'] = {
- width = 400, height = 36,
- anchor = 'BOTTOMLEFT', parent = 'TkplayerCastBar', anchorTo = 'TOPRIGHT',
- posX = -30, posY = 4,
- },
- ['focus'] = {
- width = 200, height = 36,
- anchor = 'TOPLEFT', parent = 'TkplayerCastBar', anchorTo='BOTTOMRIGHT',
- posX = 2, posY = -2
- },
- ['pet'] = {
- width = 300, height = 24,
- anchor = 'TOPRIGHT', parent = 'TkFocusBar', anchorTo='TOPLEFT',
- posX = -2, posY = 0
- },
-}
-
-local inv = T.anchor_inverse
-local d = T.direction_coord
-local a = T.anchor_direction
-local c = {}
--- c[unit]=nil is used by frame update, thus any indexing from a valid frame is implied to be for new casting info
-setmetatable(c, {
- __index = function(t,k)
- t[k] = {}
- return t[k]
- end
-})
-
-function mod:OnEnable()
- local db = T.db
-
- self.casting = c
- self.castbar = {}
-
-
- for _, unit in pairs(TRACKED_UNITS) do
- local cdb = db.castbar[unit]
- print('|cFFFF44FF' .. unit .. '|r castbar creation')
-
-
- -- State info
- c[unit] = {}
-
- -- Set frames
- local fn = 'Tk' .. unit .. 'CastBar'
- self.castbar[unit] = T:CreateBar(fn, cdb)
- local pc = self.castbar[unit]
- pc:Hide()
- pc:SetAlpha(0)
-
- T:AddLabel(pc, cdb, 'spelltext')
- local casttime = T:AddLabel(pc, cdb, 'casttime')
- pc.foreground:SetWidth(0)
-
- casttime:SetPoint('RIGHT', pc, 'RIGHT')
- casttime:SetJustifyH('RIGHT')
-
- if unit == 'player' then
- local lb = pc:CreateTexture('latency', 'OVERLAY')
- local lt = T:AddLabel(pc, cdb, 'latency')
- lt:SetPoint('TOPRIGHT', pc.casttime, 'BOTTOMRIGHT')
- lt:SetJustifyH('RIGHT')
- pc.latency = lb
- lb.text = lt
- end
-
- pc.transpt = a[cdb.fill_direction]
- pc.xtrans = function() return math.min((cdb.width + cdb.foreground_inset) * pc.percent * d[pc.transpt][1], cdb.width) end
- pc.ytrans = function() return math.min((cdb.height + cdb.foreground_inset) * pc.percent * d[pc.transpt][2], cdb.height) end
-
- pc.movement_x = 1
- pc.moving_end = 'LEFT'
-
- local glow = pc:CreateTexture('glow', 'OVERLAY')
- glow:SetTexture(CASTBAR_TAILGLOW)
- glow:SetPoint('TOPLEFT', pc, 'TOPLEFT', -5, 5)
- glow:SetPoint('BOTTOMRIGHT', pc, 'BOTTOMRIGHT', 5, -5)
- pc.glow = glow
-
- local icon = pc:CreateTexture('icon', 'ARTWORK')
- icon:SetPoint('RIGHT', pc, 'LEFT', -2, 0)
- icon:SetWidth(pc.foreground:GetHeight())
- icon:SetHeight(pc.foreground:GetHeight())
- icon:SetTexture(0,0,0,1)
- pc.icon = icon
-
- pc.unit = unit
- T:Bar_SetUpdateHandler(pc, self.TekUpdate)
- end
-
- -- Casting table events
- for i, event in pairs(TRACKED_EVENTS) do
- print('listening to |cFF00FFFF' .. event .. '|r')
- self:RegisterEvent(event, 'TekEvent')
- end
-
- -- Extra events
- self:RegisterEvent('PLAYER_TARGET_CHANGED')
- self:RegisterEvent('PLAYER_FOCUS_CHANGED')
-
- -- kill default casting bar
- -- T.cbscripts = {CastingBarFrame:GetScript('OnUpdate'), CastingBarFrame:GetScript('OnEvent')}
- CastingBarFrame:SetScript('OnUpdate', nil)
- CastingBarFrame:SetScript('OnEvent', nil)
- CastingBarFrame:Hide()
-end
-
--- Update handler for castbar
-function mod:TekUpdate()
- local glow = self.glow
- local foreground = self.foreground
- local background = self.background
- local latency = self.latency
- local time = GetTime() * 1000
- local spelltext = self.spelltext
- local timetext = self.timetext
- local cdb = self.db
- if mod.casting[self.unit] ~= nil then
-
- local u = self.unit
- local s = mod.casting[u]
- local alpha = self:GetAlpha()
-
- -- is something casting at all?
- if s.casting <= CAST_START then
-
- -- start = true whenever a new spell cast could be active (i.e. target switching)
- if s.init then
- print('|cFFDD77DD'..u..'|r init_cast (spell='..s.displayName..', startTime='..s.startTime..', endTime='..s.endTime..', channel=',s.channel,')')
- print(self:GetName(), self:IsVisible(), self:IsShown())
-
- if u == 'player' then
- self.latency.text:SetText(s.latency)
- end
-
- -- update translation point
- if s.casting == CHANNEL_START and not cdb.fill_inverse then
- self.transpt = inv[a[cdb.fill_direction]]
- else
- self.transpt = a[cdb.fill_direction]
- end
-
- -- update frame contents
- foreground:SetTexture(unpack(cdb['foreground' .. TEXTURE_SUFFIX[s.casting]] and cdb['foreground' .. TEXTURE_SUFFIX[s.casting]] or cdb.foreground_color))
- background:SetTexture(unpack(cdb['background' .. TEXTURE_SUFFIX[s.casting]] and cdb['background' .. TEXTURE_SUFFIX[s.casting]] or cdb.background_color))
-
- self.icon:SetTexture(s.texture)
- spelltext:SetText(s.displayName)
- self.duration = s.endTime - s.startTime
- self.fadeIn = s.startTime + (1-alpha) * FADE_IN_TIME
- self.fadeOut = s.endTime + FADE_OUT_TIME -- needs to exist for target changes
-
- print(s.startTime, self.fadeIn, self.fadeIn - s.startTime)
- -- clear 'start'
- s.init = nil
- end
-
- -- if we're checking this and start was never flipped, then something happened
- if time <= self.fadeIn then
- alpha = 1- ((self.fadeIn - time) / FADE_IN_TIME)
- self:SetAlpha(alpha)
- elseif alpha ~= 1 then
- self:SetAlpha(1)
- end
- self.value = time - s.startTime
- self.percent = self.value / self.duration
- self.casttime:SetText(format("%.1f", self.value / 1000))
-
- -- s.casting is nil when the spellcast has finished
- else
- -- something set a term flag
- if s.casting < CHANNEL_STOPPED and s.fade then
- print(TL, '|cFFDD77DD'..u..'|r init_fadeout (spell='..s.displayName..', startTime='..s.startTime..', endTime='..s.endTime..', channel=',s.channel,')')
- self.fadeOut = time + FADE_OUT_TIME
- foreground:SetTexture(unpack(cdb['foreground' .. TEXTURE_SUFFIX[s.casting]] and cdb['foreground' .. TEXTURE_SUFFIX[s.casting]] or cdb.foreground_color))
- background:SetTexture(unpack(cdb['background' .. TEXTURE_SUFFIX[s.casting]] and cdb['background' .. TEXTURE_SUFFIX[s.casting]] or cdb.background_color))
- s.fade = nil
- self.value = self.duration
- self.percent = 1
- end
-
- if time < self.fadeOut then
- alpha = (self.fadeOut - time) / FADE_OUT_TIME
- self:SetAlpha(alpha)
- else
- alpha = 0
- self:Hide()
- self:SetAlpha(alpha)
- self.casttime:SetText(nil)
- self.spelltext:SetText(nil)
- self.debugged = false
- self.percent = 0
- if u == 'player' then
- self.latency.text:SetText(nil)
- end
- mod.casting[self.unit] = nil
- print('|cFFDD77DD'..u..'|r work complete, hiding...')
- end
- -- hide and wait until we're pulled out again
- end
- self.foreground:SetPoint('RIGHT', self, self.transpt, self.xtrans(), self.ytrans())
- end
-end
-
-
--- event stub, filters out unwanted cast events
-function mod:TekEvent(e, unit, ...)
- if not self.castbar[unit] then
- return
- end
- if not self[e] then
- error('No method signature for event ' .. tostring(e))
- end
- print('popped |cFF00FFFF' .. e .. '|r: ', unit, ...)
- self[e](self, e, unit, ...)
-end
-
-function mod:PLAYER_TARGET_CHANGED (e, cause)
- print(e)
- self:UpdateUnit('target')
-end
-function mod:PLAYER_FOCUS_CHANGED (e, cause)
- print(e)
- self:UpdateUnit('focus')
-end
-function mod:UpdateUnit(unit)
- if UnitCastingInfo(unit) then
- mod:UNIT_SPELLCAST_START('UNIT_SPELLCAST_START', unit)
- elseif UnitChannelInfo(unit) then
- mod:UNIT_SPELLCAST_CHANNEL_START('UNIT_SPELLCAST_CHANNEL_START', unit)
- else
- mod.castbar[unit]:Hide()
- end
-end
-
--- Spell event handlers
-function mod:UNIT_SPELLCAST_SENT(e, unit, spellname, rank, target)
- -- triggered an action buttton tied to a cast
- c[unit].sentTime = math.floor(GetTime() * 1000)
- print('|cFF44FF44',e,':|r', unit, spellname, c[unit].sentTime)
- c[unit].spell = spellname
- c[unit].rank = rank
- c[unit].target = target
-end
-
-function mod:UNIT_SPELLCAST_START(e, unit) -- Server says: someone started casting
- local spellname, rank, displayName, texture, startTime, endTime, isTradeSkill, castID, nonInterruptible = UnitCastingInfo(unit)
- print('casting['..unit..'] state updated (=start): spellname='.. spellname ..', startTime='.. startTime ..', endTime='.. endTime)
-
- c[unit].castID = castID
- c[unit].spell = spellname
- c[unit].rank = rank
- c[unit].displayName = displayName
- c[unit].texture = texture
- c[unit].startTime = startTime
- c[unit].endTime = endTime
- c[unit].nonInterruptible = nonInterruptible
- c[unit].isTradeSkill = isTradeSkill
- if c[unit].sentTime then
- c[unit].latency = c[unit].startTime - c[unit].sentTime
- end
-
- -- set state and show
- c[unit].casting = CAST_START
- c[unit].init = true
- self.castbar[unit]:Show()
-end
-
-function mod:UNIT_SPELLCAST_DELAYED(e, unit, spellname, rank, castID, target) -- Server says: they're still casting but it'll take longer
- local spellname, rank, displayName, texture, startTime, endTime, isTradeSkill, castID, nonInterruptible = UnitCastingInfo(unit)
- print('casting['..unit..'] state updated (=delayed): spellname='.. spellname ..', startTime='.. startTime ..', endTime='.. endTime)
- c[unit].castID = castID
- c[unit].channel = false
- c[unit].startTime = startTime
- c[unit].endTime = endTime
- -- just update timing data, frame script will adjust
-end
-
--- set exit states
-function mod:UNIT_SPELLCAST_STOP(e, unit, spellname, rank, castID, target) -- Server says: someone stopped casting for some reason
- --c[unit].casting = CAST_STOPPED
-end
-
-function mod:UNIT_SPELLCAST_INTERRUPTED(e, unit, spellname, rank, castID, target) -- Server says: someone got interrupted
- c[unit].casting = CAST_INTERRUPTED
- c[unit].fade = true
-end
-
-function mod:UNIT_SPELLCAST_SUCCEEDED(e, unit, spellname, rank, castID, target) -- Server says: they stopped because they're done
-
- if c[unit].castID == castID and c[unit].casting ~= CHANNEL_START then
- c[unit].casting = CAST_SUCCEEDED
- c[unit].fade = true
- end
-end
-
-function mod:UNIT_SPELLCAST_FAILED(e, unit, spellname, rank, castID, target) -- Server says: someone tried to cast something but they weren't allowed
- if c[unit].castID ~= castID then -- can fire from keybind spam
- return
- end
- c[unit].casting = CAST_FAILED
- c[unit].fade = true
-end
-
-function mod:UNIT_SPELLCAST_FAILED_QUIET(e, unit, spellname, rank, castID, target) -- Server says: someone tried to cast something but they weren't allowed
- if c[unit].castID == castID and c[unit].casting == CAST_START then
- c[unit].casting = CAST_FAILED
- end
-end
-
-function mod:UNIT_SPELLCAST_INTERRUPTIBLE(e, unit)
- c[unit].notInterruptible = false
-end
-function mod:UNIT_SPELLCAST_NOT_INTERRUPTIBLE(e, unit)
- c[unit].notInterruptible = true
-end
-
-function mod:UNIT_SPELLCAST_CHANNEL_START(e, unit, spellname, rank, castID, spellID)
- local spellname, rank, displayName, texture, startTime, endTime, isTradeSkill, nonInterruptible = UnitChannelInfo(unit)
- displayName = spellname -- channels sometimes just appear as 'Channeling' according to Quartz author
- print('casting['..unit..'] state updated (=start, channel): spellname='.. spellname ..', startTime='.. startTime ..', endTime='.. endTime)
- c[unit].casting = CHANNEL_START
- c[unit].spellname = spellname
- c[unit].rank = rank
- c[unit].displayName = displayName
- c[unit].texture = texture
- c[unit].startTime = startTime
- c[unit].endTime = endTime
- c[unit].nonInterruptible = nonInterruptible
- c[unit].isTradeSkill = isTradeSkill
- c[unit].init = true
- mod.castbar[unit]:Show()
-end -- start up
-function mod:UNIT_SPELLCAST_CHANNEL_STOP(e, unit, spellname, rank, castID, spellID)
- c[unit].casting = CHANNEL_STOPPED
-end
-function mod:UNIT_SPELLCAST_CHANNEL_UPDATE(e, unit, spellname, rank, castID, spellID)
- spellname, rank, displayName, texture, startTime, endTime, isTradeSkill, nonInterruptible = UnitChannelInfo(unit)
- displayName = spellname -- channels sometimes just appear as 'Channeling' according to Quartz author
- c[unit].channel = true
-end -- recalc
-
-
-
-
diff -r 8a9a6637f082 -r a9b8b0866ece Turok.iml
--- a/Turok.iml Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok.lua
--- a/Turok.lua Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,159 +0,0 @@
-
--- GLOBALS: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
-local T = LibStub("AceAddon-3.0"):NewAddon("Turok", "AceConsole-3.0", "AceEvent-3.0")
-local _G = _G
-local rawset = _G.rawset
-_G.Turok = T
-local print = function(...)
- --_G.print('Core', ...)
-end
-
-
-T.mods = {}
-T:SetDefaultModuleState(true)
-T:SetDefaultModuleLibraries("AceEvent-3.0")
-T:SetDefaultModulePrototype({OnInitialize = function(mod)
- print('CORE', mod:GetName().. ' found')
-end})
-
--- propagates parameter data around
-function T:LinkTable(parent, child, pname, cname)
- local mt = {
- __index = function(t,k)
- if parent[k] then
- t[k] = parent[k]
- end
- print('|cFFFF8800'.. pname ..'.' .. cname .. '|r.|cFFFFFF00'.. k ..'|r inheriting value at |cFFFF8800' .. pname ..'|r.|cFFFFFF00'.. k..'|r')
- return parent[k]
- end,
- __newindex = function (t, k, v)
- rawset(t,k,v)
- if type(v) == 'table' then
- T:LinkTable(child, v, pname, k)
- print('|cFFFF8800'.. pname ..'.' .. cname .. '|r.|cFFFFFF00'.. k ..'|r sub-table created')
- end
- end
- }
- print('|cFFFF8800'.. pname ..'.|cFFFFFF00'.. cname ..'|r sub-tables will be retconned')
- setmetatable(child, mt)
- for k, v in pairs(child) do
- if type(v) == 'table' then
- T:LinkTable(child, v, cname, k)
- end
- end
-end
-
-function T:OnInitialize()
-
- local defaults = {
- background_color = {0,0,0,0},
- background_blend = 'BLEND',
- foreground_color = {1,1,1,0.5},
- foreground_blend = 'BLEND',
- foreground_inset = -1,
- width = 250,
- height = 100,
- alpha = 1,
- alpha_ooc = 0.1,
- strata = 'LOW',
- label_strata = 'HIGH',
- label_justifyH = 'LEFT',
- label_color = {1, 1, 1, 1},
- label_font = 'turok',
- label_size = 14,
- label_inset = -2,
- label_point = 'LEFT',
- label_outline = 'OUTLINE',
- anchor = 'CENTER', parent = 'UIParent', anchorTo = 'CENTER',
- focusbar = {
- foreground_color = {1, 1, 1, 0.7},
- background_color = {0,0,0,0.8},
- width = 300, height = 24,
- posX = 0, posY = -150,
- },
- }
- _G.TurokData = defaults
- if not _G.TurokData then
- _G.TurokData = defaults
- end
-
- T.db = _G.TurokData
- local db = T.db
- for k, v in pairs(db) do
- if type(v) == 'table' then
- T:LinkTable(db, v, 'db', k)
- end
- end
- setmetatable(db,
- {__newindex = function (t, k, v)
- rawset(t,k,v)
- if type(v) == 'table' then
- T:LinkTable(db, v, 'db', k)
- print('CFG', '|cFFFF0000db|r.|cFF00FFFF' .. k ..'|r created at bottom level')
- end
- end})
-
- options = {
- type = 'group',
- name = 'Turok',
- handler = T,
- set = function(info,value)
- local k = db[info[1]]
- for i = 2, #info-1 do
- if type(k[i]) ~= 'table' then
- print('fart')
- end
-
- k = k[i]
- end
- k[info[#info]] = value
- end,
- get = function(info)
- local k = db[info[1]]
- for i = 2, #info-1 do
- if type(k[i]) ~= 'table' then
- print('fart')
- end
-
- k = k[i]
- end
- return k[info[#info]]
- end,
- desc = '"Dinosaur" Hunter',
- args = {
- background_color = {
- type = 'color',
- name = 'Background Color',
- hasAlpha = true,
- }
- }
- }
- LibStub("AceConfig-3.0"):RegisterOptionsTable('Turok', options, {"tk"})
-
-end
-
-
-function T:OnEnable()
- local db = _G.TurokData
-
- print('I... am Turok')
-
- self.stats = {
- maxpower = UnitPowerMax('player')
- }
-
-
- T.focusbar = T:CreateBar('TkFocusBar', db.focusbar)
- local fb = T.focusbar
- T:AddLabel(fb, db.focusbar)
- fb:Update(UnitPower("player"), 0, UnitPowerMax("player"))
- T:Bar_SetUpdateHandler(fb, function(self)
- local pp = UnitPower("player")
- if pp == T.stats.maxpower and not T.stats.capped then
- T.stats.capped = true
- elseif T.stats.capped then
- T.stats.capped = false
- end
- T.Bar_Update(fb, pp)
- end)
-end
diff -r 8a9a6637f082 -r a9b8b0866ece Turok.toc
--- a/Turok.toc Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-## Interface: 60200
-## Title: Turok
-## Notes: Dinosaur Huntin'
-## Author: Krakyn
-## Version: 1.0
-## SavedVariables: TurokData
-## OptionalDep: Ace3
-
-Libs\LibStub\LibStub.lua
-Libs\AceConsole-3.0\AceConsole-3.0.xml
-Libs\AceAddon-3.0\AceAddon-3.0.xml
-Libs\AceConfig-3.0\AceConfig-3.0.xml
-Libs\AceEvent-3.0\AceEvent-3.0.xml
-Libs\AceTimer-3.0\AceTimer-3.0.xml
-Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml
-Libs\LibSharedMedia-3.0\lib.xml
-Media\Manifest.lua
-Turok.lua
-Fog.lua
-Tek.lua
-Equip.lua
-Spirit.lua
-Lost.lua
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/.pkgmeta
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/.pkgmeta Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,19 @@
+externals:
+ Libs/LibStub:
+ url: svn://svn.wowace.com/wow/libstub/mainline/trunk
+ tag: latest
+ Libs/CallbackHandler-1.0:
+ url: svn://svn.wowace.com/wow/callbackhandler/mainline/trunk/CallbackHandler-1.0
+ tag: latest
+ Libs/AceAddon-3.0:
+ url: svn://svn.wowace.com/wow/ace3/mainline/trunk/AceAddon-3.0
+ tag: latest
+ Libs/LibGroupInSpecT-1.1:
+ Libs/LibGroupInSpecT-1.1: svn://svn.wowace.com/wow/libgroupinspect/mainline/trunk
+
+ignore:
+ - Debug.lua
+ - Turok.iml
+ - .idea
+
+enable-nolib-creation: no
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Init.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Init.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,287 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 12/28/2015 6:40 AM
+--- Core load sequence goes here.
+--@debug@
+local ADDON, TurokEnv = ...
+local _G = _G
+--@end-debug@
+--GLOBALS: Turok, LibStub, GetAddOnMetadata
+local setmetatable, rawset, rawget, pairs, type, unpack, tostring, tinsert = setmetatable, rawset, rawget, pairs, type, unpack, tostring, table.insert
+Turok = LibStub("AceAddon-3.0"):NewAddon('Turok', 'AceEvent-3.0', 'AceTimer-3.0', 'AceConsole-3.0')
+Turok:SetDefaultModuleState(true)
+TurokEnv.Addon = Turok
+TurokEnv.LSM = LibStub("LibSharedMedia-3.0")
+TurokEnv.LGIST = LibStub("LibGroupInSpecT-1.1")
+local T = Turok
+--@debug@
+local print = function(...)
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('DB', ...)
+ end
+end
+local cTypes = { ['function'] = 'FF9922', ['table'] = '00FFAA', ['number'] = '77FF00', ['string'] = '00AAFF', ['hl'] = 'FF0088', ['field'] = '00FFFF',
+ ['boolean'] = 'CC88FF', ['false'] = 'FF7700', ['true'] = '44FF66', ['nil'] = 'FFFF00',}
+
+local Debuggers = {
+ cType = function(s) return '|cFF' .. tostring(cTypes[type(s)]) .. tostring(s) .. '|r' end,
+ cText = function(s) return '|cFF'..cTypes.string..tostring(s)..'|r' end,
+ cNum = function(n) return '|cFF'..cTypes.number .. tostring(n) .. '|r' end,
+ cWord = function(w) return '|cFF'..cTypes.table .. tostring(w) .. '|r' end,
+ cKey = function(k) return '|cFF'..cTypes.field .. tostring(k) .. '|r' end,
+ cPink = function(s) return '|cFF'..cTypes.hl .. tostring(s) .. '|r' end,
+ cBool = function(s) return '|cFF'..cTypes[tostring((not not s))] .. tostring(s) .. '|r' end,
+}
+for fname, func in pairs(Debuggers) do
+ _G[fname] = func
+end
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
+--@end-debug@
+
+T.db = {}
+T.versionString = GetAddOnMetadata("Turok", "Version")
+
+function T:OnModuleCreated(mod)
+ if mod.events then
+ print('Module', unpack(mod.events))
+ end
+end
+--- RegisterEvent embedded to module tables
+function T:RegisterCallback(event, func, ...)
+ if not T.dispatchQueue[event] then
+ T.dispatchQueue[event] = {}
+ end
+
+ if not T.dispatchQueue[event][T.ID] then
+ T.dispatchQueue[event][T.ID] = T:GetName()
+ end
+
+ if (type(func) == 'function') then
+ if type(T[event]) == 'function' then
+ local oldfunc = T[event]
+ T[event] = function(...)
+ oldfunc(...)
+ return func(...)
+ end
+ else
+ T[event] = func
+ end
+ end
+ --@debug@
+ print(cText('Adding listener for'), cKey(self:GetName()), cText('on'), cKey(event))--@end-debug@
+end
+
+--- Default settings base
+T.defaults = {
+ char = {},
+
+ lefttext = {
+ parent = 2, -- in an overlay frame
+ anchor = 'LEFT',
+ anchorTo = 'LEFT',
+ size = 18,
+ x = 5, y = 0,
+ justifyH = 'LEFT',
+ justifyV = 'MIDDLE',
+ },
+
+ righttext = {
+ parent = 2, -- in an overlay frame
+ anchor = 'RIGHT',
+ anchorTo = 'RIGHT',
+ x = -5,
+ y = 0,
+ size = 18,
+ justifyH = 'RIGHT',
+ justifyV = 'MIDDLE',
+ },
+
+ alpha = 1,
+ alpha_ooc = 1,
+ alpha_fade_in = 0.2,
+ alpha_fade_out = 0.2,
+ border_color = {0,0,0,1},
+
+ background_color = {0,.0,0,1},
+ background_blend = 'BLEND',
+
+ foreground_texture = [[Interface\Addons\Turok\Media\statusbar\Minimalist.tga]],
+ foreground_color = {0,.475,.95,1},
+ foreground_blend = 'BLEND',
+
+ foreground_inset = 0,
+ padding = 2,
+ spacing = 0,
+ fill_direction = 'RIGHT',
+
+ anchor = 'CENTER', parent = 'UIParent', anchorTo = 'CENTER',
+ x = 0, y = 0,
+ inset = -3,
+ width = 250,
+ height = 100,
+ strata = 'LOW',
+ font = "Interface\\Addons\\Turok\\Media\\font\\ArchivoNarrow-Regular.ttf",
+ size = 14,
+ text_color = {1, 1, 1, 1},
+ justifyH = 'LEFT',
+ outline = 'OUTLINE',
+ combatFade = true,
+
+ battle_noise_start = [[Interface\Addons\Turok\Media\sound\Low_Beep-Public_D-136_hifi.mp3]],
+ battle_noise_end = [[Interface\Addons\Turok\Media\sound\Electro_-S_Bainbr-7955_hifi.mp3]],
+}
+
+
+T.events = {
+ 'PLAY_MOVIE',
+ 'PLAYER_TARGET_CHANGED',
+ 'PLAYER_FOCUS_CHANGED',
+ 'PLAYER_EQUIPMENT_CHANGED',
+ 'PLAYER_REGEN_DISABLED',
+ 'PLAYER_REGEN_ENABLED',
+ 'SPELL_UDPATE_COOLDOWN',
+ 'SPELL_UPDATE_USABLE',
+ 'UNIT_AURA',
+ 'UNIT_PET',
+ 'UNIT_POWER_FREQUENT',
+ 'UNIT_SPELL_HASTE',
+ 'UNIT_SPELLCAST_SENT',
+ 'UNIT_SPELLCAST_START',
+ 'UNIT_SPELLCAST_DELAYED',
+ 'UNIT_SPELLCAST_STOP',
+ 'UNIT_SPELLCAST_CHANNEL_START',
+ 'UNIT_SPELLCAST_CHANNEL_UPDATE',
+ 'UNIT_SPELLCAST_CHANNEL_STOP',
+ 'UNIT_SPELLCAST_FAILED',
+ 'UNIT_SPELLCAST_INTERRUPTED',
+ 'UNIT_SPELLCAST_INTERRUPTIBLE',
+ 'UNIT_SPELLCAST_SUCCEEDED',
+ 'UNIT_SPELLCAST_UNINTERRUPTIBLE',
+}
+T.previousSpec = {}
+T.talents = { {}, {}}
+T.changedTalents = {{}, {} }
+T.talentInfo = {}
+T.auras = {}
+T.spells = {}
+T.spellevent = {}
+T.channeling = {}
+T.casting = {}
+T.sent = {}
+T.prototype = {}
+T.spellBook = {}
+T.equipped = {}
+
+--- player-restricted unit info and text representations
+T.player = {}
+T.playertext = {}
+T.pet = {}
+
+--- holds non-restricted unit information
+T.unit = {
+ player = {},
+ target = {},
+ focus = {},
+ pet = {},
+}
+
+-- index of frames with conditional visual properties
+T.control_regions = {}
+
+-- index of frames generated by the lua
+T.frames = {}
+
+-- units
+T.units = {}
+T.unitsBySlot = {}
+setmetatable(T.unitsBySlot, {__mode="v"})
+
+
+
+T.TrueVal = function (self,k)
+ return rawget(self,k)
+end
+--- Sets an index hierarchy for db vars and propagates config dialog info
+T.LinkTable = function (over, under, pname, cname)
+ local mt = {
+ __index = function(t,k)
+ if type(over[k]) ~= nil then
+ --t[k] = over[k]
+ --@debug@
+ --print('up-referencing '.. STACK_COLOR2 .. pname ..'|r.'.. STACK_COLOR3.. tostring(k)..'|r -> '.. STACK_COLOR3.. pname ..'.' .. cname .. '|r.'..STACK_COLORN.. tostring(k) ..'|r', over[k])--@end-debug@
+ end
+ return over[k]
+ end,
+ __newindex = function (t, k, v)
+ rawset(t,k,v)
+ if type(v) == 'table' then
+ --@debug@
+ --print('parenting '.. STACK_COLOR2.. pname ..'|r to created table '.. STACK_COLOR3.. cname ..'|r')--@end-debug@
+ T.LinkTable(under, v, pname, k)
+ end
+ end
+ }
+ --under.TrueVal = T.TrueVal
+ setmetatable(under, mt)
+ for k, v in pairs(under) do
+ if type(v) == 'table' then
+ --@debug@
+ --print('linking '..STACK_COLOR1.. pname ..'|r to '..STACK_COLOR2.. cname ..'|r')--@end-debug@
+ T.LinkTable(under, v, pname ..'.'.. cname, k)
+ end
+ end
+end
+
+
+--- Merges values of table B into table A, and copies over nested values of tables matching the keywords list
+local masked = {name = true, virtual = true}
+T.Config_Push = function(cvars, push , root, rkey)
+ local results = {}
+ root = root or cvars
+ for k, v in pairs(push) do
+ if not masked[k] then
+ if type(v) == 'table' and v ~= root then
+ cvars[k] = {}
+ T.Config_Push(cvars[k], v, root)
+ else
+ print(' |cFFFF0088B|r ', tostring(rkey)..'.'..cKey(k))
+ cvars[k] = v
+ tinsert(results, ' |cFFFF0088B|r '.. tostring(rkey)..'.'..cKey(k))
+ end
+ end
+ end
+ return cvars, results
+end
+T.Config_Merge = function(cvars, merge, root, rkey)
+ local diff = {}
+ root = root or cvars
+ rkey = rkey or '0'
+ for k, v in pairs(merge) do
+ if masked[k] or cvars[k] then
+ tinsert(diff, ' |cFF00FF00A|r '.. tostring(rkey)..'.'..cWord(k))
+ print(' |cFF00FF00A|r ', tostring(rkey)..'.'..cText(k), '=', cvars[k])
+ --cvars[k] = cvars[k]
+ else
+ if type(v) == 'table' then
+ if type(cvars[k]) == 'nil' then
+ cvars[k] = {}
+ end
+ if type(cvars[k]) == 'table' then
+ print(' |cFFFFFF00A+B|r '.. tostring(rkey)..'.'..cWord(k))
+ cvars[k] = T.Config_Merge(cvars[k], v, root, tostring(rkey)..'.'..tostring(k))
+ end
+ elseif cvars[k] == nil then
+ tinsert(diff, ' |cFFFF0088B|r '.. tostring(rkey)..'.'..cKey(k))
+ print(' |cFFFF0088B|r ', tostring(rkey)..'.'..cKey(k))
+ cvars[k] = v
+ else
+ tinsert(diff, ' |cFF00FF00A|r '.. tostring(rkey)..'.'..cWord(k))
+ print(' |cFF00FF00A|r ', tostring(rkey)..'.'..cWord(k))
+ --cvars[k] = cvars[k]
+ end
+ end
+ end
+ return cvars, diff
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Layout/Dialog.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Layout/Dialog.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,186 @@
+--- Dialog Generator
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 1/1/2016 3:37 PM
+--- Framescript template for generating intelligible dialog panels
+--[[
+-- Frame << TkListFrame
+-- {
+-- Frame << TkListItem <-- Any number of list item frames with parentArray="rows"
+-- {
+ :GetRow(row, values, id, offset) <-- Populates the uiobjects that make up the given row, with data from values[id], on display row offset
+ <-- Any layered region of child frame with parentArray=opts"
+ }
+ Button <-- Any frame with parentArray="buttons"
+
+ .Click (button, list) <-- Defines results of using a control button
+ .Check (button, row, list) <-- Defines results of operating a row widget
+ .Wheel (list, delta) <-- Defines response to mousewheel action over the list panel
+ }
+
+ Globals:
+ TkList_Init ( object, values, offset, numRows )
+ Takes the return from CreateFrame and a table of values and establishes a scrollable list interface.
+
+ TkPanel_Init ( object )
+ TkList_Init without the scrollable list operations. Lines up control buttons and nothing else.
+--]]
+local TK_LIST_SPACING = 1
+local TK_LIST_PADDING = 3
+local TK_LIST_HEADING_SIZE = 26
+local TK_LIST_ITEM_HEIGHT = 24
+local TK_LIST_DISPLAY_ITEMS = 10
+
+local print = function(...)
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('Xui', ...)
+ end
+end
+-- GLOBALS: TkList_SetView, TkList_Init, Turok
+local type, error, pairs, ipairs, tonumber, max, CreateFrame = type, error, pairs, ipairs, tonumber, math.max, CreateFrame
+local checkval = function(valtype, t, fallback)
+ return (type(t) == valtype) and t or (fallback or error('Expected table reference, got '..type(t)))
+end
+local tableval = function(t, fallback)
+ return checkval('table', t, fallback or {})
+end
+local funcval = function(f, fallback)
+ return checkval('function', f, fallback or function() end)
+end
+
+--- Orders list row
+-- Does an ipairs iteration over self.opts and distributes the referenced objects along the horizontal axis of 'self'
+-- Note that members are only aligned horizontally; no column alignment is done. Widths can be set by datafunc to accomplish that.
+local function TkListItem_Init (listrow)
+ if not listrow.opts then
+ print('no options to enumerate')
+ return
+ end
+ local rwidth = TK_LIST_PADDING*2
+ for i, z in pairs(listrow.opts) do
+ if i > 1 then
+ z:SetPoint('LEFT', listrow.opts[i-1], 'RIGHT', TK_LIST_SPACING, 0)
+ else
+ z:SetPoint('LEFT', listrow, 'LEFT', TK_LIST_PADDING, 0)
+ end
+ rwidth = rwidth + z:GetWidth()+TK_LIST_SPACING
+ z:Show()
+ end
+ listrow:SetSize(rwidth-TK_LIST_PADDING*2,TK_LIST_ITEM_HEIGHT)
+ listrow:Show()
+ print(rwidth)
+ return rwidth
+end
+
+
+---
+local function TkControls_Init(self)
+ local buttonsize = (self._dwidth - (#self.buttons -1) * TK_LIST_SPACING - TK_LIST_PADDING*2) / #self.buttons
+ for n, b in ipairs(self.buttons) do
+ --print('Spirit', buttonsize)
+ b:SetWidth(buttonsize)
+ b:SetPoint('TOPLEFT', self, 'BOTTOMLEFT', buttonsize* (n-1) + TK_LIST_SPACING * (n-1) + TK_LIST_PADDING, -TK_LIST_PADDING)
+ end
+ self.controls:SetHeight(self.buttons[1]:GetHeight()+ TK_LIST_PADDING*2)
+end
+
+--- Populates the list frame with items
+function TkList_SetView(self, start_num, num_rows)
+ print(self, start_num, num_rows)
+ if not start_num then
+ start_num = self.offset
+ end
+
+ if not num_rows then
+ num_rows = self.num_rows
+ end
+
+ if start_num > #self.info then
+ start_num = #self.info - #self.info % num_rows
+ elseif start_num < 1 then
+ start_num = 1
+ end
+
+ print(' ', self:GetName(), start_num, num_rows, #self.info)
+ self.offset = start_num
+
+ for draw_num = 1, num_rows do
+ local actual_row = draw_num + start_num - 1
+ if not self.rows[draw_num] then
+ self.rows[draw_num] = CreateFrame('Frame', self:GetName()..'_Option_'..draw_num, self, 'TurokListItem')
+ self.rows[draw_num]:SetHeight(TK_LIST_ITEM_HEIGHT)
+ self.rows[draw_num].row_num = draw_num
+ end
+ self.rows[draw_num].actual_row = actual_row
+ local row = self.rows[draw_num]
+ if self.info[actual_row] then
+ print( actual_row, draw_num)
+ self.GetRow(row, self.info, actual_row, draw_num)
+ row:Show()
+ else
+ print('|cFF888888'..actual_row, draw_num)
+ row:Hide()
+ end
+ row:SetParent(self)
+ end
+end
+
+--- Prime TkListFrame template-spawn for use
+-- @param self frame object to list-ify
+-- @param info array of list item values
+-- @param datafunc function that takes 1) frame object 2) info table 3) index number 4) row number
+-- @param offset starting offset for initial view
+function TkList_Init (self, info, offset, num_rows)
+ -- error checking
+ --[[if type(info) ~= 'table' then
+ error('arg #2 info must be an associative array')
+ end
+ if type(datafunc) ~= 'function' then
+ error('arg #3 needs a funcref or method name from the frame object')
+ end
+ --]]
+ self.GetRow = funcval(self.GetRow, function() end)
+ self.info = tableval(info, {})
+ for i, v in ipairs(info) do
+ print('Main', i, '=', v.spellName, v.spellTab)
+ self.max_row = i
+ end
+ print('Main', 'last row #', self.max_row)
+
+
+ -- obtain data contents
+ self._dwidth = 0
+ self.rows = {}
+ self.offset = offset and offset or 1
+ self.num_rows = (tonumber(num_rows) ~= nil) and num_rows or TK_LIST_DISPLAY_ITEMS
+ self.name:SetHeight(TK_LIST_HEADING_SIZE)
+ TkList_SetView(self, offset)
+
+ -- sort out the proper width
+ local rwidth = 1
+ local k = 0
+ for n, item in ipairs(self.rows) do
+ print(item:GetName())
+ if item:IsShown() then
+ if n > 1 then
+ item:SetPoint('TOPLEFT', self.rows[n-1], 'BOTTOMLEFT', 0, - TK_LIST_SPACING)
+ else
+ item:SetPoint('TOPLEFT', self, 'TOPLEFT', TK_LIST_PADDING, -(TK_LIST_PADDING+TK_LIST_HEADING_SIZE+TK_LIST_SPACING))
+ end
+ k = k+1
+ self._dwidth = max(self._dwidth, TkListItem_Init(item))
+ end
+ end
+
+ TkControls_Init(self)
+
+ self:SetSize(self._dwidth , (k*TK_LIST_ITEM_HEIGHT)+(TK_LIST_PADDING*2)+(k*TK_LIST_SPACING)+TK_LIST_HEADING_SIZE)
+end
+
+--- Set up for a non-list-style panel, no iterative controls
+function TkPanel_Init(self)
+ self._dwidth = self:GetWidth()
+ TkControls_Init(self)
+ --self:SetSize(self._dwidth , (k*TK_LIST_ITEM_HEIGHT)+(TK_LIST_PADDING*2)+(k*TK_LIST_SPACING)+TK_LIST_HEADING_SIZE)
+end
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Layout/Dialog.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Layout/Dialog.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,462 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if self:GetParent().Check then
+ self:GetParent().Check(self, self:GetParent())
+ else
+ self:GetParent():GetParent().Check(self, self:GetParent(), self:GetParent():GetParent())
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ for i, g in pairs({self:GetChildren()}) do
+ g:Show()
+ end
+ self:RegisterForDrag("LeftButton")
+
+
+ self:StartMoving()
+
+
+ self:StopMovingOrSizing()
+
+
+ self:Wheel(delta)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GameTooltip:SetOwner(self, "ANCHOR_LEFT");
+ if self.spellID then
+ GameTooltip:SetSpellByID(self.spellID);
+ else
+ GameTooltip:SetText(self.desc)
+ end
+ GameTooltip:Show();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if self.value then
+ self.value:SetText(tostring(math.floor(value)))
+ self.value:SetPoint('LEFT', self:GetThumbTexture(), 'LEFT', 1, 0)
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:ClearFocus()
+
+
+ self:ClearFocus()
+
+
+ print(self:GetName(),'gained focus')
+ self.__bg = {self.background:GetTexture()}
+ self.background:SetTexture(0,0,0,1)
+
+
+ print(self:GetName(),'lost focus')
+ self:GetParent():GetParent().EditBox(self)
+ self.background:SetTexture(unpack(self.__bg))
+ self.__bg = nil
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.Wheel = function(self, delta) print(self:GetName(), 'wheel stuff')
+ if self._scroller then
+ for i, region in ipairs(self._scroller) do
+ if region:IsMouseOver() then
+ print(self:GetName(),'hit #', i, region:GetName())
+ region:SetValue(region:GetValue()+delta)
+ end
+ end
+ else
+ print(self:GetName(),'no scrollwheel regions')
+ end
+ end
+
+ print('uhmmm', type(self))
+ LibStub("LibFog-1.0").SetAnimationGroup(self)
+ -- Turok stuff
+
+
+ TkPanel_Init(self)
+ self:RegisterForDrag("LeftButton")
+ self.name:SetText(self.timerName)
+ self.pagenum:SetText(self.timerID)
+ self:SetAlpha(0)
+ self:Fade(0.2, 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Layout/Layout.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Layout/Layout.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,725 @@
+--- LibFog-1.0
+-- In-house solution to processing frame configuration data.
+--[[
+--
+ Config Table fields:
+
+ background .. _color, _texture, _blend properties of the texture referenced by frame.background
+ foregound .. " " " properties of the texture referenced by frame.foreground
+ backdrop arguments for SetBackdrop
+ border_color sets the border color on an existing frame backdrop
+ alpha, alpha_ooc uiobject alpha for in and out of combat
+ combat_fade true to change alpha levels based on combat
+ fade_time, fade_in, fade_out fade_time = fade_in or fade_out
+
+ anchor, parent, anchorTo, x, y args for UIObject:SetPoint()
+ height, width args for Region:SetSize()
+ strata, layer, level override the strata, draw layer, and draw level where they apply
+
+ padding space between frame and background edge
+ foreground_inset space between background and foreground edge
+ spacing space between segmented foreground elements (e.g. combo points)
+
+ font, size, outline args for FontString:SetFont() respectively
+ justifyV, justifyH LEFT/CENTER/RIGHT, TOP/MIDDLE/BOTTOM
+
+ SetFrameLayout():
+ Applies:
+ anchor, parent, anchorTo, x, y
+ width, height,
+ padding, spacing, foreground_inset
+ backdrop, border_color, background_color
+ alpha, alpha_ooc
+
+ SetStatusTextures():
+ Applies:
+ foreground_texture, foreground_color, foreground_blend
+ background_texture, background_color, background_blend
+
+ Defines:
+ fill_direction, fill_width, fill_height, fill_inset
+ :TranslateX(progress)
+ :TranslateY(progress)
+ :SetFillPoints()
+
+ SetFontLayout():
+ Applies:
+ anchor, parent, anchorTo, x, y
+ width, height
+ font, size, outline
+ justifyH, justifyV
+
+ -
+ ]]
+local MAJOR, MINOR = "LibFog-1.0", 1
+local F, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+if not F then return end
+
+local _G, UIParent, type, unpack, pairs, ipairs, min, abs, tostring, print = _G, UIParent, type, unpack, pairs, ipairs, math.min, math.abs, tostring, print
+local InCombatLockdown, GetTime, PlaySoundKitID, CreateFrame = InCombatLockdown, GetTime, PlaySoundKitID, CreateFrame
+local tinsert, wipe, concat = table.insert, table.wipe, table.concat
+local FADE_OUT_TIME, FADE_IN_TIME = 1, 0.4
+
+--@debug@
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
+local ADDON, scriptargs = ...
+scriptargs.LibFog = F
+local print = function(...)
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('Layout', ...)
+ end
+end
+--- debug highlighters
+local namef = function(s) return '|cFFFFFF00' ..tostring(s).. '|r' end -- uiobject targeted function
+local namet = function(s) return '|cFFFF4400 '..tostring(s).. '|r' end -- region targeted function
+local valuef = function(s) return '|cFF88FF88'..(s ~= nil and ('"'..tostring(s)..'"') or ('nil'))..'|r' end -- uiobject name
+local valuet = function(s) return '|cFFAACCAA'..(s ~= nil and ('"'..tostring(s)..'"') or ('nil'))..'|r' end -- string value
+local valuen = function(s) return '|cFFAADD77' ..(s ~= nil and ('"'..tostring(s)..'"') or ('nil')).. '|r' end -- string enumeration
+local valued = function(s) return '|cFFFFFFFF' ..(s ~= nil and ('"'..tostring(s)..'"') or ('nil')).. '|r' end -- number
+--@end-debug@
+local GetPrint = function(trace)
+ if trace then
+ return print
+ else
+ return function() end
+ end
+end
+
+--- Layout control metadata
+local lastdb -- fallback if a table isn't found mid-operation
+local ui_meta = {
+ beepkit = 15263, -- something to play when debugging
+}
+local ui_embeds = {
+ ['Frame'] = 'SetFrameLayout',
+ ['Texture'] = 'SetTextureLayout',
+ ['Font'] = 'SetFontLayout',
+}
+
+--- Resolve a parent object from varying depths
+-- @param self target object
+-- @parent string/number name of global frame or number of GetParent() hops to make
+-- @childKey index key to retrieve from the resolved parent object
+local function ParentValue(self, parent, childKey)
+ local print = GetPrint(self.trace)
+
+ local relativeTo = parent
+ if type(parent) == 'number' then
+ print(cWord('* Parent Trace:'), cNum(parent), cKey(self:GetName()))
+ relativeTo = self:GetParent()
+ for i = 2, parent do
+ if relativeTo.GetParent and relativeTo:GetParent() ~= UIParent then
+ --@debug@
+ print(' ', 'parent =', relativeTo:GetName())
+ --@end-debug
+ local next = relativeTo:GetParent()
+ relativeTo = next
+ else
+ --@debug@
+ print(' ',cWord(self:GetName()), 'parent =', cWord(parent))
+ --@debug-end@
+ end
+ end
+ end
+
+ -- This allows us to call for an immediate sub-frame and still get a usable value if it's not there
+ if childKey and relativeTo[childKey] then
+ return relativeTo[childKey]
+ end
+ return relativeTo
+end
+
+--- Animations
+F.animate_regions = {}
+setmetatable(F.animate_regions, {
+ __newindex = function (t,k,v)
+ rawset(t,k,v)
+ v.animationID = k
+ F.SetAnimationGroup(v)
+ end
+})
+
+--- Constructs the generic status frame
+function F:SetFrameLayout(c)
+ local print = GetPrint(c.trace)
+ self.trace = c.trace or self.trace
+
+ self.db = c
+ self.labels = {}
+
+ self.name = self:GetName()
+ self.combat = InCombatLockdown()
+ self:SetPoint(c.anchor, c.parent, c.anchorTo, c.x, c.y)
+ self:SetSize(c.width, c.height)
+ self:SetFrameStrata(c.strata)
+ self.throttle_rate = 0.010
+ self.throttle_point = GetTime()
+
+ if c.backdrop then
+ c.backdrop.edgeSize = c.padding*4
+ self:SetBackdrop(c.backdrop)
+ end
+ if c.background_color and c.border_color then
+ self:SetBackdropColor(unpack(c.background_color))
+ self:SetBackdropBorderColor(unpack(c.border_color))
+ end
+
+ --@debug@
+ print(namef('SetFrameLayout'),'(', valuet(self:GetName()),')')
+ print(cText(' dimensions:'), cNum(c.width), 'by', cNum(c.height), '::', c.x, c.y, c.anchor, c.anchorTo, c.parent)
+ --@end-debug@
+
+ self.width = c.width
+ self.height = c.height
+ self.foreground_inset = c.foreground_inset
+ self.padding = c.padding
+ self.spacing = c.spacing
+ self.alpha = c.alpha
+
+ self.combatFade = c.combatFade
+ self.alpha_fade_in = c.alpha_fade_in or c.alpha_fade
+ self.alpha_fade_out = c.alpha_fade_out or c.alpha_fade
+ print(' fade on combat =', self.combatFade)
+ for _, type in ipairs({'alpha', 'alpha_ooc'}) do
+ self[type] = c[type]
+ _G.print('DB', self:GetName(), type, self[type])
+ for _, subtype in ipairs({'_passive', '_active'}) do
+ self[type..subtype] = c[type..subtype] or self[type]
+ _G.print('DB', self:GetName(), type..subtype, self[type..subtype])
+ for _, subsubtype in ipairs({'_empty', '_half', '_full'}) do
+ self[type..subtype..subsubtype] = c[type..subtype..subsubtype] or self[type..subtype]
+ _G.print('DB', self:GetName(), type..subtype..subsubtype, self[type..subtype..subsubtype])
+ self[type..subsubtype] = c[type..subsubtype] or self[type..subtype]
+ _G.print('DB', self:GetName(), type..subsubtype, self[type..subsubtype])
+ end
+ end
+ end
+ self.UpdateAlpha = F.UpdateAlpha
+ --if c.combatFade then
+ self.faderID = #F.animate_regions+1
+ F.animate_regions[#F.animate_regions+1] = self
+ print(cText(' animation target ID #'), cNum(self.faderID))
+ --end
+
+ self:UpdateAlpha(InCombatLockdown())
+
+ if self.lefttext then
+ print(' auto-lefttext')
+ F.SetFontLayout(self.lefttext, c.lefttext or c)
+ end
+ if self.righttext then
+ print(' auto-righttext')
+ F.SetFontLayout(self.righttext, c.righttext or c)
+ end
+end
+
+--- Seeds basic animations, else a template can be specified by the frame data
+function F:SetAnimationGroup(group)
+ local print = GetPrint(self.trace)
+
+ group = group or self.animationClass or nil
+ --@debug@
+ if not group then
+ print(' |cFFFF44AAseeding debug animations', self:GetName())
+ self.__flash = self:CreateAnimationGroup(self:GetName()..'Flasher')
+ self.__flash:SetToFinalAlpha(true)
+ local fade1 = self.__flash:CreateAnimation('Alpha')
+ fade1:SetChange(-1)
+ fade1:SetDuration(.6)
+ fade1:SetOrder(1)
+ local fade2 = self.__flash:CreateAnimation('Alpha')
+ fade2:SetChange(1)
+ fade2:SetDuration(.6)
+ fade2:SetOrder(2)
+ fade2:SetEndDelay(.6)
+ --@debug@
+ self.__flash.fade1 = fade1
+ self.__flash.fade2 = fade2
+ self.__flash:SetLooping('NONE')
+ self.__flash:SetScript('OnFinished', function()
+ print(self:GetName(), '[>>>] Done animating flash.')
+ self.flashing = nil
+ end)--@end-debug@
+ self.Flash = F.Flash
+
+ self.__fade = self:CreateAnimationGroup(self:GetName()..'Fader')
+ self.__fade:SetToFinalAlpha(true)
+ self.__fade:SetScript('OnFinished', function()
+ print(self:GetName(), '[>>>] Done animating fade.')
+ self.fading = nil
+ local a = self.__flash.fade1:GetToAlpha()
+ --self:SetAlpha(a)
+ if a == 0 and not self.__fade.noHide then
+ self:Hide()
+ end
+ if self.__fade.queuedFade then
+ print('[>>>] ', cWord(self:GetName())..'.'..cKey('__fade:'), 'starting queued fade')
+ local fadeTo, fadeDuration, noHide = unpack(self.__fade.queuedFade)
+ self.__fade.queuedFade = nil
+ self:Fade(fadeTo, fadeDuration, noHide)
+ end
+ end)
+ self.Fade = F.Fade
+ end
+ --@end-debug@
+ if not self.animationID then
+ tinsert(F.animate_regions, self) -- uses rawset, so won't death loop
+ self.animationID = #F.animate_regions
+ end
+end
+
+function F:Flash(duration, peak, valley, holdUp, holdDown)
+ local print = GetPrint(self.trace)
+
+ local fl = self.__flash
+ print('[>>>]', self:GetName(), duration, peak, valley, holdUp, holdDown)
+ fl.fade1:SetFromAlpha(valley)
+ fl.fade1:SetToAlpha(peak)
+ fl.fade1:SetDuration(duration)
+ fl.fade1:SetEndDelay(holdUp)
+ fl.fade2:SetFromAlpha(peak)
+ fl.fade2:SetToAlpha(valley)
+ fl.fade2:SetDuration(duration)
+ fl.fade2:SetEndDelay(2)
+ self.flashing = true
+ fl:Play()
+end
+
+--- Fade to a value; fading to 0 will hide the frame
+function F:Fade(duration, fadeTo, noHide)
+
+ print('|cFFFF6600[>>>]', cText('Fade('), self:GetName(), cText(')'))
+ local fader = self.__fade
+ local fade1 = self.__flash.fade1
+ if fader:IsPlaying() then
+ self.__fade.queuedFade = {duration, fadeTo, noHide }
+ print(' ', cText('playing:'), cNum(fader:GetDuration())..'s', cNum(fade1:GetToAlpha()))
+ print(' ', cPink('queued {'), cNum(duration)..'s', cNum(self:GetAlpha()), 'to', cNum(fadeTo), '}')
+ return
+ else
+ print(' ', cNum('starting {'), cNum(duration), cNum(self:GetAlpha()), 'to', cNum(fadeTo), '}')
+ end
+ fade1:SetParent(fader)
+ fade1:SetFromAlpha(self:GetAlpha())
+ fade1:SetToAlpha(fadeTo)
+ fade1:SetDuration(duration)
+ fade1:SetOrder(1)
+ self.__fade.noHide = noHide
+ self.fading = true
+ fader:Play()
+end
+
+function F:Beep()
+ if self.quiet then
+ return
+ end
+ PlaySoundKitID(F.beepkit) -- random anub'rhekan sounds
+end
+
+
+--- Defines the corners used in filling operations
+local directionBase = {
+ ['LEFT'] = 'TOPRIGHT',
+ ['RIGHT'] = 'TOPLEFT',
+ ['UP'] = 'BOTTOMLEFT',
+ ['DOWN'] = 'TOPLEFT'
+}
+local directionPeak ={
+ ['LEFT'] = 'BOTTOMLEFT',
+ ['RIGHT'] = 'BOTTOMRIGHT',
+ ['UP'] = 'TOPRIGHT',
+ ['DOWN'] = 'BOTTOMRIGHT',
+}
+local directionPeakTo = {
+ ['LEFT'] = 'BOTTOMRIGHT',
+ ['RIGHT'] = 'BOTTOMLEFT',
+ ['UP'] = 'BOTTOMRIGHT',
+ ['DOWN'] = 'TOPRIGHT'
+}
+local anchorInverse = {['LEFT'] = 'RIGHT', ['RIGHT'] = 'LEFT', ['TOP'] = 'BOTTOM', ['BOTTOM'] = 'TOP' }
+--- Directional coefficients for corner positions
+-- [1] = end X, [2] = end Y, [3] = base X, [4] = base Y
+local directionCoord = {
+ ['LEFT'] = {-1, 0, -1, -1},
+ ['RIGHT'] = { 1, 0, 1, -1},
+ ['UP'] = { 0, 1, 1, 1},
+ ['DOWN'] = { 0, -1, 1, -1},
+ ['CENTER'] = {.5, .5, 1, 1}
+}
+local paddingScale = {
+ ['UP'] = 1,
+ ['DOWN'] = -1,
+ ['LEFT'] = -1,
+ ['RIGHT'] = 1,
+}
+local embedScale = {
+ ['LEFT'] = {1, false},
+ ['RIGHT'] = {-1, false},
+ ['TOP'] = {false, -1},
+ ['BOTTOM'] = {false, 1}
+}
+
+--- Determines the correct relative X offset for a given progress ratio
+--- x = 0 + padding + spacing + i, where i = {embedded | icon_size +spacing}
+-- Factors padding and spacing parameters, including icon embedding dimensions.
+-- @param self frame on which the foreground/background textures and config data exist
+-- @param ratio progess from 0 to 1; 0 returns the starting corner coordinate, 1 returns end corner
+-- @param scale overrides the pixel fill length, with starting corner used as scaling origin
+local TranslateX = function(self, ratio, scale)
+ if not scale then
+ scale = self.fill_width
+ end
+ if self.fill_inverse then
+ ratio = 1 - ratio
+ end
+ _G.print('Update', 'dx', self.fill_x)
+ local x =
+ scale * ratio * directionCoord[self.fill_direction][1]
+ return min(x, scale) + self.fill_x
+end
+
+--- Determines the correct relative Y offset for a given progress ratio
+-- Factors padding and spacing parameters, including icon embedding dimensions.
+-- @param self frame on which the foreground/background textures and config data exist
+-- @param ratio progess from 0 to 1; 0 returns the starting corner coordinate, 1 returns end corner
+-- @param scale overrides the pixel fill length, with starting corner used as scaling origin
+local TranslateY = function(self, ratio, scale)
+ if not scale then
+ scale = self.fill_height
+ end
+ if self.fill_inverse then
+ ratio = 1 - ratio
+ end
+
+ _G.print('Update', 'dy', self.fill_y)
+ -- (height of bar offset by the size of any overlapping element) * progress ratio, offset by the size of any overlapping embed + inset
+ local y =
+ scale * ratio * directionCoord[self.fill_direction][2] - self.foreground_inset
+ return min(y, scale) + self.fill_y
+end
+local SetProgress = function(self, progress, scaleX, scaleY)
+ _G.print('Update', cText(self:GetName()),
+ "\n d:", progress, 'dX:', directionCoord[self.fill_direction][1], 'dY:', directionCoord[self.fill_direction][2], 'dI:', self.fill_inverse,
+ "\n peak:", self.fill_anchor, self.fill_anchorTo, TranslateX(self, progress), TranslateY(self,progress))
+
+ self.foreground:SetPoint(self.fill_anchor, self.background, self.fill_anchorTo, TranslateX(self, progress, scaleX), TranslateY(self, progress, scaleY))
+end
+
+--- Assigns textures to the generic foreground background bar regions
+-- Called as F.SetStatusTextures(MyFrame, config pointer)
+-- foreground_inset - number of pixels by which the foreground edges occlude the background (basically always negative)
+-- padding - number of pixels between the background edge and frame edge (basically always positive)
+function F:SetStatusTextures(c)
+ local print = GetPrint(self.trace)
+
+ if c == nil then
+ c = self.db or lastdb
+ if not c then
+ error('No config table found')
+ end
+ end
+ local relativeTo = ParentValue(self, c.parent, c.parentKey)
+
+
+ self.fill_direction = c.fill_direction or 'RIGHT'
+ self.fill_inset = c.padding - c.foreground_inset -- foreground edge / frame edge
+ self.fill_width = self.width - self.fill_inset*2 -- foreground left / right edges
+ self.fill_height = self.height - self.fill_inset*2 -- " top / bottom "
+ self.fill_inverse = c.fill_inverse
+ self.fill_x, self.fill_y = 0, 0
+ self.fill_insets = {
+ LEFT = self.fill_inset,
+ TOP = self.fill_inset,
+ BOTTOM = self.fill_inset,
+ RIGHT = self.fill_inset
+ }
+
+
+ -- create filling points
+ self.fill_base = directionBase[self.fill_direction]
+ self.fill_anchor = directionPeak[self.fill_direction]
+ self.fill_anchorTo = directionPeakTo[self.fill_direction]
+ print(" foreground:", self.fill_base, self.fill_base, TranslateX(self, 0), TranslateY(self, 0))
+ print(" foreground fill:", self.fill_anchor, self.fill_anchorTo)
+
+ -- calculate icon embed
+ if self.icon and self.icon.embedded then
+ print(cText('#### EMBED ####'))
+ -- change anchor point so the icon is inside
+ self.icon.anchor = self.icon.anchorTo
+ print(' * Icon anchor:' , cText(self.icon.anchor), 'to', cText(self.icon.anchorTo))
+ print(' * Fill start:', cText(self.fill_base))
+
+
+ local coordSet = {nil, nil}
+ local baseSet = {nil, nil }
+ local endSet = {nil, nil}
+ for dir, coords in pairs(embedScale) do
+ if self.icon.anchor:match(dir) then
+ print(' xtrans { matches', dir, 'include {', coords[1], coords[2], '}')
+ if not coordSet[1] then coordSet[1] = coords[1] end
+ if not coordSet[2] then coordSet[2] = coords[2] end
+
+ -- the embedding position can overlap either corner
+ if self.fill_base:match(dir) then
+ print(' base corner also matches')
+ if not baseSet[1] then baseSet[1] = coords[1] end
+ if not baseSet[2] then baseSet[2] = coords[2] end
+ else
+
+ if not endSet[1] then endSet[1] = coords[1] end
+ if not endSet[2] then endSet[2] = coords[2] end
+ end
+ end
+ end
+
+ -- make sure there are values if none of them matched at all for some reason
+ coordSet = {coordSet[1] or 0, coordSet[2] or 0}
+ baseSet = {baseSet[1] or 0, baseSet[2] or 0 }
+ -- needs to produce a negative number
+ endSet = {endSet[1] or 0, endSet[2] or 0 }
+
+
+ print(' == xtrans push =', unpack(coordSet))
+ print(' == fbase delta =', unpack(baseSet))
+ print(' == ftail delta =', unpack(endSet))
+
+ -- determine the foreground displacement
+
+ self.icon_dx = (min(self.fill_width, self.fill_height) + self.spacing)
+ self.icon_dy = (min(self.fill_width, self.fill_height) + self.spacing)
+ print(' * Foreground compression:', cNum(self.icon_dx))
+
+ self.icon_size = self.icon.size
+ self.icon_x = self.padding * baseSet[1] - (self.icon.size - self.icon_dx)
+ self.icon_y = self.padding * baseSet[2] - (self.icon.size - self.icon_dy)
+ print(' * Icon dims:' , cNum(self.icon_size), ' offset:', cNum(self.icon_dx))
+
+
+ local ofi = self.fill_insets[self.fill_direction]
+ print(' * Fill inset('..cWord(self.fill_direction)..') from', cNum(ofi), 'to', cNum(self.fill_insets[self.fill_direction]))
+
+ -- used to place the starting corner
+ self.fill_x = (self.icon_dx) * baseSet[1]
+ self.fill_y = (self.icon_dy) * baseSet[2]
+ print(' * fill offset dX:', self.fill_x)
+ print(' * fill offset dY:', self.fill_y)
+
+ -- amount taken off of fill scale, subtract spacing
+ self.icon_dx_cut = abs(self.icon_dx * -baseSet[1])
+ self.icon_dy_cut = abs(self.icon_dy * -baseSet[2])
+
+ local ofw, ofh = self.fill_width, self.fill_height
+ self.fill_width = self.fill_width - self.icon_dx_cut
+ self.fill_height = self.fill_height - self.icon_dy_cut
+ print(' * Scale dX:', self.icon_dx_cut, cNum(ofw), 'to', cNum(self.fill_width))
+ print(' * Scale dY:', self.icon_dy_cut, cNum(ofh), 'to', cNum(self.fill_height))
+
+ self.icon:ClearAllPoints()
+ self.icon:SetPoint(self.icon.anchor, self, self.icon.anchorTo, self.icon_x, self.padding * coordSet[2])
+ self.icon:SetSize(self.icon_size, self.icon_size)
+ end
+
+ --@debug@
+ print(namet('SetStatusTextures'),'(', valuef(self:GetName()), ')')
+ print(' form:', self.padding,'-', self.foreground_inset, '+', self.fill_width, self.padding,'-', self.foreground_inset, '+','x', self.padding,'-', self.foreground_inset, '+', self.fill_height, self.padding,'-', self.foreground_inset, '+')
+ print(' ', valuen(concat(c.background_color,', ')),valuet(c.background_texture), valuen(concat(c.foreground_color,', ')), valuet(c.foreground_texture))
+ print(' background:', self.padding, self.padding, 'BOTTOMLEFT', 'BOTTOMLEFT' , '::', -self.padding, -self.padding, 'TOPRIGHT', 'TOPRIGHT')
+ --@end-debug@
+
+ self.background:ClearAllPoints()
+ self.background:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', self.padding, self.padding)
+ self.background:SetPoint('TOPRIGHT', self, 'TOPRIGHT', -self.padding, -self.padding)
+ if c.background_texture ~= '' and c.background_texture ~= nil then
+ self.background:SetTexture(c.background_texture)
+ self.background:SetVertexColor(unpack(c.background_color))
+ else
+ self.background:SetTexture(unpack(c.background_color))
+ end
+ self.background:SetBlendMode(c.background_blend)
+
+ if c.foreground_texture ~= '' and c.foreground_texture ~= nil then
+ self.foreground:SetTexture(c.foreground_texture)
+ self.foreground:SetVertexColor(unpack(c.foreground_color))
+ else
+ self.foreground:SetTexture(unpack(c.foreground_color))
+ end
+ self.foreground:SetBlendMode(c.foreground_blend)
+
+ self.foreground:ClearAllPoints()
+ local dx = (directionCoord[self.fill_direction][3] * -self.foreground_inset) + self.fill_x
+ local dy = (directionCoord[self.fill_direction][4] * -self.foreground_inset) + self.fill_y
+ print(' foreground base:', cNum(dx), cNum(dy))
+ self.foreground:SetPoint(self.fill_base, self.background, self.fill_base, dx, dy)
+
+ SetProgress(self, 1)
+
+ self.TranslateX = TranslateX
+ self.TranslateY = TranslateY
+ self.SetFillPoints = SetFillPoints
+ self.SetProgress = SetProgress
+end
+--- Sets properties for a generated FontString
+-- Takes the FontString object as a self, and applies config values.
+-- In particalur, the anchor parent is derived from either a fixed number of GetParent() or global name
+-- @usage Region:SetFontLayout([table])
+function F:SetFontLayout (c)
+ local print = GetPrint(self.trace)
+
+ if c == nil then
+ c = lastdb
+ if not c then
+ error('No config table found')
+ end
+ end
+ local relativeTo = ParentValue(self, c.parent, c.parentKey)
+
+ --@debug@
+ print(namet('FontLayout'),'(', valuet(self:GetName()), ')', valuet(c.font), valuet(c.size), valuet(c.outline))
+ print(' ', valuen(c.anchor or 'CENTER'), relativeTo:GetName(), valuen(c.anchorTo or 'CENTER'), valued(c.x or 0),
+ valued(c.y or 0))
+ --@end-debug@
+ self:SetPoint(
+ c.anchor or 'CENTER',
+ relativeTo,
+ c.anchorTo or 'CENTER',
+ c.x or 0,
+ c.y or 0)
+ self:SetSize(
+ c.width or relativeTo:GetWidth(),
+ c.height or relativeTo:GetHeight())
+ self:SetFont(
+ c.font,
+ c.size,
+ c.outline)
+ self:SetJustifyH(c.justifyH or 'CENTER')
+ self:SetJustifyV(c.justifyV or 'MIDDLE')
+ self:SetTextColor(unpack(c.text_color or {1,1,1,1}))
+end
+
+--- For setting up widget pieces
+function F:SetTextureLayout(c)
+ local print = GetPrint(self.trace)
+
+ if c == nil then
+ c = lastdb
+ if not c then
+ error('No config table found')
+ end
+ end
+ local relativeTo = ParentValue(self, c.parent, c.parentKey)
+
+ self.size = c.size
+ self.width = c.width
+ self.height = c.height
+ self.x = c.x
+ self.y = c.y
+ self.embedded = c.embedded
+ self.anchor = c.anchor
+ self.anchorTo = c.anchorTo
+
+ self:SetPoint(c.anchor, relativeTo, c.anchorTo, c.x, c.y)
+ self:SetSize(c.size or c.width, c.size or c.height)
+ self:SetAlpha(c.alpha)
+ self:SetDesaturated(c.desaturated or false)
+ print('|cFF00FFFFSetTextureLayout(|r', self:GetName(), '|cFF00FFFF)|r')
+ print(' ', c.anchor, relativeTo, c.anchorT, c.x, c.v)
+ if c.combatFade and not (relativeTo.faderID and F.animate_regions[relativeTo.faderID]) then
+ tinsert(F.animate_regions, self)
+ self.faderID = #F.animate_regions
+ --@debug@
+ print('register fadeable texture #'..self.faderID)
+ --@end-debug@
+ end
+end
+
+local alphaSubType = {
+ [1] = '_passive',
+ [2] = '_active'
+}
+local alphaFillType = {
+ [1] = '_empty',
+ [2] = '_half',
+ [3] = '_full',
+}
+function F:UpdateAlpha(inCombat, displayState, fillState)
+ local print = function() end
+ print(cWord('UpdateAlpha(')..self:GetName()..cWord(')'))
+ local alphaType = inCombat and 'alpha' or 'alpha_ooc'
+ local alphaDuration = inCombat and 'alpha_fade_in' or 'alpha_fade_out'
+ local displayState = displayState or self.displayState or nil
+ local fillState = fillState or self.fillState or nil
+
+ local alphaSubType = ''
+ if displayState then
+ alphaSubType = (displayState == 1) and '_passive' or ((displayState == 2) and '_active' or '' )
+ end
+
+ local alphaFillType = ''
+ if fillState then
+ alphaFillType = (fillState == 1) and '_half' or ((fillState == 2) and '_full' or '_empty')
+ end
+
+ local fadeTo = self[alphaType..alphaSubType..alphaFillType]
+ local fadeDuration = self[alphaDuration] or 0
+ print(' alphaKey:', cWord(alphaType..alphaSubType..alphaFillType))
+ print(' alphaTo:', cNum(fadeTo), 'duration:', cNum(fadeDuration))
+ if self:IsVisible() and fadeDuration ~= 0 then
+ self:Fade(fadeDuration, fadeTo or (inCombat and 1 or 0.5), true)
+ print(' |cFFFFFF00 :Fade()|r', 'dur='..cNum(fadeDuration), cNum(fadeTo), cWord(self:GetName()))
+ else
+ self:SetAlpha(fadeTo)
+ print(' |cFF00FF00 :SetAlpha('..fadeTo..')|r', cText(self:GetName()))
+ end
+end
+
+--- Sets an OnUpdate within a time-throttled wrapper
+-- throttle rate should be slightly smaller than 1/average frame rate
+function F:SetFrameScript(updateFunc, showFunc, hideFunc, ...)
+ local print = GetPrint(self.trace)
+
+ if not self.__oldscripts then
+ self.__oldscripts = {}
+ end
+
+ self:SetScript('OnUpdate', nil) -- clear any scripts
+ self:SetSCript('OnUpdate', function(self)
+ if GetTime() < self.throttle_time then
+ return
+ end
+ self.throttle_time = self.throttle_time + self.throttle_rate
+ updateFunc(self)
+ end) -- put the new function in its place
+ local changeSet = {
+ { self.__oldscripts,onUpdate = self:GetScript('OnUpdate') },
+ }
+
+ if showFunc then
+ tinsert(changeSet,
+ {onShow = self:GetScript('OnShow')})
+ self:SetScript('OnShow', showFunc)
+ end
+
+ if hideFunc then
+ tinsert(changeSet,
+ {onHide = self:GetScript('OnShow')})
+ self:SetScript('OnHide', hideFunc)
+ end
+end
+
+--- Embed
+function F:Embed(object)
+ print('Doing embed')
+ for k, v in pairs(ui_embeds) do
+ print('embedding Set'..k..'Layout')
+ object['Set'..k..'Layout'] = self[v]
+ end
+ object.SetStatusTextures = self.SetStatusTextures
+
+ --- map a generic layout method if embedded into a frame object
+ if object.GetObjectType and ui_embeds[object.GetObjectType()] then
+ if ui_embeds[object.GetObjectType()] then
+ object.SetLayout = ui_embeds[object.GetObjectType()]
+ end
+ end
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Layout/Layout.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Layout/Layout.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+ self.throttle_point = 0
+ if self.labels then
+ for _,label in pairs(self.labels) do
+ label:Show()
+ end
+ end
+
+
+ if self.labels then
+ for _,label in pairs(self.labels) do
+ label:Hide()
+ end
+ end
+
+
+ if GetTime() < self.throttle_point then
+ return
+ end
+ self.throttle_point = self.throttle_point + 0.010
+ if self.db and self.db.preUpdate then
+ self.db.preUpdate(self)
+ end
+ self:Update()
+ if self.db and self.db.postUpdate then
+ self.db.postUpdate(self)
+ end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.lefttext = self.overlay.lefttext
+ self.righttext = self.overlay.righttext
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Media.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,96 @@
+local LSM = LibStub("LibSharedMedia-3.0")
+
+-- -----
+-- BACKGROUND
+-- -----
+
+-- -----
+-- BORDER
+-- ----
+LSM:Register("border", "BG-Solid", [[Interface\Addons\Turok\Media\border\BG-Solid.blp]])
+LSM:Register("border", "BG-Solid", [[Interface\Addons\Turok\Media\border\BG-Solid.png]])
+LSM:Register("border", "BigBorder-Solid", [[Interface\Addons\Turok\Media\border\BigBorder-Solid.blp]])
+LSM:Register("border", "BigBorder-Solid", [[Interface\Addons\Turok\Media\border\BigBorder-Solid.png]])
+
+-- -----
+-- FONT
+-- -----
+LSM:Register("font", "ArchivoNarrow-Bold", [[Interface\Addons\Turok\Media\font\ArchivoNarrow-Bold.ttf]])
+LSM:Register("font", "ArchivoNarrow-BoldItalic", [[Interface\Addons\Turok\Media\font\ArchivoNarrow-BoldItalic.ttf]])
+LSM:Register("font", "ArchivoNarrow-Italic", [[Interface\Addons\Turok\Media\font\ArchivoNarrow-Italic.ttf]])
+LSM:Register("font", "ArchivoNarrow-Regular", [[Interface\Addons\Turok\Media\font\ArchivoNarrow-Regular.ttf]])
+LSM:Register("font", "Arvo-Bold", [[Interface\Addons\Turok\Media\font\Arvo-Bold.ttf]])
+LSM:Register("font", "Arvo-BoldItalic", [[Interface\Addons\Turok\Media\font\Arvo-BoldItalic.ttf]])
+LSM:Register("font", "Arvo-Italic", [[Interface\Addons\Turok\Media\font\Arvo-Italic.ttf]])
+LSM:Register("font", "Arvo-Regular", [[Interface\Addons\Turok\Media\font\Arvo-Regular.ttf]])
+LSM:Register("font", "constan", [[Interface\Addons\Turok\Media\font\constan.ttf]])
+LSM:Register("font", "DroidSerif-Bold", [[Interface\Addons\Turok\Media\font\DroidSerif-Bold.ttf]])
+LSM:Register("font", "DroidSerif-BoldItalic", [[Interface\Addons\Turok\Media\font\DroidSerif-BoldItalic.ttf]])
+LSM:Register("font", "DroidSerif-Italic", [[Interface\Addons\Turok\Media\font\DroidSerif-Italic.ttf]])
+LSM:Register("font", "DroidSerif", [[Interface\Addons\Turok\Media\font\DroidSerif.ttf]])
+LSM:Register("font", "OpenSans-Bold", [[Interface\Addons\Turok\Media\font\OpenSans-Bold.ttf]])
+LSM:Register("font", "OpenSans-BoldItalic", [[Interface\Addons\Turok\Media\font\OpenSans-BoldItalic.ttf]])
+LSM:Register("font", "OpenSans-ExtraBold", [[Interface\Addons\Turok\Media\font\OpenSans-ExtraBold.ttf]])
+LSM:Register("font", "OpenSans-ExtraBoldItalic", [[Interface\Addons\Turok\Media\font\OpenSans-ExtraBoldItalic.ttf]])
+LSM:Register("font", "OpenSans-Italic", [[Interface\Addons\Turok\Media\font\OpenSans-Italic.ttf]])
+LSM:Register("font", "OpenSans-Light", [[Interface\Addons\Turok\Media\font\OpenSans-Light.ttf]])
+LSM:Register("font", "OpenSans-LightItalic", [[Interface\Addons\Turok\Media\font\OpenSans-LightItalic.ttf]])
+LSM:Register("font", "OpenSans-Regular", [[Interface\Addons\Turok\Media\font\OpenSans-Regular.ttf]])
+LSM:Register("font", "OpenSans-SemiboldItalic", [[Interface\Addons\Turok\Media\font\OpenSans-SemiboldItalic.ttf]])
+LSM:Register("font", "PT_Sans-Narrow-Web-Bold", [[Interface\Addons\Turok\Media\font\PT_Sans-Narrow-Web-Bold.ttf]])
+LSM:Register("font", "PT_Sans-Narrow-Web-Regular", [[Interface\Addons\Turok\Media\font\PT_Sans-Narrow-Web-Regular.ttf]])
+LSM:Register("font", "Roboto-Black", [[Interface\Addons\Turok\Media\font\Roboto-Black.ttf]])
+LSM:Register("font", "Roboto-BlackItalic", [[Interface\Addons\Turok\Media\font\Roboto-BlackItalic.ttf]])
+LSM:Register("font", "Roboto-Bold", [[Interface\Addons\Turok\Media\font\Roboto-Bold.ttf]])
+LSM:Register("font", "Roboto-BoldItalic", [[Interface\Addons\Turok\Media\font\Roboto-BoldItalic.ttf]])
+LSM:Register("font", "Roboto-Italic", [[Interface\Addons\Turok\Media\font\Roboto-Italic.ttf]])
+LSM:Register("font", "Roboto-Light", [[Interface\Addons\Turok\Media\font\Roboto-Light.ttf]])
+LSM:Register("font", "Roboto-LightItalic", [[Interface\Addons\Turok\Media\font\Roboto-LightItalic.ttf]])
+LSM:Register("font", "Roboto-Medium", [[Interface\Addons\Turok\Media\font\Roboto-Medium.ttf]])
+LSM:Register("font", "Roboto-MediumItalic", [[Interface\Addons\Turok\Media\font\Roboto-MediumItalic.ttf]])
+LSM:Register("font", "Roboto-Regular", [[Interface\Addons\Turok\Media\font\Roboto-Regular.ttf]])
+LSM:Register("font", "Roboto-Thin", [[Interface\Addons\Turok\Media\font\Roboto-Thin.ttf]])
+LSM:Register("font", "Roboto-ThinItalic", [[Interface\Addons\Turok\Media\font\Roboto-ThinItalic.ttf]])
+LSM:Register("font", "RobotoSlab-Bold", [[Interface\Addons\Turok\Media\font\RobotoSlab-Bold.ttf]])
+LSM:Register("font", "RobotoSlab-Light", [[Interface\Addons\Turok\Media\font\RobotoSlab-Light.ttf]])
+LSM:Register("font", "RobotoSlab-Regular", [[Interface\Addons\Turok\Media\font\RobotoSlab-Regular.ttf]])
+LSM:Register("font", "RobotoSlab-Thin", [[Interface\Addons\Turok\Media\font\RobotoSlab-Thin.ttf]])
+LSM:Register("font", "SourceCodePro-Black", [[Interface\Addons\Turok\Media\font\SourceCodePro-Black.ttf]])
+LSM:Register("font", "SourceCodePro-Bold", [[Interface\Addons\Turok\Media\font\SourceCodePro-Bold.ttf]])
+LSM:Register("font", "SourceCodePro-ExtraLight", [[Interface\Addons\Turok\Media\font\SourceCodePro-ExtraLight.ttf]])
+LSM:Register("font", "SourceCodePro-Light", [[Interface\Addons\Turok\Media\font\SourceCodePro-Light.ttf]])
+LSM:Register("font", "SourceCodePro-Medium", [[Interface\Addons\Turok\Media\font\SourceCodePro-Medium.ttf]])
+LSM:Register("font", "SourceCodePro-Regular", [[Interface\Addons\Turok\Media\font\SourceCodePro-Regular.ttf]])
+LSM:Register("font", "SourceCodePro-Semibold", [[Interface\Addons\Turok\Media\font\SourceCodePro-Semibold.ttf]])
+LSM:Register("font", "turok", [[Interface\Addons\Turok\Media\font\turok.ttf]])
+
+-- -----
+-- SOUND
+-- -----
+LSM:Register("sound", "Bell", [[Interface\Addons\Turok\Media\sound\Bell.ogg]])
+LSM:Register("sound", "Chime", [[Interface\Addons\Turok\Media\sound\Chime.ogg]])
+LSM:Register("sound", "Electro_-S_Bainbr-7953_hifi", [[Interface\Addons\Turok\Media\sound\Electro_-S_Bainbr-7953_hifi.mp3]])
+LSM:Register("sound", "Electro_-S_Bainbr-7955_hifi", [[Interface\Addons\Turok\Media\sound\Electro_-S_Bainbr-7955_hifi.mp3]])
+LSM:Register("sound", "FLASH", [[Interface\Addons\Turok\Media\sound\FLASH.mp3]])
+LSM:Register("sound", "Heart", [[Interface\Addons\Turok\Media\sound\Heart.ogg]])
+LSM:Register("sound", "High_Bee-Public_D-135_hifi", [[Interface\Addons\Turok\Media\sound\High_Bee-Public_D-135_hifi.mp3]])
+LSM:Register("sound", "IM", [[Interface\Addons\Turok\Media\sound\IM.ogg]])
+LSM:Register("sound", "Info", [[Interface\Addons\Turok\Media\sound\Info.ogg]])
+LSM:Register("sound", "Kachink", [[Interface\Addons\Turok\Media\sound\Kachink.ogg]])
+LSM:Register("sound", "Link", [[Interface\Addons\Turok\Media\sound\Link.ogg]])
+LSM:Register("sound", "Low_Beep-Public_D-136_hifi", [[Interface\Addons\Turok\Media\sound\Low_Beep-Public_D-136_hifi.mp3]])
+LSM:Register("sound", "Oringz-881", [[Interface\Addons\Turok\Media\sound\Oringz-881.mp3]])
+LSM:Register("sound", "Oringz-940", [[Interface\Addons\Turok\Media\sound\Oringz-940.mp3]])
+LSM:Register("sound", "polish-xrikazen-7425_hifi", [[Interface\Addons\Turok\Media\sound\polish-xrikazen-7425_hifi.mp3]])
+LSM:Register("sound", "Quack", [[Interface\Addons\Turok\Media\sound\Quack.ogg]])
+LSM:Register("sound", "SquishFart", [[Interface\Addons\Turok\Media\sound\SquishFart.ogg]])
+LSM:Register("sound", "Text1", [[Interface\Addons\Turok\Media\sound\Text1.ogg]])
+LSM:Register("sound", "Text2", [[Interface\Addons\Turok\Media\sound\Text2.ogg]])
+LSM:Register("sound", "wilhelm", [[Interface\Addons\Turok\Media\sound\wilhelm.ogg]])
+LSM:Register("sound", "Xylo", [[Interface\Addons\Turok\Media\sound\Xylo.ogg]])
+
+-- -----
+-- STATUSBAR
+-- -----
+LSM:Register("statusbar", "Minimalist", [[Interface\Addons\Turok\Media\statusbar\Minimalist.tga]])
+LSM:Register("statusbar", "Otravi", [[Interface\Addons\Turok\Media\statusbar\Otravi.tga]])
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/Manifest.bat.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Media/Manifest.bat.txt Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,59 @@
+@echo off
+echo This script will create our assets manifest for LibSharedMedia
+
+
+echo Creating the file...
+echo local LSM = LibStub("LibSharedMedia-3.0") > ..\Media.lua
+
+echo BACKGROUND
+echo.>> ..\Media.lua
+echo -- ----- >> ..\Media.lua
+echo -- BACKGROUND >> ..\Media.lua
+echo -- ----- >> ..\Media.lua
+for %%F in (..\Media\background\*.*) do (
+echo %%~nF
+echo LSM:Register("background", "%%~nF", [[Interface\Addons\Turok\Media\background\%%~nxF]]^) >> ..\Media.lua
+)
+
+echo BORDER
+echo.>> ..\Media.lua
+echo -- ----- >> ..\Media.lua
+echo -- BORDER >> ..\Media.lua
+echo -- ---- >> ..\Media.lua
+for %%F in (..\Media\border\*.*) do (
+echo %%~nF
+echo LSM:Register("border", "%%~nF", [[Interface\Addons\Turok\Media\border\%%~nxF]]^) >> ..\Media.lua
+)
+
+echo FONT
+echo.>> ..\Media.lua
+echo -- ----->> ..\Media.lua
+echo -- FONT>> ..\Media.lua
+echo -- ----->> ..\Media.lua
+for %%F in (..\Media\font\*.ttf) do (
+echo %%~nF
+echo LSM:Register("font", "%%~nF", [[Interface\Addons\Turok\Media\font\%%~nxF]]^) >> ..\Media.lua
+)
+
+echo SOUND
+echo.>> ..\Media.lua
+echo -- ----->> ..\Media.lua
+echo -- SOUND>> ..\Media.lua
+echo -- ----->> ..\Media.lua
+for %%F in (..\Media\sound\*.*) do (
+echo %%~nF
+echo LSM:Register("sound", "%%~nF", [[Interface\Addons\Turok\Media\sound\%%~nxF]]^) >> ..\Media.lua
+)
+
+echo STATUSBAR
+echo.>> ..\Media.lua
+echo -- ----->> ..\Media.lua
+echo -- STATUSBAR>> ..\Media.lua
+echo -- ----->> ..\Media.lua
+for %%F in (..\Media\statusbar\*.*) do (
+echo %%~nF
+echo LSM:Register("statusbar", "%%~nF", [[Interface\Addons\Turok\Media\statusbar\%%~nxF]]^) >> ..\Media.lua
+)
+
+:end_of_file
+pause
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/border/BG-Solid.blp
Binary file Turok/Media/border/BG-Solid.blp has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/border/BG-Solid.png
Binary file Turok/Media/border/BG-Solid.png has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/border/BigBorder-Solid.blp
Binary file Turok/Media/border/BigBorder-Solid.blp has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/border/BigBorder-Solid.png
Binary file Turok/Media/border/BigBorder-Solid.png has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Bell.ogg
Binary file Turok/Media/sound/Bell.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Chime.ogg
Binary file Turok/Media/sound/Chime.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Electro_-S_Bainbr-7953_hifi.mp3
Binary file Turok/Media/sound/Electro_-S_Bainbr-7953_hifi.mp3 has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Electro_-S_Bainbr-7955_hifi.mp3
Binary file Turok/Media/sound/Electro_-S_Bainbr-7955_hifi.mp3 has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/FLASH.mp3
Binary file Turok/Media/sound/FLASH.mp3 has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Heart.ogg
Binary file Turok/Media/sound/Heart.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/High_Bee-Public_D-135_hifi.mp3
Binary file Turok/Media/sound/High_Bee-Public_D-135_hifi.mp3 has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/IM.ogg
Binary file Turok/Media/sound/IM.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Info.ogg
Binary file Turok/Media/sound/Info.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Kachink.ogg
Binary file Turok/Media/sound/Kachink.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Link.ogg
Binary file Turok/Media/sound/Link.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Low_Beep-Public_D-136_hifi.mp3
Binary file Turok/Media/sound/Low_Beep-Public_D-136_hifi.mp3 has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Oringz-881.mp3
Binary file Turok/Media/sound/Oringz-881.mp3 has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Oringz-940.mp3
Binary file Turok/Media/sound/Oringz-940.mp3 has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Quack.ogg
Binary file Turok/Media/sound/Quack.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/SquishFart.ogg
Binary file Turok/Media/sound/SquishFart.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Text1.ogg
Binary file Turok/Media/sound/Text1.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Text2.ogg
Binary file Turok/Media/sound/Text2.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/Xylo.ogg
Binary file Turok/Media/sound/Xylo.ogg has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/sound/polish-xrikazen-7425_hifi.mp3
Binary file Turok/Media/sound/polish-xrikazen-7425_hifi.mp3 has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/statusbar/Aluminium.tga
Binary file Turok/Media/statusbar/Aluminium.tga has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/statusbar/Armory.tga
Binary file Turok/Media/statusbar/Armory.tga has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/statusbar/Minimalist.tga
Binary file Turok/Media/statusbar/Minimalist.tga has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Media/statusbar/Otravi.tga
Binary file Turok/Media/statusbar/Otravi.tga has changed
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/Castbar.Init.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/Castbar.Init.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,124 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 12/28/2015 8:00 AM
+
+Turok.defaults.tek = {
+ width = 300, height = 30,
+ anchor = 'CENTER', parent = 'UIParent', anchorTo = 'CENTER',
+ x = 0, y = 0,
+ foreground_blend = 'BLEND',
+ background_blend = 'BLEND',
+ background_texture = '',
+ background_color = {1,1,1,0.2},
+ combatFade = false,
+
+ foreground_channeling = {0.4,0.2,0.9,1},
+ background_channeling = {0.25,0.25,0.25,1},
+ foreground_casting = {0.01, 0.46, 0.93, 1},
+ background_casting = {0,0,0,0.0},
+ background_interrupted = {1,0,0,1},
+ foreground_interrupted = {1, 0.5, 0, 1},
+ foreground_uninterruptible = {0.8, 0.8, .8, 1},
+ background_uninterruptible = {0,0,0,0.25},
+ background_failed = {0.25,0.25,0.25, 1},
+ foreground_failed = {1,0.5,0.5,0.25},
+ foreground_finished = {0.4,.7,.1, 1},
+ background_finished = {0,0,0,0.25},
+ foreground_inset = 0,
+ padding = 2,
+ spacing = 1,
+
+ icon = {
+ size = 56,
+ anchor = 'RIGHT', anchorTo = 'LEFT',
+ parent = 1,
+ x = 0, y = 0,
+ },
+
+ fill_direction = 'RIGHT',
+
+ glow_texture = "Tooltip-BigBorder",
+ glow_size = 2,
+ spark_texture = "",
+ spark_size = 2,
+ spellname = {},
+ casttime = {},
+ ping = {
+ anchor='TOPRIGHT',
+ anchorTo='BOTTOMRIGHT',
+ x = -6, y= 0,
+ parent = 1,
+ parentKey = 'background',
+ color = {1,1,0,0.7},
+ size = 12,
+ font = "Interface\\Addons\\Turok\\Media\\font\\ArchivoNarrow-Bold.ttf",
+ justifyH = 'RIGHT',
+ justifyV = 'BOTTOM'
+ },
+ casttime = {
+ parent = 1,
+ parentKey = 'background',
+ x = -6, y= 0,
+ anchor = 'RIGHT',
+ anchorTo = 'RIGHT',
+ justifyH = 'RIGHT',
+ justifyV = 'MIDDLE'
+ },
+ spelltext = {
+ parent = 1,
+ parentKey = 'foreground',
+ x = 6, y = 0,
+ anchor = 'LEFT',
+ anchorTo = 'LEFT',
+ justifyH = 'LEFT',
+ justifyV = 'MIDDLE',
+ },
+ downtime = {
+ parent = 1,
+ parentKey = 'foreground',
+ anchor='TOPLEFT',
+ anchorTo='BOTTOMLEFT',
+ x = 0, y = 0,
+ text_color = {.75,.75,.75,1},
+ justifyH = 'LEFT',
+ },
+ ['player'] = {
+ icon = {
+ embedded = true,
+ size = 36,
+ anchor = 'RIGHT', anchorTo = 'LEFT',
+ parent = 1,
+ x = -2, y = 0,
+ },
+ width = 330, height = 32,
+ anchor = 'TOP', parent = 'UIParent', anchorTo = 'CENTER',
+ x = 0, y = -254,
+ },
+ ['target'] = {
+ icon = {
+ embedded = true,
+ size = 36,
+ width = 300,
+ anchor = 'LEFT', anchorTo = 'LEFT',
+ parent = 'TekplayerCastBar',
+ x = -2, y = 0,
+ },
+
+ width = 300, height = 24,
+ height = 36,
+ anchor = 'BOTTOMLEFT', parent = 'TekplayerCastBar', anchorTo = 'TOPRIGHT',
+ x = 1, y =1,
+ },
+ ['focus'] = {
+ width = 200, height = 36,
+ anchor = 'TOPLEFT', parent = 'TekplayerCastBar', anchorTo='BOTTOMRIGHT',
+ x = 2, y = -2
+ },
+ ['pet'] = {
+ width = 300, height = 24,
+ anchor = 'TOPRIGHT', parent = 'TekplayerCastBar', anchorTo='TOPLEFT',
+ x = -2, y = 0
+ },
+}
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/Castbar.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/Castbar.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,510 @@
+--- Turok
+-- Castbar.lua
+-- Created: 12/4/2015 11:17 PM
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Deals with casting events and works the castingbar interface
+local print, tostring, tonumber, rep, pairs, min, format, unpack, select, strpad = print, tostring, tonumber, string.rep, pairs, math.min, string.format, unpack, select, string.rep
+local GetTime, UnitCastingInfo, UnitChannelInfo, GetSpellInfo, GetSpellTabInfo = GetTime, UnitCastingInfo, UnitChannelInfo, GetSpellInfo, GetSpellTabInfo
+local floor = math.floor
+local T = Turok
+local db
+local PING_CEILING = 190 -- transpacific
+local PING_MIDLINE = 100
+local PING_FLOOR = 10 -- transcontinental
+--@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('Tek', ...)
+ end
+end
+
+local EVENT_COLOR = '|cFF44FF44'
+local EVENT_COLOR2 = '|cFF88FF88'
+local DATA_COLOR = '|cFFDD77DD'
+--@end-debug@
+
+local mod = T:NewModule("Tek")
+function mod:OnInitialize()
+ self.db = T.db.tek
+ self.castbar = {}
+ self.UNIT_SPELLCAST_SENT = self.SpellCastRequest
+ self.UNIT_SPELLCAST_START = self.SpellCastEvent
+ self.UNIT_SPELLCAST_DELAYED = self.SpellCastEvent
+ self.UNIT_SPELLCAST_SUCCEEDED = self.SpellCastEvent
+ self.UNIT_SPELLCAST_STOP = self.SpellCastEvent
+ self.UNIT_SPELLCAST_FAILED = self.SpellCastEvent
+ self.UNIT_SPELLCAST_INTERRUPTED = self.SpellCastEvent
+ self.UNIT_SPELLCAST_CHANNEL_START = self.SpellCastEvent
+ self.UNIT_SPELLCAST_CHANNEL_STOP = self.SpellCastEvent
+ self.UNIT_SPELLCAST_CHANNEL_UPDATE = self.SpellCastEvent
+ self.UNIT_SPELLCAST_INTERRUPTIBLE = self.SpellCastEvent
+ self.UNIT_SPELLCAST_UNINTERRUPTIBLE = self.SpellCastEvent
+end
+
+--- events & units
+local TRACKED_UNITS = {'player', 'target', 'focus', 'pet'}
+local FADE_OUT_TIME, FADE_IN_TIME = 1, .2
+
+local TEXTURE_SUFFIX = {
+ ['CHANNEL_START'] = '_channeling',
+ ['CHANNEL_UPDATE'] = '_channeling',
+ ['CHANNEL_STOPPED'] = '_channeling',
+ ['START'] = '_casting',
+ ['INTERRUPTED'] = '_interrupted',
+ ['SUCCEEDED'] = '_finished',
+}
+
+function mod:OnEnable()
+ db = self.db
+ -- setup castingbar frames
+ local c = self.castbar
+ for _, unit in pairs(TRACKED_UNITS) do
+ local cdb = db[unit]
+ --@debug@
+ print(DATA_COLOR .. unit .. '|r castbar creation')--@end-debug@
+
+ -- Set frames
+ local fn = 'Tek' .. unit .. 'CastBar'
+ c[unit] = CreateFrame('Frame', fn, _G[cdb.parent], 'TurokCastingBar')
+
+ local pc = c[unit]
+ T.SetFrameLayout(pc, cdb)
+ T.SetTextureLayout(pc.icon, cdb.icon or db.icon)
+ T.SetStatusTextures(pc, cdb.statusbar or db.statusbar)
+
+ if unit == 'player' then
+ T.SetFontLayout(pc.ping, db.ping)
+ T.SetFontLayout(pc.downtime, db.downtime)
+ pc.pingbar:ClearAllPoints()
+ pc.pingbar:SetPoint('TOPRIGHT', pc.background, 'TOPRIGHT', 0, 0)
+ pc.pingbar:SetHeight(pc.background:GetHeight())
+ else
+ if pc.interrupt then
+ pc.interrupt:SetSize(pc.icon.size*3, pc.icon.size* 3)
+ end
+
+ end
+
+ T.SetFontLayout(pc.casttime, cdb.casttime or db.casttime)
+ T.SetFontLayout(pc.spelltext, cdb.spelltext or db.spelltext)
+
+ pc:SetAlpha(0)
+ pc.last = nil
+ pc.sent = {}
+ pc.unit = unit
+ pc.SetSpell = self.SetSpell
+ pc.SetState = self.SetState
+ pc.Update = self.Update
+ end
+
+
+ -- kill default casting bar
+ -- T.cbscripts = {CastingBarFrame:GetScript('OnUpdate'), CastingBarFrame:GetScript('OnEvent')}
+ CastingBarFrame:SetScript('OnUpdate', nil)
+ CastingBarFrame:SetScript('OnEvent', nil)
+ CastingBarFrame:Hide()
+ PetCastingBarFrame:SetScript('OnUpdate', nil)
+ PetCastingBarFrame:SetScript('OnEvent', nil)
+ PetCastingBarFrame:Hide()
+end
+
+function mod:UpdateLocked()
+ for k, v in pairs(self.castbar) do
+ if T.unlocked then
+ local name, texture, offset, numSpells = GetSpellTabInfo(T.specPage)
+ v.value = offset
+ v.duration = numSpells
+ v.spelltext:SetText(k)
+ v.icon:SetTexture(texture)
+ v:SetAlpha(1)
+ v:Show()
+ v:EnableMouse(true)
+ v:SetMovable(true)
+ v:RegisterForDrag("LeftButton")
+ v:SetScript('OnDragStart', function(self) self:StartMoving() end)
+ v:SetScript('OnDragStop', function(self) self:StopMovingOrSizing() end)
+ else
+
+ v:SetScript('OnDragStart', nil)
+ v:SetScript('OnDragStop', nil)
+ v:EnableMouse(false)
+ v:SetMovable(false)
+
+ print('Saving bar coordinates post unlock')
+
+ db[k].x = v:GetLeft()
+ db[k].y = v:GetTop()
+ db[k].anchor = 'BOTTOMLEFT'
+ db[k].anchorTo = 'BOTTOMLEFT'
+ db[k].parent = 'UIParent'
+ end
+ end
+end
+
+--- Store spell requests for use in tracking lag time
+function mod:SpellCastRequest(e, unit, spellName, rank, target, castID)
+ print('|cFFFF4400Request sent:|r ', spellName, castID, target)
+ self.castbar.player.sent[castID] = {
+ spellName = spellName,
+ castID = castID,
+ sendTime = GetTime()*1000,
+ }
+end
+
+--- Handle events pertaining to a cast bar
+function mod:SpellCastEvent(event, unit, ...)
+ if not self.castbar[unit] then
+ return
+ end
+
+ local u = T.unit[unit]
+ local c = self.castbar[unit]
+
+ --- doubling as an invocation source test
+ local spellName, rank, castID, spellID = ...
+
+ local channelinfo = T.unit[unit].channeling
+ local castinginfo = T.unit[unit].casting
+ local sendq = c.sent
+ local castd = c.last
+ local timestamp = GetTime()*1000
+
+ --todo: remove truncation
+ local e = event:match("UNIT_SPELLCAST_([%a_]+)")
+ print(GetTime(), '|cFFFF8747'..e..(strpad(' ',12-#e))..'|r |cFFDDFF00#'..tostring(castID)..'|r', spellName, spellID)
+
+ c.channeling = channelinfo and channelinfo[1] or nil
+ c.casting = castinginfo and castinginfo[1] or nil
+ if c.channeling then
+ -- {name, subText, text, texture, startTime, endTime, isTradeSkill, notInterruptible}
+ c.startTime = channelinfo[5]
+ c.endTime = channelinfo[6]
+ c.nonInterruptible = channelinfo[8]
+ elseif c.casting then
+ --name, subText, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible
+ c.startTime = castinginfo[5]
+ c.endTime = castinginfo[6]
+ c.castID = castinginfo[8]
+ c.nonInterruptible = castinginfo[9]
+ else
+ print(' |cFFFF7700internal data was nil|r')
+ end
+
+ --- process the "event"
+ local setSpell, setState
+ if e == 'START' then
+ setSpell = true
+ setState = true
+
+ -- player data calculations
+ if unit == 'player' then
+ if sendq[castID] and sendq[castID].spellName == spellName then
+ local sent = sendq[castID]
+ print(' |cFF00AAFFmatched:|r', sent.spellName, castID)
+ c.pingTime = c.startTime - sent.sendTime
+ print(' ping:', c.pingTime)
+ for cid, cdata in pairs(sendq) do
+ if cdata.sendTime <= sent.sendTime then
+ --print(' forgetting #'..cdata.sendTime, cid, cdata.spellName)
+ sendq[cid] = nil
+ end
+ end
+
+ if castd ~= nil then
+ print(' downtime calc hit')
+ c.downTime = timestamp - castd.endTime
+ castd = nil
+ else
+ c.downTime = nil
+ end
+ c.castID = castID
+ end
+ end
+ elseif e == 'CHANNEL_START' or e == 'CHANNEL_UPDATE' then
+ setSpell = true
+ setState = true
+ c.event = e
+
+ elseif e == 'STOP' then
+ setState = true
+ c.casting = nil
+ castd = {
+ spellName = spellName,
+ spellID = spellID,
+ castID = castID,
+ endTime = timestamp,
+ }
+ print(' |cFFFFFF00found', timestamp, spellName)
+
+ elseif e == 'CHANNEL_STOP' then
+ setState = true
+ c.channeling = nil
+ castd = {
+ spellName = spellName,
+ spellID = spellID,
+ castID = castID,
+ endTime = timestamp,
+ }
+ print(' |cFFFF0088found', timestamp, spellName)
+
+ elseif e == 'SUCCEEDED' then
+ if c.spellName == spellName and not c.channeling then
+ setState = true
+ print(' |cFFFF4400',c.spellName,'=',spellName,' pushing event', e)
+ end
+ -- if there are 'send' args when this fires, it means it's an instant cast
+ if sendq[castID] and sendq[castID].spellName == spellName then
+ castd = {
+ spellName = spellName,
+ spellID = spellID,
+ castID = castID,
+ endTime = timestamp,
+ }
+ print(' |cFFFFAA00found', timestamp, spellName)
+ end
+
+ elseif e =='FAILED' then
+ if spellName == c.spellName and not c.channeling then
+ setState = true
+ end
+
+ elseif e == 'INTERRUPTED' then
+ setState = true
+
+ end
+
+
+
+
+ if setSpell then
+ print(' |cFF44FF00setting spell', spellName)
+ end
+ if setState then
+ print(' |cFFFF4400pushing event', e)
+ end
+
+ if setSpell then
+ c:SetSpell(e)
+ end
+ if setState then
+ c:SetState(e)
+ end
+end
+
+
+--- Sets all the static elements of the casting bar, such as config values, icon texture, and name
+function mod.SetSpell(c, event)
+ local _
+ local time, alpha = GetTime(), c:GetAlpha()
+ local u, cdb = T.unit[c.unit], c.db
+
+ c.stopped = nil
+ c.stopping = nil
+ print('New spell:', c.spellName)
+ --- use only internal info
+ local data = (event == 'CHANNEL_START' or event == 'CHANNEL_UPDATE' or event == 'CHANNEL_STOP') and u.channeling or u.casting
+ local spellName, rank, displayName, texture, startTime, endTime, isTradeSkill, castID, nonInterruptible = unpack(data)
+
+
+ if spellName == nil then
+ print(" Can't do arithmetic, no data.")
+ else
+ print(cText(" Arithmetic vars:"), cNum(startTime), cNum(endTime))
+ end
+
+ c.spellName = spellName
+ c.castID = castID or 0
+ c.rank = rank
+ c.displayName = displayName
+ c.texture = texture
+ c.nonInterruptible = nonInterruptible
+ c.isTradeSkill = isTradeSkill
+ c.endTime = endTime or 0
+ c.startTime = startTime or 0
+ c.duration = c.endTime - c.startTime
+
+ if c.unit == 'player' then
+ if c.pingTime then
+ print(' ping',c.pingTime, endTime, startTime, c.duration)
+ local draw_dist = (c.pingTime / c.duration) * (c.fill_width)
+ if draw_dist > c.fill_width then
+ draw_dist = c.fill_width
+ end
+ print('SET AND SHOW PING ', c.pingTime,'on', c.pingbar:GetName())
+ c.pingbar:SetWidth(draw_dist)
+ c.pingbar:Show()
+
+ local rv = c.pingTime - PING_FLOOR
+ local rr = PING_MIDLINE - PING_FLOOR
+ local gv = c.pingTime - PING_MIDLINE
+ local gr = PING_CEILING - PING_MIDLINE
+ local r = c.pingTime > PING_MIDLINE and 1 or (c.pingTime < PING_FLOOR and 0 or (rv / rr))
+ local g = c.pingTime < PING_MIDLINE and 1 or (c.pingTime > PING_CEILING and 0 or 1-(gv / gr))
+ print(c.pingTime, rv, '/', rr, '=', r)
+ print(c.pingTime, gv, '/', gr, '=', g)
+
+ c.ping:SetText(floor(c.pingTime))
+ c.ping:SetTextColor(r,g,0)
+ c.ping:Show()
+ else
+ c.pingbar:Hide()
+ c.ping:Hide()
+ end
+ if c.downTime then
+ c.downtime:Show()
+ if c.downTime > 1500 then
+ c.downtime:SetText(nil)
+ else
+ c.downtime:SetText(c.downTime)
+ end
+ else
+ c.downtime:Hide()
+ end
+ else
+ if c.nonInterruptible then
+ c.interrupt:Show()
+ else
+ c.interrupt:Hide()
+ end
+ end
+
+ c.icon:SetTexture(texture)
+ c.spelltext:Show()
+ c.spelltext:SetText(spellName)
+
+ c.fill_inverse = c.channeling
+ -- set timers
+end
+
+--- Deals with failed/succeeded/interrupted visuals and fading cues
+-- Fired by one of those events, or cast/channel info is returning nothing
+function mod:SetState(event)
+ if T.unlocked then
+ return
+ end
+
+ local time = GetTime() * 1000
+ print(' ',self:GetName(), '|cFF44FF00event trigger:|r', event)
+
+ -- We want these to be updating no matter what is happening
+ if TEXTURE_SUFFIX[event] then
+ local cdb = self.db
+ if cdb.foreground_texture then
+ print(' |cFF00AAFFevent|r '..event..', |cFF00AAFFtexture|r ', cdb.foreground_texture)
+ self.foreground:SetVertexColor(unpack(cdb['foreground' .. TEXTURE_SUFFIX[event]] and cdb['foreground' .. TEXTURE_SUFFIX[event]] or cdb.foreground_color))
+ else
+ self.foreground:SetTexture(unpack(cdb['foreground' .. TEXTURE_SUFFIX[event]] and cdb['foreground' .. TEXTURE_SUFFIX[event]] or cdb.foreground_color))
+ end
+
+ if cdb.background_texture then
+ print(' texture=', cdb.background_texture)
+ self.background:SetVertexColor(unpack(cdb['background' .. TEXTURE_SUFFIX[event]] and cdb['background' .. TEXTURE_SUFFIX[event]] or cdb.background_color))
+ else
+ self.background:SetTexture(unpack(cdb['background' .. TEXTURE_SUFFIX[event]] and cdb['background' .. TEXTURE_SUFFIX[event]] or cdb.background_color))
+ end
+ end
+
+ -- are we starting or stopping
+ if event == 'START' or event == 'CHANNEL_START' then
+ print(' |cFF00AAFFStarting display|r ', self.spellName)
+ self:Show()
+ if self.__fade:IsPlaying() then
+ self.__fade:Stop()
+ end
+
+ self:Fade(FADE_IN_TIME, self.alpha)
+ else
+ if event == 'SUCCEEDED' and not self.channeling then
+ print(' |cFF00AAFFsuccess deduced values|r', self.value, 'to', self.duration)
+ self.percent = 1
+ self.value = self.duration
+ end
+
+ -- Actual fading out begins here, anything else is statistical sugar
+ if event == 'STOP' or event == 'CHANNEL_STOP' then
+ print('yeah we done')
+ if self.__fade:IsPlaying() then
+ self.__fade:Stop()
+ end
+ self:Fade(FADE_OUT_TIME, 0)
+ end
+ end
+end
+
+--- Animation loop
+function mod:Update()
+ local time = GetTime() * 1000
+ local u = self.unit
+ local s = self
+
+ -- update vals
+ if s.casting or s.channeling then
+ self.value = s.casting and (time - s.startTime) or (s.endTime - time)
+ self.percent = (time - s.startTime) / self.duration
+ if time > s.endTime then
+ self.value = self.fill_inverse and 0 or s.duration
+ self.percent = self.fill_inverse and 0 or 1
+ self.elapsed = time - s.endTime
+ end
+ --_G.print('Update',' ',self.unit, self.value, self.percent)
+ else
+ self.value = 1000
+ self.percent = 1
+ end
+ self.casttime:SetText(format("%.2f", self.value / 1000))
+
+ self:SetProgress(self.percent)
+end
+
+--- Refresh the CastingBar for things like target change, pet despawn, etc.
+-- Will attempt to flush out any existing cast action data, then re-invoke SpellCastEvent() with as much data can be acquired.
+-- There is no event data such as spellID directly available, so this is essentially the biggest constraint we have on what
+-- the castingbar can depend on.
+function mod:UpdateUnit(unit)
+ local print = function(...) _G.print('Update', ...) end
+ print(cText 'GUID changed:|cFFFFFF99', unit)
+ local c = mod.castbar[unit]
+ if c.channeling or c.casting then
+ print(cText ' was casting a spell, run STOP event and hide completely')
+ c:SetState(c.casting and 'STOP' or 'CHANNEL_STOP')
+ c.channeling = nil
+ c.casting = nil
+ c:Hide()
+ end
+
+ if T.unit[unit].casting then
+ print(cText(' new target is CASTING'))
+ mod:SpellCastEvent('UNIT_SPELLCAST_START', unit)
+ end
+ if T.unit[unit].channeling then
+ print(cText(' new target is CHANNELING'))
+ mod:SpellCastEvent('UNIT_SPELLCAST_CHANNEL_START', unit)
+ end
+
+ T:UNIT_SPELLCAST(unit)-- name, subText, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible
+ T:UNIT_CHANNEL(unit) -- name, subText, text, texture, startTime, endTime, isTradeSkill, notInterruptible
+
+end
+
+function mod:UpdateInterrupt(e, unit, ...)
+ mod.castbar[unit].nonInterruptible = (e == 'UNIT_SPELLCAST_UNINTERRUPTIBLE') and true or false
+ if unit ~= 'player' and unit ~='pet' then
+
+ end
+end
+
+mod.UNIT_PET = function(self, e, unit)
+ if unit == 'player' then
+ self:UpdateUnit('pet')
+ end
+end
+mod.PLAYER_TARGET_CHANGED = function(self, ...)
+ _G.print('Main', cPink(self),...)
+ self:UpdateUnit('target')
+end
+mod.PLAYER_FOCUS_CHANGED = function(self)
+ self:UpdateUnit('focus')
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/Castbar.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/Castbar.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,74 @@
+
+
+
+
+
+ self:SetAlpha(0)
+ self.casttime:SetText(nil)
+ self.spelltext:SetText(nil)
+ self.casting = nil
+ self.channeling = nil
+ self.succeeded = nil
+ self.fading = nil
+ self.fadeIn = nil
+ self.fadeOut = nil
+ self.stopping = nil
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/Combat.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/Combat.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/CombatLog.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/CombatLog.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,758 @@
+--- Combat
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 1/11/2016 4:27 PM
+--- Data collector for API Combat Log Event
+local T, _G = Turok, _G
+local mod = T:NewModule("Combat")
+local pairs, ipairs, select, concat, format, tinsert, wipe = pairs, ipairs, select, table.concat, string.format, tinsert, table.wipe
+local GetSpellTexture, CreateFrame, GetTime, unpack, floor = GetSpellTexture, CreateFrame, GetTime, unpack, floor
+local db
+local cText, cNum, cKey, cWord, cPink, cType, cBool = cText, cNum, cKey, cWord, cPink, cType, cBool
+local print = function(...)
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('CombatText', ...)
+ end
+end
+
+
+--- performance constants
+local SCT_NAME = 'TurokSCT%s'
+local SCT_TEMPLATE = 'TurokSCTAnchorTemplate'
+local SCT_PREGAME = 5
+local SCT_MESSAGE_TEMPLATE = 'TurokCombatMessageTemplate'
+local SCT_MESSAGE_NAME = 'CombatString%d'
+local LOG_TEMPLATE = 'TurokCombatLogAnchorTemplate'
+
+--- UX structures
+T.defaults.CombatText = {
+ width = 400, height = 800,
+ parent = 'UIParent',
+ Outgoing = {
+ anchor = 'RIGHT', anchorTo = 'RIGHT',
+ x = -400, y = -200,
+ },
+ Incoming = {
+ anchor = 'LEFT', anchorTo = 'LEFT',parent = 'UIParent',
+ x = 400, y = -200,
+ },
+ DoTTracker = {
+ anchor = 'BOTTOMLEFT', anchorTo = 'BOTTOM', parent = 'UIParent',
+ x = 80, y = 400,
+ },
+ defaultFont = {"Interface\\Addons\\Turok\\Media\\font\\ArchivoNarrow-Regular.ttf", 18, 'OUTLINE'},
+ defaultAnimation = 'slide',
+
+ textFonts = {
+ font1 = {"Interface\\Addons\\Turok\\Media\\font\\ArchivoNarrow-Regular.ttf" , 30, 'OUTLINE'},
+ font2 = {"Interface\\Addons\\Turok\\Media\\font\\ArchivoNarrow-Regular.ttf" , 24, 'OUTLINE'},
+ font3 = {"Interface\\Addons\\Turok\\Media\\font\\ArchivoNarrow-Bold.ttf" , 20, 'OUTLINE'},
+ },
+
+ --- [(string) combatEvent] = {[1] = (string) format [, [2] = fontKey]}
+ --- Substitution values
+ -- %d [1] amount [2] overkill [3] absorbed [4] blocked
+ -- %s [5] spell [6] caster [7] school
+ textFormat = {
+ ['SWING_DAMAGE'] = {'%d'},
+ ['SPELL_DAMAGE'] = {'%d'},
+ ['RANGE_DAMAGE'] = {'%d'},
+ Incoming = {
+ ['SWING_DAMAGE'] = {'-%d'},
+ ['SPELL_DAMAGE'] = {'-%d (%s)'},
+ ['RANGE_DAMAGE'] = {'-%d'},
+ },
+ },
+ textModifiers ={
+ critical = {'%s!', 'pop'},
+ overKill = {'%s |cFF0088FFKilling Blow!|r', 'slide'},
+ multistrike = {'<%s>', 'lateralSlide', 'font3'},
+ absorbed = {'%s (%d)', 'slide'},
+ blocked = {'%s {%d}', 'slide'},
+ pet = {'(%s)', 'lateralSlide'},
+ grouped = {'%s (%d hit)', 'slide'},
+ },
+ --- [AnimationGroup key] = {[XML attrib] = [value], d[x/y] = (number) 0-1 }
+ -- d[x/y] indicates the proportional relevance of each FontString dimension when frames are displaced by a new event
+ -- x/y indicates the ranges of movement made by an animation, and are also considered when calculating displacement
+ animation = {
+ slide = {
+ x = 0, dx = 0,
+ y = 300, dy = 1,
+ duration = 2
+ },
+ lateralSlide = {
+ x = 300, dx = 1,
+ y = 0, dy = 0,
+ duration = 2
+ },
+ pop = {
+ toScale = 1.4,
+ fromScale = 0.1,
+ duration = 0.14,
+ dx = 0, dy = 1,
+ },
+ fadeOut = {change = -1, duration = 0.5},
+ },
+}
+--- [1] text wrapper [2] animation type
+local dotEvents = {
+ SPELL_AURA_APPLIED = true,
+ SPELL_PERIODIC_DAMAGE = true,
+ SPELL_AURA_REMOVED = true,
+ SPELL_AURA_REFRESHED = true,
+}
+local petGUID = {}
+
+------------- data structures
+local defaultAnimation, defaultFont
+local criticalModifier, absorbedModifier, blockedModifier, overKillModifier, multistrikeModifier, groupedModifier
+local criticalAnimation, absorbedAnimation, blockedAnimation, overKillAnimation, multistrikeAnimation, groupedAnimation
+local criticalFont, absorbedFont, blockedFont, overKillFont,multistrikeFont, groupedFont
+local textFonts = {}
+local textFormat = {}
+local animation = {}
+local spellCache = {}
+local DoTFrames = {}
+
+local dotTrackingEvents = {
+ ['SPELL_AURA_APPLIED'] = true,
+ ['SPELL_AURA_REMOVED'] = true,
+ ['SPELL_AURA_REFRESHED'] = true,
+}
+
+--- multi-hit events data
+-- [(string) localized name] = {
+-- [1] = (bool) controlled channel
+-- [2] = (number) minimum time to wait for next damage tick
+-- [3] = (number) maximum time to log grouped spell hits
+-- [4] = (string) combatEvent full string
+-- [5] = (string) combatEvent short prefix (as opposed to SPELL_PERIODIC)
+-- [6] = (string) combatEvent short suffix (as opposed to AURA_APPLIED)
+-- }
+-- tailing fields are set to reduce the number of arguments passed around
+local groupedSpells = {
+ global = {false, 1, 'SPELL_PERIODIC_DAMAGE', 'SPELL', 'DAMAGE'},
+ ['Crimson Tempest'] = {false, 0.3, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- shockwave dot
+ ['Mind Sear'] = {false, 1, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- scanning aoe
+ ['Searing Insanity'] = {false, 1, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- scanning aoe
+ ['Ice Nova'] = {false, 0.4, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- shockwave aoe
+ ['Blizzard'] = {false, 1, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- scanning aoe
+ ['Frozen Orb'] = {false, 1, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'},
+ ['Ice Bomb'] = {false, 0.4, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- shockwave aoe
+ ['Comet Storm'] = {false, 2.5, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- staggered multi-hit
+ ['Barrage'] = {false, 1.1, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- projectile vommit
+ ['Glaive Toss'] = {false, 3, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}, -- path projectile,
+ ['Doom Nova'] = {false, 0.4, 'SPELL_DAMAGE', 'SPELL', 'DAMAGE'}
+}
+
+local dotSpellIndex = {
+ ['Shadow Word: Pain'] = {'HARMFUL|PLAYER'},
+ ['Vampiric Touch'] = {'HARMFUL|PLAYER'}
+}
+
+local offhandSpellIndex = {
+ ['Execute'] = {'Execute Off-Hand'},
+ ['Mutilate'] = {'Mutilate Off-Hand'},
+ ['Stormstrike'] = {'Stormstrike Off-Hand'},
+}
+
+--- stored as a list of field representations to be concatenated together within a loadstring def
+
+
+
+--- Tracking tables
+local groupedQueue = {}
+local groupedEvents = {}
+local offhandQueue = {}
+local sct_format = {}
+
+
+local function GetGUIDInfo(guid)
+ local unitType, flags1, flags2 = guid:match('(%a+)\-(%x+)\-(%x+)')
+ return concat({unitType, flags1, flags2},'|r::|cFF0088FF')..'|r'
+end
+
+local SpellSchoolColors = {
+ [1] = {255, 255,0}, -- physical
+ [2] = {255, 230, 128}, -- holy
+ [3] = {255, 255, 128}, -- holy+phys
+ [4] = {255, 128, 0}, -- fire
+ [8] = {77, 255, 77}, -- nature
+ [16] = {128, 255, 255}, -- frost
+ [20] = {255, 192, 128}, -- frostfire
+ [32] = {128, 128, 255}, -- shadow
+ [48] = {128, 192, 255}, -- shadow+frost
+ [64] = {255, 128, 255}, -- arcane,
+ [72] = {255, 128, 128}, -- spellstorm,
+}
+
+local h = '|cFF%02X%02X%02X'
+local SpellSchoolColor = function (flags, spellName)
+ local i = 64
+ local rA, gA, bA
+ if SpellSchoolColors[flags] then
+ print(flags, 'match')
+ print(format('%02X%02X%02X', unpack(SpellSchoolColors[flags])))
+ return format(h, unpack(SpellSchoolColors[flags]))
+ end
+
+ repeat
+ local rB, gB, bB = unpack(SpellSchoolColors[i])
+ if i <= flags then
+ if not rA then
+ rA = rB
+ gA = gB
+ bA = bB
+ else
+ rA = (rA+rB)/2
+ gA = (gA+gB)/2
+ bA = (bA+bB)/2
+ end
+ print('test:', cWord(i), '<=', cKey(flags), '=', (i <= flags), cPink(rA), cNum(gA), cText(bA))
+ flags = flags - i
+ else
+ print(i, 'skip')
+ end
+ i = i/2
+ until (i == 1)
+ SpellSchoolColors[flags] = {rA, gA, bA }
+ --print(string.format('%02X%02X%02X', unpack(SpellSchoolColors[flags])))
+ return format(h, unpack(SpellSchoolColors[flags]))
+end
+local myGUID
+
+mod.NewCombatMessage = function(frame, index)
+ local ct = CreateFrame('Frame', SCT_MESSAGE_NAME:format(frame.lineID), frame, SCT_MESSAGE_TEMPLATE)
+ index = index and 'active' or 'expired'
+ frame.lineID = frame.lineID + 1
+ frame.active[#frame.active+1] = ct
+ ct.index = #frame.active
+ ct.x = 0
+ ct.y = 0
+ ct.point = 'BOTTOMLEFT'
+ return ct
+end
+
+--- frame interaction logic
+mod.AddCombatMessage = function(frame, text, icon, animationType, fontKey)
+ local line
+ print(fontKey)
+
+ local expired = frame.expired
+ local active = frame.active
+ local a = 1
+ local shiftY, shiftX
+ local lastFrame
+ --- If animation has overlap delta values, find the last active frame of that animation type and check for overlaps.
+ --- Frames are considered overlapping when the last member's ((height - distance traveled) * delta) is over 0.
+ --- This assumes the same string height for the upcoming frame since wordwrap isn't enabled.
+ print(animationType)
+ if animation[animationType].dx or animation[animationType].dy then
+ print('animation has displacement')
+ if frame.last then
+ lastFrame = frame.last
+ local dp = lastFrame[animationType]:GetProgress()
+ if animation[animationType].dx then
+ local dx = dp * animation[animationType].x
+ shiftX = (lastFrame.string:GetStringWidth() - dx) * animation[animationType].dx
+ end
+ if animation[animationType].dy then
+ local dy = dp * animation[animationType].y
+ shiftY = (lastFrame.string:GetStringHeight() - dy) * animation[animationType].dy
+ print(' ', 'h=', floor(lastFrame.string:GetStringHeight()), 'dY=', dy, 'offsetY=', shiftY)
+ end
+ print(cWord('lastFrame hit:'), lastFrame and lastFrame:GetName(), cNum(shiftX), cNum(shiftY))
+ end
+ end
+
+ -- find a usable frame
+ local currentFrame
+ for i, ct in ipairs(frame.active) do
+ if not currentFrame then
+ if ct.discard then
+ ct.discard= nil
+ currentFrame = ct
+ end
+ end
+
+ if lastFrame and ct.animationType == animationType and not ct.discard then
+ --print('lastFrame defined, check for overlap')
+ if shiftY > 0 then
+ print(cWord(' * vertical shift'), cNum('+'..floor(shiftY)))
+ ct.y = ct.y + shiftY
+ end
+ if shiftX > 0 then
+ print(cWord(' * horizontal shift'), cNum('+'..floor(shiftX)))
+ ct.x = ct.x + shiftX
+ end
+ ct:SetPoint(ct.point, frame, ct.point, ct.x, ct.y)
+ end
+ end
+ -- if no expired frames became available, make a new one (should max at 20 or so if groupings are right)
+ if not currentFrame then
+ currentFrame = mod.NewCombatMessage(frame)
+ print(cNum(' creating new string object for the heap'))
+ end
+
+ print(cText(' * Starting'), cPink(animationType), 'on', cKey(currentFrame:GetName()), ' ['..cNum(currentFrame.index)..']')
+
+ if icon then
+ currentFrame.icon:Show()
+ currentFrame.icon:SetTexture(icon)
+ else
+ currentFrame.icon:Hide()
+ end
+ if fontKey then
+ local newFont = fontKey and textFonts[fontKey] or defaultFont
+
+ local path, size, flags = currentFrame.string:GetFont()
+ path = newFont[1] or path
+ size = newFont[2] or size
+ flags = newFont[3] or flags
+ print(cText('font ('..cWord(fontKey)..'):'), path, size, flags)
+ local result = currentFrame.string:SetFont(path, size, flags)
+ print(cNum(' result:'), cNum(result), currentFrame.string:GetFont())
+ --currentFrame.fontKey = fontKey
+ end
+
+ currentFrame.animationType = animationType
+ currentFrame.string:SetText(text)
+ local cHeight = currentFrame.string:GetStringHeight()
+ currentFrame:SetSize(currentFrame.string:GetStringWidth(), cHeight)
+ currentFrame.icon:SetSize(cHeight, cHeight)
+ currentFrame.y = 0
+ currentFrame.x = 0
+ currentFrame:SetPoint(currentFrame.point, frame, currentFrame.point, currentFrame.x, currentFrame.y)
+ currentFrame[animationType]:Play()
+ frame.last = currentFrame
+end
+
+local GetTextFormatFunc = function(amount, overKill, absorbed, blocked, multistrike, spellName, sourceName, destName)
+ local sub_text = {
+ ['%d'] = amount,
+ ['%o'] = overKill,
+ ['%a'] = absorbed,
+ ['%b'] = blocked,
+ ['%m'] = multistrike,
+ ['%s'] = spellName,
+ ['%n'] = sourceName,
+ ['%t'] = destName,
+ }
+ local func = function(token)
+ print(cPink('gsub run:'), token)
+ return sub_text[token]
+ end
+ return func
+end
+
+--- builds CT messages from combat log event data
+-- separated from frame interaction for auxiliary events such as combat/loot/etc
+local CreateDamageText = function(frame, timestamp, combatEvent, sourceName, destName, spellID, spellName, effectSchool, amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand, multistrike, ticks)
+ if combatEvent:match('^SWING') then
+ spellID = 1
+ spellName = 'Attack'
+ elseif combatEvent:match('^RANGE') then
+ spellID = 2
+ spellName = 'Auto Shot'
+ end
+ if not combatEvent:match('DAMAGE') then
+ return
+ end
+
+
+ local fontKey = 'font1'
+ local icon = GetSpellTexture(spellID)
+ local animationType = defaultAnimation
+ local text = amount
+ if textFormat[combatEvent] then
+ local tString, fontKey = unpack(textFormat[combatEvent])
+ if amount > 1000000 then
+ amount = (floor(amount/100000)/10) ..'M'
+ elseif amount > 1000 then
+ amount = (floor(amount/100)/10) ..'k'
+ end
+
+ text = tString:gsub('%%[doabsnt]', GetTextFormatFunc(amount, overKill, absorbed, blocked, multistrike, spellName, sourceName, destName))
+ print("** font override:", '"'..cText(tString)..'",', cPink(font), cNum(size), cWord(outline))
+ end
+
+ print('** getting color data', cText(spellName))
+ if type(effectSchool) == 'number' then
+ text = SpellSchoolColor(effectSchool) ..text..'|r'
+ end
+
+ if overKill > 0 then
+ text = overKillModifier:format(text, overKill)
+ animationType = overKillAnimation
+ fontKey = overKillFont or fontKey
+ end
+ if critical then
+ text = criticalModifier:format(text)
+ animationType = criticalAnimation
+ fontKey = criticalFont or fontKey
+ end
+ if absorbed then
+ text = absorbedModifier:format(text, absorbed)
+ animationType = absorbedAnimation
+ fontKey = absorbedFont or fontKey
+ end
+ if blocked then
+ text = blockedModifier:format(text, blocked)
+ animationType = blockedAnimation
+ fontKey = blockedFont or fontKey
+ end
+ if multistrike then
+ text = multistrikeModifier:format(text, multistrike)
+ animationType = multistrikeAnimation
+ fontKey = multistrikeFont or fontKey
+ end
+
+ print(ticks)
+ if ticks then
+ text = groupedModifier:format(text, ticks)
+ animationType = groupedAnimation
+ fontKey = groupedFont or fontKey
+ end
+
+
+ print('** sending format to SCT:', text, icon, animationType, fontKey)
+
+
+ mod.AddCombatMessage(frame, text .. '|r', icon, animationType, fontKey)
+end
+
+local CT_ShowConsolidated = function()
+ for spellName, queuedSpell in pairs(groupedQueue) do
+ local isChannel, minDelay, combatEvent, sourceName, destName, spellID, school, SCT, timestamp = unpack(queuedSpell)
+ for i, v in ipairs(queuedSpell) do
+ print(' ', i, '=', v)
+ end
+
+ print(spellName, 'vars:', spellID, spellName, school, SCT, timestamp)
+ if groupedEvents[spellName] and #groupedEvents[spellName] ~= 0 then
+ local amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, multistrike, hit = 0, -1, 0, 0, 0, 0, 0, 0, 0, 0
+ for i, line in ipairs(groupedEvents[spellName]) do
+ -- extra strike?
+ --{amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, multistrike}
+ local amount_n, overKill_n, resisted_n, blocked_n, absorbed_n, critical_n, glancing_n, crushing_n, multi_n, sourceGUID, destGUID, sourceName, destName = unpack (line)
+
+ amount = amount + amount_n
+ if overKill_n > 0 then overKill = overKill + overKill_n end
+ if blocked_n then blocked = blocked + line[4] end
+ if absorbed_n then absorbed = absorbed + line[5] end
+ if critical_n then critical = critical + 1 end
+ if multi_n then multistrike = multistrike + 1 end
+
+ hit = hit + 1
+ end
+ if overKill == -1 then
+ overKill = overKill + 1
+ end
+ wipe(groupedEvents[spellName])
+ groupedQueue[spellName] = nil
+ print(' expelling', spellName, cText('A:'), cNum(amount), cText('O:'), cNum(overKill), cText('Ticks:'), cNum(hit), cText('Crits:'), cNum(critical), cText(school))
+ print(SCT, timestamp, combatEvent, sourceName, destName, spellID, spellName, school, amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, multistrike, hit)
+ CreateDamageText(SCT, timestamp, combatEvent, sourceName, destName, spellID, spellName, school, amount, -1, nil, nil, nil, false, glancing, crushing, false, multistrike, hit)
+ end
+ end
+end
+
+local CT_ConsolidateText = function (self, timestamp, sourceGUID, destGUID, sourceName, destName, spellID, spellName, school, amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand, multistrike)
+ local archive = groupedSpells[spellName] and groupedSpells[spellName] or groupedSpells.global
+ local isChannel, minDelay, combatEvent = unpack(archive)
+ if not groupedEvents[spellName] then
+ groupedEvents[spellName] = {}
+ end
+
+ if #groupedEvents[spellName] == 0 then
+ groupedQueue[spellName] = {isChannel, minDelay, combatEvent, sourceName, destName, spellID, school, self, timestamp}
+ T:ScheduleTimer(CT_ShowConsolidated, minDelay)
+ print(' starting archive for', select(7, unpack(archive)))
+ else
+ print(' recording into archive', cText(spellName))
+ end
+ tinsert(groupedEvents[spellName], {amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, multistrike, sourceGUID, destGUID, sourceName, destName, sourceName, destName,})
+end
+
+local CT_OnCast = function(self, event, unit, spellName, lineID, spellID)
+ if unit ~= 'player' and unit ~= 'pet' then
+ return
+ end
+
+ if groupedSpells[spellName] then
+ print(cText('** Spell casting info received'))
+ local isChannel, delay = unpack(groupedSpells[spellName])
+ if isChannel and event == 'CHANNEL_STOP' and groupedEvents[spellName] then
+ T:ScheduleTimer(CT_ShowConsolidated, delay)
+ else
+ if not groupedEvents[spellName] then
+ groupedEvents[spellName] = {}
+ end
+ end
+ end
+end
+
+local CT_Unlock = function(str)
+ for i, CT in pairs(mod.CombatTextFrames) do
+ local frame = CT.frame
+ frame.configMode = (frame.configMode == nil) and true or nil
+ frame:RegisterForDrag(frame.configMode and 'LeftButton' or nil)
+ frame:EnableMouse(frame.configMode and true or false)
+ print(i, frame.configMode and 'ON' or 'OFF')
+ for _, reg in ipairs(frame.configRegions) do
+ if frame.configMode then
+ reg:Show()
+ else
+ reg:Hide()
+ end
+ end
+
+ if frame.configMode then
+ CT.configTimer = T:ScheduleRepeatingTimer(function()
+ print(i, 'config tick')
+ for i, s in ipairs(CT.sample) do
+ CT.OnEvent(frame, unpack(s))
+ end
+ end, 2)
+ else
+ print(CT.configTimer)
+ T:CancelTimer(CT.configTimer)
+ end
+
+ end
+end
+
+--- check for sectors
+local queue = {}
+mod.OnDamage = function(self, event, ...)
+ local isVisible
+
+ local timestamp, combatEvent = ...
+ print(cText('* CT'), cKey(combatEvent))
+ if combatEvent == 'UNIT_DIED' then
+ return
+ end
+ local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, _, spellID, spellName, spellSchool = select(4, ...)
+ print(' from', cPink(sourceGUID), 'spell', cNum(spellID), cText(spellName), '->', cKey(destGUID))
+
+ -- SWING starts at arg 10, SPELL/RANGE start at arg 13, ENVIRONMENTAL starts at arg 8
+ local offset = 15
+ print(combatEvent:sub(0,3))
+ if combatEvent:sub(0,3) == 'SWI' then
+ offset = 10
+ elseif combatEvent:sub(0,3) == 'ENV' then
+ offset = 8
+ end
+ local amount, overKill, effectSchool, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand, multistrike = select(offset, ...)
+
+ print(' dmg', amount, overKill)
+
+ local sc = SpellSchoolColors[effectSchool]
+ if groupedSpells[spellName] then
+ print('* ', cText(spellName), 'to consolidator')
+ CT_ConsolidateText(self, timestamp, sourceGUID, destGUID, sourceName, destName, spellID, spellName, effectSchool, amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand, multistrike)
+ return
+ end
+
+ print('displaying on', cWord(self:GetName()))
+ CreateDamageText(self, timestamp, combatEvent, sourceName, destName, spellID, spellName, effectSchool, amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand, multistrike)
+end
+
+mod.maxDotFrame = 1
+mod.OnDotEvent = function (self, event, timestamp, combatEvent, ...)
+ print(cWord('DOT'), combatEvent)
+ local sourceGUID, sourceName, sourceFlags, _, destGUID, destName, destFlags, destExtraFlags, spellID, spellName, castSchool, amount, overKill, resisted, blocked, absorbed, critical, glancing, crushing, isOffHand, multistrike = select(2, ...)
+ print(cText('dot from'), cWord(sourceGUID), 'to', cKey(destGUID))
+ if sourceGUID == T.GUID then
+ local p = mod.PeriodicTable
+ p[destGUID] = p[destGUID] or {}
+ local unit = p[destGUID]
+ if not p[spellID] then
+ if not p.frames[#p.frames] then
+ unit[spellID] = CreateFrame('Frame', 'DotBar'..mod.maxDotFrame, p, 'TkDotBarTemplate')
+ mod.maxDotFrame = mod.maxDotFrame + 1
+ unit[spellID].dotID = mod.maxDotFrame
+
+ print(' create new frame ['..cKey(unit[spellID]:GetID(), '] for'), cWord(spellName), cKey(destGUID))
+ else
+ unit[spellID] = p.frames[#p.frames]
+ p.frames[#p.frames] = nil -- remove that entry
+ print(' recycling frame ['..cKey(unit[spellID].dotID, '] for'), cWord(spellName), cKey(destGUID))
+ end
+
+ unit[spellID]:Show()
+ end
+ local dot = unit[spellID]
+ local time = GetTime()
+ end
+end
+
+
+
+
+function mod:OnInitialize()
+ print('This is a thing.')
+ self.UNIT_SPELLCAST_SUCCEEDED = CT_OnCast
+ self.UNIT_SPELLCAST_CHANNEL_START = CT_OnCast
+ self.UNIT_SPELLCAST_CHANNEL_STOP = CT_OnCast
+end
+
+function mod:OnInitialize()
+ mod.db = TurokData.CombatText
+ db = TurokData.CombatText
+ myGUID = T.GUID
+ mod.PeriodicTable = mod.PeriodicTable or CreateFrame('Frame', 'TurokPeriodicFrame', UIParent)
+ mod.PeriodicTable.frames = {}
+
+ local m = mod.db.textModifiers
+ --- These values are going to be looked up a lot, so cache as close as possible
+ criticalModifier = m.critical[1] or '%s CRIT'
+ criticalAnimation = m.critical[2] or 'slide'
+ criticalFont = m.critical[3]
+
+ absorbedModifier = m.absorbed[1] or '%s ABS'
+ absorbedAnimation = m.absorbed[2] or 'slide'
+ absorbedFont = m.absorbed[3]
+
+ blockedModifier = m.blocked[1] or '%s BLK'
+ blockedAnimation = m.blocked[2] or 'slide'
+ blockedFont = m.blocked[3]
+
+ overKillModifier = m.overKill[1] or '%s KILL'
+ overKillAnimation = m.overKill[2] or 'slide'
+ overKillFont = m.overKill[3]
+
+ multistrikeModifier = m.multistrike[1] or '%s MS'
+ multistrikeAnimation = m.multistrike[2] or 'slide'
+ multistrikeFont = m.multistrike[3]
+
+ groupedModifier = m.grouped[1] or '%s'
+ groupedAnimation = m.grouped[2] or 'slide'
+ groupedFont = m.grouped[3]
+
+ --- Same as above, but for specific table values, key is determined by the combat event
+ defaultAnimation = mod.db.defaultAnimation
+ defaultFont = mod.db.defaultFont
+ for k,v in pairs(mod.db.textFormat) do
+ textFormat[k] = {v[1], v[2]}
+ print('imported textFormat.'..k, cText(textFormat[k][1]), cNum(textFormat[k][2]))
+ end
+ for k,v in pairs(mod.db.textFonts) do
+ textFonts[k] = {v[1] or defaultFont[1], v[2] or defaultFont[2], v[3] or defaultFont[3]}
+ print('imported font.'..k, cText(textFonts[k][1]), cNum(textFonts[k][2]), cWord(textFonts[k][3]))
+ end
+
+ for k,v in pairs(mod.db.animation) do
+ animation[k] = {}
+ animation[k].x = v.x
+ animation[k].y = v.y
+ animation[k].dx = v.dx
+ animation[k].dy = v.dy
+ animation[k].fromScale = v.fromScale
+ animation[k].toScale = v.toScale
+ animation[k].deviation = v.deviation
+ animation[k].change = v.change
+ animation[k].fromAlpha = v.fromAlpha
+ animation[k].toAlpha = v.toAlpha
+ animation[k].duration = v.duration
+ end
+end
+
+function mod:OnEnable()
+ T:RegisterChatCommand('tkc', CT_Unlock)
+
+ --- Populate CT frames
+ for name, CT in pairs(mod.CombatTextFrames) do
+ print('create CT', name)
+ -- make frame
+ CT.frame = CT.frame or CreateFrame('Frame', SCT_NAME:format(name), UIParent, SCT_TEMPLATE)
+
+ -- local vars
+ local db = db[name] or db
+ local frame = CT.frame
+
+ -- script defs
+ frame.IsFrameEvent = CT.trigger
+ frame.name = name
+ frame.lineID = 0
+ frame.expired = {}
+ frame.active = {}
+
+ -- frame defs
+ frame:SetPoint(db.anchor, db.parent, db.anchorTo, db.x, db.y)
+ frame:RegisterEvent('COMBAT_LOG_EVENT_UNFILTERED')
+ print('bound ', name, 'with', CT.OnEvent)
+ db.sample = {}
+ local logged = {}
+ frame:SetScript('OnEvent', function(self, e,...)
+ if CT.trigger(e, ...) then
+ print('event trigger fired', name)
+ if #db.sample < 5 and not logged[select(2,...)] then
+ logged[select(2,...)] = true
+ tinsert(db.sample, {e, ...})
+ end
+
+ CT.OnEvent(frame, e, ...)
+ end
+ end)
+
+ -- configurators
+ frame.configHeader:SetText(name)
+ frame:EnableMouse(false)
+
+ -- pre-pop some text frames
+ for i = (CT.lineID or 1), SCT_PREGAME do
+ print(frame:GetName(), 'pre-pop #'..i)
+ mod.NewCombatMessage(frame)
+ end
+ end
+end
+
+
+local damageEvents = {
+ ['SPELL_DAMAGE'] = true,
+ ['SPELL_PERIODIC_DAMAGE'] = true,
+ ['SWING_DAMAGE'] = true,
+ ['RANGE_DAMAGE'] = true,
+ ['SPELL_HEAL'] = true,
+}
+mod.CombatTextFrames = {
+ Incoming = {
+ trigger = function(e, _, c, _, _, _, _, _, d) return (d == T.GUID and damageEvents[c]) end,
+ OnEvent = mod.OnDamage,
+ sample = {
+ {"COMBAT_LOG_EVENT_UNFILTERED", 1455887795.271, "SPELL_HEAL", false, "Player-3684-07235A4E", "Klakyn", 1297, 0, "Player-3684-07235A4E", "Klakyn", 1297, 0, 143924, "Leech", 1, 93, 93, 0, false, false, },
+ }
+ },
+ Outgoing = {
+ trigger = function(e, _,c,_, s) return (s == T.GUID and damageEvents[c]) end,
+ OnEvent = mod.OnDamage,
+ sample = {
+ {
+ "COMBAT_LOG_EVENT_UNFILTERED", 1455887795.006, "SPELL_DAMAGE", false, "Player-3684-07235A4E", "Klakyn", 1297, 0, "Creature-0-3684-1116-7-87761-0000C32119", "Dungeoneer's Training Dummy", 68136, 0, 589, "Shadow Word: Pain", 32, 3944, -1, 32, nil, nil, nil, false, false, false, false, false, }, {
+ "COMBAT_LOG_EVENT_UNFILTERED", 1455887795.271, "SPELL_HEAL", false, "Player-3684-07235A4E", "Klakyn", 1297, 0, "Player-3684-07235A4E", "Klakyn", 1297, 0, 143924, "Leech", 1, 93, 93, 0, false, false, }, {
+ "COMBAT_LOG_EVENT_UNFILTERED", 1455887797.377, "SPELL_PERIODIC_DAMAGE", false, "Player-3684-07235A4E", "Klakyn", 1297, 0, "Creature-0-3684-1116-7-87761-0000C32119", "Dungeoneer's Training Dummy", 68136, 0, 589, "Shadow Word: Pain", 32, 3944, -1, 32, nil, nil, nil, false, false, false, false, false, }, {
+ "COMBAT_LOG_EVENT_UNFILTERED", 1455887812.702, "SWING_DAMAGE", false, "Player-3684-07235A4E", "Klakyn", 1297, 0, "Creature-0-3684-1116-7-87761-0000C32119", "Dungeoneer's Training Dummy", 68136, 0, 279, -1, 1, nil, 120, nil, false, false, false, false, false, }, -- [4]
+ }
+ },
+ DoTTracker = {
+ trigger = function(e, _, c, _, s) return (s == T.GUID and dotEvents[c]) end,
+ OnEvent = mod.OnDotEvent,
+ sample = {
+ {"COMBAT_LOG_EVENT_UNFILTERED", 1455887795.006, "SPELL_AURA_APPLIED", false,
+ "Player-3684-07235A4E", "Klakyn", 1297, 0,
+ "Creature-0-3684-1116-7-87761-0000C32119", "Dungeoneer's Training Dummy", 68136, 0,
+ 589, "Shadow Word: Pain", 32, "DEBUFF", },
+ {"COMBAT_LOG_EVENT_UNFILTERED", 1455887797.377, "SPELL_PERIODIC_DAMAGE", false,
+ "Player-3684-07235A4E", "Klakyn", 1297, 0,
+ "Creature-0-3684-1116-7-87761-0000C32119", "Dungeoneer's Training Dummy", 68136, 0,
+ 589, "Shadow Word: Pain", 32, 3944, -1, 32, nil, nil, nil, false, false, false, false, false, },
+ {"COMBAT_LOG_EVENT_UNFILTERED", 1455887807.199, "SPELL_AURA_REMOVED", false,
+ "Player-3684-07235A4E", "Klakyn", 1297, 0,
+ "Player-3684-07235A4E", "Klakyn", 1297, 0,
+ 15473, "Shadowform", 32, "BUFF", },
+ }
+ }
+}
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/CombatLog.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/CombatLog.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:GetParent():Show()
+
+
+ local ct = self:GetParent()
+ ct.discard = true
+ ct:Hide()
+
+
+ local ct = self:GetParent()
+ ct.discard = true
+ ct:Hide()
+
+
+
+
+
+
+
+
+ self:GetParent():Show()
+
+
+ local ct = self:GetParent()
+ ct.discard = true
+ ct:Hide()
+
+
+ local ct = self:GetParent()
+ ct.discard = true
+ ct:Hide()
+
+
+
+
+
+
+
+
+ self:GetParent():Show()
+
+
+ local ct = self:GetParent()
+ ct.discard = true
+ ct:Hide()
+
+
+ local ct = self:GetParent()
+ ct.discard = true
+ ct:Hide()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if button ~= 'LeftButton' then
+ return
+ end
+
+ print(self.sizer:GetCenter(), self.sizer:IsMouseOver())
+ if self.sizer:IsMouseOver() then
+ self:StartSizing()
+ else
+ self:StartMoving()
+ end
+ self:SetScript('OnUpdate', function()
+ self.configHeader:SetText(self.name .."\n"
+ ..math.floor(self:GetWidth())..' x '..math.floor(self:GetHeight()).."\n("
+ ..math.floor(self:GetLeft())..', '.. math.floor(self:GetTop())..')')
+ print('hammer')
+ end)
+
+
+ if button ~= 'LeftButton' then
+ return
+ end
+ self:SetScript('OnUpdate', nil)
+ print('stop')
+ self:StopMovingOrSizing()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ print('Layout', self:GetName(), 'has arrived.')
+
+
+ print('Layout', self:GetName(), ' hidden.')
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/Powerbar.Init.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/Powerbar.Init.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,119 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 12/28/2015 8:01 AM
+
+
+Turok.defaults.powerbar = {
+ trace = true,
+ alpha_ooc = 0.1,
+ alpha_full_ooc = .1,
+ alpha = 1,
+ alpha_fade_out = 5,
+ alpha_fade_in = 0.15,
+ combatFade = true,
+ graph_safe = {.5,.5,.5,1},
+ graph_alert = {1,0,0,1},
+ graph_blend = 'ADD',
+ graph_blend_alert = 'BLEND',
+ foreground_color = {.1,.5,1 ,1},
+ background_color = {0.2,0.2,0.2,0.2},
+ y = -188,
+ x = 0,
+ height = 20,
+ width = 300,
+ padding = 0,
+ spacing = 1,
+ strata = 'BACKGROUND',
+ level = 5,
+ resource_max_noise = [[Interface\Addons\Turok\Media\sound\SquishFart.ogg]],
+ resource_low_noise = [[]],
+ resource_empty_noise = [[Interface\Addons\Turok\Media\sound\wilhelm.ogg]],
+ font = [[Interface\Addons\Turok\Media\font\ArchivoNarrow-Bold.ttf]],
+ secondary = {
+ anchor = 'BOTTOMLEFT',
+ anchorTo = 'TOPLEFT',
+ parent = 'TkPowerBar',
+ spacing = 1,
+ padding = 0,
+ height = 10,
+ foreground_inset = 0,
+ foreground_color = {1,1,1,.4},
+ foreground_blend = 'ADD',
+ background_color = {0,0,0,0},
+ background_blend = 'BLEND',
+ x = 0, y = 1,
+ },
+ secondary1 = {
+ anchor = 'BOTTOMLEFT',
+ anchorTo = 'TOPLEFT',
+ parent = 'TkPowerBar',
+ spacing = 1,
+ padding = 0,
+ height = 7,
+ foreground_inset = 0,
+ foreground_color = {.7, .4, 1, 1},
+ foreground_blend = 'ADD',
+ background_color = {0,0,0,0.3},
+ background_blend = 'BLEND',
+ x = 0, y = 2,
+ },
+ secondary2 = {
+ anchor = 'BOTTOMLEFT',
+ anchorTo = 'TOPLEFT',
+ parent = 'TkPowerBar',
+ spacing = 1,
+ padding = 0,
+ height = 5,
+ foreground_inset = 0,
+ foreground_color = {1,1,1,.8},
+ foreground_blend = 'ADD',
+ background_color = {0,0,1,0},
+ background_blend = 'BLEND',
+ x = 0, y = 8,
+ },
+ secondary3 = {
+ anchor = 'BOTTOMLEFT',
+ anchorTo = 'TOPLEFT',
+ parent = 'TkPowerBar',
+ spacing = 1,
+ padding = 0,
+ height = 5,
+ foreground_inset = 0,
+ foreground_color = {1,.5,.2,1},
+ foreground_blend = 'MOD',
+ background_color = {0,0,1,0},
+ background_blend = 'BLEND',
+ x = 0, y = 16,
+
+ },
+
+ powerText = {
+ y = 0,
+ x = 6,
+ anchor='LEFT',
+ anchorTo='LEFT',
+ parent = 1,
+ justifyH = 'LEFT',
+ justifyV = 'MIDDLE',
+ text_color = {1,1,1,1},
+ size = 18,
+ },
+ secondaryText = {
+ y = 0,
+ x = -6,
+ anchor='RIGHT',
+ anchorTo='RIGHT',
+ parent = 1,
+ justifyH = 'RIGHT',
+ justifyV = 'BOTTOM',
+ text_color = {1,1,0,1},
+ size = 18,
+ },
+ graph1 = {
+ foreground_color = {.2,1,.5,1 },
+ foreground_texture = '',
+
+ },
+}
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/Powerbar.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/Powerbar.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,585 @@
+-- User: Krakyn
+-- Created: 12/15/2015 7:31 PM
+--[[
+-- Turok by @project-author@
+-- @file-author@
+-- @file-revision@:@project-revision@
+-- @file-date-iso@
+--
+-- Visible element operations begin here
+--]]
+local _G = _G
+local T, pairs, select, setmetatable, type, tinsert = _G.Turok, pairs, select, setmetatable, type, tinsert
+local mod = T:NewModule("PowerBar")
+local UnitPower, UnitPowerMax, GetTalentInfoByID, GetTalentInfo, CreateFrame = UnitPower, UnitPowerMax, GetTalentInfoByID, GetTalentInfo, CreateFrame
+local bar, db, prototype -- convenience upvalues
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cText, cNum, cWord, cKey, cPink, cBool
+ --@debug
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cText, cNum, cWord, cKey, cPink, cBool
+local print = function(...)
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('PowerBar', ...)
+ end
+end
+print('Peep!', ...)
+local addon, tg = ...
+tg.what = tostring(tg.what)..'more'
+print(tg.what)
+--@end-debug@
+mod.OnInitialize = function(self)
+ self.UNIT_SPELLCAST_START = self.SpellCastEvent
+ self.UNIT_SPELLCAST_STOP = self.SpellCastEvent
+ self.UNIT_SPELLCAST_SUCCEEDED = self.SpellCastEvent
+ self.UNIT_SPELLCAST_CHANNEL_START = self.SpellCastEvent
+ self.UNIT_SPELLCAST_CHANNEL_STOP = self.SpellCastEvent
+ self.SPELL_UPDATE_COOLDOWN = self.SpellCooldownEvent
+ self.PLAYER_REGEN_DISABLED = self.CombatStart
+ self.PLAYER_REGEN_ENABLED = self.CombatEnd
+ self.focusbar = {}
+ self.parserLog = {}
+ self.currentParse = {}
+end
+local SPELL_POWER_MANA, SPELL_POWER_ENERGY, SPELL_POWER_RAGE, SPELL_POWER_FOCUS = SPELL_POWER_MANA, SPELL_POWER_ENERGY, SPELL_POWER_RAGE, SPELL_POWER_FOCUS
+local SPELL_POWER_SHADOW_ORBS = SPELL_POWER_SHADOW_ORBS
+local SPELL_POWER_SOUL_SHARDS, SPELL_POWER_BURNING_EMBERS, SPELL_POWER_DEMONIC_FURY = SPELL_POWER_SOUL_SHARDS, SPELL_POWER_BURNING_EMBERS, SPELL_POWER_DEMONIC_FURY
+local SPELL_POWER_HOLY_POWER = SPELL_POWER_HOLY_POWER
+local SPELL_POWER_CHI = SPELL_POWER_CHI
+local SPELL_POWER_COMBO_POINTS = SPELL_POWER_COMBO_POINTS
+
+-- indexes for talent_update cleanup
+mod.secondary_rows = {}
+mod.disabled_frames = {}
+
+--[[
+-- Prototype list naming all the data sources and events that need to be handled for the logged in character
+-- .power_type {[bliz const] = event token} list of resources represented by global SPELL_POWER_* constants in the blizzard ui and the UNIT_POWER* token argument representing it
+-- .frame string frameXML template
+-- .spells {[spell name/id] = {events}} list of spells tracked by the updater
+-- .secondary {[aura name] = {}} list of auras tracked as secondary resources such as Thrill of Hunt, Anticipatin, Evangelism, etc.
+--]]
+mod.prototype = {
+ ['HUNTER'] = {
+ primary = {
+ [1] = {"FOCUS", SPELL_POWER_FOCUS}, -- array of power type constants associated to event strings
+ },
+ frame = 'TkThinComboTemplate', ---------------------- desired frame template
+ spells = {
+ ["Steady Shot"] = {'UNIT_SPELL_CAST_SUCCEEDED', 'UNIT_SPELLCAST_STOP', 'UNIT_SPELLCAST_START'} -- spell events that this frame should listen to
+ },
+ secondary = {},
+ spec = {
+ [1] = {
+ secondary = {
+ ['Frenzy'] = {
+ type = 'aura',
+ order = 1,
+ scale = 5,
+ filters = 'HELPFUL',
+ max = 5,
+ specPage = 1,
+ unit = 'player',
+ spellID = 19623,
+ },
+ ['Focus Fire'] = {
+ type = 'aura',
+ max = 40,
+ order = 2,
+ scale = 5,
+ line = 3, --------------- use this subtext value instead of count field
+ filters = 'HELPFUL',
+ specPage = 1,
+ unit = 'player',
+ spellID = 19623,
+ }
+ }
+ },
+ [2] = {
+ secondary = { ------------------------ list of buffs that act as a secondary resource
+ ['Thrill of the Hunt'] = {
+ order = 1,
+ unit = 'player',
+ type = 'aura',
+ max = 3,
+ scale = 5,
+ filters = 'HELPFUL',
+ talent = {4,3},
+ display = 'progressbar'
+ },
+ },
+ },
+ },
+ },
+ ['PRIEST'] = {
+ primary = {
+ [1] = {'MANA', SPELL_POWER_MANA}
+ },
+ frame = 'TkThinComboTemplate',
+ secondary = {},
+ spec = {
+ [1] = {
+ secondary = {
+ ['Evangelism'] = {
+ order = 1,
+ max = 5,
+ scale = 5,
+ type='aura',
+ unit = 'player',
+ filters = 'HELPFUL|PLAYER',
+ spellID = 81662,
+ }
+ }
+ },
+ [3] = {
+ primary = {
+ [1] = {'SHADOW_ORBS', SPELL_POWER_SHADOW_ORBS},
+ },
+ secondary = {
+ ["Surge of Darkness"] = {
+ order = 2,
+ type = 'aura',
+ filters = 'HELPFUL|PLAYER',
+ spellID = 87160,
+ talentID = 21751,
+ max = 3,
+ scale = 5,
+ unit = 'player',
+ },
+ ["Insanity"] = {
+ order = 2,
+ type = 'aura',
+ binary = true,
+ regress = true,
+ size = 1, scale = 1, max = 1,
+ filters = 'HELPFUL|PLAYER',
+ spellID = 132573,
+ unit = 'player',
+ talentID = 21753},
+ }
+ },
+ },
+ },
+ ['ROGUE'] = {
+ primary = {
+ [1] = {'ENERGY', SPELL_POWER_ENERGY},
+ [2] = {'COMBO_POINTS', SPELL_POWER_COMBO_POINTS}
+ },
+ frame = 'TkThinComboTemplate',
+ secondary = {
+ ['Anticipation'] = {
+ type = 'aura',
+ order = 1,
+ max = 5,
+ scale = 5,
+ unit = 'player',
+ talentID = 19250,
+ },
+ },
+ spec = {},
+ },
+ ['MAGE'] = {
+ primary = {
+ [1] = {'MANA', SPELL_POWER_MANA},
+ },
+ frame = 'TkThinComboTemplate',
+ secondary = {
+
+ ["Incanter's Flow"] = {
+ type = 'aura',
+ unit = 'player',
+ filters = 'HELPFUL|PLAYER',
+ spellID = 1463,
+ max = 5,
+ scale = 5,
+ order = 2,
+ talentID = 16033,
+ },
+ ["Rune of Power"] = {
+ type = 'aura',
+ unit = 'player',
+ filters = 'HELPFUL|PLAYER',
+ binary = true,
+ max = 1,
+ scale = 1,
+ order = 2,
+ talentID = 16032,
+ }
+ },
+ spec = {
+ [1] = {
+ secondary = {
+ ['Arcane Charge'] = {
+ type ='aura',
+ unit = 'player',
+ filters = 'HARMFUL|PLAYER',
+ spellID = 114664,
+ scale = 4,
+ max = 4,
+ order = 1,
+ },
+ }
+ },
+ [3] = {
+ secondary = {
+ ['Fingers of Frost'] = {
+ type = 'aura',
+ unit = 'player',
+ filters = '',
+ spellID = 112965,
+ max = 2,
+ scale = 4,
+ order = 1,
+ },
+ ['Brain Freeze'] = {
+ type = 'aura',
+ unit = 'player',
+ filters = '',
+ spellID = 44549,
+ scale = 4,
+ max = 2,
+ order = 1,
+ mirror = true,
+ }
+ }
+ },
+ }
+ }
+}
+local P = mod.prototype
+
+function mod:OnEnable()
+ self.disabled_freams = {
+ [T.playerClass] = {
+ [T.specPage] = {}
+ }
+ }
+ self.watched_units = {}
+ self.watched_auras = {}
+ self.watched_spells = {}
+ self.db = TurokData.powerbar
+ db = self.db
+
+ self:Prototype_Init()
+end
+function mod:Prototype_Init()
+ -- consult prototype vars
+ prototype = {}
+ mod.dcopy = function(t1, t2, d)
+ d = d or ''
+ for k,v in pairs(t2) do
+ if type(v) == 'table' then
+ if type(t1[k]) ~= 'table' then
+ t1[k] = {}
+ print(d, 'adding table', cKey(k))
+ else
+ print(d, 'merging tables', cKey(k))
+ end
+ mod.dcopy(t1[k], v, d..' ')
+ else
+ if t1[k] then
+ print(d, 'clobbered', k)
+ else
+ print(d, k, '=', cType(v))
+ end
+ t1[k] = v
+ end
+ end
+ end
+ mod.dcopy(prototype, mod.prototype[T.playerClass])
+ if mod.prototype[T.playerClass].spec[T.specPage] then
+ mod.dcopy(prototype, mod.prototype[T.playerClass].spec[T.specPage])
+ end
+
+ mod.thisproto = prototype
+
+ print('|cFFFF0088Template:|r', 'Frame', 'TkPowerBarFrame', UIParent, prototype.frame)
+ db = self.db
+
+ if bar and bar.GetObjectType then
+ bar:Hide()
+ mod.disabled_frames[bar.specPage] = bar
+ print('putting away old frame')
+ end
+
+ if not bar then
+ bar = CreateFrame('Frame', 'TkPowerBar', UIParent, prototype.frame)
+ end
+ bar.specPage = T.specPage
+ bar.specID = T.specID
+ bar.primary = {} -- {current, max, token}
+ bar.secondary = {} -- {current, max, token}
+ bar.aura = {} -- {name, duration, expires, unit, flags}
+ bar.spell = {} -- copy of the last T.spellevent match
+ print(' setting layout', db)
+ print(bar:GetName())
+ T.SetFrameLayout(bar, prototype.cvars and db[prototype.cvars] or db)
+ T.SetStatusTextures(bar, db)
+
+ print(' setting methods')
+ bar.Init = mod.Bar_Init
+ bar.Event = mod.Bar_Event
+ bar.Update = mod.Bar_Update
+
+
+ --- loop through aura definitions and flag accordingly
+ print('Primary power types:')
+ for order, power_data in pairs(prototype.primary) do
+ print( order, unpack(power_data))
+ local token, power_type = unpack(power_data)
+ local power, max = UnitPower('player', power_type), UnitPowerMax('player', power_type)
+ bar.primary[token] = {power, max, power_type, order}
+ print(' ', cKey(token), '= {', power, max, power_type, order, '}')
+ end
+
+ --- go through secondary data args and assign the appropriate source functions
+ local useAura, useCooldown
+ local used_rows = {}
+ if prototype.secondary then
+ mod.secondary = {}
+ for name, c in pairs(prototype.secondary) do
+ local isActive = true
+ print('parsing extra handler', name)
+ if c.talentID then
+ print(c.talentID, T.specPage)
+ isActive = (type(c.talentID) == 'table') and select(4, GetTalentInfo(unpack(c.talentID), T.specGroup)) or
+ select(4, GetTalentInfoByID(c.talentID, T.specGroup))
+ print(' talentID:', cNum(isActive))
+ end
+ if isActive then
+ local sc = {}
+
+ sc = c
+ print(' enable:', cNum(isActive), cWord(c.type))
+ if c.type == 'aura' then
+ sc.spellName = name
+ if c.binary then
+ sc.Get = function(self)
+ print('get: UnitAura', self.unit, self.spellName, c.filters)
+ local exists = UnitAura(self.unit, self.spellName, nil, self.filters)
+ return (exists) and 1 or 0
+ end
+ else
+ sc.Get = function(self)
+ print('get: UnitAura', self.unit, self.spellName, c.filters)
+ local _,_,_, count = UnitAura(self.unit, self.spellName, nil, self.filters)
+ return count or 0
+ end
+ end
+
+ useAura = true
+ elseif c.type == 'cooldown' then
+ if c.inverse then
+ sc.Get = function(self)
+ local start, duration, enabled = GetSpellCooldown(c.spellID)
+ sc[1] = (duration > 0) and (GetTime() - start) or c.max
+ print('get: GetSpellCooldown (inverse)', c.spellID, '=', sc[1])
+ end
+ else
+ sc.Get = function(self)
+ local start, duration, enabled = GetSpellCooldown(c.spellID)
+ sc[1] = (duration > 0) and (start + duration - GetTime()) or 0
+ print('get: GetSpellCooldown', c.spellID, '=', sc[1])
+ end
+ end
+ useCooldown = true
+ end
+ print(' committing', name, 'to row', sc.order)
+ bar.secondary[name] = sc
+ used_rows[sc.order] = true -- index the drawn rows for talent_update
+ end
+ end
+ end
+
+
+ if useAura then bar:RegisterEvent('UNIT_AURA') end
+ if useCooldown then bar:RegisterEvent('UNIT_SPELLCAST_SUCCEEDED') end
+
+ bar:SetScript('OnUpdate', nil) -- make sure any xml embeds are cleaned out
+ bar:SetScript('OnEvent', mod.Bar_Event)
+ bar:RegisterEvent('UNIT_POWER_FREQUENT')
+
+ bar:Init()
+ bar:Show()
+
+ -- metrics used by data plots
+ bar.width = db.width
+ bar.foreground_inset = db.foreground_inset
+ bar.right_edge = bar:GetRight()
+ bar.fill_limit = bar.right_edge
+ bar.foreground.width = bar.width + (bar.foreground_inset)
+ bar.spacing = 1
+
+ mod.powerbar = bar
+end
+
+mod.Bar_Init = function(self)
+ local mainPower, comboPower
+ for token, power in pairs(self.primary) do
+ if power[4] == 1 then
+ mainPower = power
+ elseif power[4] == 2 then
+ comboPower = power
+ end
+ end
+
+ if mainPower then
+ local power, max, type, token = unpack(mainPower)
+ if power and max then
+ self.powerText:SetText(power)
+ self:SetProgress(power/max)
+ end
+ end
+
+ if comboPower then
+ local power, max, type, token = unpack(comboPower)
+ local px = (self.width-db.secondary.spacing* (max -1)-db.secondary.padding*2) / max
+ self.combo = {}
+ for i = 1, max do
+ if not self.combo[i] then
+ self.combo[i] = self:CreateTexture('TkPrimaryResourcePellet'..i, 'OVERLAY')
+ end
+
+ local k = i - 1
+ local cx = db.secondary.padding + px * k + db.secondary.spacing * k
+ local cy = db.secondary.padding
+ self.combo[i]:ClearAllPoints()
+ self.combo[i]:SetSize(px, db.secondary.height)
+ self.combo[i]:SetPoint(db.secondary.anchor, self, db.secondary.anchorTo, cx, cy)
+ --print(' ', self.combo[i]:GetName(), self.pointsize1, cx, cy, self.combo[i]:GetDrawLayer())
+
+ self.combo[i]:Show()
+ end
+ end
+
+
+ if self.secondary then
+ if not self.resources then
+ print('|cFFFF0000creating resources block')
+ self.resources = {}
+ else
+ local hidecount = 0
+ for i, row in pairs(self.resources) do
+ for j, col in pairs(row) do
+ col:Hide()
+ hidecount = hidecount + 1
+ end
+ end
+ print('hiding', hidecount, 'regions')
+ end
+ for name, secondary in pairs(self.secondary) do
+ local n = secondary.order
+ local sid = 'secondary'..n
+ local c = db[sid] or db
+ if not self.resources[n] then
+ print(' |cFFFF8800creating resource row')
+ self.resources[n] = {}
+ end
+ local row = self.resources[n]
+
+ print('secondary resource', cText(name), 'max= '..cNum(secondary.max), 'scale= '..cNum(secondary.scale))
+ local px = c.padding
+ local pw = (self.width - c.padding*2 - c.spacing * (secondary.scale - 1)) / secondary.scale
+ for i = 1, (secondary.max or 1) do
+ if not row[i] then
+ row[i] = bar:CreateTexture('TkResourcePellet.'..tostring(secondary.order)..'.'..tostring(i))
+ end
+ row[i]:Show()
+ row[i]:SetDrawLayer('OVERLAY', sid)
+ row[i]:SetPoint('BOTTOMLEFT', self, 'TOPLEFT', px, c.y)
+ row[i]:SetSize(pw, db[sid].height or db.height)
+
+ print(' *', cNum(i), cKey(sid), cNum(px), cNum(c.padding))
+ px = px + pw + c.spacing
+ end
+ end
+ end
+
+ mod.Bar_Event(self, nil, 'player')
+end
+
+-- we only want to update at specific points
+mod.Bar_Event = function(self, event, ...)
+ local unit, token = ...
+ _G.print('Update', event, unit, token)
+ if token and unit == 'player' then
+ mod.Bar_Power(self, token)
+ end
+ --print(unit, token, ...)
+ mod.Bar_Aura(bar, event, unit, token, ...)
+end
+
+mod.Bar_Aura = function (self, event, unit)
+ _G.print('Update','bar updating function called', event, unit)
+
+
+ if event == 'UNIT_AURA' or event == nil then
+ for token, info in pairs(self.secondary) do
+ local row = self.resources[info.order]
+ if info.unit == unit then
+ local count = info.Get(info)
+ local db = db['secondary'..info.order] or db
+ for i = 1, info.max do
+ local palette = (i > count) and ('background_color') or ('foreground_color')
+
+ print(token, i, count, (i > count), palette, unpack(db[palette]))
+ row[i]:SetTexture(unpack(db[palette]))
+ end
+ end
+ end
+ end
+end
+
+function mod:Bar_Power(token)
+ if not self.primary[token] then
+ return
+ end
+
+ local p = self.primary[token]
+ -- 1=cur, 2=max, 3=type, 4=token
+ p[1] = UnitPower('player', p[3])
+ p[2] = UnitPowerMax('player', p[3])
+ _G.print('Update',' ', table.concat(self.primary[token],', '))
+
+ if p[4] == 1 then
+ _G.print('Update', 'progress:', p[1]/p[2])
+ --print(unpack(p))
+ self.powerText:SetText(p[1])
+ self:SetProgress(p[1]/p[2])
+ elseif p[4] == 2 then
+ --print('update on', token, 'c:', p[1], 'm:', p[2])
+ self.secondaryText:SetText(p[1])
+ for i = 1, p[2] do
+ local palette = (i > p[1]) and 'background_color' or 'foreground_color'
+ self.combo[i]:SetTexture(unpack(db.secondary[palette]))
+
+ end
+ end
+end
+
+--- Spell parsing
+function mod:SpellCastEvent(e, u, spellName, rank, castID, spellID)
+ if u ~= 'player' then
+ return true
+ end
+ if e == 'UNIT_SPELLCAST_DELAYED' then
+ elseif e == 'UNIT_SPELLCAST_START' then
+ bar.casting = true
+ bar.spellevent = T.spellevent[u]
+ bar.spell = T.casting[u]
+ elseif e == 'UNIT_SPELLCAST_CHANNEL_START' then
+ bar.channeling = true
+ bar.spellevent = T.spellevent[u]
+ bar.spell = T.channeling[u]
+ elseif e == 'UNIT_SPELLCAST_SUCCEEDED' then
+ elseif e == 'UNIT_SPELLCAST_STOP' then
+ bar.casting = nil
+ bar.casting = nil
+ elseif e == 'UNIT_SPELLCAST_CHANNEL_STOP' then
+ bar.channeling = nil
+ bar.channeling = nil
+ end
+end
+
+function mod:PLAYER_TALENT_UPDATE(event, unit)
+ print(cText('*** Talent Update'), cKey('Spec:'), cWord(T.specName), cNum(T.specPage))
+ mod:Prototype_Init()
+end
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Combat/Powerbar.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Combat/Powerbar.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ print('PowerBar', '|cFF44FFFF'..self:GetName()..'|r loaded.')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Aura.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Aura.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,163 @@
+--- Turok - Aura.lua
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 12/25/2015 5:58 AM
+-- Aura data collection
+local GetTime, UnitAura, GetSpellDescription, GetSpellInfo = GetTime, UnitAura, GetSpellDescription, GetSpellInfo
+local T, _G, tinsert = Turok, _G, tinsert
+local mod = T:GetModule("TimerControl")
+
+--@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('Aura', ...)
+ end
+end
+print('Peep!', ...)
+--@end-debug@
+
+T.defaults.spirit.aura = {
+ counterText = "%p",
+ subCounterText = "%.p",
+ chargesText = "%s",
+ justifyH = 'CENTER',
+ justifyV = 'TOP',
+ leftText = "%p",
+ rightText = "%n",
+
+ passive = {
+ icon = {
+ desaturated = false,
+ color = {1, 1, 1, 1},
+ blend = 'BLEND'
+ }
+ },
+ active = {
+ icon = {
+ desaturated = false,
+ color = {1, 1, 1, 1},
+ blend = 'BLEND'
+ }
+ },
+}
+
+local p = mod.prototype.trigger.aura
+p.class = 'trigger' -- identifier values that are visible from function scope
+p.type = 'aura'
+p.cvars = { -- only define things that could break the frame here
+}
+p.events = {
+ ['UNIT_AURA'] = true,
+}
+
+--- takes user supplied values or fills itself with the cvar values provided
+p.Init = function(self, auraName, auraFilters, auraUnit)
+
+ _G.print('Prototype', 'Aura.Init')
+ self.unit = auraUnit and auraUnit or self.dvars.unit
+ self.spellName = auraName and auraName or self.spellName
+ self.filters = auraFilters and auraFilters or self.dvars.filters
+ -- set inversion states, states 0 and 1 are only processed when prevState differs
+ if self.cvars.inverse then
+ self.flags = {
+ active = 0,
+ active_prev = 2,
+ passive = 0,
+ passive_prev = 1,
+ hidden = 1,
+ hidden_prev = 0,
+ }
+ self.duration = 1
+ self.expires = 1
+ else
+ self.flags = {
+ active = 2,
+ active_prev = 0,
+ passive = 1,
+ passive_prev = 0,
+ hidden = 0,
+ hidden_prev = 1}
+ end
+ print(cWord('Load:'),cNum(self.spellID or self.inventoryID or self.itemID), cText(self.spellName))
+end
+
+p.Unload = function(self)
+ print('unloading events')
+ for k,v in pairs(p.events) do
+ self:UnregisterEvent(k)
+ end
+end
+
+--- Return current status data
+p.Query = function(self)
+ print( ' Q:', self.unit , self.spellName, nil, self.filters)
+ return UnitAura(self.unit , self.spellName, nil, self.filters)
+end
+
+p.SetText = mod.SetText
+
+--- Set supplied status data, using the list returned by p.Query()
+p.Set = function(self, ...)
+ self.active, self.rank, _, self.count, self.dispelType, self.duration, self.expires, self.caster,
+ self.isStealable, self.shouldConsolidate, self.spellID, self.canApplyAura, self.isBossDebuff = ...
+ if self.active then
+ if self.cvars.duration then
+ self.duration = self.cvars.duration
+ print(cKey('force duration ='), cNum(self.cvars.duration))
+ end
+ self.start = self.expires - self.duration
+ end
+end
+
+--- Handle in the frame itself to limit collateral from bugs
+function p.Event(self, event, unit)
+ self.event = event
+ if not event then
+ print(' DRY FIRE')
+ elseif unit ~= self.unit then
+ return
+ end
+
+ --- 3 states: nil, 0, >0
+
+ local active, rank, _, count, dispelType, duration, expires, caster, isStealable, shouldConsolidate, spellID, canApplyAura, isBossDebuff = self:Query()
+ local state
+ if self.cvars.duration and active ~= self.active then
+ print('passive aura with forced duration')
+ state = self.flags.active
+ duration = self.cvars.duration
+ expires = GetTime() + self.cvars.duration
+ elseif (not self.cvars.duration and (duration ~= self.duration or expires ~= self.expires)) or active ~= self.active then
+ if not active then
+ if (not self.untriggerFunc) or self:untriggerFunc() then
+ state = self.flags.hidden
+ end
+ else
+ if (not self.triggerFunc) or self:triggerFunc() then
+ if duration == 0 then
+ print('passive aura')
+ state = self.flags.passive
+ else
+ print('updating an active aura')
+ state = self.flags.active
+ end
+ self.start = expires - duration
+ end
+ end
+ end
+
+ if state then
+ T:Dispatch('TK_AURA_UPDATE', self.spellID, self.filters, state, self.displayState)
+ self:Set(active, rank, _, count, dispelType, duration, expires, caster, isStealable, shouldConsolidate, spellID, canApplyAura, isBossDebuff)
+ self:SetState(state)
+ print(cText('push state'), cNum(self.displayState).. ' (prev: '.. cNum(self.prevState)..')', self.timerName, cText(active), cKey(duration), cNum(expires), cBool(self.cvars.inverse))
+ else
+ print(cText('no changes'), cNum(self.displayState).. ' (prev: '.. cNum(self.prevState)..')', cText(self.timerName))
+ 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
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Container.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Container.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,157 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 1/16/2016 12:20 AM
+local _G, CreateFrame = _G, CreateFrame
+local T, tinsert, UIParent = _G.Turok, table.insert, _G.UIParent
+local mod = T.modules.TimerControl
+local db, CollectorTray
+
+local pairs, ipairs, gsub, sub, setmetatable = pairs, ipairs, string.gsub, string.sub, setmetatable
+local INVTYPE_FINGER, INVSLOT_FINGER1, INVSLOT_FINGER2, INVTYPE_TRINKET, INVSLOT_TRINKET1, INVSLOT_TRINKET2 =
+INVTYPE_FINGER, INVSLOT_FINGER1, INVSLOT_FINGER2, INVTYPE_TRINKET, INVSLOT_TRINKET1, INVSLOT_TRINKET2
+--@debug@
+local DEBUG = true
+--@end-debug@
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
+local print = function(...)
+ if not DEBUG then return end
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('TimerContainer', ...)
+ end
+end
+print('Peep!', ...)
+
+--- defaults
+local Containers = {}
+
+--- manages collections of timer displays
+local TimerContainer_Init = function(frame, cvars)
+
+ frame.num_timers = 0
+ frame.anchor = cvars.anchor
+ frame.parent = cvars.parent
+ frame.anchorTo = cvars.anchorTo
+ frame.x = cvars.x
+ frame.y = cvars.y
+ frame.name = cvars.name
+ frame.padding = cvars.padding
+ frame.spacing = cvars.spacing
+ frame.width = cvars.width
+ frame.height = cvars.height
+ frame.timers = {}
+ frame.childAnchor = cvars.childAnchor
+ frame.childAnchorTo = cvars.childAnchorTo
+
+ frame:ClearAllPoints()
+ frame:SetPoint(cvars.anchor, cvars.parent, cvars.anchorTo, cvars.x, cvars.y)
+ frame:SetSize(cvars.width, cvars.height) -- initial values
+ frame.NameText:SetText(frame.name)
+end
+
+local TimerContainer_Add = function(frame, timer)
+ if timer.containerHandle then
+ print('stop now')
+ return
+ end
+ timer.containerHandle = 1
+
+ print('adding', timer.timerName, 'to', frame.name)
+ local handle = frame.num_timers + 1
+ -- if the timer is ordered, start from the top and shift each item upward until they are no longer
+ -- above the
+ print('resulting handle:', handle)
+ print(#frame.timers)
+
+ frame.num_timers = frame.num_timers + 1
+
+ tinsert(frame.timers, timer)
+ timer.containerHandle = #frame.timers
+ --frame.timers[handle] = timer
+end
+
+local TimerContainer_Unlock = function(frame)
+
+end
+
+local TimerContainer_Update = function(frame)
+ local frameCount, hiddenCount = 0, 0
+ local w = frame.padding
+ local translation_points = {}
+ local dx, dy = 0, 0 -- net change in container dimensions
+ for k, spirit in pairs(frame.timers) do
+ hiddenCount = hiddenCount + 1
+ if spirit:IsVisible() and not(spirit.trash or spirit.cvars.absolute) then
+ frameCount = frameCount + 1
+ spirit.index = frameCount
+ print(' -', cNum(hiddenCount), cNum(frameCount), cKey(spirit:GetName()))
+ --tinsert(frame.timers, spirit)
+ spirit:ClearAllPoints()
+ local tx = w
+ local ty = 0
+ if spirit.cvars.relative then
+ tx = tx + spirit.cvars.x
+ ty = ty + spirit.cvars.y
+ else
+ w = w + spirit:GetWidth() + frame.spacing
+ end
+ translation_points[k] = {
+ x = spirit.cvars.x, y = spirit.cvars.y,
+ dx = tx - spirit.cvars.x, dy = ty - spirit.cvars.y
+ }
+ end
+
+ --- track the size of in/outbound frames
+ if not spirit.collected then
+ if spirit.trash then
+ dx = dx - spirit.width
+ elseif spirit.add then
+ dx = dx + spirit.width
+ end
+ spirit.collected = true
+ end
+ end
+ print(cText(' dx:'), cNum(dx))
+
+
+ frame.width = frame.width + dx
+ frame:SetWidth(frame.width)
+ local ddX = dx / frameCount
+
+ for id, a in pairs(translation_points) do
+ local spirit = frame.timers[id]
+
+
+ spirit.slide.t1:SetOffset(a.dx, a.dy)
+ spirit.slide:SetScript('OnFinished', function()
+ spirit.cvars.x = a.x + a.dx
+ spirit.cvars.y = a.y + a.dy
+ spirit:SetPoint(frame.childAnchor, frame, frame.childAnchorTo, spirit.cvars.x, spirit.cvars.y)
+ end)
+ spirit.slide:Play()
+ end
+end
+
+--- Updates the appropriate containers' object positions
+function mod.Report(self)
+ if not self.container then
+ self.container = 'default'
+ print('reporting to default container')
+ else
+ print('reporting to container', self.container)
+ end
+
+ if not Containers[self.container] then
+ print('need to create')
+ Containers[self.container] = CreateFrame('Frame', 'TkCollectorFrame'..self.container, UIParent, 'TkContainerTemplate')
+ TimerContainer_Init(Containers[self.container], mod.db.containers[self.container] or mod.db.containers)
+ end
+
+ if not self.containerHandle then
+ TimerContainer_Add(Containers[self.container], self)
+ else
+ print(self.timerName, 'has a container assigned')
+ end
+ TimerContainer_Update(Containers[self.container])
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Cooldown.lua
--- /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
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Editor.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Editor.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,257 @@
+--- Modules
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 1/18/2016 3:33 PM
+local _G = _G
+local T, type, pairs = _G.Turok, type, pairs
+local mod = T.modules.TimerControl
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
+local print = function(...)
+ if Devian and DevianDB.workspace ~= 1 then
+ print('Dialog', ...)
+ end
+end
+print('Peep!', ...)
+
+
+local TimerConfig = {
+ conf = {
+ padding = 4,
+ spacing = 1,
+ width = 450,
+ },
+ info = {
+ { key = 'timerName',
+ desc = 'Unique Name:',
+ type='EditBox', name = 'timerName', fill=true,
+ line = true,
+ },
+ { key = 'spellEnable',
+ inherits = 'TurokCheckButtonOverlay',
+ type='CheckButton', name = 'spellEnable', fixed=25, point='LEFT',
+ get = Dialog_Boolean, getarg = 'spellID',
+ collapse = true,
+ desc = 'Spell Name',
+ },
+ { key = 'spellID',
+ type='EditBox', name = 'spellName',
+ line = true, float = true
+ },
+ { key = 'fill_inverse',
+ desc = 'Reverse Fill',
+ type='CheckButton', name='fillInverse', fixed=25, point='LEFT',
+ get = Dialog_Boolean, getarg = 'fill_inverse', text='Inverted Fill',
+ line = true,
+ },
+ { key = 'display',
+ desc = 'Display Type',
+ type='EditBox', name='displayType',
+ line = true,
+ },
+ },
+}
+
+local Dialog_SetField = {}
+local dget = function(name, key)
+ if mod.db.timers[name] then
+ return mod.db.timers[name][key]
+ end
+ return nil
+end
+local inherits = {
+ EditBox = 'TkEditBox',
+ CheckButton = 'TurokCheckButtonInline',
+ Slider = 'TkSlider',
+}
+
+Dialog_SetField['CheckButton'] = function(self, checked) self:SetChecked(checked) end
+Dialog_SetField['EditBox'] = function(self, text)
+ print(' ', cKey(self:GetName()), text)
+ self:SetText(text or '') end
+Dialog_SetField['Button'] = function(self, text) self:SetText(text) end
+
+
+local function Dialog_Boolean(name, key)
+ print(' Dialog_Boolean', name, key)
+ return (mod.db.timers[name][key] and true or false)
+end
+
+function mod.Dialog_Select(self, key)
+ local timer
+ if self.parent_values[key] then
+ print('matched timer name', key)
+ timer = self.parent_values[key]
+ elseif rawget(mod.frames.spellID, key) then
+ print('matched spellID', key)
+ timer = mod.frames.spellID[key][1]
+ for k,v in pairs(timer) do
+ print(' -', k, '=', v)
+ end
+ end
+
+ if timer then
+ self.values = timer
+ self.timerName = timer.timerName
+ else
+ self.values = {
+ timerName = 'New Timer'
+ }
+ self.timerName = 'New Timer'
+ end
+ mod.Dialog_Init(self, TimerConfig.conf, TimerConfig.info)
+end
+
+function mod.Dialog_Init(self, dconf, dinfo)
+ print('init,', self.values.timerName)
+
+ if not self.fields then
+ self.fields = {}
+ self.rows = {}
+ self.Click = mod.Dialog_Click
+ self.Check = mod.Dialog_Check
+ self.EditBox = mod.Dialog_EditBox
+ end
+ print(self.name, self.timerName)
+ self.name:SetText(self.timerName)
+
+ local inset = dconf.padding + dconf.spacing
+ -- frame X max
+ local fX = 0
+ -- row number, row Y offset
+ local rn, ry = 1, -34
+ -- row x offset left-align, row x offset right-aligned, largest collapsed element
+ local rxL, rxR, rC, rh = dconf.spacing, dconf.spacing, 0, 0
+ for i, opt in ipairs(dinfo) do
+ if not self.rows[rn] then
+ self.rows[rn] = CreateFrame('Frame', self:GetName()..'Row'..rn, self, 'TurokDialogRow')
+ end
+
+ local k = opt.key
+ if self.fields[i] == nil then
+ self.fields[i] = CreateFrame(opt.type, self:GetName()..opt.name, self.rows[rn], opt.inherits or inherits[opt.type])
+ self.fields[i].index = i
+ self.fields[i].key = k
+ -- row point (from), row point (to), row x offset
+ local rp, rpt, rx
+ -- row delta
+ local rd
+ if opt.fill then
+ rpt = opt.float and 'BOTTOMLEFT' or 'BOTTOMRIGHT'
+ -- row point X offset
+ local rpx = opt.float and dconf.spacing or -dconf.spacing
+ self.fields[i]:SetPoint(rpt, self.rows[rn], rpt, rpx, 0)
+ print(' fill:', rpt, '-', rpt,' :: ', rpx, 0)
+ rd = 0
+ else
+ rd = self.fields[i]:GetWidth() + dconf.spacing
+ end
+ if opt.float then
+ rp = 'BOTTOMRIGHT'
+ rx = -rxR
+ rxR = rxR + rd
+ elseif opt.collapse then
+ rp = 'BOTTOMLEFT'
+ rx = dconf.spacing
+ rC = math.max(rC, rd + dconf.spacing) -- spacing L + rd{width + spacing R}
+ else
+ rp = 'BOTTOMLEFT'
+ rx = rxL
+ rxL = rxL + rd
+ end
+
+ rh = math.max(rh, self.fields[i]:GetHeight())
+ self.fields[i]:SetPoint(rp, self.rows[rn], rp, rx, dconf.spacing)
+ print(' align:', rp, '-', rp, ' :: ', rx, 0)
+ print(' dR:', cNum(rd), 'nR:',cWord(rn), 'rX:', cNum(rx), 'i:', cText(i))
+
+ if opt.line or (not dinfo[i+1]) then
+ print(cText'nR:', cNum(rn), 'rY:', cNum(ry))
+ self.rows[rn]:ClearAllPoints()
+ self.rows[rn]:SetPoint('TOPLEFT', self, 'TOPLEFT', dconf.padding, ry)
+ self.rows[rn]:SetPoint('TOPRIGHT', self, 'TOPRIGHT', -dconf.padding, ry)
+ self.rows[rn]:SetHeight(rh + dconf.spacing*2)
+ self.rows[rn]:Show()
+ rn = rn + 1
+ ry = ry - (rh + dconf.spacing*3) -->| {spacing T + rh + spacing B} + spacing dR |<--
+
+ print('fX:',cNum(fX), 'rX:', cNum(rxL+rxR+dconf.spacing), 'rC:', cNum(rC))
+ fX = math.max(fX, rxL+rxR+dconf.spacing)
+ fX = math.max(fX, rC)
+ rxL, rxR = dconf.spacing, dconf.spacing
+ rh = 0
+ end
+ end
+
+ self.fields[i]:Show()
+ if opt.desc and self.fields[i].description then
+ self.fields[i].description:SetText(opt.desc)
+ end
+ Dialog_SetField[opt.type](self.fields[i], opt.get and opt.get(self.values.timerName, opt.getarg) or self.values[k])
+
+ end
+ if not self.initialized then
+ self.initialized = true
+ self:SetSize(fX + dconf.padding + dconf.spacing*2, dconf.padding + math.abs(ry))
+ end
+end
+
+function mod.Dialog_Click(self,...)
+ local command = self:GetName():match("_(a%+)$")
+
+ print(command)
+end
+
+function mod.Dialog_Check(self, ...)
+ print('field #', self.index, self.key, 'checked')
+ --self:SetChecked(self:GetChecked() and false or true)
+end
+
+function mod.Dialog_EditBox(self, ...)
+ print('field #', self.index, self.key, 'changed', self:GetText())
+
+ if self.key == 'timerName' then
+ self.values.timerName = self:GetText()
+ self.name:SetText(self.values.timerName)
+ self.timerName = self.values.timerName
+ elseif self.key == 'spellID' then
+ print('handling spellID')
+ end
+
+end
+
+function mod.Dialog_Command(str, editbox)
+ --local spellID = T:GetArgs(str, 1,0)
+ local f = mod.EditDialog
+ f.values = {}
+ local db = mod.db
+
+
+ local func, t, z = pairs(db.timers) -- iterator, table
+ local name, values, y = func(t) -- index, values
+ f.parent_values = {[name] = values}
+ f.timerName = name
+ f.values = values
+ f.values.timerName = name
+ for k,v in pairs(f.values) do
+ print(cText(k), cType(v))
+ end
+ print('pairs1', func, t)
+ print('pairs2', z, y)
+ name, values = func(t, name)
+ while name do
+ print(' entry:', name, values)
+ f.parent_values[name] = values
+ name, values = func(t, name)
+ end
+
+
+
+ if f:IsVisible() then
+ f:Hide()
+ else
+ mod.Dialog_Init(f, TimerConfig.conf, TimerConfig.info)
+
+ f:Show()
+ end
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Icon.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Icon.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,245 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 1/15/2016 6:31 PM
+local T, _G = Turok, _G
+local mod = T.modules.TimerControl
+local GetTime, floor, unpack, tconcat = GetTime, floor, unpack, table.concat
+local HIDDEN, PASSIVE, ACTIVE = 0, 1,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('Icon', ...)
+ end
+end
+print('Peep!', ...)
+--@end-debug@
+local GetPrint = function(trace)
+ if trace then
+ return print
+ else
+ return function() end
+ end
+end
+
+T.defaults.spirit.icon = {
+ combatFade = true,
+ alpha = 1,
+ alpha_passive = 1,
+ alpha_active = 1,
+ alpha_ooc_passive = 0,
+ alpha_ooc_active = 1,
+ alpha_ooc = 0.25,
+ size = 48,
+ container = 'default',
+ strata = 'LOW',
+ fade_in_time = 0.2,
+ fade_out_time = 0.3,
+ anchor = 'BOTTOM', anchorTo = 'BOTTOM',
+ parent = 1,
+ size = 48,
+ width = 48, height = 48,
+ x = 0,
+ y = 0,
+ strata = 'MEDIUM',
+ padding = 3,
+ spacing = 1,
+ foreground_inset= 0,
+}
+
+local p = mod.prototype.display.icon
+
+p.type='display'
+p.inherits = 'TurokIconTemplate'
+
+--- if config flags need to overrided
+p.cvars = {
+ enableIcon = true
+}
+--- Negotiate the config differences between different display states
+-- Hidden - display is or should (via fade-out) be hidden
+-- Passive - display is visible, but no timing information is processed
+-- Active - display is visible and counting time; on expiration, it will downgrade itself to passive or hidden
+p.Init = function(self)
+ local print = GetPrint(self.trace)
+
+ print('display.Icon.Load')
+ local c = self.cvars
+ if c.type == 'aura' then
+ self.spiral:SetReverse(true)
+ else
+ self.spiral:SetReverse(false)
+ end
+
+ if not self.icon:IsShown() then
+ self.icon:Show()
+ end
+ print('icon texture=', self.spellIcon or self.itemIcon)
+ self.icon:SetTexture(self.spellIcon or self.itemIcon)
+end
+
+
+--- Advances the display state, applying any visual transitions as necessary;
+-- @param self frame object
+-- @param newState state value; 1 for inactive, 2 for untimed active, 3 for timed active
+-- @param forcePrevious force the frame's lastState to this value to block off OnUpdate difference tests
+-- even if forced, the actual history value will still be used for method scope
+p.SetState = function(self, newState, forcePrevious)
+
+ --print(cWord(self:GetName()), 'state change issued:', cNum(state), cType(previous))
+
+ local previous = self.displayState
+ self.prevState = forcePrevious and forcePrevious or previous
+ self.displayState = newState
+ print('SetState', cNum(newState), '(from '..cType(previous)..')', cText(self.timerName))
+ --_G.print('Prototype.'..self.cvars.type, 'SetState', cNum(newState), '(from '..cType(previous)..')', cText(self.timerName))
+
+ --- Change transitions
+ if newState ~= previous then
+ print(cText(' Transition'))
+ if newState == HIDDEN then
+ print(cText(' to HIDDEN'))
+ -- to HIDDEN
+ if previous then
+ -- has to have been ACTIVE or PASSIVE at this point
+ if previous == ACTIVE then
+ print(' from ACTIVE')
+ self.spiral:StopAnimating()
+ else
+ print(' from PASSIVE')
+ end
+
+ self.Intro:Stop()
+ if self.event then
+ print(' set by event script')
+ self.Outro:Play()
+ else
+ print(' non-event source')
+ self:Hide()
+ end
+ end
+ -- want to end here if HIDDEN from nil
+ else
+ -- to ACTIVE or PASSIVE
+ self.Outro:Stop() -- stop any running outro
+
+
+ if newState == ACTIVE then
+
+ -- and is ACTIVE
+ self:Show()
+ self.spiral:Show()
+ self.spiral:SetCooldown(self.charges and self.chargeStart or self.start, self.charges and self.chargeDuration or self.duration)
+ print('spiral:Play() new', self.charges and self.chargeStart or self.start, self.charges and self.chargeDuration or self.duration)
+ end
+
+ if previous and previous ~= HIDDEN then
+ print(cText(' from vis'))
+ -- from visible
+ if self.event then
+ self.refresh = true
+ self.Retro:Play()
+ end
+ else
+ print(cText(' from non-vis'))
+ if self.event then
+ self.Intro:Play()
+ else
+ self:Show()
+ end
+ end
+ end
+ else
+ --- No-change transitions
+ if newState == ACTIVE then
+ -- ACTIVE to ACTIVE
+ print(cText(''))
+ self.spiral:Show()
+ self.spiral:SetCooldown(self.charges and self.chargeStart or self.start, self.charges and self.chargeDuration or self.duration)
+ print('spiral:Play() new', self.charges and self.chargeStart or self.start, self.charges and self.chargeDuration or self.duration)
+ else
+ print(cPink('stopping spiral'))
+ self.spiral:Hide()
+ end
+
+ -- non-HIDDEN to non-HIDDEN and not a dry fire
+ if self.event and newState ~= HIDDEN then
+ self.refresh = true
+ self.Retro:Play()
+ end
+ end
+
+ if newState ~= HIDDEN then
+ print(cText(' CVars:'))
+ local c
+ if newState == ACTIVE then
+ print('apply active profile')
+ c = self.cvars.active
+ self.fillState = 1
+ else
+ print('apply passive profile')
+ c = self.cvars.passive
+ self.fillState = 2
+ end
+
+ if self.icon and c.icon then
+
+ print(cText(' '), cWord('desat=')..cBool(c.icon.desaturated), cWord('color=')..cNum(tconcat(c.icon.color, ', ')))
+ self.icon:SetVertexColor(unpack(c.icon.color))
+ self.icon:SetDesaturated(c.icon.desaturated)
+ end
+ self:UpdateAlpha(T.inCombat, self.displayState, self.fillState)
+ end
+end
+
+p.Update = function(self)
+
+ if self.displayState == 0 and self.prevState ~= 0 then
+ print('flip to', self.displayState)
+ self.prevState = self.displayState -- quietly advance state
+ self.percent = 1
+ self.valueFull = 0
+ self.value = 0
+ self:SetText()
+ elseif self.displayState == 1 and self.prevState ~= 1 then
+ print('flip to', self.displayState)
+ self.prevState = self.displayState -- quietly advance state
+ self.valueFull = 0
+ self.value = 0
+ self.percent = 1
+ self:SetText()
+ print(self.percent, self.duration, self.start, self.expires)
+ elseif self.displayState == 2 then
+ if self.prevState ~= 2 or self.refresh then
+ print('flipped to', self.displayState)
+ self.prevState = self.displayState -- quietly advance state
+ self.refresh = nil
+ end
+ -- prevState is set externally
+ local time = GetTime()
+ if self.expires <= time and self.charges == self.maxCharges then
+ _G.print(self.cvars.type, 'timer expired, set to', (self.cvars.persist and self.flags.passive or self.flags.hidden))
+ self.percent = 1
+ self.duration = 0
+ self.expires = 0
+ self.start= 0
+ self.valueFull = self.duration
+ self.value = self.duration
+ self.elapsed = self.duration
+ self.remaining = 0
+ self:SetState(self.cvars.persist and self.flags.passive or self.flags.hidden)
+ else
+ self.percent = (self.charges and self.charges < self.maxCharges) and ((time - self.chargeStart) / self.chargeDuration) or ((time - self.start) / self.duration)
+ self.valueFull = self.expires - time
+ self.elapsed = time - self.start
+ self.remaining = self.duration - time
+
+ self.value = floor(self.valueFull)
+ end
+
+ --PlaySoundFile(self.cvars.sound_active)
+ self:SetText()
+ end
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Import.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Import.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,331 @@
+--- Turok - Import.lua
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 1/4/2016 11:07 AM
+-- Dialog interfaces and framework debugging tools; see the Google Doc
+
+local tconcat, unpack, pairs, ipairs, tostring, string = table.concat, unpack, pairs, ipairs, tostring, string
+local BOOKTYPE_SPELL, GetSpellBookItemName, GetSpellBookItemInfo = BOOKTYPE_SPELL, GetSpellBookItemName, GetSpellBookItemInfo
+local GetSpellTabInfo, GetNumSpellTabs, GetSpellInfo, GetFlyoutInfo, GetSpellDescription = GetSpellTabInfo, GetNumSpellTabs, GetSpellInfo, GetFlyoutInfo, GetSpellDescription
+local GetFlyoutSlotInfo, GetSpellBaseCooldown, FindSpellBookSlotBySpellID, IsTalentSpell = GetFlyoutSlotInfo, GetSpellBaseCooldown, FindSpellBookSlotBySpellID, IsTalentSpell
+local GetNumClasses, GetClassInfo, GetNumSpecializationsForClassID, GetSpecializationInfoForClassID
+= GetNumClasses, GetClassInfo, GetNumSpecializationsForClassID, GetSpecializationInfoForClassID
+local _G, setmetatable, type, T = _G, setmetatable, type, Turok
+local mod = Turok.modules.TimerControl
+mod.EditDialog = TkTimerConfig
+mod.SelectDialog = {}
+
+local print = function(...)
+ if Devian and DevianDB.workspace ~= 1 then
+ print('Dialog', ...)
+ end
+end
+print('Peep!', ...)
+local strpad = function(str, num)
+ return tostring(str) .. string.rep(' ', num - #tostring(str))
+end
+
+--- Handles mouse click on spellbook row frame
+mod.SpellBook_Click = function(self, btn)
+ print('mouse', btn, self.spellID)
+ mod.Dialog_Select(mod.EditDialog, self.spellID)
+end
+
+--- Creates the spell book import frame
+--
+local cmd
+function mod.Import_Open()
+ local self = mod
+ print('Spirit', 'SpecSpells')
+ local book_list = {}
+ local tab = {}
+ local list_info = {}
+ local book_max = 0
+ for k = 1, GetNumSpellTabs() do
+ local name, texture, offset, numSpells = GetSpellTabInfo(k)
+ tab[offset] = {k, name, texture, numSpells}
+ print('Spirit', name, offset, numSpells)
+ book_max = offset + numSpells
+ end
+ local tabID, tabName, tabTexture
+ local flyout, spellflyout = {}, {}
+ for i = 1, book_max do
+ if tab[i] then
+ tabID, tabName, tabTexture = unpack(tab[i])
+ end
+
+ if book_list[i] == nil then
+ local skillType, spellID = GetSpellBookItemInfo(i, BOOKTYPE_SPELL)
+ local spellNameUpper, spellSubText = GetSpellBookItemName(i, BOOKTYPE_SPELL)
+ local spellName, spellRank, spellTexture, castTime, minRange, maxRange = GetSpellInfo(spellID)
+ _G.print('Spirit', i, spellID, spellName)
+ _G.print('Spirit', ' ', skillType, spellSubText)
+
+ local spellDesc
+ if skillType == 'FLYOUT' then
+ local numSlots
+ spellName, spellDesc, numSlots = GetFlyoutInfo(spellID)
+ print('flyout #'..spellID..':', spellName)
+ flyout[spellID] = {}
+ for i=1, numSlots do
+ local fspellID, _, isKnown, fSpellName, fSpellValue = GetFlyoutSlotInfo(spellID, i)
+ print(' spell #', fspellID, fSpellName, isKnown)
+ if isKnown then
+ flyout[spellID][i] = fspellID
+ spellflyout[fspellID] = spellID
+ end
+ end
+
+ else
+ spellDesc = GetSpellDescription(spellID)
+ end
+
+ book_list[i] = {
+ skillType = skillType,
+ spellIndex = i,
+ spellID = spellID,
+ spellName = spellName,
+ spellDesc = spellDesc,
+ spellNameUpper = spellNameUpper,
+ spellSubText = spellSubText,
+ spellTexture = spellTexture,
+ spellCooldown = GetSpellBaseCooldown(spellID),
+ castTime = castTime,
+ minRange = minRange,
+ maxRange = maxRange,
+ tabID = tabID,
+ tabName = tabName,
+ tabTexture = tabTexture
+ }
+
+
+
+ end
+ end
+
+ local selector = CreateFrame('Frame', 'TkSpellSelector', UIParent, 'TurokListFrame')
+ self.frames.selector = selector
+ selector.name:SetText("Spells")
+ selector:SetPoint('TOP')
+ selector.page = 1
+
+ selector.GetRow = function(row, info, id, item_num)
+ print(' ', row:GetName(), info, id, item_num)
+ if not row.opts then
+ row.opts = {
+ CreateFrame('CheckButton', 'TkCheck_'..item_num, row, 'TurokCheckButtonInline'),
+ row:CreateFontString('TextItem_'..item_num, 'OVERLAY', 'TurokFontDetail'),
+ row:CreateTexture(nil, 'OVERLAY'),
+ row:CreateTexture(nil, 'OVERLAY'),
+ row:CreateFontString('TextItem_'..item_num..'ID', 'OVERLAY', 'TurokFontDetail'),
+ }
+ end
+ local page = book_list[id]
+ if page.skillType == 'FLYOUT' then
+ row.background:SetTexture(1,.2,.3,.4)
+
+ elseif rawget(mod.frames.spellID, page.spellID) then
+ print('has timer frame under spell #', page.spellID, mod.frames.spellID[page.spellID])
+ row.background:SetTexture(1,1,0,1)
+ local timer = mod.frames.spellID[page.spellID]
+ row:SetScript('OnMouseDown', function(self) self.clicked = true end)
+ row:SetScript('OnMouseUp', function(self) if self.clicked then self.clicked = nil mod.Dialog_Select(mod.Editor, timer.timerName) end end)
+ elseif page.spellCooldown and page.spellCooldown > 0 then
+ row.background:SetTexture(.3,.6,1,1)
+ else
+ row.background:SetTexture(0,0,0,0.3)
+ end
+
+ row:SetScript('OnMouseDown', mod.SpellBook_Click)
+
+ row.desc = page.spellDesc
+ row.spellID = page.spellID
+ row.opts[1].desc = page.skillType
+ row.opts[1]:SetSize(20,20)
+ row.opts[1].description:SetText(nil)
+ row.opts[1]:SetChecked(page.checked)
+ row.opts[2]:SetText(page.spellName)
+ row.opts[2]:SetWidth(200)
+ row.opts[2]:SetJustifyH('LEFT')
+ row.opts[3]:SetSize(20,20)
+ row.opts[3]:SetTexture(page.spellTexture)
+ row.opts[3]:SetPoint('CENTER')
+ row.opts[4]:SetSize(20,20)
+ row.opts[4]:SetTexture(page.tabTexture)
+ row.opts[4]:SetPoint('CENTER')
+ row.opts[5]:SetWidth(60)
+ row.opts[5]:SetJustifyH('LEFT')
+ row.opts[5]:SetText(page.spellID)
+ end
+
+ selector.Click = function(button, list)
+ local b = button:GetName():match("_(%a+)$")
+ if b == 'Prev' then
+ --print(b, list.offset, list.num_rows)
+ if list.page > 1 then
+ list.page = list.page - 1
+ TkList_SetView(list, list.num_rows * (list.page-1) + 1)
+ end
+ list.pagenum:SetText(list.page)
+ elseif b == 'Next' then
+ --print(' ',list.page, list.num_rows, list.max_row)
+ if (list.page) * list.num_rows < list.max_row then
+ list.page = list.page + 1
+ TkList_SetView(list, list.offset + list.num_rows)
+ end
+ list.pagenum:SetText(list.page)
+
+ elseif b == 'Add' then
+ mod.CommitBook(book_list, tab, list_info)
+ end
+ --print(list.page, list.offset, list.num_rows)
+ end
+
+ selector.Wheel = function(self, delta)
+ local offset = self.offset - delta
+ if offset > 0 and offset <= (self.max_row - self.num_rows) then
+ TkList_SetView(self, offset)
+ end
+ end
+
+ selector.Check = function(checkbutton, row, list)
+ local index = checkbutton:GetParent().actual_row
+ book_list[index].checked = (not book_list[index].checked) and true or false
+ checkbutton:SetChecked(book_list[index].checked)
+
+ if book_list[index].skillType == 'FLYOUT' then
+ for slot, spellID in pairs(flyout[book_list[index].spellID]) do
+
+ local spIndex = FindSpellBookSlotBySpellID(spellID)
+ print(' also toggling', slot, spellID, ' book slot', spIndex, book_list[spIndex].spellName)
+ book_list[spIndex].checked = book_list[index].checked
+ end
+ TkList_SetView(list, list.offset)
+ end
+ end
+ TkList_Init(selector, book_list, 1, 12)
+ selector:Show()
+ mod.SelectDialog = selector
+end
+--@end-debug@
+
+
+function mod.CommitBook(bookInfo, tabInfo, uiInfo)
+ print('committing')
+ print(' book data: ', #bookInfo, 'entries')
+ print(' tab data: ', #tabInfo, 'entries')
+
+ for index, e in ipairs(bookInfo) do
+ if e.checked then
+ local spellPretext = ''
+ if IsTalentSpell(index) then
+ spellPretext = 'Talent'
+ end
+ print(' ', strpad(spellPretext .. e.spellName, 20))
+ print(' ', strpad(e.spellSubText, 10), strpad(e.spellCooldown,5), strpad(e.skillType,6))
+
+ end
+ end
+end
+
+
+
+
+--- /tki command
+-- Constructs an index that associates global spec ID's with a list of the timers that would display under it.
+-- List entries are stored as [name] = true to prevent duplication of values in SavedVariables.
+
+function mod:CreateIndex()
+
+ --@debug@ Revert config to defaults
+ _G.TurokData = T.defaults
+ --@end-debug@
+
+ mod.db.timerindex = {}
+ setmetatable(mod.db.timerindex, {__mode = "v"}) -- ensure that dead leafs fall off
+ local index = mod.index
+ local timers = mod.timersByName
+
+ -- build class info hash and create subtables
+ local classID = {}
+ local className = {}
+ local specIDPage = {}
+ local specPageID = {}
+ local classSpecs = {}
+ print('|cFF0088FFCreateIndex|r')
+
+ --- use the internal class/specialization list
+ for i = 1, GetNumClasses() do
+ local _, tag, id = GetClassInfo(i)
+ classID[tag] = id
+ className[id] = tag
+ index[id] = {}
+ specPageID[tag] = {}
+ index[tag] = index[id]
+
+ classSpecs[tag] = GetNumSpecializationsForClassID(id)
+ for j = 1, classSpecs[tag] do
+ local specID, specName = GetSpecializationInfoForClassID(id, j)
+ print('|cFFFF0088map:|r', tag, j, specID, specName)
+ specIDPage[specID] = j
+ specPageID[tag][j] = specID
+ index[specID] = {}
+ index[id][j] = {}
+ end
+ end
+ index.global = {}
+
+ for name,timer in pairs(timers) do
+ -- class is set
+ if type(timer) == 'table' then
+ print(name)
+ if timer.playerClass then
+
+ index[timer.playerClass][name] = true
+
+ -- spec restricted
+ if timer.specPage then
+ if type(timer.specPage) ~= 'table' then
+ -- fix it up
+ timer.specPage = {timer.specPage }
+ end
+
+ print(' |cFFFFFF00class:|r', timer.playerClass .. ', |cFF99FF00spec:|r '.. tconcat(timer.specPage,', '))
+ for _, specPage in ipairs(timer.specPage) do
+ index[timer.playerClass][specPage][name] = true
+ index[specPageID[timer.playerClass][specPage]][name] = true
+ end
+
+ -- no spec restriction, copy it out
+ elseif not timer.specID then
+ print(' |cFFFFFF00class:|r', timer.playerClass .. ', |cFF99FF00spec:|r ALL')
+ for i = 1, classSpecs[timer.playerClass] do
+ local specID = specPageID[timer.playerClass][i]
+
+ index[timer.playerClass][i][name] = true -- store for local ID
+ index[specID][name] = true -- store for global ID
+ end
+ end
+ end
+
+ if timer.specID then
+ index[timer.specID][name] = true
+ end
+
+ if not (timer.playerClass or timer.specID or timer.specPage) then
+ for tag, id in pairs(classID) do
+ index[tag][name] = true
+ for specPage, specID in pairs(specPageID[tag]) do
+ index[tag][specPage][name] = true
+ index[specID][name] = true
+ end
+ end
+ print(' |cFFFFFF00class:|r ALL, |cFF99FF00spec:|r ALL')
+ end
+ end
+ end
+
+ _G.TurokData.timerindex = index
+ T:Print('Hive data updated. /rl to commit.')
+end
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Presets.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Presets.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,394 @@
+local ADDON, Tk = ...
+local T = Tk.Addon
+local mod, tinsert, ipairs, pairs = T.modules.TimerControl, tinsert, ipairs, pairs
+local print = function(...) print('TimerPresets', ...) end
+
+
+
+--- Timer config presets
+mod.AddTimer = function(batch, container)
+ if container then
+ Turok.defaults.spirit.containers[container] = {}
+ end
+
+ for i, entry in ipairs(batch) do
+ print(cPink('AddTimer(#=')..cWord(#batch)..cPink(', ')..cWord(container)..cPink(')'))
+ if container then
+ entry.container = container
+ print(' container set to', container)
+ end
+ print(' unpacking', entry.name)
+ tinsert(Turok.defaults.spirit.timers, entry)
+ end
+end
+local tp = mod.index.preset
+
+mod.LoadPresets = function()
+ for setName, setFunc in pairs(tp) do
+ setFunc()
+ end
+end
+
+tp.Containers = function()
+ local defs = {
+ anchor = 'TOPLEFT', parent = 'TekplayerCastBar', anchorTo = 'BOTTOMLEFT', x = 0, y = -3, width = 700,
+ height = 200,
+ spacing = 3,
+ padding = 0,
+ ["default"] = {
+ name = "Default",
+ childAnchor = 'TOPLEFT',
+ childAnchorTo = 'TOPLEFT',
+ },
+ ["DoTs"] = {
+ anchor ='BOTTOM', anchorTo='TOP',
+ parent='TekplayerCastBar',
+ display = 'icon',
+ size = 48,
+ height = 48, width = 48,
+ x = 0, y = 16,
+ padding = 0,
+ spacing = 0,
+ childAnchor = 'BOTTOMLEFT',
+ childAnchorTo = 'BOTTOMLEFT',
+ }
+ }
+ for k,v in pairs(defs) do
+ TurokData.spirit.containers[k] = v
+ end
+end
+
+tp.Rogue = function()
+ mod.AddTimer(
+ {
+ {
+ name = "Vendetta",
+ type = 'cooldown',
+ display = 'icon',
+ unit = 'player',
+ spellID = 79140,
+ playerClass = 'ROGUE',
+ specPage = 1,
+ },
+ {
+ name = "Burst of Speed",
+ type = 'cooldown',
+ display = 'icon',
+ unit = 'player',
+ spellID = 108212,
+ playerClass = 'ROGUE'
+ },
+ {
+ name = "Rupture",
+ type = 'aura',
+ display = 'icon',
+ unit = 'target',
+ spellID = 1943,
+ filters = 'PLAYER|HARMFUL',
+ playerClass = 'ROGUE',
+ specPage = {1,3},
+ },
+ {
+ name = "Slice and Dice",
+ type = 'aura',
+ display = 'icon',
+ spellID = 5171,
+ unit = 'player',
+ filters = 'PLAYER|HELPFUL',
+ playerClass = 'ROGUE',
+ specPage = {2,3},
+ },
+ {
+ name = "Deadly Missing",
+ type = 'aura',
+ spellID = 2823,
+ display = 'icon',
+ unit = 'player',
+ playerClass = 'ROGUE',
+ specPage = {1,3},
+ inverse = true,
+ },
+ {
+ name = "Stealth",
+ type ='aura',
+ spellID = 1784,
+ display = 'icon',
+ unit = 'player',
+ playerClass = 'ROGUE',
+ },
+ {
+ name = "Recuperate",
+ type ='aura',
+ spellID = 73651,
+ display = 'icon',
+ unit = 'player',
+ playerClass = 'ROGUE',
+ },
+ })
+end
+tp.Mage = function()
+ mod.AddTimer({
+ {
+ name = "Rune of Power",
+ type = 'aura',
+ spellID = 116014,
+ unit = 'player',
+ display = 'icon',
+ playerClass = 'MAGE',
+ talentID = 16032,
+ },
+ {
+ name = "Mage Nova",
+ spellID = {157980, 157981, 157997},
+ talentOffset = {5, 3},
+ unit = 'player',
+ type='cooldown',
+ display='icon',
+ playerClass='MAGE',
+ persist = true,
+ },
+ {
+ name = "Mage Bomb",
+ talentOffset = {5, 1},
+ unit = 'target',
+ type= 'aura',
+ display='icon',
+ filters = 'HARMFUL|PLAYER',
+ playerClass='MAGE',
+ persist = true,
+ },
+ {
+ name = "Frozen Orb",
+ spellID = 84714,
+ threschold = 2,
+ unit = 'player',
+ type='cooldown',
+ display='icon',
+ playerClass='MAGE',
+ specPage=3,
+ },
+ {
+ name = 'Arcane Power',
+ type = 'cooldown',
+ display = 'icon',
+ unit = 'player',
+ spellID = 12042,
+ playerClass = 'MAGE',
+ specPage = 1,
+ }
+ })
+end
+tp.UseEffects = function()
+ mod.AddTimer({
+
+ {
+ name = "Trinket 1",
+ type ='cooldown', display = 'icon',
+ unit = 'player',
+ persist = true,
+ inventoryID = 13,
+ },
+ {
+ name = "Maalus Effect", -- Maalus
+ playerClass = {'HUNTER', 'ROGUE'},
+ type = 'aura', display = 'progressbar',
+ unit = 'player', filters = 'HELPFUL',
+ leftText = "%c", rightText= "%p",
+ duration = 15,
+ spellID = 187615, itemID = 124636, hideIcon = true,
+
+ sound_active = [[Interface\Addons\Turok\Media\sound\FLASH.mp3]],
+
+ absolute = true, x = 0, y = -10, width = 300, height = 10,
+ anchor = 'BOTTOMLEFT', anchorTo = 'BOTTOMLEFT',
+ parent = 'TekplayerCastBar', padding = 0, spacing = 0,
+
+ foreground_inset = 0, foreground_color = {1,1,1,1}, foreground_blend = 'ADD',
+ background_color = {0,0,0,0},
+ icon = false,
+ },
+
+ {
+ name = "Maalus CD",
+ type = 'cooldown', display = 'icon',
+ unit = 'player',
+ spellID = 187615, itemID = 124636,
+ playerClass = 'HUNTER',
+ },
+ })
+end
+
+tp.Hunter = function()
+ mod.AddTimer({
+ ---- Icon templates
+ { virtual = true, name = "Hunter",
+ playerClass = 'HUNTER', unit = 'player', container = 'default', display= 'icon', },
+ { virtual = true, name = "HunterSticky", inherits = "Hunter",
+ showAura = true, persist = true, },
+ { virtual = true, name = "HunterBar",
+ playerClass = 'HUNTER', unit = 'player', },
+ ---- Talents
+ {
+ inherits= "HunterSticky",
+ name = "Heavy Artillery", type = 'cooldown',
+ talentRow = 6,
+ trace = true},
+ {
+ inherits= "HunterSticky",
+ name = "Animal Power", type = 'cooldown',
+ talentRow = 5,
+ trace = true},
+ --- Spells
+ {
+ inherits = 'Hunter', name = "Camouflage",
+ type = 'cooldown', display = 'icon',
+ spellID = 51753, },
+ {
+ inherits = 'Hunter', name = "Ice Trap",
+ type = 'cooldown', display = 'icon',
+ spellID = 13809, },
+ {
+ inherits = 'Hunter', name = "Concussive Shot",
+ type = 'cooldown', display = 'icon',
+ spellID = 5116, },
+ {
+ inherits = 'Hunter', name = "Flare",
+ type = 'cooldown', display = 'icon',
+ spellID = 1543, },
+ {
+ inherits = 'Hunter', name = "Disengage",
+ type = 'cooldown', display = 'icon',
+ spellID = 781, },
+ {
+ inherits = "HunterSticky", name = "Rapid Fire",
+ type = 'cooldown', display = 'icon',
+ spellID = 3045, specPage = 2, },
+ {
+ inherits = 'HunterSticky', name = "Bestial Wrath",
+ type = 'cooldown', display = 'icon',
+ spellID = 19574, specPage = 1,
+ trace = true
+ },
+
+ --- Progress Bars
+ {
+ inherits = 'HunterBar', name = "Chimaera Shot",
+ type = 'cooldown', display = 'progressbar',
+ spellID = 53209, specPage = 2, persist = true,
+
+ hideIcon = true,
+ leftText = "", rightText = "%p",
+ width = 300, height = 8,padding = 0, spacing = 0,
+ absolute = true, x = 0, y = 0, anchor = 'TOPLEFT', anchorTo = 'TOPLEFT', parent = 'TekplayerCastBar', strata='MEDIUM',
+ foreground_color = {1,.125,0.43,1}, foreground_blend = 'ADD', foreground_inset = 0,
+ background_color = {.5,.5,.5,0}, background_blend = 'BLEND',
+ },
+ {
+ inherits = 'HunterBar', name = "Sniper Training (duration)",
+ type = 'aura', display = 'progressbar',
+ spellID = 168811, specPage = 2,
+
+ hideIcon = true,
+ leftText = "", rightText= "",
+ width= 330, height = 12, padding = 0,
+ absolute = true, x = 0, y = 0, anchor = 'BOTTOMLEFT', anchorTo = 'BOTTOMLEFT', parent = 'TekplayerCastBar', level = 1,
+ foreground_color = {1,0,0,1}, foreground_blend = 'BLEND',
+ sound_active = '', sound_hidden = '', sound_passive = '',
+ },
+ {
+ inherits = 'HunterBar', name = "Sniper Training: Recently Moved",
+ type = 'aura', display = 'progressbar',
+ spellID = 168809, specPage = 2,
+
+ hideIcon = true,
+ leftText = "", rightText= "",
+ height = 12, width= 160, padding = 0,
+ absolute = true, x = 0, y = 0, anchor = 'BOTTOMLEFT', anchorTo = 'BOTTOMLEFT', parent = 'TekplayerCastBar', level = 2,
+ foreground_color = {1,1,0,1}, foreground_blend = 'BLEND',
+ sound_active = '', sound_hidden = '', sound_passive = '',
+ },
+
+ --- Static Warnings
+ {
+ inherits='Hunter', name = "Aspect of the Pack",
+ type = 'aura', display = 'icon',
+ spellID = 13159
+ },
+ {
+ inherits = 'Hunter', name = "Trap Launcher",
+ type = 'aura', display = 'icon',
+ spellID = 77769, inverse = true,
+
+ absolute = true, x = 0, y = 200,
+ width = 100, height = 100,
+ foreground_color = {1,1,1, 0.5}, foreground_blend = 'BLEND',
+ },
+ })
+end
+tp.SPriest = function()
+ mod.AddTimer( {
+ {
+ virtual = true, name = "Caster Icon", container = 'DoTs',
+ playerClass = 'PRIEST',
+
+ combatFade = true,
+ height = 48, width = 48,
+ icon = { size = 48, },
+ persist = true,
+ },
+ {
+ inherits = "Caster Icon", name = "Shadowfiend",
+ unit = "player", spellID = 132603,
+ type = 'cooldown', display = 'icon',
+ container ='DoTs',
+ },
+ {
+ inherits = "Caster Icon", name = "Insanity",
+ type = 'aura', display = 'icon',
+ unit = 'player', filters = 'PLAYER|HELPFUL',
+ spellID = 132573, playerClass = 'PRIEST',
+ order = 3,
+ },
+ {
+ name = "Shadow Word: Pain",
+ type = 'aura', display = 'icon',
+ unit = 'target', filters = 'PLAYER|HARMFUL',
+ spellID = 589, playerClass = 'PRIEST', specPage = 3,
+
+ container = 'DoTs',
+ order = 1,
+ sound_active = '',
+ },
+ {
+ name = "Mental Fatigue",
+ type = 'aura', display = 'icon',
+ unit = 'target', filters = 'PLAYER|HARMFUL',
+ spellID = 184915, playerClass = 'PRIEST', specPage = 3,
+
+ parent = 'TekplayerCastBar',
+ container = 'DoTs',
+ order = 1,
+ sound_active = '',
+ },
+ {
+ name = "Vampiric Touch",
+ container = 'DoTs',
+ type = 'aura', display = 'icon',
+ unit = 'target', filters = 'PLAYER|HARMFUL',
+ spellID = 34914, playerClass = 'PRIEST', specPage = 3,
+ order =2,
+ },
+ {
+ name = "PW:Shield",
+ type = 'cooldown', display = 'icon',
+ unit = 'player',
+ spellID = 17, playerClass = 'PRIEST',
+ },
+ {
+ name = "Cascade",
+ type = 'cooldown', display = 'icon',
+ unit = 'player',
+ spellID = 127632, talentID = 21718, playerClass = 'PRIEST',
+ },
+ })
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Progressbar.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Progressbar.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,246 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 1/15/2016 6:38 PM
+local T, _G = Turok, _G
+local GetTime, PlaySoundFile, format = GetTime, PlaySoundFile, string.format
+local unpack, tconcat = unpack, table.concat
+local ACTIVE, PASSIVE, HIDDEN = 2, 1, 0
+local mod = T.modules.TimerControl
+--@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('Progressbar', ...)
+ end
+end
+print('Peep!', ...)
+--@end-debug@
+local GetPrint = function(trace)
+ if trace then
+ return print
+ else
+ return function() end
+ end
+end
+T.defaults.spirit.progressbar = {
+ combatFade = true,
+ alpha = 1,
+ alpha_ooc = 0,
+ alpha_ooc_passive = 0,
+ alpha_ooc_active = 1,
+
+ width = 200, height = 24,
+ parent = 1,
+ anchor = 'CENTER', anchorTo = 'CENTER',
+ setAllPoints = true,
+ strata = 'MEDIUM',
+
+ foreground_color = {1,0.5,0,0.5},
+ foreground_blend = 'ADD',
+ foreground_texture = [[Interface\Addons\Turok\Media\statusbar\Minimalist.tga]],
+ background_color = {1,1,1,0.5},
+ background_blend = 'BLEND',
+ padding = 3,
+ spacing = 1,
+ foreground_inset= 0,
+ icon = {
+ embedded = true,
+ alpha = 1,
+ alpha_ooc = 1,
+ size = 24,
+ x = -6, y = 0,
+ anchor = 'RIGHT', anchorTo = 'LEFT',
+ parent = 1,
+ },
+
+ -- text
+ color = {0,0,0,.5},
+}
+
+local p = mod.prototype.display.progressbar
+p.type='display'
+
+p.inherits = 'TurokProgressbarTemplate'
+p.cvars = {}
+
+--- Load-time config retrieval
+p.Init = function (self)
+ local print = GetPrint(self.trace)
+
+ print(' ', self:GetName(),'<- Progressbar.Load')
+ print(' ', self:GetHeight())
+
+ if self.cvars.hideIcon then
+ self.enableIcon = false
+ print('Icon hidden')
+ else
+ self.icon:Hide()
+ if self.cvars.icon then
+ print('Icon data:')
+ for k,v in pairs(self.cvars.icon) do
+ print(' ', k, '=', v)
+ end
+ print(cWord(' icon=')..cText(self.itemIcon or self.spellIcon))
+ self.icon:SetTexture(self.itemIcon or self.spellIcon)
+ self.icon:ClearAllPoints()
+ T.SetTextureLayout(self.icon, self.cvars.icon)
+ self.enableIcon = true
+ self.icon:Show()
+ end
+
+ end
+
+ T.SetStatusTextures(self, self.cvars)
+
+ _G.print('Update', self.background:GetWidth(), self.background:GetHeight())
+ _G.print('Update', self.foreground:GetWidth(), self.foreground:GetHeight())
+end
+
+
+--- Negotiate the config differences between different display states
+-- Hidden - display is or should (via fade-out) be hidden
+-- Passive - display is visible, but no timing information is processed
+-- Active - display is visible and counting time; on expiration, it will downgrade itself to passive or hidden
+p.SetState = function(self, newState, forcePrevious)
+ local print = GetPrint(self.trace)
+
+ local previous = self.displayState
+ self.prevState = forcePrevious and forcePrevious or previous
+ self.displayState = newState
+
+ local newState, previous = self.displayState, self.prevState
+ --- Transition
+ if newState ~= previous then
+ print(cText(' Transition:'), cWord(self.spellName))
+ if newState == HIDDEN then
+ print(cText(' to HIDDEN'))
+ -- to HIDDEN
+ if previous then
+ -- has to have been ACTIVE or PASSIVE at this point
+ self.Intro:Stop()
+ if self.event then
+ self.Outro:Play()
+ else
+ self:Hide()
+ end
+ end
+ -- want to end here if HIDDEN from nil
+ else
+ -- to ACTIVE or PASSIVE
+ self.Outro:Stop() -- stop any running outro
+
+
+ if newState == ACTIVE then
+
+ -- and is ACTIVE
+ self:Show()
+ end
+
+ print(cText(' from'), cNum(previous))
+ if previous and previous ~= HIDDEN then
+ -- from visible
+ if self.event then
+ self.refresh = true
+ self.Retro:Play()
+ end
+ else
+ if self.event then
+ self.Intro:Play()
+ else
+ self:Show()
+ end
+ end
+ end
+ else
+ if newState == ACTIVE then
+ print(cText(''))
+ -- and is ACTIVE
+ end
+
+ if self.event and newState ~= HIDDEN then
+ self.refresh = true
+ self.Retro:Play()
+ end
+ end
+
+ if newState ~= HIDDEN then
+ print(cText(' CVars:'))
+ local c = (newState == ACTIVE) and self.cvars.active or self.cvars.passive
+ if self.icon and c.icon then
+ print(cText(' '), cWord('desat=')..cBool(c.icon.desaturated), cWord('color=')..cNum(tconcat(c.icon.color, ', ')))
+ self.icon:SetVertexColor(unpack(c.icon.color))
+ self.icon:SetDesaturated(c.icon.desaturated)
+ end
+ local c
+ if newState == ACTIVE then
+ self.fillState = 1
+ c = self.cvars.active
+ else
+ self.fillState = 2
+ c = self.cvars.passive
+ end
+
+ if self.icon and c.icon then
+ print(cText(' '), cWord('desat=')..cBool(c.icon.desaturated), cWord('color=')..cNum(tconcat(c.icon.color, ', ')))
+ self.icon:SetVertexColor(unpack(c.icon.color))
+ self.icon:SetDesaturated(c.icon.desaturated)
+ end
+
+ self:UpdateAlpha(T.inCombat)
+ end
+end
+
+p.Update = function (self)
+ local print = GetPrint(self.trace)
+
+ -- Trigger business
+ -- Passive or Hidden, evaluate once
+ if self.displayState == 0 and self.prevState ~= 0 then
+ self.prevState = self.displayState -- quietly advance state
+ self.percent = 0
+ self.valueFull = 0
+ self.value = 0
+ self:SetText()
+ self:SetProgress(self.percent)
+ print('go LOW')
+ elseif self.displayState == 1 and self.prevState ~= 1 then
+ self.prevState = self.displayState -- quietly advance state
+ self.valueFull = 0
+ self.value = 0
+ self.percent = 1
+ self:SetText()
+ self:SetProgress(self.fill_inverse and 0 or 1)
+ print('go PASSIVE', self.percent, self.duration, self.start, self.expires)
+ elseif self.displayState == 2 then
+ if self.prevState ~= 2 or self.refresh then
+ self.prevState = self.displayState -- quietly advance state
+ self.refresh = nil
+ end
+ -- prevState is set externally
+ local time = GetTime()
+ if self.expires <= time and self.charges == self.maxCharges then
+ self.percent = 1
+ self.duration = 0
+ self.expires = 0
+ self.start= 0
+ self.valueFull = self.duration
+ self.value = self.duration
+ self.elapsed = self.duration
+ self.remaining = 0
+ self:SetState(self.cvars.persist and self.flags.passive or self.flags.hidden)
+ else
+ self.valueFull = self.expires - time
+ self.percent = self.valueFull / self.duration
+ self.elapsed = time - self.start
+ self.remaining = self.duration - time
+
+ self.value = floor(self.valueFull)
+ end
+
+ --PlaySoundFile(self.cvars.sound_active)
+ self:SetText()
+ self:SetProgress(self.percent)
+ end
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Status.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Status.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,278 @@
+local _G, T = _G, Turok
+local mod = T.modules.TimerControl
+local P = mod.prototype
+local GetInventoryItemID, GetItemInfo, GetInventoryItemTexture = GetInventoryItemID, GetItemInfo, GetInventoryItemTexture
+local GetSpellDescription, GetSpellInfo, GetSpellCharges = GetSpellDescription, GetSpellInfo, GetSpellCharges
+local GetTalentRowSelectionInfo = GetTalentRowSelectionInfo
+local tinsert, type, tonumber, pairs, ipairs, unpack = tinsert, type, tonumber, pairs, ipairs, unpack
+local UnitGUID = UnitGUID
+local GetTalentInfo, GetTalentInfoByID, GetItemSpell, PaperDoll_IsEquippedSlot = GetTalentInfo, GetTalentInfoByID, GetItemSpell, PaperDoll_IsEquippedSlot
+local print = function(...) print('Timer', ...) end
+print('Peep!', ...)
+
+--@debug@
+local DEBUG = true
+--@end-debug@
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
+local print = function(...)
+ if not DEBUG then return end
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('Timer', ...)
+ end
+end
+------------------------------------------
+--- Parameter Prototypes
+
+local Timer_GetPrintHandler = function(self)
+ return self.trace and function(...)
+ print(...)
+ _G.print('TimerFocus', ...)
+ end or print
+end
+
+local Timer_UpdateIndex = function(self, key, value)
+ local print = Timer_GetPrintHandler(self)
+ -- sfk[value] = frame index key-value handle
+ -- mfkv = key-value frame index
+ -- mfkv[sfk[value]] = *frame
+ if self.frames[key] then
+ local sfk = self.frames[key]
+ -- for each unique value
+ for oldValue, index in pairs(sfk) do
+ local mfkv = mod.frames[key][oldValue]
+ -- for each offset after index
+ for i = index+1, #mfkv do
+ mfkv[i-1] = mfkv[i] -- slide it down
+ end
+ sfk[oldValue] = nil
+ print(cText(' *= self.frames')..'['..cKey(key)..']['..cNum(value)..'] =', cNum(self.frames[key][value]))
+ print(cText(' *= mod.frames')..'['..cKey(key)..']['..cNum(value)..']['..cNum(index)..'] =', cNum(self:GetName()))
+ end
+ else
+ self.frames[key] = {}
+ end
+
+ if value then
+ local mfkv = mod.frames[key][value]
+ local sfk = self.frames[key]
+ mfkv[#mfkv+1] = self
+ sfk[value] = #mfkv
+ print(' *= self.frames['..cKey(key)..']['..cNum(value)..'] = ', sfk[value])
+ end
+end
+
+--- spellID
+do
+ local spellID = P.status.spellID
+ spellID.Init = function(self, spellID)
+ local print = Timer_GetPrintHandler(self)
+
+ if type(spellID) == 'table' then
+ spellID = spellID[T.specPage]
+ end
+
+ -- May have changed if invoked through a slot assignment
+ if spellID ~= self.spellID then
+ self.spellID = spellID
+ self.charges, self.maxCharges, self.chargeStart, self.chargeDuration = GetSpellCharges(spellID)
+ self.spellDescription = GetSpellDescription(spellID)
+ self.spellName, self.spellRank, self.spellIcon, self.castingTime, self.minRange, self.maxRange = GetSpellInfo(spellID)
+ --@debug@
+ print(' ', cWord('spellID ='), cKey(self.spellID), cNum(self.spellName), cText(self.spellDescription and '' or ''))--@end-debug@
+
+ Timer_UpdateIndex(self, 'spellID', spellID)
+ end
+ end
+end
+
+--- spellName
+do
+ local spellName = P.status.spellName
+ spellName.Init = function(self, spellName)
+ local print = Timer_GetPrintHandler(self)
+ -- attempt to get spell info
+ local exists, _, _, _, _, _, spellID = GetSpellInfo(spellName)
+ if exists then
+ local charges, maxCharges, start, duration = GetSpellCharges(spellID or spellName)
+ Timer_UpdateIndex(self, 'spellName', nil)
+ print(' ', cKey("spellID"), '=', spellID)
+ P.status.spellID.Init(self, spellID)
+ else
+ print(' ', cPink("spellID"), '=', 'not sure')
+ Timer_UpdateIndex(self, 'spellID', nil)
+ Timer_UpdateIndex(self, 'spellName', spellName)
+ end
+ end
+end
+
+
+--- talentID
+do
+ local talentID = P.status.talentID
+ local GetTalentInfoByID = GetTalentInfoByID
+ talentID.type = 'status'
+ talentID.Init = function(self, talentID)
+ local print = Timer_GetPrintHandler(self)
+
+ self.talentID, self.spellName, self.spellIcon, self.talentSelected = GetTalentInfoByID(talentID, T.specGroup)
+
+ if self.talentSelected then
+ print(' ', cKey("spellName"), '=', cWord(self.spellName))
+ P.status.spellName.Init(self, self.spellName)
+ else
+ self.disable = true
+ self.debug_info ('Talent not selected.')
+ end
+
+ print(' ', cKey('talentID ('..cNum(self.talentID)..', '..cNum(T.specGroup)..'):'), self.spellName, self.talentSelected )
+ Timer_UpdateIndex(self, 'talentID', talentID)
+
+ end
+end
+
+--- talentRow - use whatever is in that row as data
+do
+ local talentRow = P.status.talentRow
+ talentRow.Init = function(self, row)
+ local print = Timer_GetPrintHandler(self)
+ self.talentRow = row
+ local noSelect, talentID = GetTalentRowSelectionInfo(row)
+ if noSelect then
+ self.disable = true
+ self.debug_info("No talent selected in target row.")
+ else
+ P.status.talentID.Init(self, talentID)
+ end
+ print(' ', cKey('talentRow ('.. cNum(row).. ') ='), talentID or 'none')
+ Timer_UpdateIndex(self, 'talentRow', row)
+ end
+end
+
+
+--- talentOffset
+do
+ local talentOffset = P.status.talentOffset
+ talentOffset.Init = function(self, coords)
+ local print = Timer_GetPrintHandler(self)
+
+ local tier, column = unpack(coords)
+
+
+ local selected, usable, _
+ self.talentID, self.spellName, self.spellIcon, selected, usable = GetTalentInfo(tier, column, T.specGroup)
+ print(' ', cKey('talentOffset'), '=', cNum(tier), cNum(column), self.spellName, selected, usable)
+ if not (selected and usable) then
+ self.disable = true
+ self.debug_info ((not usable) and 'Unavailable at current level.' or 'Talent not selected.')
+ end
+ Timer_UpdateIndex(self, 'talentID', self.talentID)
+ end
+end
+
+--- specPage
+do
+ local specPage = P.status.specPage
+ specPage.type = 'status'
+ specPage.Init = function(self, specPage)
+ local print = Timer_GetPrintHandler(self)
+ local match
+ if tonumber(specPage) then
+ match = specPage == T.specPage
+ elseif type(specPage) == 'table' then
+ for _, pageID in ipairs(specPage) do
+ if T.specPage == pageID then
+ specPage = pageID
+ match = true
+ break
+ end
+ end
+ else
+ self.disable = true
+ self.debug_info ('Bad value for', '('..cWord(self.timerName)..').'..cKey('specPage'))
+ Timer_UpdateIndex(self,'specPage', nil)
+ end
+
+ if match then
+ print(' ', cKey('specPage'), '=', '['..cNum(specPage)..']')
+ Timer_UpdateIndex(self,'specPage', specPage)
+ else
+ print(' ', cKey('specPage'), '~=', '['..cNum(specPage)..']')
+ self.disable = true
+ self.debug_info('Not active spec.')
+ end
+ end
+end
+
+--- itemID
+do
+ local itemID = P.status.itemID
+ itemID.type = 'status'
+ itemID.Init = function(self, item)
+ local print = Timer_GetPrintHandler(self)
+
+ if not self.dvars.inventoryID then
+ self.itemID = item or self.dvars.itemID
+ self.itemType = self.dvars.itemType
+ else
+ self.itemID = item
+ end
+
+ --@debug@
+ --name, link, quality, iLevel, reqLevel, class, subclass, maxStack, equipSlot, texture, vendorPrice = GetItemInfo(itemID) or GetItemInfo("itemName") or GetItemInfo("itemLink")
+ if not self.itemID then
+ self.disable = true
+ self.debug_info ('bad itemID value')
+ end
+
+ self.spellName = GetItemSpell(self.itemID)
+
+ if not self.spellName then
+ self.disable = true
+ self.debug_info('no spell detected')
+ else
+ if not (self.frames.spellName and self.frames.spellName[self.spellName]) then
+ if not self.frames.spellName then
+ self.frames.spellName = {}
+ end
+
+ Timer_UpdateIndex(self, 'spellName', self.spellName)
+ end
+ end
+ print(' ', cKey('itemID'), cNum(self.itemID), self.isEquipped)--@end-debug@
+ end
+end
+
+do
+ local inventoryID = P.status.inventoryID
+ inventoryID.type = 'status'
+ inventoryID.Init = function(self, slot)
+ local print = Timer_GetPrintHandler(self)
+
+ self.inventoryID = slot
+ self.itemID = GetInventoryItemID(self.dvars.unit, slot)
+ local name = GetItemInfo(self.itemID)
+ if not PaperDoll_IsEquippedSlot(slot) then
+ self.disable = true
+ self.debug_info('slot un-equipped')
+ return
+ end
+
+ P.status.itemID.Init(self, self.itemID)
+ self.spellIcon = GetInventoryItemTexture(self.dvars.unit, slot)
+ print(' ', cKey('inventoryID'), '=', '{'..cNum(self.inventoryID).. ' -> '.. cNum(self.itemID or 'no-equip').. '}')
+ end
+end
+
+
+--- unit
+local unit = P.status.unit
+unit.type = 'status'
+unit.Init = function(self, unit)
+ local print = Timer_GetPrintHandler(self)
+
+ self.unitGUID = UnitGUID(unit)
+ self.unit = unit
+ print(' ', cWord('unitGUID'), '=', cText(self.unitGUID))
+ tinsert(mod.frames.unit[unit], self)
+ self.frames.unit = #mod.frames.unit[unit]
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Timer.Init.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Timer.Init.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,205 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 12/28/2015 7:40 AM
+--
+local _, Tk = ...
+local T = Tk.Addon
+local mod = T:NewModule("TimerControl", "AceTimer-3.0")
+local pairs, ipairs, rawset, getmetatable, setmetatable, type, tostring, tinsert = pairs, ipairs, rawset, getmetatable, setmetatable, type, tostring, tinsert
+local cWord, cNum, cText, cKey = cWord, cNum, cText, cKey
+local print = function(...) print('Timer', ...) end
+local index_mt = {
+ __newindex = function(t,k,v)
+ rawset(t,k,v)
+ if type(v) == 'table' then
+ print('new table', cKey(k))
+ setmetatable(v, getmetatable(t))
+ else
+ print('new index', cText(k))
+ end
+ end
+ }
+mod.index = {}
+mod.index.name = setmetatable({}, index_mt)
+mod.index.global = setmetatable({}, index_mt)
+mod.index.preset = {}
+-- dummies
+mod.prototype = {
+ status = {
+ spellID = {},
+ spellName = {},
+ talentID = {},
+ talentRow = {},
+ talentOffset = {},
+ itemID = {},
+ inventoryID = {},
+ specPage = {},
+ specID = {},
+ unit = {},
+ },
+ trigger = {
+ aura = {},
+ cooldown = {},
+ complex = {},
+ },
+ display = {
+ icon = {},
+ progressbar = {},
+ },
+}
+
+Turok.defaults.spirit = {
+ global = {
+ alpha = 1,
+ alpha_ooc = 0.5,
+
+ sound_active = '[[Interface\Addons\Turok\Media\sound\link.ogg]]',
+ sound_passive = [[Interface\Addons\Turok\Media\sound\Heart.ogg]],
+ sound_hidden = [[Interface\Addons\Turok\Media\sound\Electro_-S_Bainbr-7955_hifi.mp3]],
+
+ strata = 'LOW',
+ anchor = 'CENTER',
+ parent = 'UIParent',
+ anchorTo = 'CENTER',
+ width = 100,
+ height = 100,
+ x = 0,
+ y = 100,
+ alpha = 1,
+ alpha_ooc = 0.3,
+ inverse = false,
+ persist = false,
+ desaturated = false,
+
+ icon = {},
+
+ passive = {
+ icon = {}
+ },
+ active = {
+ inco = {}
+ },
+ },
+
+ font = [[Interface\Addons\Turok\Media\font\ArchivoNarrow-Regular.ttf]],
+ lefttext = {
+ size = 14,
+ inset = -2,
+ point = 'LEFT',
+ outline = 'OUTLINE',
+ format = '%n %pd',
+ text_color = {1, 1, 1, 1},
+ },
+ containers = {
+ },
+ timers = {},
+}
+
+local tdb = Turok.defaults.spirit.timers
+
+mod.GetInherited = function(dvars, merge, inherited)
+ if not inherited then
+ inherited = {}
+ end
+ inherited[merge] = merge
+ T.Config_Merge(dvars, merge)
+
+ if merge.inherits then
+ local t = mod.index.name[merge.inherits]
+ if t and not inherited[t] then
+ mod.GetInherited(dvars, t, inherited)
+ end
+ end
+end
+
+local GetClassInfo, GetNumClasses, GetNumSpecializationsForClassID, GetSpecializationInfoForClassID = GetClassInfo, GetNumClasses, GetNumSpecializationsForClassID, GetSpecializationInfoForClassID
+mod.GetIndex = function()
+ print(cWord('**** Index Init'))
+
+ local index = mod.index
+ local globalIndex = index.global
+ local nameIndex = index.name
+ local tdb = TurokData.spirit.timers
+ local classID = {}
+ local className = {}
+ local classSpecID = {}
+ local specIDClass = {}
+
+ for id=1, GetNumClasses() do
+ local _, name = GetClassInfo(id)
+ classID[name] = id
+ className[id] = name
+ index[name] = setmetatable({}, index_mt)
+
+ classSpecID[id] = {}
+ for h=1, GetNumSpecializationsForClassID(id) do
+ local specID, specName = GetSpecializationInfoForClassID(id, h)
+ classSpecID[id][h] = specID
+ specIDClass[specID] = id
+ end
+ end
+
+ if not tdb then
+ print('Missing config table.')
+ return
+ end
+ --- Setup virtuals
+ for setID, entry in ipairs(tdb) do
+ if entry.virtual then
+ print('loading virtual set:', entry.name)
+ globalIndex[setID] = entry
+ nameIndex[entry.name or ('noname'.. setID)] = entry
+ end
+ end
+
+ --- Starting readin'
+ for setID, entry in ipairs(tdb) do
+ if not entry.virtual then
+
+ print('* .index.global['.. setID..'] =', entry.name)
+ local dvars = T.Config_Push({}, entry, nil, cKey('['..setID..']')..'.'..cWord('dvars'))
+ dvars.name = entry.name
+ globalIndex[setID] = dvars
+
+ local name = dvars.name or ('noname'..setID)
+ nameIndex[name] = entry
+ print('* .timersByName['..name..'] =', setID, entry.setID)
+
+ --- Combine with any inherited templates
+ if dvars.inherits and nameIndex[dvars.inherits] then
+ print('* Adding heritable data from', cText(dvars.inherits))
+ mod.GetInherited(dvars, nameIndex[dvars.inherits], {[dvars] = dvars})
+ --T.Config_Merge(dvars, nameIndex[dvars.inherits], dvars, cKey('['..setID..']')..'.'..cWord('dvars'))
+ end
+ -- class index
+ if not (dvars.playerClass or dvars.specID) then
+ for id, class in pairs(className) do
+ index[class][setID] = dvars
+ end
+ print('* indexed globally')
+ else
+ if dvars.playerClass then
+ if type(dvars.playerClass) ~= 'table' then
+ dvars.playerClass = {dvars.playerClass }
+ end
+ for i, playerClass in ipairs(dvars.playerClass) do
+ index[playerClass][setID] = dvars
+ print('* applying playerClass entry '..cNum(i)..': '..cWord(playerClass))
+ end
+ end
+
+ if dvars.specID then
+ if type(dvars.specID) ~= 'table' then
+ dvars.specID = {dvars.specID }
+ end
+ for i, specID in ipairs(dvars.specID) do
+ print('* applying globalSpecID entry '..cNum(i)..': '..cNum(specID)..' -> '..cWord(className[specIDClass[dvars.specID]]))
+ index[className[specIDClass[specID]]][setID] = dvars
+ end
+ end
+ end
+ end
+ end
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Timer.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Timer.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,587 @@
+--- Turok - Timer/Timer.lua
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+--- Defines common elements for the various timer HUDs
+local ADDON, _A = ...
+local _G, CreateFrame, tconcat, GetInventoryItemsForSlot, GetInventoryItemID = _G, CreateFrame, table.concat, GetInventoryItemsForSlot, GetInventoryItemID
+local T, F, tostring, type, max, tinsert, unpack, UIParent, loadstring = _A.Addon, _A.LibFog, tostring, type, max, table.insert, unpack, _G.UIParent, loadstring
+local mod = T.modules.TimerControl
+local P = mod.prototype
+local db
+
+local pairs, ipairs, gsub, sub, setmetatable = pairs, ipairs, string.gsub, string.sub, setmetatable
+local INVTYPE_FINGER, INVSLOT_FINGER1, INVSLOT_FINGER2, INVTYPE_TRINKET, INVSLOT_TRINKET1, INVSLOT_TRINKET2 =
+INVTYPE_FINGER, INVSLOT_FINGER1, INVSLOT_FINGER2, INVTYPE_TRINKET, INVSLOT_TRINKET1, INVSLOT_TRINKET2
+--@debug@
+local DEBUG = true
+--@end-debug@
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
+local print = function(...)
+ if not DEBUG then return end
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('Timer', ...)
+ end
+end
+
+local Timer_GetPrintHandler = function(self)
+ if self.trace then
+ return function(...)
+ print(...)
+ _G.print('TimerFocus', ...)
+ end else
+ return print
+ end
+end
+local pb_suppressed = {}
+
+function mod:OnInitialize()
+
+ --@debug@
+ TurokData.spirit.timers = Turok.defaults.spirit.timers
+ --@end-debug@
+ self.db = TurokData.spirit
+ db = self.db
+ self.active_cooldowns = {}
+ self.cast_units = {}
+ self.buff_units = {}
+ self.loaded_types = {}
+ self.loaded_triggers = {}
+ self.equipped = {}
+ self.containers = {}
+ self.timers = {} -- active timers
+ self.empty_frames = {} -- foster table for frames released by talent change
+
+
+ T:RegisterChatCommand("tsp", self.Import_Open)
+ T:RegisterChatCommand("tka", self.Dialog_Command)
+ T:RegisterChatCommand("tki", self.CreateIndex)
+ --T:Print("/tsp to import spells. /tka to open create dialog")
+ -- suppress cacophony from all cooldowns activating at login
+ self.quiet = true
+ --self:ScheduleTimer(function() self:Dialog_Command() end, 4)
+
+end
+
+local mt_single = {
+ __mode = "v",
+ __newindex = function(t,k,v)
+ rawset(t,k,v)
+ _G.print('DB', 'TCMeta: adding leaf', k, '=', v)
+ end}
+local mt_double = {
+ __index = function(t,k)
+ t[k] = setmetatable({}, mt_single)
+ _G.print('DB', 'TCMeta: add layer', k, '=', t[k])
+ return t[k]
+ end,
+ __newindex = function(t,k,v)
+ rawset(t,k,v)
+ _G.print('DB', 'TCMeta: adding to top layer', k, '=', v)
+ end
+}
+local mt_error = {
+ __call =function (t, txt)
+ t.disable = true
+ tinsert(t, txt)
+ end
+}
+
+--- Sets and cleans up index data used by event handlers
+local Timer_UpdateIndex = function(self, key)
+
+ -- Is there already an entry for this key/value?
+ if self.frames[key] then
+ local lim = #mod.frames[key]
+ --[[
+ for i = self.frames[key]+1, lim, 1 do
+ mod.frames[key][i] = mod.frames[key+1]
+ end]]
+ --self.frames[key] = nil
+ print(' ', cText('mod.frames.')..cWord(key), '=', #mod.frames[key])
+ print(' ', cText('self.frames.')..cWord(key), '=', cNum(self.frames[key]))
+ end
+
+ if key then
+ local i = #mod.frames[key]+1
+ --mod.frames[key][i] = self
+ self.frames[key] = i
+ print(' ', cText('self.frames.')..cWord(key), '=', #mod.frames[key])
+ end
+ mod.loaded_types[key] = (#mod.frames[key] == 0) and nil or true
+ print(' ',cText(key..'_is_loaded'), '=', cBool(mod.loaded_types[key]))
+end
+
+--- Loading initators
+function mod:OnEnable()
+ mod.LoadPresets()
+ mod.GetIndex()
+ -- setup indexes, use nested weak table for status since they implicitly have a key variable
+ mod.frames = {}
+ for class, p in pairs(mod.prototype.status) do
+ print('nested index table', class)
+ mod.frames[class] = setmetatable({}, mt_double)
+ end
+ mod.frames.spellName = setmetatable({}, mt_double)
+ for class, p in pairs(mod.prototype.display) do
+ mod.frames[class] = setmetatable({}, mt_single)
+ end
+ for class, p in pairs(mod.prototype.trigger) do
+ mod.frames[class] = setmetatable({}, mt_single)
+ end
+
+ local srcIndex = mod.timers
+ if T.playerClass and mod.index[T.playerClass] then
+ srcIndex = mod.index[T.playerClass]
+ print('*** Found index for '..tostring(T.playerClass)..', using that.')
+ else
+ print(cWord('*** Using global index.'))
+ end
+ mod.activeSpec = T.specID
+
+ --- go through that list
+ for id, timer in pairs(srcIndex) do
+ local result, message = mod:EnableTimer(id, timer)
+ end
+
+ mod.InitTimers()
+ --- Delay sound activations so there isn't a giant cacophony on load
+ mod:ScheduleTimer(function()
+ self.quiet = nil
+ end, db.audio_delay or 2)
+end
+
+function mod:EnableTimer(id, dvars)
+ local print = Timer_GetPrintHandler(dvars)
+ print('-{', cPink(dvars.name))
+ if not dvars then
+ if not mod.index.global[id] then
+ return false, "Unable to resolve dvars table."
+ end
+ dvars = mod.index.global[id]
+ end
+ if dvars.virtual then
+ return
+ end
+
+ local spirit, newFrame = mod:GetTimer(id, dvars)
+ if not spirit then return spirit, newFrame end
+
+ local cvars = spirit.cvars
+ local dvars = spirit.dvars
+ local trigger = P.trigger[cvars.type]
+ local display = P.display[cvars.display]
+ local cvars = spirit.cvars
+ local index = mod.frames
+ local print = Timer_GetPrintHandler(cvars)
+
+ if spirit.disable then
+ return false, "Manually disabled." -- nothing to do, nothing to say
+ end
+
+ --- Interpret STATUS vars
+ print(cText(' *** Merging Status Data'))
+ spirit.disable = dvars.disable
+ local pcount = 1
+ for k, handler in pairs(P.status) do
+ if cvars[k] then
+ if handler.Init then
+ print(cWord(' * Firing ')..cKey(k)..cWord('.Init'), cNum(cvars[k]))
+ handler.Init(spirit, cvars[k])
+ else
+ print(' ', cText('skipped'), cKey(k))
+ end
+ pcount = pcount + 1
+ end
+ end
+
+ spirit.Event = trigger.Event
+ spirit.Value = trigger.Value
+ spirit.SetText = mod.SetText
+ spirit.LoadText = mod.LoadText
+ spirit.Query = trigger.Query
+ spirit.Set = trigger.Set
+
+ --- Display handler init
+ if display.Init then
+ print(cText(' * Display Init:'), cKey(dvars.display))
+ display.Init(spirit)
+ end
+
+ --- Trigger handler and events Load()
+ print(cText(' * Trigger Init:'), cKey(dvars.type))
+ trigger.Init(spirit)
+
+
+ if C_PetBattles.IsInBattle() then
+ spirit.disable = true
+ spirit.debug_info("Hidden for pet battle")
+ pb_suppressed[id] = true
+ end
+
+
+ if spirit.disable then
+ spirit:UnregisterAllEvents()
+ spirit.displayState = nil
+ spirit.prevState = nil
+ spirit:Hide()
+ return false, tconcat(spirit.debug_info,"\n")
+ else
+ print('--', self.disable and cPink('DISABLED') or cNum('ENABLED'), #spirit.debug_info > 0 and tconcat(spirit.debug_info,"\n"), '}')
+ return true, tconcat(spirit.debug_info,"\n")
+ end
+end
+
+function mod:GetTimer(id, dvars)
+ local print = Timer_GetPrintHandler(dvars)
+ local newFrame
+ if not mod.timers[id] then
+ print(cKey(' [[CreateTimer'))
+ newFrame = true
+ --- Compile the cvar table from the various config layers:
+ -- Start with timer dvars, overwritten by any container settings, then a disable check, then merge in prototype values
+ local cvars = T.Config_Push({}, dvars, nil, cKey('['..id..']')..'.'..cWord('cvars'))
+ cvars.name = dvars.name -- push function ignores name keys
+
+ if dvars.container and db.containers[dvars.container] then
+ print(cText(' * Merging Container overrides'))
+ T.Config_Push(cvars, db.containers[dvars.container], cvars, cKey('['..id..']')..'.'..cWord('cvars'))
+ end
+
+ --- Stop here if disabled via SavedVars
+ if cvars.disable then
+ return false, "Manually disabled"
+ end
+
+ --- Localize the stuff we are going to loop over
+ local display = P.display[cvars.display]
+ local trigger = P.trigger[cvars.type]
+ local displayType = cvars.display
+ local triggerType = cvars.type
+ if not (display and trigger) then
+ return nil, "Missing prototype data. Summary: "..tostring(displayType).."="..(display and 'OK' or 'MISSING') ..
+ " "..tostring(triggerType).."="..(trigger and 'OK' or 'MISSING')
+ end
+
+ --- Establish the order in which values are merged
+ print(cText(' * Merging object CVars'))
+ local cvar_class = {cWord('db.'..displayType), cWord('db.'..triggerType), cWord('db.global')}
+ local cvar_array = {
+ db[displayType],
+ db[triggerType],
+ db.global,
+ }
+ local override_class = {cWord('trigger.'..cvars.type), cWord('display.'.. cvars.display)}
+ local override_array = {
+ display.cvars,
+ trigger.cvars }
+
+ --- Table merge user settings
+ for i, p in pairs(cvar_array) do
+ print(' '..cNum(i)..' merge ['..cvar_class[i]..']')
+ T.Config_Merge(cvars, p, cvars, cKey('['..id..']')..'.'..cWord('cvars'))
+ end
+
+ --- Overwrite with anything defined by the prototype structure because it's important
+ local _, odiff
+ for i, p in ipairs(override_array) do
+ _, odiff = T.Config_Push(cvars, p, cvars, cKey('['..id..']')..'.'..cWord('cvars'))
+ end
+ local print = Timer_GetPrintHandler(cvars)
+
+ --- Create the UI frame and seed it with the data we just composed
+ local spirit = CreateFrame('Frame', 'TurokTimerFrame'..gsub(dvars.name, "[^%a%d]", ''), UIParent, display.inherits)
+ spirit.trace = cvars.trace
+ spirit.timerID = id
+ spirit.timerName = dvars.name
+ spirit.container = dvars.container
+ spirit.cvars = cvars
+ spirit.dvars = dvars
+ spirit.Update = display.Update
+ spirit.SetState = display.SetState
+ spirit.Report = mod.Report
+ spirit.Stats = trigger.Stats
+
+ --- Set Layout Statics
+ T.SetFrameLayout(spirit, cvars)
+
+ --- Create troubleshooting collection
+ spirit.debug_info = setmetatable({}, mt_error)
+
+ --- Add the frame to corresponding prototype indexes
+ spirit.frames = {}
+ spirit.events = {}
+
+ if spirit.display ~= displayType then
+ spirit.display = displayType
+ Timer_UpdateIndex(spirit, displayType)
+ end
+ if spirit.type ~= triggerType then
+ spirit.type = triggerType
+ Timer_UpdateIndex(spirit, triggerType)
+ end
+ --- Add the frame to global index
+ mod.timers[id] = spirit
+ end
+
+ return mod.timers[id], newFrame
+end
+
+function mod.InitTimers()
+ local print = function(...) _G.print('TimerEvent', ...) end
+ print('INIT TIMERS ====================')
+ for id, spirit in pairs(mod.timers) do
+ if spirit.disable then
+ print(id, 'disabled:', tconcat(spirit.debug_info or {}, ', '))
+ else
+
+ print(cText('init'), cNum(id), cWord(spirit.name))
+ --- Throw a dry event to initialize values
+ print(cText(' *'), cWord('prototype.'..cKey(spirit.dvars.type)..'.'..cWord('Load')))
+ P.trigger[spirit.dvars.type].Event(spirit)
+
+ --- Set loose
+ print(cText(' *'), cWord('prototype')..'.'..cKey('events')..'.'..cWord('Load'))
+ mod.UpdateEvents(spirit, P.trigger[spirit.dvars.type].events)
+ end
+ end
+ print('INIT DONE =========================')
+end
+
+function mod:DisableTimer(name, timer)
+ local timer_frame = mod.db.timers[name]
+ if timer_frame and not timer_frame.disable then
+ timer_frame.disable = true
+ timer_frame:UnregisterAllEvents()
+ timer_frame:Hide()
+ end
+end
+
+function mod.UpdateEvents(self, events)
+ local print = Timer_GetPrintHandler(self)
+
+ self:SetScript('OnEvent', nil)
+ self:UnregisterAllEvents()
+
+ local proxy, listen = {}, {}
+ for event, handler in pairs(events) do
+ if mod[event] then
+ tinsert(proxy, cNum(event))
+ else
+ tinsert(listen, cWord(event))
+ self:RegisterEvent(event)
+ end
+ self.events[event] = handler
+ end
+
+ if #proxy > 0 then
+ print( ' -', cKey(self.name), cWord('receiving'), tconcat(proxy, ', '))
+ end
+ if #listen > 0 then
+ print( ' -', cKey(self.name), cText('listening'), tconcat(listen, ', '))
+ end
+
+ self:SetScript('OnEvent', self.Event)
+end
+
+local match_sub = {
+ {'%%c', "' .. tostring(t.caster).. '"},
+ {'%%h', "' .. tostring((t.valueFull >= 60) and (math.floor(t.valueFull/60)) or t.value) .. '"},
+ {'%%i', "' .. tostring((t.valueFull >= 60) and (t.value % 60) or ((t.valueFull < 6) and math.floor((t.ValueFull * 100) % 100) or '')) .. '"},
+ {'%%n', "' .. tostring(t.spellName) .. '"},
+ {'%%p', "' .. tostring(t.value) .. '"},
+ {'%%d', "' .. tostring(t.chargeDuration or t.duration) .. '"},
+ {'%%%.p', "' .. string.sub(tostring((t.valueFull %% 1) * 100),0,1) .. '"},
+ {"%%s", "' .. (t.stacks or t.charges or '') .. '"},
+}
+
+-- dot syntax implies use as embedded method
+function mod.LoadText(self)
+ print(cKey('parsing textRegions for'), self.timerName, self.timerID)
+ self.textTypes = {}
+ self.textValues = {}
+ for name, region in pairs(self.textRegions) do
+ print(' ', cWord('textRegions')..'["'.. cType(self.timerName)..'"].'..cType(name))
+ if self.cvars[name..'Text'] then
+
+ -- todo: collect match counts and index the text fields by match types
+ local str = self.cvars[name..'Text']
+ for i, args in ipairs(match_sub) do
+ if str:match(args[1]) then
+ if not self.textTypes[args[1]] then
+ self.textTypes[args[1]] = {}
+ end
+ tinsert(self.textTypes[args[1]], region)
+ str = str:gsub(args[1], args[2])
+ end
+ end
+ str = "local t = _G.Turok.modules.TimerControl.timers["..self.timerID.."]\n"
+ .. "\n return '" .. str .. "'"
+ local func = assert(loadstring(str))
+ self.textValues[name] = func
+ end
+ end
+
+ --mod.SetText(self)
+end
+
+--- generic text setter
+local HIDDEN, PASSIVE, ACTIVE = 0, 1, 2
+mod.SetText = function(self)
+ if self.displayState ~= ACTIVE then
+ for name, region in pairs(self.textRegions) do
+ region:SetText(nil)
+ end
+ return
+ end
+
+ if not self.textValues then
+ self.textValues = {}
+ mod.LoadText(self, self.cvars)
+ end
+
+ -- hide when above a certain number
+
+ if self.spiral and self.spiral.subCounter then
+ if self.valueFull > 6 then
+ if self.textValues.subCounter then
+ --print('hiding milliseconds')
+ self.textRegions.subCounter:Hide()
+ self.textRegionsSub = self.textRegions.subCounter
+ self.textValuesSub = self.textValues.subCounter
+ self.textRegions.subCounter = nil
+ self.textValues.subCounter = nil
+ end
+ else
+ if not self.textValues.subCounter then
+ --print('showing milliseconds')
+ self.textValues.subCounter = self.textValuesSub
+ self.textRegions.subCounter = self.textRegionsSub
+ self.textRegions.subCounter:Show()
+ end
+ end
+ end
+
+ for name, region in pairs(self.textRegions) do
+ --print(name)
+ --print(name, self.timerName, self.textValues[name](self))
+ region:SetText(self.textValues[name](self))
+ end
+end
+
+
+-------------------------------------------------------------------------
+--- Second-tier handlers to cut down on the number of Status:Event() polls
+
+--- UNIT_SPELLCAST_*** use args to filter out the number of full handler runs
+function mod:UNIT_SPELLCAST_SUCCEEDED (e, unit, spellName, rank, castID, spellID)
+ if not mod.frames.unit[unit] then
+ return
+ end
+
+ if #mod.frames.spellName[spellName] > 0 then
+ print('spellName-ID relation detected:', cWord(spellName), cNum(spellID))
+ for i, frame in pairs(mod.frames.spellName[spellName]) do
+ if not frame.frames.spellID then
+ frame.frames.spellID = {}
+ end
+ if not frame.frames.spellID[spellID] then
+
+ tinsert(mod.frames.spellID[spellID], frame)
+ frame.frames.spellID[spellID] = #mod.frames.spellID[spellID]
+ print(cText(' updating'), cKey(frame.timerName))
+ end
+ end
+ mod.frames.spellName[spellName] = nil
+ end
+
+
+
+ if mod.frames.spellID[spellID] then
+ for i, timer_frame in pairs(mod.frames.spellID[spellID]) do
+ print(cText('caught spell'), cWord(spellName), 'for', timer_frame:GetName())
+ timer_frame:Event(e, unit, spellName, rank, castID, spellID)
+ end
+ end
+end
+mod.UNIT_SPELLCAST_CHANNEL_START = mod.UNIT_SPELLCAST_SUCCEEDED
+
+--- Fire a dry event to force status updates on units with changing GUID's
+function mod:PLAYER_TARGET_CHANGED(e, unit)
+ print('doing a target swap thing')
+ for k, v in pairs( self.frames.unit.target) do
+ print(k, v)
+ v:Event(nil, 'target')
+ end
+end
+
+--- Same thing but for talent/spec-driven
+function mod:PLAYER_TALENT_UPDATE(e, unit)
+ print('')
+ print('')
+ print(cText(e), T.specPage, T.specName)
+
+ local update_queue = {}
+ for _, k in ipairs({'talentID', 'talentRow', 'specPage'}) do
+ for value, frameSet in pairs(mod.frames.talentID) do
+ for id, frame in ipairs(frameSet) do
+ print(frame.timerID, frame.timerName)
+ update_queue[frame.timerID] = frame
+ end
+ end
+ end
+
+ for id, frame in pairs(update_queue) do
+ print('Refreshing spec-related frames', id, frame.timerName)
+ frame.disable = nil
+ table.wipe(frame.debug_info)
+ local res, msg = mod:EnableTimer(id, frame.dvars)
+ end
+
+end
+
+function mod:PLAYER_EQUIPMENT_CHANGED(e, slot, hasItem)
+ print(e, slot, hasItem)
+ local itemCheckList
+ if mod.frames.inventoryID and mod.frames.inventoryID[slot] then
+ print(' Inventory Frames:')
+ itemCheckList = GetInventoryItemsForSlot(slot, {}, false)
+ for id, slotFrame in pairs(mod.frames.inventoryID[slot]) do
+ print(' * Updating', cNum(id), cWord(slotFrame.timerName))
+ local res, msg = mod:EnableTimer(slotFrame.timerID, slotFrame.dvars)
+ print(' ', cBool(res), cText(msg))
+ end
+ end
+ if itemCheckList then
+ print(unpack(itemCheckList))
+ end
+ local itemID = GetInventoryItemID('player', slot)
+ if itemID and mod.frames.itemID[itemID] then
+ print(' Item ID Frames:')
+ for id, itemFrame in pairs(mod.frames.itemID[itemID]) do
+ print(' * Updating', cNum(id), cWord(itemFrame.timerName))
+
+ local res, msg = mod:EnableTimer(itemFrame.timerID, itemFrame.dvars)
+ print(' ', cBool(res), cText(msg))
+ end
+ end
+end
+function mod:PET_BATTLE_OPENING_START ()
+ for i, v in pairs(mod.timers) do
+ if not v.disable then
+ print('suppressing', v:GetName())
+ v.disable = true
+ v:Hide()
+ pb_suppressed[i] = true
+ end
+ end
+end
+function mod:PET_BATTLE_CLOSE()
+ for id, v in pairs(mod.timers) do
+ if pb_suppressed[id] then
+ print('restoring', v:GetName())
+ mod:EnableTimer(id)
+ pb_suppressed[id] = nil
+ end
+ end
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Timer/Timer.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Timer/Timer.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,327 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.textRegions = {}
+
+
+ self:Report()
+
+
+ self:Report()
+
+
+ self:Update()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ local g = self:GetParent()
+ g.collected = nil
+ g.add = true
+ g:Report()
+ --@debug@
+ print('Layout', g.cvars.type, 'Intro |cFFFFFF00START', g:GetName())--@end-debug@
+ g:Show()
+ if g.cvars.sound_active then
+ PlaySoundFile(g.cvars.sound_active)
+ end
+ if g.icon then
+ g.iconIntro:Play()
+ end
+
+
+ local g = self:GetParent()
+ --@debug@
+ print('Layout', g.cvars.type, 'Intro |cFFFF4400STOP', g:GetName())--@end-debug@
+ if g.enableIcon then
+ g.iconIntro:Stop()
+ end
+
+
+ local g = self:GetParent()
+ --@debug@
+ print('Layout', g.cvars.type, 'Intro |cFF00FF00FINISH', g:GetName())--@end-debug@
+ if g.enableIcon then
+ g.iconIntro:Stop()
+ end
+ g:UpdateAlpha(Turok.inCombat, g.displayState, g.fillState)
+
+
+
+
+
+
+
+
+
+
+
+ local g = self:GetParent()
+ g.collected = nil
+ g.trash = true
+ g:Report()
+ --@debug@
+ print('Layout', g.cvars.type, '|cFF0088FFOutro |cFFFFFF00START', g:GetName())--@end-debug@
+ if g.spiral then
+ g.spiral:StopAnimating()
+ g.spiral:Hide()
+ end
+ if g.cvars.sound_hidden then
+ PlaySoundFile(g.cvars.sound_hidden)
+ end
+ if g.enableIcon then
+ g.iconOutro:Play()
+ end
+
+
+ local g = self:GetParent()
+ --@debug@
+ print('Layout', g.cvars.type, '|cFF0088FFOutro |cFFFF4400STOP', g:GetName())--@end-debug@
+ if g.enableIcon then
+ g.iconOutro:Stop()
+ end
+
+
+ local g = self:GetParent()
+ g.trash = false
+ --@debug@
+ print('Layout', g.cvars.type, '|cFF0088FFOutro |cFF00FF00Finish', g:GetName())--@end-debug@
+ if g.enableIcon then
+ g.iconOutro:Stop()
+ end
+ g:Hide()
+
+
+
+
+
+
+
+
+ local g = self:GetParent()
+ --@debug@
+ print('Layout', g.cvars.type, '|cFFFFFF00Retro |cFFFFFF00START', g:GetName())--@end-debug@
+ if g.iconFlash then
+ g.iconFlash:Show()
+ end
+
+
+ local g = self:GetParent()
+ --@debug@
+ print('Layout',g.cvars.type, '|cFFFFFF00Retro |cFFFF4400STOP', self:GetParent():GetName())--@end-debug@
+
+
+ local g = self:GetParent()
+ --@debug@
+ print('Layout',g.cvars.type, '|cFFFFFF00Retro |cFF00FF00FINISH', g:GetName())--@end-debug@
+ if g.iconFlash then
+ g.iconFlash:Hide()
+ end
+ g:UpdateAlpha(Turok.inCombat, g.displayState, g.fillState)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -- not using parentArray because we want name info
+ self.textRegions = {
+ counter = self.spiral.counter,
+ subCounter = self.spiral.subCounter,
+ charges = self.spiral.charges
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.textRegions = {
+ left = self.left,
+ right = self.right
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:RegisterForDrag('LeftButton')
+ self:EnableMouse(false) -- for now
+
+
+ if self:GetEnableMouse() then
+ self.cx = self:GetLeft()
+ self.cy = self:GetTop()
+ self:StartMoving()
+ end
+
+
+ self:StopMovingOrSizing()
+ self.x = self.x + (self:GetLeft() - self.cx)
+ self.y = self.y + (self:GetTop() - self.cy)
+ self:SetPoint(self.anchor, self.parent, self.anchorTo, self.x, self.y)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Utilities/Chat.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Utilities/Chat.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,8 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 2/19/2016 9:00 AM
+local ADDON, env = ...
+local mod = Turok:NewModule("Chat")
+setfenv(0, env)
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Utilities/PetBattle.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Utilities/PetBattle.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,288 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 1/17/2016 6:51 PM
+
+local ADDON, Turok = ...
+local T, _G, pairs, pairs = Turok.Addon, _G, pairs, ipairs
+local mod = T:NewModule("PetBattle")
+local print = function(...) _G.print('Petz', ...) end
+local trace = function(self, e, ...)
+ print(e, ...)
+end
+
+local PBS
+local turn_font = [[Interface\Addons\Turok\Media\font\ArchivoNarrow-Bold.ttf]]
+local turn_size = 24
+local turn_outline = 'OUTLINE'
+local icon_size = 64
+local spacing = 5
+local padding = 0
+local strongweak_size = 20
+
+local cpb = C_PetBattles
+T.defaults.petbattle = {
+ swatch = {
+ anchor = 'BOTTOM', anchorTo = 'BOTTOM',
+ parent = 'UIParent',
+ x = 0, y =240,
+ width = 200, height = 100,
+ font = [[Interface\Addons\Turok\Media\font\ArchivoNarrow-Bold.ttf]],
+ size = 16,
+ },
+ spell = {
+ anchor = 'TOPLEFT', anchorTo = 'TOPLEFT',
+ size = 24,
+ width = 72, height = 72,
+ x = 0, y =0,
+ padding = 0,
+ spacing = 0,
+ },
+ sideSwatch = {
+ width = 100, height = 50, padding = 0, spacing = 5,
+ anchor = 'TOPLEFT', anchorTo = 'BOTTOMLEFT', x = 0, y = 0,
+ parent = 'TkPetSwatch',
+ },
+ sideSpell = {
+ anchor = 'TOPLEFT', anchorTo = 'TOPLEFT',
+ size = 16,
+ width = 36, height = 36,
+ padding = 0,
+ spacing = 0,
+ },
+ icon = {
+ size = 72,
+ width = 64,
+ height = 64,
+ }
+}
+mod.abilityButtons = {}
+mod.switcherButtons = {}
+mod.icons = {}
+mod.strongweak = {}
+mod.turns = {}
+mod.petlist = {}
+local PLAYER, ENEMY = 1, 2
+local function PBS_UpdateEnemySwatch(self)
+
+ print('UpdateSwatch')
+ local db = TurokData.petbattle.swatch
+ local playerActivePet = cpb.GetActivePet(PLAYER)
+ local enemyActivePet = cpb.GetActivePet(ENEMY)
+ local enemyNumPets = cpb.GetNumPets(ENEMY)
+ local playerPetType = cpb.GetPetType(PLAYER, playerActivePet)
+ local enemyPetType = cpb.GetPetType(ENEMY, enemyActivePet)
+ local enemyPetName = cpb.GetName(ENEMY, playerActivePet)
+ for petSlot=1, 3 do
+ local swatchFrame = (petSlot == enemyActivePet) and self or ((petSlot < enemyNumPets) and self.sideSwatch or self.sideSwatch2)
+ local db = (swatchFrame == self) and db.spell or db.sideSpell
+ local type = cpb.GetPetType(ENEMY, petSlot)
+ print(cText(' PetType='), enemyActivePet)
+ print(cText(' current='), enemyPetType)
+ for spellSlot=1, 3 do
+ print(' ', cText('PetSlotOffset='), cNum(petSlot), cText('AbilitySlotOffset'), cNum(spellSlot))
+ local id, name, texture, cooldown, desc, numTurns, attackType, noStrongWeakHints = cpb.GetAbilityInfo(ENEMY, petSlot, spellSlot)
+ local usable, remaining = cpb.GetAbilityState(ENEMY, petSlot, spellSlot)
+
+ --print('info', cpb.GetAbilityInfo(ENEMY, petSlot, spellSlot))
+ -- print('effect', cpb.GetAbilityEffectInfo(id, turnIdx, effectIdx, paramName)
+ --print('state', cpb.GetAbilityState(ENEMY,petSlot,spellSlot))
+ --print('statemod', cpb.GetAbilityStateModification(ENEMY,petSlot,spellSlot))
+ --print('proc', cpb.GetAbilityProcTurnIndex(ENEMY,petSlot,spellSlot))
+ --print('statemod', cpb.GetAbilityState(ENEMY,petSlot,spellSlot))
+ local AbilityButton, icon, strong, turns -- Icon, Strength/Weakness, Turns cooldown
+ if not swatchFrame.buttons[spellSlot] then
+ swatchFrame.buttons[spellSlot] = CreateFrame('Frame', 'TkPetSpell'..spellSlot, swatchFrame, 'TkPetSpellTemplate')
+ AbilityButton = swatchFrame.buttons[spellSlot]
+
+ AbilityButton:SetSize(db.width, db.height)
+ AbilityButton:SetPoint(db.anchor, swatchFrame, db.anchor, (spellSlot-1)*(db.width+ db.spacing), 0)
+
+ AbilityButton.icon:SetSize(db.width, db.height)
+ AbilityButton.icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
+
+ AbilityButton.strongWeakHint:SetSize(strongweak_size, strongweak_size)
+ AbilityButton.strongWeakHint:SetPoint('CENTER', swatchFrame.buttons[spellSlot], 'CENTER', 0, 0)
+
+ AbilityButton.turnsLeft:SetFont(turn_font, turn_size, turn_outline)
+ AbilityButton.turnsLeft:SetPoint('CENTER', icon, 'CENTER')
+ else
+ AbilityButton = swatchFrame.buttons[spellSlot]
+ end
+ local icon, strong , turns = AbilityButton.icon, AbilityButton.strongWeakHint, AbilityButton.turnsLeft
+
+ print('Working on:', swatchFrame, AbilityButton)
+ print('AbilityState('..petSlot..', '..spellSlot..')', 'usable=', usable, 'turnsLeft=', remaining)
+ print(cWord(name), cKey(attackType))
+
+ if petSlot > enemyNumPets then
+ -- this will also eval true when pet battle over since numPets will be 0
+ AbilityButton.popOut:Play()
+ else
+ local abilityChanged
+ if id ~= AbilityButton.spellID then
+ abilityChanged = true
+ AbilityButton.spellID = id
+ AbilityButton.spellName = name
+ AbilityButton.spellDesc = desc
+ AbilityButton.spellType = attackType
+ AbilityButton.spellMaxCooldown = cooldown
+ AbilityButton.spellDesc = desc
+ AbilityButton.spellCooldown = remaining
+ AbilityButton.spellNumTurns = numTurns
+ end
+ if AbilityButton.petType ~= enemyPetType then
+ AbilityButton.petType = enemyPetType
+ AbilityButton.noStrongWeakHints = noStrongWeakHints
+ end
+
+ if not usable then
+ icon:SetDesaturated(true)
+ icon:SetVertexColor(0.5, 0.5, 0.5, 1)
+ else
+ icon:SetDesaturated(false)
+ icon:SetVertexColor(1, 1, 1, 1)
+ end
+
+ icon:SetTexture(texture)
+ turns:SetText((cooldown > 0) and cooldown or nil)
+ --AbilityButton.damage:SetText()
+
+ print('noStrongWeakHints', noStrongWeakHints)
+ print('abilityModification', cpb.GetAttackModifier(enemyPetType, playerPetType))
+ local modifier = cpb.GetAttackModifier(enemyPetType, playerPetType)
+ if not noStrongWeakHints then
+ if modifier < 1 then
+ strong:SetTexture(0,1,0,0.5)
+ else
+ strong:SetTexture(1,0,0,0.5)
+ end
+
+ strong:Show()
+ else
+ strong:Hide()
+ end
+ if numTurns then
+ print('numTurns=',numTurns)
+ end
+ if not AbilityButton:IsVisible() or abilityChanged then
+ AbilityButton:Show()
+ AbilityButton.popIn:Play()
+ end
+
+ end
+
+
+ end
+ swatchFrame:SetSize(db.width*3+db.spacing*2+db.padding*2, db.height+padding*2)
+ swatchFrame.petName = enemyPetName
+ swatchFrame.petType = enemyPetType
+ local db = (swatchFrame == self) and db.swatch or db.sideSwatch
+ swatchFrame:Show()
+ end
+end
+
+local function PBS_Switch ()
+ print('Switch button was clicked.')
+end
+mod.PLAYER_ENTERING_WORLD = function(self, e)
+ print(cpb.IsInBattle())
+ if cpb.IsInBattle() then
+ PBS_UpdateEnemySwatch(PBS, e, 2)
+ end
+
+
+ if _G.PetBattleFrame.BottomFrame.SwitchPetButton then
+ print("There's a pet battle frame button ")
+ --_G.PetBattleFrame.BottomFrame.SwitchPetButton:SetScript('OnClick', PBS_Switch)
+ end
+end
+
+local PBS_Hide = function()
+ for i = 1, 3 do
+ if PBS.buttons[i] then
+ PBS.buttons[i].popOut:Play()
+ end
+ if PBS.sideSwatch.buttons[i] then
+ PBS.sideSwatch.buttons[i].popOut:Play()
+ end
+ if PBS.sideSwatch2.buttons[i] then
+ PBS.sideSwatch2.buttons[i].popOut:Play()
+ end
+ end
+end
+
+local PBS_Event = function(self, e, ...)
+ print('event', e)
+ local owner = ...
+ if e == 'PET_BATTLE_PET_ROUND_PLAYBACK_COMPLETE' or e == 'PET_BATTLE_OPENING_DONE' then
+ PBS_UpdateEnemySwatch(PBS)
+ elseif e == 'PET_BATTLE_CLOSE' then
+ PBS_Hide(PBS)
+ end
+end
+function mod:OnEnable()
+ PBS = CreateFrame('Frame', 'TkPetSwatch', UIParent, 'TkPetSwatchTemplate')
+ PBS.buttons = {}
+ PBS.sideSwatch = CreateFrame('Frame', 'TkSideSwatch', PBS, 'TkPetSwatchTemplate')
+ PBS.sideSwatch.buttons = {}
+ PBS.sideSwatch2 = CreateFrame('Frame', 'TkSideSwatch', PBS, 'TkPetSwatchTemplate')
+ PBS.sideSwatch2.buttons = {}
+ local db = TurokData.petbattle
+ T.SetFrameLayout(PBS, db.swatch)
+ T.SetFrameLayout(PBS.sideSwatch, db.sideSwatch)
+ T.SetFrameLayout(PBS.sideSwatch2, db.sideSwatch)
+ PBS.sideSwatch2:ClearAllPoints()
+ PBS.sideSwatch2:SetPoint('LEFT', PBS.sideSwatch, 'RIGHT', db.sideSpell.spacing, 0)
+
+ mod.effectIndex = {
+ cpb.GetAllEffectNames()
+ }
+
+ PBS:SetScript('OnEvent', PBS_Event)
+ PBS:RegisterEvent('PET_BATTLE_OPENING_DONE')
+ PBS:RegisterEvent('PET_BATTLE_PET_CHANGED')
+ PBS:RegisterEvent('PET_BATTLE_OVER')
+ PBS:RegisterEvent('PET_BATTLE_CLOSE')
+ PBS:RegisterEvent('PET_BATTLE_ABILITY_CHANGED')
+ PBS:RegisterEvent('PET_BATTLE_ACTION_SELECTED')
+ --PBS:RegisterEvent('PET_BATTLE_AURA_APPLIED')
+ --PBS:RegisterEvent('PET_BATTLE_AURA_CANCELED')
+ --PBS:RegisterEvent('PET_BATTLE_PET_TYPE_CHANGED')
+ PBS:RegisterEvent('PET_BATTLE_TURN_STARTED')
+ --PBS:RegisterEvent('PET_BATTLE_HEALTH_CHANGED')
+ --PBS:RegisterEvent('PET_BATTLE_MAX_HEALTH_CHANGED')
+ PBS:RegisterEvent('PET_BATTLE_PET_ROUND_RESULTS')
+ PBS:RegisterEvent('PET_BATTLE_PET_ROUND_PLAYBACK_COMPLETE')
+end
+
+--[[
+mod.PET_BATTLE_OPENING_DONE = trace
+mod.PET_BATTLE_OPENING_START = trace
+mod.PET_BATTLE_OVER = trace
+mod.PET_BATTLE_ABILITY_CHANGED = trace
+mod.PET_BATTLE_ACTION_SELECTED = trace
+mod.PET_BATTLE_AURA_APPLIED = trace --
+mod.PET_BATTLE_AURA_CANCELED = trace --
+mod.PET_BATTLE_AURA_CHANGED = trace --
+mod.PET_BATTLE_CAPTURED = trace
+mod.PET_BATTLE_CLOSE = trace
+mod.PET_BATTLE_FINAL_ROUND = trace --
+mod.PET_BATTLE_HEALTH_CHANGED = trace --
+mod.PET_BATTLE_LEVEL_CHANGED = trace
+mod.PET_BATTLE_LOOT_RECEIVED = trace
+mod.PET_BATTLE_MAX_HEALTH_CHANGED = trace
+mod.PET_BATTLE_PET_CHANGED = trace --
+mod.PET_BATTLE_PET_TYPE_CHANGED = trace --
+mod.PET_BATTLE_PET_ROUND_PLAYBACK_COMPLETE = trace --
+mod.PET_BATTLE_PET_ROUND_RESULTS = trace --
+mod.PET_BATTLE_PVP_DUEL_REQUESTED = trace
+mod.PET_BATTLE_PVP_DUEL_REQUEST_CANCEL = trace
+mod.PET_BATTLE_QUEUE_PROPOSAL_ACCEPTED = trace
+mod.PET_BATTLE_QUEUE_PROPOSAL_DECLINED = trace
+mod.PET_BATTLE_QUEUE_PROPOSE_MATCH = trace
+mod.PET_BATTLE_QUEUE_STATUS = trace
+mod.PET_BATTLE_TURN_STARTED = trace
+mod.PET_BATTLE_XP_CHANGED = trace --
+--]]
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Utilities/Raid.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Utilities/Raid.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,152 @@
+--- Turok Raid/Raid.lua
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+--- Defines the interfaces for raid tools
+local T = Turok
+local mod = T:NewModule('RaidReady')
+mod.OnInitialize = function(self)
+ self.db = TurokData.Lost
+ self.events = {
+ PARTY_MEMBERS_CHANGED = self.MembersChangedEvent,
+ PLAYER_SPECIALIZATION_CHANGED = self.SpecChangeEvent,
+ ENCOUNTER_START = self.EncounterStart,
+ UNIT_AURA = self.UnitAura
+ }
+end
+
+T.defaults.Lost = {
+ parent = 'UIParent',
+ anchor = 'BOTTOMRIGHT', anchorTo = 'BOTTOMRIGHT',
+ x = -300, y = 300,
+ height = 24*9, width = 72,
+ width = 72,
+ height = 24,
+ size = 11,
+ font = "Interface\\Addons\\Turok\\Media\\font\\ArchivoNarrow-Bold.ttf",
+
+ raidbuff = {
+ icon = {},
+ status = {},
+ },
+
+ durability = {
+
+ },
+
+ toast = {
+
+ },
+}
+local _G = _G
+local print = function(...) if Devian and DevianDB.workspace~= 1 then print('RaidInfo', ...) end end
+local CreateFrame, floor, GetRaidBuffTrayAuraInfo, NUM_LE_RAID_BUFF_TYPES = CreateFrame, math.floor, GetRaidBuffTrayAuraInfo, NUM_LE_RAID_BUFF_TYPES
+local GetSpecialization, GetSpecializationInfo, GetSpecializationInfoByID = GetSpecialization, GetSpecializationInfo, GetSpecializationInfoByID
+local IsInRaid, IsInGroup, GetInspectSpecialization = IsInRaid, IsInGroup, GetInspectSpecialization
+local find, match, sub = string.find, string.match, string.sub
+local GetRealmName, GetRaidRosterInfo, UnitGUID = GetRealmName, GetRaidRosterInfo, UnitGUID
+local db
+
+function mod:OnEnable()
+ db = self.db
+
+ self.raidbuffs = {} -- active raid buffs
+ self.buffinfo = {} -- raid buff text
+ self.available = {} -- availability info
+ self.units_raid = {}
+
+ self.raidbuffs_tray = _G.TurokRaidbuffsTray
+
+ -- seed raid buff analyzer assets
+ self.num_raidbuff_columns = floor(db.raidbuff.width / db.raidbuff.icon.width)
+ for i = 1, 9 do
+ --print('TurokRaidbuffButton'..i, self.raidbuffs_tray, 'TurokRaidbuffButton')
+ local buff = CreateFrame('Button', 'TurokRaidbuffButton'..i, self.raidbuffs_tray, 'TurokRaidbuffButton')
+
+ -- T.SetFrameLayout(buff, db.raidbuff)
+ end
+
+ db.raidevent = {}
+
+
+
+
+end
+
+function mod:PLAYER_SPECIALIZATION_CHANGED(e, unit)
+ local specID
+ --print(e, unit)
+ if unit == 'player' then
+ specID = GetSpecializationInfo(GetSpecialization())
+ else
+ --NotifyInspect(unit)
+ specID = GetInspectSpecialization()
+ end
+ if specID then
+ --print(GetSpecializationInfoByID(specID))
+ end
+end
+
+function mod:PARTY_MEMBERS_CHANGED(e, ...)
+ if IsInRaid() or IsInGroup() then
+ self.raidbuffs_frame:Show()
+ self:RaidBuffScan()
+ else
+ end
+end
+
+function mod:ENCOUNTER_START(e,...)
+ --print(e,...)
+end
+
+-- Updates available raid/party buffs
+function mod:RaidbuffsUpdate(unit)
+ if not (IsInGroup() or IsInRaid()) then
+ self.raidbuffs_tray:Hide()
+ return
+ end
+
+ local c = db.raidbuff
+ local k = 0
+ for i = 1, NUM_LE_RAID_BUFF_TYPES do
+
+ local rb = self.raidbuffs[i]
+ local buff = {GetRaidBuffTrayAuraInfo(i) }
+ --name, rank, texture, duration, expiration, spellId, slot
+ local isShown = false
+ if buff[1] then
+ isShown = true
+ self.raidbuffs[i] = buff
+ else
+ self.raidbuffs[i] = nil
+ end
+
+ if isShown then
+ rb:Show()
+ rb.bufftype:SetText(sub(_G['RAID_BUFF_'..i],0,2))
+ rb.spellname:SetText(self.buffinfo[i])
+
+ local pn = k -- need (n-1) for lua grid math
+ local py = floor(pn / self.num_raidbuff_columns) * c.height
+ local px = (pn * c.width) % db.width -- x-offset
+ --print('buff slot '..i..' (draw position '..k..')', pn, py, px)
+ rb:SetPoint(c.anchor, self.raidbuffs_tray, c.anchor, px, py)
+
+ k = k + 1
+ end
+ end
+ if k == 0 and self.raidbuffs_tray:IsVisible() then
+ self.raidbuffs_tray:Hide()
+ elseif not self.raidbuffs_tray:IsVisible() then
+ self.raidbuffs_tray:Show()
+ end
+end
+
+function mod:RosterScan()
+ local lim = 1
+ if IsInRaid() then
+ lim = 40
+ elseif IsInGroup() then
+ lim = 5
+ end
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Utilities/Raid.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Utilities/Raid.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Utilities/Toast.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Utilities/Toast.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,372 @@
+--- ${PACKAGE_NAME}
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+-- Created: 2/2/2016 12:09 AM
+
+local mod = Turok:NewModule("Toast", "AceTimer-3.0")
+local _G = _G
+local db
+local T, tostring, type, max, tinsert, UIParent, loadstring = _G.Turok, tostring, type, max, table.insert, _G.UIParent, loadstring
+--@debug@
+local DEBUG = true
+--@end-debug@
+local cType, cText, cNum, cWord, cKey, cPink, cBool = cType, cText, cNum, cWord, cKey, cPink, cBool
+local print = function(...)
+ if not DEBUG then return end
+ if _G.Devian and _G.DevianDB.workspace ~= 1 then
+ _G.print('Toast', ...)
+ end
+end
+
+-- GLOBALS:BossBanner_OnEvent, BossBanner
+-- kill off the default BossBanner
+local old_bb = BossBanner_OnEvent
+BossBanner_OnEvent = function(self, event, ...)
+ T:Print(event, ...)
+end
+
+T.defaults.toast = {
+ alert_hold = 2,
+ alert_fade = 1,
+ alert_flash = .6,
+ anchor = 'TOP',
+ parent = 'UIParent',
+ anchorTo = 'TOP',
+ x = 0, y= -56,
+ loot = {
+ background_color = {},
+ }
+}
+
+mod.events = {
+ "ACHIEVEMENT_EARNED",
+ "CRITERIA_EARNED",
+ "LFG_COMPLETION_REWARD",
+ "GUILD_CHALLENGE_COMPLETED",
+ "CHALLENGE_MODE_COMPLETED",
+ "LOOT_ITEM_ROLL_WON",
+ "SHOW_LOOT_TOAST",
+ "SHOW_LOOT_TOAST_UPGRADE",
+ "SHOW_PVP_FACTION_LOOT_TOAST",
+ "PET_BATTLE_CLOSE",
+ "STORE_PRODUCT_DELIVERED",
+ "GARRISON_BUILDING_ACTIVATABLE",
+ "GARRISON_MISSION_FINISHED",
+ "GARRISON_FOLLOWER_ADDED",
+ "GARRISON_RANDOM_MISSION_ADDED",
+ "BOSS_KILL",
+ "ENCOUNTER_LOOT_RECEIVED",
+}
+
+mod.events_args = {
+ ['ACHIEVEMENT_EARNED'] = {12, false},
+ ['ACHIEVEMENT_EARNED'] = {12, true},
+ ['LFG_COMPLETED_REWARD'] = {},
+}
+local y_factor = -1
+local x_factor = 0
+local tkAlerts = TkAlertContainer
+local AlertFrame_FixPosition = function(alertFrame)
+ print(' pos:', alertFrame.order, cKey(alertFrame.x), cWord(alertFrame.y))
+ alertFrame:SetPoint('TOPLEFT', tkAlerts, 'TOPLEFT', alertFrame.x, alertFrame.y)
+end
+
+--- Goes through the alert container index and fixes the frame positions
+-- used before and after an alert frame changes visibility
+local AlertContainer_Update = function(self)
+ local anum = 1
+ local offset = 0
+ for i, alert in ipairs(tkAlerts.alerts) do
+ if alert:IsShown() then
+ alert.x = offset * x_factor
+ alert.y = offset * y_factor
+ alert.drawHeight = alert.ename:GetStringHeight()+ alert.desc:GetStringHeight()
+ alert.order = anum
+ anum = anum + 1
+ offset = offset + alert.drawHeight
+ print(' draw height:', i, cText(alert.drawHeight))
+ print(' position:', i, cPink(offset))
+ AlertFrame_FixPosition(alert)
+ print('index', i, 'shifted from position', cNum(alert.order), 'to', cNum(anum), ' at draw point', alert.y)
+ print(' draw distance update ', cNum(0), 'x', cNum(offset))
+ else
+ print('index', i, 'is not visible')
+ end
+ end
+ self:SetHeight(offset)
+end
+
+--- config mode blocking command
+local AlertFrame_Block = function(alertFrame)
+ -- only do stuff when configMode is on
+ if not mod.configMode then
+ return
+ end
+end
+
+--- if not config mode, then fire at the end of fadeIn animation to queue fadeOut
+local AlertFrame_Pin = function(alertFrame)
+ if not mod.configMode then
+ alertFrame.fadeOut.a1:SetStartDelay(db.alert_hold)
+ alertFrame.fadeOut:Play()
+ end
+end
+
+--- if not config mode, then fire at the end of fadeOut to remove the frame from view and trigger positions update
+local AlertFrame_Remove = function(alertFrame)
+ mod.num_events = mod.num_events - 1
+ alertFrame:Hide()
+ print(mod.num_events)
+ AlertContainer_Update(tkAlerts)
+end
+
+--- orders all visible frames to fadeOut
+-- @param stagger forces the spacing of startDelay times for each frame
+local AlertContainer_Clear = function(self, stagger)
+ stagger = stagger or 0.1
+ for i = #self.alerts, 1, -1 do
+ print('clear check', i)
+ local alert = self.alerts[i]
+ if alert:IsShown() and not alert.fadeOut:IsPlaying() then
+ alert.fadeOut.a1:SetStartDelay((#self.alerts-i)* stagger)
+ alert.fadeOut:Play()
+ end
+ end
+end
+local AlertContainer_Unlock = function()
+end
+
+--- Displays a new alert
+-- @param name text naming the class of event that occurred
+-- @param text alert subtext describing basic info about the event
+-- @order order (optional) sets display slot of the alert
+local function AlertContainer_ShowAlert(self, name, text, order)
+ local db = TurokData.toast
+ mod.num_events = mod.num_events + 1
+
+ local alertFrame
+ if not order then
+ local i = 1
+ while i <= #self.alerts and not alertFrame do
+ if not self.alerts[i]:IsShown() then
+ alertFrame = self.alerts[i]
+ print('re-using alert frame #', i)
+ end
+ i = i +1
+ end
+ else
+ alertFrame = self.alerts[order]
+ end
+
+ if not alertFrame then
+ alertFrame = CreateFrame('Frame', 'TkAlertPanel'..(order or #self.alerts+1), self, 'TkAlertFrame')
+ self.alerts[#self.alerts+1] = alertFrame
+ print('creating new alert frame', #self.alerts)
+
+ alertFrame.Pin = AlertFrame_Pin
+ alertFrame.Remove = AlertFrame_Remove
+ end
+
+ alertFrame.ename:SetText(name)
+ local height1 = alertFrame.ename:GetStringHeight()
+ alertFrame.desc:SetText(text)
+ local height2 = height1+ alertFrame.desc:GetStringHeight()
+ alertFrame.desc:SetPoint('TOPLEFT', alertFrame, 'TOPLEFT', 0, -height1)
+
+ alertFrame.order = order or mod.num_events
+ alertFrame:SetSize(300, height2)
+ alertFrame:Show()
+ --alertFrame.flashIn.a1:SetDuration(db.alert_flash/2)
+ --alertFrame.flashIn.a2:SetDuration(db.alert_flash/2)
+ alertFrame.flashIn:Play()
+ if not mod.configMode then
+ AlertContainer_Update(tkAlerts)
+ end
+end
+
+
+--- updates the completed missions index and returns info on the mission ID if passed
+local completedMissions
+local Garrison_UpdateCompleteMissions = function(missionID)
+ completedMissions = C_Garrison.GetCompleteMissions()
+ --- slide entries around for reference
+ for i, set in ipairs(completedMissions) do
+ if i ~= set.missionID then
+ completedMissions[set.missionID] = set
+ completedMissions[i] = nil
+ end
+ end
+
+ if missionID and completedMissions[missionID] then
+ local m = completedMissions[missionID]
+ return m.name, m.location, m.locPrefix, m.isRare, m.followers, m.rewards, m.state
+ else
+ return false
+ end
+end
+--- container events handler
+local AlertContainer_OnEvent = function (self, event, ...)
+ print(event, ...)
+ tkAlerts:Show()
+ if event == 'SHOW_LOOT_TOAST' then
+ local typeIdentifier, itemLink, quantity, specID, sex, isPersonal, lootSource = ...;
+ if typeIdentifier == "currency" then
+ AlertContainer_ShowAlert(self, itemLink, 'x'..quantity)
+ elseif typeIdentifier == "item" then
+ local _, _, _, ilvl, _, _, _, _, equipSlot = GetItemInfo(itemLink)
+ AlertContainer_ShowAlert(self, itemLink, tostring(ilvl)..' '..tostring(_G[equipSlot]))
+ end
+ elseif event == 'GARRISON_MISSION_FINISHED' then
+ local missionID = ...
+ local name, location, locPrefix, isRare, followers, rewards = Garrison_UpdateCompleteMissions(missionID)
+ local mission_info = {
+ (isRare and ('|cFF44BBFF') or ('|cFFFFFF00')..name.. '|r'),
+ }
+
+ if followers then
+ for i, guid in ipairs(followers) do
+ print(C_Garrison.GetFollowerInfo(guid))
+ end
+ end
+
+ --'|T:'..icon..':0
+
+
+ AlertContainer_ShowAlert(self, 'Mission Complete')
+ elseif event == 'GARRISON_BUILDING_ACTIVATABLE' then
+ local missionID = ...
+ elseif event == 'ACHIEVEMENT_EARNED' then
+ elseif event == 'LFG_COMPLETION_REWARD' then
+ local name, typeID, subtypeID, textureFilename, moneyBase, moneyVar, experienceBase, experienceVar, numStrangers, numRewards = GetLFGCompletionReward()
+ local _, _, _, _, hasBonusStep, isBonusStepComplete = C_Scenario.GetInfo();
+
+ end
+end
+
+local AlertContainer_Test = function()
+ if not mod.configMode then
+ print('starting test mode')
+ tkAlerts:Show()
+ mod.configMode = true
+
+ tkAlerts.configBG:Show()
+ tkAlerts.configBG:SetTexture(0,0.5,0,0.5)
+ tkAlerts:RegisterForDrag('LeftButton')
+ tkAlerts:EnableMouse(true)
+
+ for i, frame in ipairs(tkAlerts.tools) do
+ frame:Show()
+ end
+ -- test fillers
+ local _,_, offset, range = GetSpellTabInfo(2)
+ print(offset, range)
+
+ for i, event in ipairs(mod.events) do
+ --print(i, event)
+ local _, id = GetSpellBookItemInfo(math.random(offset, offset+range), 'spell')
+ print(id)
+
+ local name = GetSpellLink(id)
+ local text = GetSpellDescription(id)
+ if not tkAlerts.alerts[i] then
+ print('creating alert frame #', i)
+ AlertContainer_ShowAlert(tkAlerts, name, text, i)
+ else
+ print('updating alert frame #', i)
+ local alert = tkAlerts.alerts[i]
+ alert:Show()
+ alert.order = i
+ alert.ename:SetText(name)
+ alert.desc:SetText(text)
+ if alert.fadeOut:IsPlaying() then
+ alert.fadeOut:Stop()
+ alert.backdrop:SetAlpha(0.5)
+ end
+
+ alert.flashIn:Play()
+ end
+ end
+ AlertContainer_Update(tkAlerts)
+ else
+ tkAlerts:EnableMouse(false)
+ tkAlerts.configBG:Hide()
+ mod.configMode = nil
+ for i, frame in ipairs(tkAlerts.tools) do
+ frame:Hide()
+ end
+ for i, alert in ipairs(tkAlerts.alerts) do
+ for j, frame in ipairs(alert.tools) do
+ frame:Hide()
+ end
+ alert.fadeOut.a1:SetStartDelay(i*0.2)
+ alert.fadeOut:Play()
+ end
+
+ end
+end
+
+mod.OnEnable = function()
+ db = TurokData.toast
+
+ --- find the closest frame to the center bottom and anchor to that
+
+ local cX, cY = (GetScreenWidth() / 2), (GetScreenHeight() / 2)
+ local min_skewness = cX
+ local max_centrality, center_frame
+ for n, f in ipairs({UIParent:GetChildren()}) do
+ if type(f) == 'table' and f.GetObjectType and f.GetName then
+ if f.IsForbidden and f:IsForbidden() then
+ print(n, 'is a forbidden object')
+ else
+ local name = f:GetName()
+
+ if f:IsVisible() and f:IsMouseEnabled() then
+ print(name and name or tostring(f):sub(8), 'is a frame!')
+ local x = f:GetCenter()
+ local y = f:GetTop() -- Y need center top position
+ if (x and y) and (y <= cY) then
+ x = math.abs(x - cX) -- X works in either direction
+
+ -- distance of current - distant of record / max to get ratio of 1 where direct center results in 1
+ local skewness_factor = (cX - x) / cX
+ local vertness_factor = y / cY
+ local centrality = skewness_factor * vertness_factor
+ print('result: (', floor(x), floor(y), ') = ', skewness_factor, 'skew,', vertness_factor, 'vertness.\nTotal score:', cNum(centrality))
+ if (not max_centrality) or max_centrality < centrality then
+ center_frame = f
+ max_centrality = centrality
+ print(cWord(name and name or tostring(f):sub(8)),cPink(' is the new record!'))
+ end
+
+ end
+ end
+ end
+ end
+ end
+
+ mod.num_events = 0
+ tkAlerts.alerts = {}
+ for i, event in ipairs(mod.events) do
+ tkAlerts:RegisterEvent(event)
+ end
+
+ tkAlerts.Clear = AlertContainer_Clear
+ tkAlerts.Unlock = AlertContainer_Unlock
+ tkAlerts.Close = AlertContainer_Test
+
+ tkAlerts:ClearAllPoints()
+ tkAlerts:SetPoint(db.anchor, db.parent, db.anchorTo, db.x, db.y)
+ tkAlerts.x = db.x
+ tkAlerts.y = db.y
+ tkAlerts.parent = db.parent
+ tkAlerts.anchor = db.anchor
+ tkAlerts.anchorTo = db.anchorTo
+ tkAlerts:EnableMouse(false)
+
+ tkAlerts:SetScript('OnEvent', AlertContainer_OnEvent)
+ T:RegisterChatCommand("alert", AlertContainer_Test)
+ T:RegisterChatCommand("atest", function()
+ AlertContainer_OnEvent(tkAlerts, 'GARRISON_MISSION_FINISHED', 327)
+ end)
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Modules/Utilities/Utilities.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Modules/Utilities/Utilities.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,252 @@
+
+
+
+
+ self.cx = self:GetLeft()
+ self.cy = self:GetTop()
+ self:StartMoving()
+
+
+ self:StopMovingOrSizing()
+ self.x = self.x + self:GetLeft() - self.cx
+ self.y = self.y + self:GetTop() - self.cy
+ self:ClearAllPoints()
+ self:SetPoint(self.anchor, self.parent, self.anchorTo, self.x, self.y)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:GetParent().flashBG:Show()
+
+
+ self:GetParent().flashBG:Hide()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ print(self:GetParent():GetParent():GetName())
+ print(self:GetParent():GetParent().num_events)
+
+
+ self:GetParent():Pin()
+
+
+
+
+
+
+
+
+ self:GetParent():Remove()
+
+
+
+
+
+
+
+
+
+
+ self:GetParent():GetParent().flare:Show()
+
+
+ self:GetParent():GetParent().flare:Hide()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ print(self:GetName(), self.spellID, 'enter')
+ GameTooltip:SetOwner(self, 'ANCHOR_TOP')
+ --GameTooltip:SetPetAction(self.spellID)
+ GameTooltip:Show()
+
+
+ print(self:GetName(), 'leave')
+ GameTooltip:Hide()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:GetParent():Show()
+ self:GetParent():SetAlpha(0)
+
+
+
+
+
+
+
+
+ self:GetParent():Hide()
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Turok.iml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Turok.iml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Turok.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Turok.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,554 @@
+--- Turok
+-- @file-author@
+-- @project-revision@ @project-hash@
+-- @file-revision@ @file-hash@
+--- Defines the mechanisms for the storage and dispatch of events data.
+--@debug@
+--@end-debug@
+-- GLOBALS: LibStub, Turok, TurokData, ReloadUI
+local ADDON, Tk = ...
+local db, L
+local MAJOR, MINOR = "Turok", "@project-revision@"
+local T, LGIST, _G = Tk.Addon, Tk.LGIST, _G
+
+
+local pcall, type, ipairs, pairs, format, tinsert, match, strpad, error = pcall, type, ipairs, pairs, string.format, table.insert, string.match, string.rep, error
+local PlaySoundFile, LoadAddOn, IsAddOnLoaded, UnitName, UnitGUID, UnitPowerMax = PlaySoundFile, LoadAddOn, IsAddOnLoaded, UnitName, UnitGUID, UnitPowerMax
+local GetSpecializationInfo, GetSpecialization, UnitSpellHaste, GetActiveSpecGroup = GetSpecializationInfo, GetSpecialization, UnitSpellHaste, GetActiveSpecGroup
+local UnitInfo, UnitCastingInfo, UnitChannelInfo = UnitInfo, UnitCastingInfo, UnitChannelInfo
+local rawset, unpack, tostring, setmetatable, xpcall, unpack = rawset, unpack, tostring, setmetatable, xpcall, unpack
+
+--@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('Turok', ...)
+ end
+end
+local GetPrint = function(trace)
+ return trace and print or function() end
+end
+--@end-debug@
+
+
+
+--- Pull saved variables and make them sane
+function T.OnInitialize(T)
+
+ --@debug@
+ local tmpidx
+ if TurokData and TurokData.spirit and TurokData.spirit.timerindex then
+ tmpidx = TurokData.spirit.timerindex
+ end
+ TurokData = Turok.defaults
+ if tmpidx then
+ TurokData.spirit.timerindex = tmpidx
+ end
+ --@end-debug@
+ T.db = _G.TurokData
+ LibStub("LibFog-1.0"):Embed(T)
+ if T.db.queue_for_wipe then
+ T:Print("db reset flag received")
+ local index = _G.TurokData.spirit.timerindex
+ _G.TurokData = T.defaults
+ T.db = _G.TurokData
+ T.db.spirit.timerindex = index
+ end
+
+ T:RegisterChatCommand("tkr", function()
+ T.db.queue_for_wipe = true
+ ReloadUI()
+ end)
+
+ -- db hierarchy
+ for k, v in pairs(T.db) do
+ if type(v) == 'table' then
+ --@debug@
+ --print('|cFF44FF88loading stored db|r: db.|cFF44AAFF'.. k ..'|r')--@end-debug@
+ T.LinkTable(T.db, v, 'db', k)
+ end
+ end
+ setmetatable(T.db,
+ {__newindex = function (t, k, v)
+ rawset(t,k,v)
+ if type(v) == 'table' then
+ --@debug@
+ --print('|cFF44FF88creating new db|r: db.|cFF44AAFF'.. k ..'|r')--@end-debug@
+ T.LinkTable(T.db, v, 'db', k)
+ end
+ end})
+ T.L = setmetatable({}, {__call = function(t, s) return t[s] or s end})
+end
+
+--- Get everything rolling
+function T:OnEnable()
+ db = TurokData
+ L = T.L
+
+ self.dispatchQueue = {}
+ self.sharedTables = {}
+ local skip = {modules = true, db = true, defaultModuleLibraries = true, orderedModules = true, prototype = true, events = true} -- local data that exists before init
+ for id, mod in pairs(self.orderedModules) do
+ mod.ID = id
+ mod.RegisterCallback = self.RegisterCallback
+ print('load', mod:GetName())
+ for k, v in pairs(mod) do
+ if not skip[k] then
+ if match(k, '^[%u_]+$') then
+ if not self.dispatchQueue[k] then
+ self.dispatchQueue[k] = {}
+ end
+ self:RegisterEvent(k, 'Dispatch')
+ self.dispatchQueue[k][id] = mod:GetName()
+ end
+ end
+ end
+ end
+
+ print('events')
+ for k, v in pairs(self.dispatchQueue) do
+ print(' ',k,'->', unpack(v))
+ end
+
+ print('shared')
+ for k, v in pairs(self.sharedTables) do
+ print(' ',k)
+ end
+ --@debug@
+ self:Print(MAJOR, MINOR, 'enabled.')--@end-debug@
+ self:RegisterChatCommand("tkl", function()
+ PlaySoundFile([[Interface\Addons\Turok\Media\sound\wilhelm.ogg]])
+ if not IsAddOnLoaded("Turok_Config") then
+ local loaded, message = LoadAddOn("Turok_Config")
+ if not loaded then
+ return T:Print("|cFFFF0000Load-on-Demand failed!|r Reason: " .. message)
+ end
+ --self.config = LibStub('AceConfigDialog-3.0'):AddToBlizOptions(MAJOR)
+ end
+ InterfaceOptionsFrame_OpenToCategory(MAJOR)
+ InterfaceOptionsFrame_OpenToCategory(MAJOR)
+ end)
+
+ self:RegisterChatCommand("unlock", function()
+ T.unlocked = (not T.unlocked) and true or nil
+ if T.unlocked then
+ self:Print('frames unlocked')
+ else
+ self:Print('frames locked')
+ end
+ for k, v in pairs(self.orderedModules) do
+ if v.UpdateLocked then
+ v:UpdateLocked()
+ end
+ end
+ end)
+
+ self:RegisterChatCommand("lsm", function(input)
+ local a1, n = self:GetArgs(input, 1,0)
+ local a2 = self:GetArgs(input, 1, n)
+ self:Print(self.LSM:Fetch(a1, a2))
+ end)
+
+ local name, realm = UnitFullName('player')
+ LGIST.RegisterCallback(self, "GroupInSpecT_InspectReady", 'GIST_InspectReady')
+ LGIST.RegisterCallback(self, "GroupInSpecT_Update", 'GIST_Update')
+ self:RegisterCharacterInfo(name, realm)
+
+ if InCombatLockdown() then
+ T.inCombat = true
+ end
+
+ T:PLAYER_SPECIALIZATION_CHANGED('PLAYER_SPECIALIZATION_CHANGED','player')
+ for order, event in ipairs(self.events) do
+ self:RegisterEvent(event, 'Dispatch')
+ end
+end
+
+do
+ local bucket_events = {['PLAYER_SPECIALIZATION_CHANGED'] = {}, ['PLAYER_TALENT_UPDATE'] = {}}
+ local bucket_start = {}
+ local event_queue = {}
+ local wipe, debugstack = table.wipe, debugstack
+
+ --- Passes event data to the appropriate handlers, and runs any callback returned
+ -- @param e event name
+ -- @param ... event arguments as given by WoW Lua
+ -- @return callback1 runs after its corresponding method has been dispatched to
+ -- @return callback2 runs after all dispatching has completed, in the order that dispatches occurred
+ function T:Dispatch(event, ...)
+ if not (self[event] or self.dispatchQueue[event]) then
+ return
+ end
+
+
+ if bucket_events[event] then
+ local unit = ...
+ if unit and unit ~= 'player' then
+ return
+ end
+
+ print(cText('*** Bucket Event:'), cWord(event))
+ if not bucket_start[event] then
+ self['TKBATCH_'..event] = {}
+ bucket_start[event] = GetTime()
+ T:ScheduleTimer( function()
+ print('*** Firing bucketed event ('..#bucket_events[event]..'):', event, unpack(bucket_events[event][#bucket_events[event]]))
+ T:Dispatch('TKBATCH_'..event, unpack(bucket_events[event][#bucket_events[event]]))
+ bucket_start[event] = nil
+
+ self['TKBATCH_'..event] = nil
+ end,0.1)
+ end
+ tinsert(bucket_events[event], {...})
+ return
+ else
+ event = event:gsub('^TKBATCH_', '')
+ end
+
+
+ if event ~= 'COMBAT_LOG_EVENT_UNFILTERED' then print('|cFFFF0088received|r', event, ...) end
+ local args = {event, ...}
+
+ -- if addon is listening directly
+ if self[event] then
+ print(cWord(event))
+ local reg = function() print(unpack(args)) self[event](self, unpack(args)) end
+ tinsert(event_queue, {self, event, reg})
+
+
+ -- if modules want this event directly
+ end
+ if self.dispatchQueue[event] then
+ for id, name in pairs(self.dispatchQueue[event]) do
+ local mod = self.orderedModules[id]
+ local reg = function() print(unpack(args)) mod[event](mod, unpack(args)) end
+ tinsert(event_queue, {mod, event, reg})
+ end
+ else
+ print("Received", event, "but nothing is listening to it.")
+ end
+
+ for i, entry in ipairs(event_queue) do
+ local handler, event, func = unpack(entry)
+ print('->', cWord(handler:GetName()), cBool(result), cText(message))
+ local result, message = xpcall(func, function(m) print(m, debugstack()) return debugstack() end)
+
+ if bucket_events[event] then
+ wipe(bucket_events[event])
+ bucket_events[event].history = {}
+ end
+ end
+ wipe(event_queue)
+ end
+end
+--- Store character data to speed up spec-specific load time
+function T:RegisterCharacterInfo(name,realm)
+ local classLocalized, classEnglish, classID = UnitClass('player')
+
+ -- set savedvars
+ self.playerName = name
+ self.playerRealm = realm
+ self.playerClass = classEnglish
+ self.playerClassLocalized = classLocalized
+ self.playerClassID = classID
+ self.GUID = UnitGUID('player')
+ local namerealm = name..'-'..realm
+ if not db.char[namerealm] then
+ db.char[namerealm] = {
+ spellBook = {}
+ }
+ end
+ T.spellBook = db.char[namerealm].spellBook
+
+ -- push combat ratings calc
+ self:COMBAT_RATING_UPDATE()
+end
+
+--- Polls for specialization info until it's available
+function T:RegisterSpecEvents()
+ local specPage = GetSpecialization()
+ if specPage then
+
+ local specID, specName, specDesc, specTexture = GetSpecializationInfo(specPage)
+ local specGroup = GetActiveSpecGroup()
+ print('Turok', cText('* Spec Info:'), GetSpecializationInfo(GetSpecialization()))
+ if T.specID and specID ~= T.specID then
+ print('pushing out old spec data')
+ T.previousSpec = {
+ specPage = T.specPage,
+ specGroup = T.specGroup,
+ specID = T.specID,
+ specName = T.specName,
+ specTexture = T.specTexture
+ }
+ elseif not T.previousSpec then
+ print('first run probably')
+ T.previousSpec = {}
+ end
+
+
+ T.specUpdate = (specID ~= T.specID)
+ T.talentsChanged = (T.specGroup ~= specGroup)
+ T.specPage = specPage
+ T.specGroup = specGroup
+ T.specID = specID
+ T.specName = specName
+ T.specTexture = specTexture
+ else
+ print('Turok', cText('* No Spec Info yet, start polling'))
+ -- repeat until we get something to update with
+ T:ScheduleTimer('RegisterSpecEvents', 1)
+ end
+
+ if T.specID and not T.__specevents then
+ T.__specevents = true
+ T:PLAYER_SPECIALIZATION_CHANGED('PLAYER_SPECIALIZATION_CHANGED','player')
+ T:RegisterEvent('PLAYER_TALENT_UPDATE', 'Dispatch')
+ T:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED', 'Dispatch')
+ T:RegisterEvent('ACTIVE_TALENT_GROUP_CHANGED', 'Dispatch')
+ T:RegisterEvent('UNIT_SPELLCAST_INTERRUPTED', 'Dispatch')
+ end
+end
+
+--- Event handler wrapper for the Specialization getter used at load time
+ local GetSpecializationSpells, GetSpellInfo = GetSpecializationSpells, GetSpellInfo
+ function T:PLAYER_SPECIALIZATION_CHANGED(event, unit)
+ -- make sure this was fired for player
+ if (unit ~= 'player') then
+ return
+ end
+
+
+ print('Turok', '|cFF00FF00'.. event)
+ -- Set current spec values and fill out previousSpec table
+ T:RegisterSpecEvents()
+ local ot = T.previousSpec
+
+ -- Is the new spec different?
+ if T.specUpdate then
+ print(cText('Spec changed from'), cWord(ot.specName), cText('to'), cKey(T.specName))
+
+ if ot.specPage and not T.spellBook[ot.specPage] then
+ T.spellBook[ot.specPage] = {}
+ end
+
+ local spellBook = {GetSpecializationSpells(T.specPage)}
+ if not T.spellBook[T.specPage] then
+ T.spellBook[T.specPage] = {}
+ for i = 1, #spellBook, 2 do
+ T.spellBook[T.specPage][spellBook[i]] = GetSpellInfo(spellBook[i])
+ if (not ot.specPage) or (T.spellBook[ot.specPage] and not T.spellBook[ot.specPage][spellBook[i]]) then
+ print(cText('activating for spell'), T.spellBook[T.specPage][spellBook[i]])
+ end
+ end
+ end
+
+
+
+ -- list changed spells for use by spell posession checks
+ local diff = {
+ gained = {},
+ lost = {}
+ }
+
+ --- Check against current for removed spells
+ if T.spellBook[ot.specPage] then
+ for id, spellInfo in pairs(T.spellBook[ot.specPage]) do
+ if not T.spellBook[ot.specPage] then
+ tinsert(diff.lost, spellInfo)
+ print('lost', spellInfo.spellName)
+ else
+ print('keep', spellInfo.spellName)
+ end
+ end
+ end
+
+ T.spellBook.change = diff
+ end
+ end
+
+ local GetInventoryItemID, GetItemSpell, GetSpellInfo, GetItemInfo = GetInventoryItemID, GetItemSpell, GetSpellInfo, GetItemInfo
+ function T:PLAYER_EQUIPMENT_CHANGED(event, slot, hasItem)
+ print('Equip slot #', slot, ' has?', hasItem)
+ if hasItem then
+ local itemID = GetInventoryItemID('player', slot)
+ print('itemID?', itemID)
+ local spellName = GetItemSpell(itemID)
+ print('spell?', spellName)
+ local _, spellID
+ if spellName then
+ _, _, _, _, _, _, spellID = GetSpellInfo(spellName)
+ end
+
+ local name, link, quality, iLevel, reqLevel, class, subclass, maxStack, equipSlot, texture, vendorPrice = GetItemInfo(itemID)
+ T.equipped[slot] = {
+ itemID = itemID,
+ spellName = spellName,
+ spellID = spellID,
+ name = name,
+ link = link,
+ equipSlot = equipSlot,
+ texture = texture,
+ }
+ print('equipped', name)
+
+ else
+ self.equipped[slot] = nil
+ end
+ end
+
+ local GetPowerRegen, UnitPowerType = GetPowerRegen, UnitPowerType
+ function T:COMBAT_RATING_UPDATE(t,e)
+ --@debug@
+ print('|cFF00FFFFCOMBAT_RATING_UPDATE')--@end-debug@
+ self.haste = UnitSpellHaste('player')
+ self.powerRegen = GetPowerRegen()
+ self.powerType = UnitPowerType('player')
+ self.castTimeMod = 1+ self.haste/100
+ self.GCD = 1.5 * self.castTimeMod
+
+ L.haste = format('%.2f', self.haste)
+ L.focusregen = format('%.2f', self.powerRegen)
+ L.castingmod = format('%.2f', self.castTimeMod)
+ end
+
+function T:UNIT_SPELLCAST_INTERRUPTED(e, unit, spellName, rank, target, castID)
+ if not T.isEventUnit[unit] then
+ return
+ end
+ T.spellevent[unit] = {unit, spellName, rank, target, castID, nil }
+end
+
+function T:UNIT_SPELLCAST_SENT(e,unit, spellName, rank, target, castID)
+ if not T.isEventUnit[unit] then
+ return
+ end
+ T.unit[unit].spellEventString = e
+ T.unit[unit].spellevent = {unit, spellName, rank, target, castID}
+end
+
+function T:UNIT_SPELLCAST (e, unit, spellName, rank, castID, spellID)
+ if not T.isEventUnit[unit] then
+ return
+ end
+ --name, subText, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible
+ local q = {UnitCastingInfo(unit)}
+ T.unit[unit].casting = q[1] and q or false
+ T.unit[unit].spellEventString = e
+ T.unit[unit].spellevent = {unit, spellName, rank, nil,castID, spellID }
+ print(e, unit)
+end
+
+function T:UNIT_CHANNEL(e, unit, spellName, rank, castID, spellID)
+ if not T.isEventUnit[unit] then
+ return
+ end
+ --name, subText, text, texture, startTime, endTime, isTradeSkill, notInterruptible
+ local q = {UnitChannelInfo(unit) }
+ T.unit[unit].channeling = q[1] and q or false
+ T.unit[unit].spellEventString = e
+ T.unit[unit].spellevent = {unit, spellName, rank, nil, castID, spellID }
+ print(e, unit)
+end
+
+T.UNIT_SPELLCAST_START = T.UNIT_SPELLCAST
+T.UNIT_SPELLCAST_STOP = T.UNIT_SPELLCAST
+T.UNIT_SPELLCAST_DELAYED = T.UNIT_SPELLCAST
+T.UNIT_SPELLCAST_INTERRUPTED = T.UNIT_SPELLCAST
+T.UNIT_SPELLCAST_FAILED = T.UNIT_SPELLCAST
+T.UNIT_SPELLCAST_SUCCEEDED = T.UNIT_SPELLCAST
+T.UNIT_SPELLCAST_CHANNEL_START = T.UNIT_CHANNEL
+T.UNIT_SPELLCAST_CHANNEL_UPDATE= T.UNIT_CHANNEL
+T.UNIT_SPELLCAST_CHANNEL_STOP= T.UNIT_CHANNEL
+
+local UnitExists, GetRealmName, UnitClassification, UnitClass, UnitIsFriend, UnitIsEnemy, UnitIsFeignDeath
+ = UnitExists, GetRealmName, UnitClassification, UnitClass, UnitIsFriend, UnitIsEnemy, UnitIsFeignDeath
+function T:UnitChanged(e, unit)
+ local u = T.unit[unit]
+ local exists = UnitExists(unit)
+ local realm
+ _G.print('Update', cText(' '..unit..' change:'), cText(unit), cText(exists and UnitName(unit)))
+
+ u.exists = exists
+ u.name, realm = UnitName(unit)
+ u.realm = realm or GetRealmName()
+ u.classification = UnitClassification(unit)
+ u.class = UnitClass(unit)
+ u.isFriendly = UnitIsFriend('player', unit)
+ u.isEnemy = UnitIsEnemy('player', unit)
+ u.isFeign = UnitIsFeignDeath(unit)
+ u.isNeutral = not(u.isHostile or u.isFriendly)
+
+ local castinfo, channelinfo = {UnitCastingInfo(unit)}, {UnitChannelInfo(unit)}
+ u.casting = (u.exists and castinfo[1]) and castinfo or false
+ u.channeling = (u.exists and channelinfo[1]) and channelinfo or false
+ u.isCasting = (u.casting or u.channeling) and true or false
+
+
+ for k,v in pairs(T.unit[unit]) do
+ _G.print('Update', cText(' -'), cText(k),'->', cText(v))
+ end
+end
+function T:PLAYER_TARGET_CHANGED(e)
+ T:UnitChanged(e, 'target')
+end
+function T:PLAYER_FOCUS_CHANGED(e)
+ T:UnitChanged(e, 'focus')
+end
+function T:UNIT_PET(e, unit,...)
+ if unit == 'player' then
+ print(e, unit, ...)
+ T:UnitChanged(e, 'pet')
+ end
+end
+
+local Turok_OnCombat = function(inCombat)
+ print(cText('* CombatToggle:'), cBool(inCombat))
+ PlaySoundFile(db['battle_noise'.. (inCombat and '_start' or '_end')])
+
+ for _, region in pairs(Tk.LibFog.animate_regions) do
+ if region.combatFade then
+ print(' |cFFFFFF00+|r', region:GetName())
+ region:UpdateAlpha(inCombat)
+ else
+ print(' |cFFFF4400-|r', region:GetName())
+ end
+ end
+end
+
+--- InCombatLockdown() isn't updated immediately, so we have to assume
+function T:PLAYER_REGEN_DISABLED(e,...)
+ T.inCombat = true
+ Turok_OnCombat(true)
+end
+function T:PLAYER_REGEN_ENABLED(e,...)
+ T.inCombat = nil
+ Turok_OnCombat(false)
+end
+
+-- GIST datas
+function T:GIST_InspectReady (event, guid, unit)
+ print('GIST barf', guid, unit)
+end
+
+function T:GIST_Update(event, guid, unit, info)
+
+ if info.class_id and info.global_spec_id and info.guid and info.lku then
+ --_G.print('GIST', 'Update', unit)
+ --_G.print('GIST',' class:', info.class_id, 'specid:', info.global_spec_id, 'guid:', info.guid)
+
+ self.units[info.guid] = info
+ self.unitsBySlot[info.lku] = info
+ end
+end
+
+-- todo: re-locate these
+
+T.PLAY_MOVIE = function (e, id)
+ MovieFrame:Hide()
+ T:Print('skipped a shitty movie', e, id)
+end
+T.CINEMATIC_START = function(...)
+ CinematicFrame_CancelCinematic()
+ T:Print('skipped a shitty cinematic', ...)
+end
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Turok.toc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Turok.toc Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,13 @@
+## Interface: 60200
+## Title: Turok - Dinosaur HUD
+## Notes: General UI supplement for the raiding hunter.
+## Author: Krakyn
+## Version: 1.0-@project-revision@
+## SavedVariables: TurokData
+## OptionalDeps: Ace3, LibGroupInSpeCT-1.1, LibSharedMedia-3.0
+## X-Category: Interface Enhancements, Hunter, Combat
+## X-Website: http://www.curse.com/addons/wow/turok
+## DefaultState: Enabled
+## LoadOnDemand: 0
+
+Turok.xml
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Turok.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Turok.xml Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/Turok_Config.lua
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/Turok_Config.lua Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,323 @@
+-- User: Krakyn
+-- Created: 12/19/2015 12:18 AM
+
+local _G = _G
+local T = LibStub("AceAddon-3.0"):GetAddon("Turok")
+local TL = 'Options'
+local mod = T:NewModule(TL)
+local LSM = LibStub("LibSharedMedia-3.0")
+local ConfigDialog = LibStub("AceConfigDialog-3.0")
+--@debug
+local print = function(...) _G.print(TL, ...) end
+local db
+
+local TITLE_FONT_COLOR = '|cFF88FF44'
+local INPUT_FONT_COLOR = '|cFFFFFF00'
+local STACK_COLOR1 = '|cFFFF8800'
+local STACK_COLOR2 = '|cFFFFFF00'
+local FONTVAR_COLOR = '|cFFFFAA44'
+local FRAMEVAR_COLOR = '|cFFFFFF44'
+local PARAMETER_COLOR = '|cFF9999FF'
+local STATE_COLOR = '|cFFFF99FF'
+
+function mod:OnInitialize()
+ T:Print("config mod init")
+end
+
+function mod:OnEnable()
+ T:Print("config mod enable")
+ db = T.db
+ LibStub("AceConfig-3.0"):RegisterOptionsTable('Turok', T.MakeOptions(), {"turok"})
+ T.configDialog = ConfigDialog:AddToBlizOptions("Turok")
+end
+
+local optL = {
+ background_color = 'Background color',
+ foreground_color = 'Foreground color',
+ width = FRAMEVAR_COLOR..'Width',
+ height = FRAMEVAR_COLOR..'Height',
+ alpha = FRAMEVAR_COLOR..'Alpha',
+ alpha_ooc = STATE_COLOR..'Alpha (OOC)',
+ label_strata = FONTVAR_COLOR..'Text Strata',
+ label_font = FONTVAR_COLOR..'Font',
+ label_size = FONTVAR_COLOR..'Font Size',
+ label_inset = FONTVAR_COLOR..'Text Insets',
+ foreground_blend = 'Foreground Blend Mode',
+ background_blend = 'Background Blend Mode',
+ isStatic = PARAMETER_COLOR..'Static Bar',
+ duration = PARAMETER_COLOR..'Duration',
+ isIcon = PARAMETER_COLOR..'Icon Only',
+}
+
+local anchors = {
+ ['CENTER'] = 'Center',
+ ['TOPLEFT'] = 'Top Left',
+ ['TOP'] = 'Top',
+ ['TOPRIGHT'] = 'Top Right',
+ ['RIGHT'] = 'Right',
+ ['BOTTOMRIGHT'] = 'Bottom Right',
+ ['BOTTOM'] = 'Bottom',
+ ['BOTTOMLEFT'] = 'Bottom Left',
+ ['LEFT'] = 'Left'
+}
+
+local frames = {
+ ['UIParent'] = 'UIParent',
+ ['TkPowerBar'] = 'Power Bar',
+ ['TekplayerCastBar'] = 'Player Castbar',
+ ['TektargetCastBar'] = 'Target Castbar',
+ ['TekfocusCastBar'] = 'Focus Castbar',
+ ['TekpetCastBar'] = 'Pet Castbar'
+}
+
+local range = {
+ ['alpha'] = {0, 1, .01},
+ ['alpha_ooc'] = {0, 1, .01},
+ ['label_size'] = {1, 72, 1},
+ ['label_inset'] = {-30, 30, 1},
+ ['width'] = {0, 1200, 1},
+ ['height'] = {0, 1200, 1},
+ ['raidbuff_width'] = {0, 1200, 1},
+ ['raidbuff_height'] = {0, 1200, 1},
+ ['duration'] = {0, 6000, 0.1 },
+ ['glow_size'] = {0, 30, 1},
+ ['spark_size'] = {0, 30, 1},
+}
+
+local opt_order = {
+ ['width'] = 10,
+ ['height'] = 15,
+ ['anchor'] = 20,
+ ['anchorTo'] = 25,
+ ['parent'] = 30,
+
+ ['alpha'] = 110,
+ ['alpha_ooc'] = 115,
+ ['label_size'] = 200,
+ ['label_inset'] = 210,
+ ['label_font'] = 220,
+
+ ['background_texture'] = 300,
+ ['background_color'] = 320,
+ ['foreground_texture'] = 350,
+ ['foreground_color'] = 370,
+}
+local opt_width = {
+
+}
+
+-- options dialog root
+T.myopts = {
+ type = 'group',
+ name = TITLE_FONT_COLOR..'Turok|r',
+ desc = 'Dinosaur HUD',
+ handler = T,
+ set = function(info,value, ...)
+ local db = T.db
+ local index = db
+ local traversal = 'db'
+ for i = 1, #info-1 do
+ if type(index[info[i]]) == 'table' then
+ --print('|cFFFF0000SET|r:', i, info[i])
+ traversal = traversal .. '.' .. info[i]
+ index = index[info[i]]
+ end
+
+ end
+ --print('|cFFFF0000SET|r: hops=',#info,'index=', traversal, ' key=', info[#info])
+
+ if type(value) ~= 'boolean' and select('#',...) == 3 then
+ --print('|cFFFF0000SET|r', 'multi-args', select('#',...))
+ value = {value, ... }
+ else
+ --print('|cFFFF0000SET|r', 'single-arg', value)
+ end
+
+ index[info[#info]] = value
+ end,
+ get = function(info)
+ local db = T.db
+ local value = db[info[1]]
+ local traversal = info[1]
+ if #info > 1 then
+ for i=2, #info do
+ traversal = traversal .. '.' .. info[i]
+ if value[info[i]] ~= nil then
+ value = value[info[i]]
+ end
+ end
+ end
+ --print('|cFFFF00FFGET|r: hops=', #info, 'index=', traversal, 'value=', value)
+
+ if type(value) == 'table' then
+ return unpack(value)
+ end
+ return value
+ end,
+}
+
+function T:MakeOptions(dbtable, index, name, prefix)
+ -- index = option insertion destination
+ -- parent = nesting point
+ local parent
+ if not (index and dbtable) then
+ dbtable = db
+ name = 'root'
+ prefix = ''
+ parent = T.myopts
+ parent.args = {
+ main = {
+ order = 1,
+ type = 'group',
+ name = 'Global',
+ get = function(info) print('db.'..info[#info]..' get')
+ if type(db[info[#info]]) == 'table' then
+ print('getting color data', unpack(db[info[#info]]))
+ return unpack(db[info[#info]])
+ end
+ return db[info[#info]]
+ end,
+ set = function(info, value, ...) print('db.'..info[#info]..' SET')
+ if select('#',...) == 3 then
+ print('receiving color data', value, ...)
+ value = {value, ...}
+ end
+ db[info[#info]] = value
+ end,
+ args = {},
+ }}
+ index = parent.args.main
+ print(STACK_COLOR1..'using TurokData as index')
+ else
+ index.type = 'group'
+ index.name = name
+ index.args = {}
+ parent = index
+ end
+
+ local order = 2
+ for k, v in pairs(dbtable) do
+ k = tostring(k)
+ local kt = INPUT_FONT_COLOR .. (optL[k] or k)
+ local nested = false
+ --@debug@
+ print(STACK_COLOR2..prefix..'.'..STACK_COLOR1..k..'|r =',v)--@debug@
+ if type(v) == 'table' then
+ if table.getn(v) == 4 then
+ index.args[k] = {
+ name = kt,
+ type = 'color',
+ hasAlpha = true,
+ --@debug@
+ print('color_pack=',unpack(v))--@debug@
+ }
+ else
+ parent.args[k] = {}
+ nested = true
+ T:MakeOptions(v, parent.args[k], k, prefix .. '.' .. name)
+ end
+ elseif type(v) == 'string' then
+ if string.match(k, "_font") then
+ local font_list = {}
+ for k, v in pairs(LSM:HashTable('font')) do
+ font_list[v] = k
+ end
+ index.args[k] = {
+ name = kt,
+ type = 'select',
+ values = font_list
+ }
+ elseif k:match('anchor$') or k:match('_point$') or k:match('anchorTo') then
+
+ index.args[k] = {
+ name = kt,
+ type = 'select',
+ values = anchors
+ }
+
+ elseif k:match('justifyH$') then
+ index.args[k] = {
+ name = kt,
+ type = 'select',
+ values = {
+ ['LEFT'] = 'Left',
+ ['CENTER'] = 'Center',
+ ['RIGHT'] = 'Right'
+ }
+ }
+
+ elseif k:match('strata$') then
+ index.args[k] = {
+ name = kt,
+ type = 'select',
+ values = {
+ BACKGROUND = 'BACKGROUND (clickthrough)',
+ LOW = 'LOW',
+ MEDIUM = 'MEDIUM',
+ HIGH = 'HIGH',
+ DIALOG = 'DIALOG',
+ FULLSCREEN = 'FULLSCREEN',
+ FULLSCREEN_DIALOG = 'FULLSCREEN_DIALOG',
+ TOOLTIP = 'TOOLTIP (clickthrough)',
+ }
+ }
+
+ elseif k:match('outline$') then
+ index.args[k] = {
+ name = kt,
+ type = 'select',
+ values = {
+ ['NONE'] = 'NONE',
+ ['OUTLINE'] = 'OUTLINE',
+ ['THICKOUTLINE'] = 'THICKOUTLINE'
+ }
+ }
+ elseif k:match('parent') then
+ index.args[k] = {
+ name = kt,
+ type = 'select',
+ values = frames
+ }
+ else
+
+ index.args[k] = {
+ name = kt,
+ type = 'input',
+ width = 'full',
+ }
+ end
+ elseif type(v) == 'number' then
+
+ if not range[k] then
+ range[k] = {0,150,1 }
+ print('missing range values for', k)
+ end
+
+ index.args[k] ={
+ name = kt,
+ type = 'range',
+ min = range[k][1],
+ max = range[k][2],
+ softMax = range[k][2],
+ step = range[k][3],
+ bigStep = range[k][3],
+ }
+ elseif type(v) == 'boolean' then
+
+ index.args[k] = {
+ name = kt,
+ type = 'toggle',
+ }
+ end
+ if nested then
+ parent.args[k].order = order + (opt_order[k] and opt_order[k] or 0)
+ elseif index.args[k] then
+ index.args[k].order = order + (opt_order[k] and opt_order[k] or 0)
+ print(' '..kt..' order = '..index.args[k].order)
+ else
+ print('|cFF99FFFFSkipped|r', kt)
+ end
+ end
+
+ return parent
+end
diff -r 8a9a6637f082 -r a9b8b0866ece Turok/readme.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok/readme.txt Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,42 @@
+Turok: Dinosaur HUD
+
+Hardcode of various WeakAura configurations. This is created as a personal learning challenge, so it may or may not be faster than the actual jumble of WeakAuras because that addon is written very well.
+
+Project Goals:
+
+ - Focus bar with dynamic coloring and prediction lines based on talent effects
+ - Unit cast bars that are thematically linked with everything else
+ - Dynamically arranged tracking icons and sliders cooldown/aura information
+ - Quality-of-life alerts for Lone Wolf and Aspect of the Pack
+
+Coding Conventions:
+
+ Although AceAddon modules are used, the addon is not truly modular.
+ The structure provides simple control over the internal loading sequence.
+ So if needed, "module" enables can be scattered over several post-load frames to make in-combat /reload less hazardous.
+
+ SavedVars data is arranged in a non-propagating hierarchical metatable.
+ Accessing a deeply-nested member will traverse its parents until one of them contains data.
+ The only exception to this is on lazy read expressions, such as:
+
+ > if (childtable.unsetvar) then
+
+ This will always yield a false, whether or not a value is assigned in its parents.
+ To check for hierarchical flag variables, you can compare the index against nil, like so:
+
+ > if (childtable.unsetvar ~= nil) then
+
+ The operation will trigger __index and a value from the hierarchy will be presented.
+ Any positive flag state will be copied down when direct assignment is used.
+ To get a useful flag state, you need to run the first logical expression within a ternary idiom:
+
+ > childflag = (childtable.unsetvar) and true or nil -- pulls the true flag value
+ > parentflag = childtable.unsetvar -- pulls any non-nil value
+
+ Another thing to note is hierarchical values are not assigned downstream.
+ If an empty child value is indexed, it will always traverse up the tree.
+ As a result, values consulted frequently will be computationally taxing.
+ These should be copied into a local variable and read from that instead.
+ Then, when an event that might change the value is detected, the local variable is updated instead.
+ From a performance standpoint, the effects are net-positive, since assignments potentially cover dozens of keys.
+ The memory footprint also isn't much different, while the assignment operations are carried out in spaced intervals.
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece Turok_Config/Turok_Config.toc
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Turok_Config/Turok_Config.toc Sun Feb 21 08:32:53 2016 -0500
@@ -0,0 +1,9 @@
+## Interface: 60200
+## Title: Turok Options
+## Notes: Option Panel
+## Author: Krakyn
+## Version: 1.0
+## Dependencies: Turok
+## LoadOnDemand: 1
+
+..\Turok\Turok_Config.lua
\ No newline at end of file
diff -r 8a9a6637f082 -r a9b8b0866ece readme.txt
--- a/readme.txt Tue Dec 15 10:10:22 2015 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,11 +0,0 @@
-Turok: Dinosaur HUD
-
-Hardcode of various WeakAura configurations. This is created as a personal learning challenge, so it may or may not be faster than the actual jumble of WeakAuras because that addon is written very well.
-
-Project Goals:
-
- - Focus bar with dynamic coloring and prediction lines based on talent effects
- - Unit cast bars that are thematically linked with everything else
- - Dynamically arranged tracking icons and sliders cooldown/aura information
- - Quality-of-life alerts for Lone Wolf and Aspect of the Pack
-