diff --git a/.pkgmeta b/.pkgmeta
new file mode 100644
index 00000000..b5c3db68
--- /dev/null
+++ b/.pkgmeta
@@ -0,0 +1,10 @@
+move-folders:
+ Details/plugins/Details_DmgRank: Details_DmgRank
+ Details/plugins/Details_EncounterDetails: Details_EncounterDetails
+ Details/plugins/Details_ErrorReport: Details_ErrorReport
+ Details/plugins/Details_RaidInfo-ThroneOfThunder: Details_RaidInfo-ThroneOfThunder
+ Details/plugins/Details_SaveData: Details_SaveData
+ Details/plugins/Details_SpellDetails: Details_SpellDetails
+ Details/plugins/Details_TimeAttack: Details_TimeAttack
+ Details/plugins/Details_TinyThreat: Details_TinyThreat
+ Details/plugins/Details_Vanguard: Details_Vanguard
\ No newline at end of file
diff --git a/Details.toc b/Details.toc
new file mode 100644
index 00000000..1e6fae12
--- /dev/null
+++ b/Details.toc
@@ -0,0 +1,92 @@
+## Interface: 50300
+## Title: Details
+## Notes: Computes detailed infos about combats.
+## SavedVariables: _detalhes_global
+## SavedVariablesPerCharacter: _detalhes_database
+## OptionalDeps: Ace3, LibSharedMedia-3.0, LibBossIDs-1.0, LibGraph-2.0, !ClassColors
+
+#@no-lib-strip@
+embeds.xml
+#@end-no-lib-strip@
+
+locales\Details-ptBR.lua
+locales\Details-enUS.lua
+
+boot.lua
+core\util.lua
+
+functions\boss.lua
+functions\spells.lua
+functions\events.lua
+functions\classes.lua
+functions\buff.lua
+functions\link.lua
+functions\spellcache.lua
+functions\attributes.lua
+functions\savedata.lua
+functions\slash.lua
+functions\playerclass.lua
+functions\timedata.lua
+functions\report.lua
+
+core\timemachine.lua
+
+framework\framework.lua
+framework\colors.lua
+framework\label.lua
+framework\slider.lua
+framework\picture.lua
+framework\help.lua
+framework\cooltip.xml
+framework\textentry.xml
+framework\panel.xml
+framework\normal_bar.xml
+framework\split_bar.xml
+framework\button.xml
+framework\dropdown.xml
+framework\pictureedit.lua
+
+gumps\anime.lua
+gumps\anime.xml
+gumps\janela_copy.lua
+gumps\janela_options.lua
+gumps\janela_info.lua
+gumps\janela_report.lua
+gumps\janela_principal.lua
+gumps\janela_custom.lua
+gumps\fw_mods.lua
+gumps\switch.lua
+gumps\toolbar_button.xml
+
+classes\classe_error.lua
+classes\classe_combate.lua
+classes\classe_damage.lua
+classes\classe_damage_habilidade.lua
+classes\classe_heal.lua
+classes\classe_heal_habilidade.lua
+classes\classe_energy.lua
+classes\classe_energy_habilidade.lua
+classes\classe_others.lua
+classes\classe_others_habilidade.lua
+classes\classe_instancia.lua
+classes\classe_target.lua
+classes\classe_custom.lua
+
+core\control.lua
+
+classes\container_combatentes.lua
+classes\container_habilidades.lua
+classes\container_historico.lua
+classes\container_pets.lua
+
+core\plugins.lua
+core\plugins_toolbar.lua
+core\plugins_statusbar.lua
+core\plugins_raid.lua
+core\plugins_solo.lua
+core\gears.lua
+core\windows.lua
+core\meta.lua
+core\parser.lua
+
+startup.lua
\ No newline at end of file
diff --git a/Details.xml b/Details.xml
new file mode 100644
index 00000000..2fff79f6
--- /dev/null
+++ b/Details.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ self:RegisterEvent ("ADDON_LOADED");
+ self:RegisterEvent ("PLAYER_LOGOUT");
+
+
+ _detalhes.OnEvent (self, event, ...);
+
+
+
+
diff --git a/Libs/AceAddon-3.0/AceAddon-3.0.lua b/Libs/AceAddon-3.0/AceAddon-3.0.lua
new file mode 100644
index 00000000..70369317
--- /dev/null
+++ b/Libs/AceAddon-3.0/AceAddon-3.0.lua
@@ -0,0 +1,659 @@
+--- **AceAddon-3.0** provides a template for creating addon objects.
+-- It'll provide you with a set of callback functions that allow you to simplify the loading
+-- process of your addon.\\
+-- Callbacks provided are:\\
+-- * **OnInitialize**, which is called directly after the addon is fully loaded.
+-- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
+-- * **OnDisable**, which is only called when your addon is manually being disabled.
+-- @usage
+-- -- A small (but complete) addon, that doesn't do anything,
+-- -- but shows usage of the callbacks.
+-- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+--
+-- function MyAddon:OnInitialize()
+-- -- do init tasks here, like loading the Saved Variables,
+-- -- or setting up slash commands.
+-- end
+--
+-- function MyAddon:OnEnable()
+-- -- Do more initialization here, that really enables the use of your addon.
+-- -- Register Events, Hook functions, Create Frames, Get information from
+-- -- the game that wasn't available in OnInitialize
+-- end
+--
+-- function MyAddon:OnDisable()
+-- -- Unhook, Unregister Events, Hide frames that you created.
+-- -- You would probably only use an OnDisable if you want to
+-- -- build a "standby" mode, or be able to toggle modules on/off.
+-- end
+-- @class file
+-- @name AceAddon-3.0.lua
+-- @release $Id: AceAddon-3.0.lua 1036 2011-08-16 22:45:05Z nevcairiel $
+
+local MAJOR, MINOR = "AceAddon-3.0", 11
+local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceAddon then return end -- No Upgrade needed.
+
+AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
+AceAddon.addons = AceAddon.addons or {} -- addons in general
+AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
+AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
+AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
+AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
+
+-- Lua APIs
+local tinsert, tconcat, tremove = table.insert, table.concat, table.remove
+local fmt, tostring = string.format, tostring
+local select, pairs, next, type, unpack = select, pairs, next, type, unpack
+local loadstring, assert, error = loadstring, assert, error
+local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub, IsLoggedIn, geterrorhandler
+
+--[[
+ xpcall safecall implementation
+]]
+local xpcall = xpcall
+
+local function errorhandler(err)
+ return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+ local code = [[
+ local xpcall, eh = ...
+ local method, ARGS
+ local function call() return method(ARGS) end
+
+ local function dispatch(func, ...)
+ method = func
+ if not method then return end
+ ARGS = ...
+ return xpcall(call, eh)
+ end
+
+ return dispatch
+ ]]
+
+ local ARGS = {}
+ for i = 1, argCount do ARGS[i] = "arg"..i end
+ code = code:gsub("ARGS", tconcat(ARGS, ", "))
+ return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {__index=function(self, argCount)
+ local dispatcher = CreateDispatcher(argCount)
+ rawset(self, argCount, dispatcher)
+ return dispatcher
+end})
+Dispatchers[0] = function(func)
+ return xpcall(func, errorhandler)
+end
+
+local function safecall(func, ...)
+ -- we check to see if the func is passed is actually a function here and don't error when it isn't
+ -- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
+ -- present execution should continue without hinderance
+ if type(func) == "function" then
+ return Dispatchers[select('#', ...)](func, ...)
+ end
+end
+
+-- local functions that will be implemented further down
+local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
+
+-- used in the addon metatable
+local function addontostring( self ) return self.name end
+
+--- Create a new AceAddon-3.0 addon.
+-- Any libraries you specified will be embeded, and the addon will be scheduled for
+-- its OnInitialize and OnEnable callbacks.
+-- The final addon object, with all libraries embeded, will be returned.
+-- @paramsig [object ,]name[, lib, ...]
+-- @param object Table to use as a base for the addon (optional)
+-- @param name Name of the addon object to create
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create a simple addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
+--
+-- -- Create a Addon object based on the table of a frame
+-- local MyFrame = CreateFrame("Frame")
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
+function AceAddon:NewAddon(objectorname, ...)
+ local object,name
+ local i=1
+ if type(objectorname)=="table" then
+ object=objectorname
+ name=...
+ i=2
+ else
+ name=objectorname
+ end
+ if type(name)~="string" then
+ error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
+ end
+ if self.addons[name] then
+ error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
+ end
+
+ object = object or {}
+ object.name = name
+
+ local addonmeta = {}
+ local oldmeta = getmetatable(object)
+ if oldmeta then
+ for k, v in pairs(oldmeta) do addonmeta[k] = v end
+ end
+ addonmeta.__tostring = addontostring
+
+ setmetatable( object, addonmeta )
+ self.addons[name] = object
+ object.modules = {}
+ object.orderedModules = {}
+ object.defaultModuleLibraries = {}
+ Embed( object ) -- embed NewModule, GetModule methods
+ self:EmbedLibraries(object, select(i,...))
+
+ -- add to queue of addons to be initialized upon ADDON_LOADED
+ tinsert(self.initializequeue, object)
+ return object
+end
+
+
+--- Get the addon object by its name from the internal AceAddon registry.
+-- Throws an error if the addon object cannot be found (except if silent is set).
+-- @param name unique name of the addon object
+-- @param silent if true, the addon is optional, silently return nil if its not found
+-- @usage
+-- -- Get the Addon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+function AceAddon:GetAddon(name, silent)
+ if not silent and not self.addons[name] then
+ error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
+ end
+ return self.addons[name]
+end
+
+-- - Embed a list of libraries into the specified addon.
+-- This function will try to embed all of the listed libraries into the addon
+-- and error if a single one fails.
+--
+-- **Note:** This function is for internal use by :NewAddon/:NewModule
+-- @paramsig addon, [lib, ...]
+-- @param addon addon object to embed the libs in
+-- @param lib List of libraries to embed into the addon
+function AceAddon:EmbedLibraries(addon, ...)
+ for i=1,select("#", ... ) do
+ local libname = select(i, ...)
+ self:EmbedLibrary(addon, libname, false, 4)
+ end
+end
+
+-- - Embed a library into the addon object.
+-- This function will check if the specified library is registered with LibStub
+-- and if it has a :Embed function to call. It'll error if any of those conditions
+-- fails.
+--
+-- **Note:** This function is for internal use by :EmbedLibraries
+-- @paramsig addon, libname[, silent[, offset]]
+-- @param addon addon object to embed the library in
+-- @param libname name of the library to embed
+-- @param silent marks an embed to fail silently if the library doesn't exist (optional)
+-- @param offset will push the error messages back to said offset, defaults to 2 (optional)
+function AceAddon:EmbedLibrary(addon, libname, silent, offset)
+ local lib = LibStub:GetLibrary(libname, true)
+ if not lib and not silent then
+ error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
+ elseif lib and type(lib.Embed) == "function" then
+ lib:Embed(addon)
+ tinsert(self.embeds[addon], libname)
+ return true
+ elseif lib then
+ error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
+ end
+end
+
+--- Return the specified module from an addon object.
+-- Throws an error if the addon object cannot be found (except if silent is set)
+-- @name //addon//:GetModule
+-- @paramsig name[, silent]
+-- @param name unique name of the module
+-- @param silent if true, the module is optional, silently return nil if its not found (optional)
+-- @usage
+-- -- Get the Addon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- -- Get the Module
+-- MyModule = MyAddon:GetModule("MyModule")
+function GetModule(self, name, silent)
+ if not self.modules[name] and not silent then
+ error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
+ end
+ return self.modules[name]
+end
+
+local function IsModuleTrue(self) return true end
+
+--- Create a new module for the addon.
+-- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
+-- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
+-- an addon object.
+-- @name //addon//:NewModule
+-- @paramsig name[, prototype|lib[, lib, ...]]
+-- @param name unique name of the module
+-- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create a module with some embeded libraries
+-- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
+--
+-- -- Create a module with a prototype
+-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
+-- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
+function NewModule(self, name, prototype, ...)
+ if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
+ if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end
+
+ if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
+
+ -- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
+ -- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
+ local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
+
+ module.IsModule = IsModuleTrue
+ module:SetEnabledState(self.defaultModuleState)
+ module.moduleName = name
+
+ if type(prototype) == "string" then
+ AceAddon:EmbedLibraries(module, prototype, ...)
+ else
+ AceAddon:EmbedLibraries(module, ...)
+ end
+ AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
+
+ if not prototype or type(prototype) == "string" then
+ prototype = self.defaultModulePrototype or nil
+ end
+
+ if type(prototype) == "table" then
+ local mt = getmetatable(module)
+ mt.__index = prototype
+ setmetatable(module, mt) -- More of a Base class type feel.
+ end
+
+ safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
+ self.modules[name] = module
+ tinsert(self.orderedModules, module)
+
+ return module
+end
+
+--- Returns the real name of the addon or module, without any prefix.
+-- @name //addon//:GetName
+-- @paramsig
+-- @usage
+-- print(MyAddon:GetName())
+-- -- prints "MyAddon"
+function GetName(self)
+ return self.moduleName or self.name
+end
+
+--- Enables the Addon, if possible, return true or false depending on success.
+-- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
+-- and enabling all modules of the addon (unless explicitly disabled).\\
+-- :Enable() also sets the internal `enableState` variable to true
+-- @name //addon//:Enable
+-- @paramsig
+-- @usage
+-- -- Enable MyModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Enable()
+function Enable(self)
+ self:SetEnabledState(true)
+ return AceAddon:EnableAddon(self)
+end
+
+--- Disables the Addon, if possible, return true or false depending on success.
+-- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
+-- and disabling all modules of the addon.\\
+-- :Disable() also sets the internal `enableState` variable to false
+-- @name //addon//:Disable
+-- @paramsig
+-- @usage
+-- -- Disable MyAddon
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:Disable()
+function Disable(self)
+ self:SetEnabledState(false)
+ return AceAddon:DisableAddon(self)
+end
+
+--- Enables the Module, if possible, return true or false depending on success.
+-- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
+-- @name //addon//:EnableModule
+-- @paramsig name
+-- @usage
+-- -- Enable MyModule using :GetModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Enable()
+--
+-- -- Enable MyModule using the short-hand
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:EnableModule("MyModule")
+function EnableModule(self, name)
+ local module = self:GetModule( name )
+ return module:Enable()
+end
+
+--- Disables the Module, if possible, return true or false depending on success.
+-- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
+-- @name //addon//:DisableModule
+-- @paramsig name
+-- @usage
+-- -- Disable MyModule using :GetModule
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyModule = MyAddon:GetModule("MyModule")
+-- MyModule:Disable()
+--
+-- -- Disable MyModule using the short-hand
+-- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
+-- MyAddon:DisableModule("MyModule")
+function DisableModule(self, name)
+ local module = self:GetModule( name )
+ return module:Disable()
+end
+
+--- Set the default libraries to be mixed into all modules created by this object.
+-- Note that you can only change the default module libraries before any module is created.
+-- @name //addon//:SetDefaultModuleLibraries
+-- @paramsig lib[, lib, ...]
+-- @param lib List of libraries to embed into the addon
+-- @usage
+-- -- Create the addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+-- -- Configure default libraries for modules (all modules need AceEvent-3.0)
+-- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
+-- -- Create a module
+-- MyModule = MyAddon:NewModule("MyModule")
+function SetDefaultModuleLibraries(self, ...)
+ if next(self.modules) then
+ error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
+ end
+ self.defaultModuleLibraries = {...}
+end
+
+--- Set the default state in which new modules are being created.
+-- Note that you can only change the default state before any module is created.
+-- @name //addon//:SetDefaultModuleState
+-- @paramsig state
+-- @param state Default state for new modules, true for enabled, false for disabled
+-- @usage
+-- -- Create the addon object
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
+-- -- Set the default state to "disabled"
+-- MyAddon:SetDefaultModuleState(false)
+-- -- Create a module and explicilty enable it
+-- MyModule = MyAddon:NewModule("MyModule")
+-- MyModule:Enable()
+function SetDefaultModuleState(self, state)
+ if next(self.modules) then
+ error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
+ end
+ self.defaultModuleState = state
+end
+
+--- Set the default prototype to use for new modules on creation.
+-- Note that you can only change the default prototype before any module is created.
+-- @name //addon//:SetDefaultModulePrototype
+-- @paramsig prototype
+-- @param prototype Default prototype for the new modules (table)
+-- @usage
+-- -- Define a prototype
+-- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
+-- -- Set the default prototype
+-- MyAddon:SetDefaultModulePrototype(prototype)
+-- -- Create a module and explicitly Enable it
+-- MyModule = MyAddon:NewModule("MyModule")
+-- MyModule:Enable()
+-- -- should print "OnEnable called!" now
+-- @see NewModule
+function SetDefaultModulePrototype(self, prototype)
+ if next(self.modules) then
+ error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
+ end
+ if type(prototype) ~= "table" then
+ error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
+ end
+ self.defaultModulePrototype = prototype
+end
+
+--- Set the state of an addon or module
+-- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
+-- @name //addon//:SetEnabledState
+-- @paramsig state
+-- @param state the state of an addon or module (enabled=true, disabled=false)
+function SetEnabledState(self, state)
+ self.enabledState = state
+end
+
+
+--- Return an iterator of all modules associated to the addon.
+-- @name //addon//:IterateModules
+-- @paramsig
+-- @usage
+-- -- Enable all modules
+-- for name, module in MyAddon:IterateModules() do
+-- module:Enable()
+-- end
+local function IterateModules(self) return pairs(self.modules) end
+
+-- Returns an iterator of all embeds in the addon
+-- @name //addon//:IterateEmbeds
+-- @paramsig
+local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
+
+--- Query the enabledState of an addon.
+-- @name //addon//:IsEnabled
+-- @paramsig
+-- @usage
+-- if MyAddon:IsEnabled() then
+-- MyAddon:Disable()
+-- end
+local function IsEnabled(self) return self.enabledState end
+local mixins = {
+ NewModule = NewModule,
+ GetModule = GetModule,
+ Enable = Enable,
+ Disable = Disable,
+ EnableModule = EnableModule,
+ DisableModule = DisableModule,
+ IsEnabled = IsEnabled,
+ SetDefaultModuleLibraries = SetDefaultModuleLibraries,
+ SetDefaultModuleState = SetDefaultModuleState,
+ SetDefaultModulePrototype = SetDefaultModulePrototype,
+ SetEnabledState = SetEnabledState,
+ IterateModules = IterateModules,
+ IterateEmbeds = IterateEmbeds,
+ GetName = GetName,
+}
+local function IsModule(self) return false end
+local pmixins = {
+ defaultModuleState = true,
+ enabledState = true,
+ IsModule = IsModule,
+}
+-- Embed( target )
+-- target (object) - target object to embed aceaddon in
+--
+-- this is a local function specifically since it's meant to be only called internally
+function Embed(target, skipPMixins)
+ for k, v in pairs(mixins) do
+ target[k] = v
+ end
+ if not skipPMixins then
+ for k, v in pairs(pmixins) do
+ target[k] = target[k] or v
+ end
+ end
+end
+
+
+-- - Initialize the addon after creation.
+-- This function is only used internally during the ADDON_LOADED event
+-- It will call the **OnInitialize** function on the addon object (if present),
+-- and the **OnEmbedInitialize** function on all embeded libraries.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- @param addon addon object to intialize
+function AceAddon:InitializeAddon(addon)
+ safecall(addon.OnInitialize, addon)
+
+ local embeds = self.embeds[addon]
+ for i = 1, #embeds do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
+ end
+
+ -- we don't call InitializeAddon on modules specifically, this is handled
+ -- from the event handler and only done _once_
+end
+
+-- - Enable the addon after creation.
+-- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
+-- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
+-- It will call the **OnEnable** function on the addon object (if present),
+-- and the **OnEmbedEnable** function on all embeded libraries.\\
+-- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- Use :Enable on the addon itself instead.
+-- @param addon addon object to enable
+function AceAddon:EnableAddon(addon)
+ if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
+ if self.statuses[addon.name] or not addon.enabledState then return false end
+
+ -- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
+ self.statuses[addon.name] = true
+
+ safecall(addon.OnEnable, addon)
+
+ -- make sure we're still enabled before continueing
+ if self.statuses[addon.name] then
+ local embeds = self.embeds[addon]
+ for i = 1, #embeds do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedEnable, lib, addon) end
+ end
+
+ -- enable possible modules.
+ local modules = addon.orderedModules
+ for i = 1, #modules do
+ self:EnableAddon(modules[i])
+ end
+ end
+ return self.statuses[addon.name] -- return true if we're disabled
+end
+
+-- - Disable the addon
+-- Note: This function is only used internally.
+-- It will call the **OnDisable** function on the addon object (if present),
+-- and the **OnEmbedDisable** function on all embeded libraries.\\
+-- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
+--
+-- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
+-- Use :Disable on the addon itself instead.
+-- @param addon addon object to enable
+function AceAddon:DisableAddon(addon)
+ if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
+ if not self.statuses[addon.name] then return false end
+
+ -- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
+ self.statuses[addon.name] = false
+
+ safecall( addon.OnDisable, addon )
+
+ -- make sure we're still disabling...
+ if not self.statuses[addon.name] then
+ local embeds = self.embeds[addon]
+ for i = 1, #embeds do
+ local lib = LibStub:GetLibrary(embeds[i], true)
+ if lib then safecall(lib.OnEmbedDisable, lib, addon) end
+ end
+ -- disable possible modules.
+ local modules = addon.orderedModules
+ for i = 1, #modules do
+ self:DisableAddon(modules[i])
+ end
+ end
+
+ return not self.statuses[addon.name] -- return true if we're disabled
+end
+
+--- Get an iterator over all registered addons.
+-- @usage
+-- -- Print a list of all installed AceAddon's
+-- for name, addon in AceAddon:IterateAddons() do
+-- print("Addon: " .. name)
+-- end
+function AceAddon:IterateAddons() return pairs(self.addons) end
+
+--- Get an iterator over the internal status registry.
+-- @usage
+-- -- Print a list of all enabled addons
+-- for name, status in AceAddon:IterateAddonStatus() do
+-- if status then
+-- print("EnabledAddon: " .. name)
+-- end
+-- end
+function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
+
+-- Following Iterators are deprecated, and their addon specific versions should be used
+-- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
+function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
+function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
+
+-- Event Handling
+local function onEvent(this, event, arg1)
+ -- 2011-08-17 nevcairiel - ignore the load event of Blizzard_DebugTools, so a potential startup error isn't swallowed up
+ if (event == "ADDON_LOADED" and arg1 ~= "Blizzard_DebugTools") or event == "PLAYER_LOGIN" then
+ -- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
+ while(#AceAddon.initializequeue > 0) do
+ local addon = tremove(AceAddon.initializequeue, 1)
+ -- this might be an issue with recursion - TODO: validate
+ if event == "ADDON_LOADED" then addon.baseName = arg1 end
+ AceAddon:InitializeAddon(addon)
+ tinsert(AceAddon.enablequeue, addon)
+ end
+
+ if IsLoggedIn() then
+ while(#AceAddon.enablequeue > 0) do
+ local addon = tremove(AceAddon.enablequeue, 1)
+ AceAddon:EnableAddon(addon)
+ end
+ end
+ end
+end
+
+AceAddon.frame:RegisterEvent("ADDON_LOADED")
+AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
+AceAddon.frame:SetScript("OnEvent", onEvent)
+
+-- upgrade embeded
+for name, addon in pairs(AceAddon.addons) do
+ Embed(addon, true)
+end
+
+-- 2010-10-27 nevcairiel - add new "orderedModules" table
+if oldminor and oldminor < 10 then
+ for name, addon in pairs(AceAddon.addons) do
+ addon.orderedModules = {}
+ for module_name, module in pairs(addon.modules) do
+ tinsert(addon.orderedModules, module)
+ end
+ end
+end
diff --git a/Libs/AceAddon-3.0/AceAddon-3.0.xml b/Libs/AceAddon-3.0/AceAddon-3.0.xml
new file mode 100644
index 00000000..17c568c9
--- /dev/null
+++ b/Libs/AceAddon-3.0/AceAddon-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Libs/AceComm-3.0/AceComm-3.0.lua b/Libs/AceComm-3.0/AceComm-3.0.lua
new file mode 100644
index 00000000..b4763a33
--- /dev/null
+++ b/Libs/AceComm-3.0/AceComm-3.0.lua
@@ -0,0 +1,382 @@
+--- **AceComm-3.0** allows you to send messages of unlimited length over the addon comm channels.
+-- It'll automatically split the messages into multiple parts and rebuild them on the receiving end.\\
+-- **ChatThrottleLib** is of course being used to avoid being disconnected by the server.
+--
+-- **AceComm-3.0** can be embeded into your addon, either explicitly by calling AceComm:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceComm itself.\\
+-- It is recommended to embed AceComm, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceComm.
+-- @class file
+-- @name AceComm-3.0
+-- @release $Id: AceComm-3.0.lua 1019 2011-03-27 12:08:33Z mikk $
+
+--[[ AceComm-3.0
+
+TODO: Time out old data rotting around from dead senders? Not a HUGE deal since the number of possible sender names is somewhat limited.
+
+]]
+
+local MAJOR, MINOR = "AceComm-3.0", 7
+
+local AceComm,oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceComm then return end
+
+local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
+local CTL = assert(ChatThrottleLib, "AceComm-3.0 requires ChatThrottleLib")
+
+-- Lua APIs
+local type, next, pairs, tostring = type, next, pairs, tostring
+local strsub, strfind = string.sub, string.find
+local match = string.match
+local tinsert, tconcat = table.insert, table.concat
+local error, assert = error, assert
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: LibStub, DEFAULT_CHAT_FRAME, geterrorhandler, RegisterAddonMessagePrefix
+
+AceComm.embeds = AceComm.embeds or {}
+
+-- for my sanity and yours, let's give the message type bytes some names
+local MSG_MULTI_FIRST = "\001"
+local MSG_MULTI_NEXT = "\002"
+local MSG_MULTI_LAST = "\003"
+local MSG_ESCAPE = "\004"
+
+if not RegisterAddonMessagePrefix then
+ AceComm.multipart_origprefixes = AceComm.multipart_origprefixes or {} -- e.g. "Prefix\001"="Prefix", "Prefix\002"="Prefix"
+ AceComm.multipart_reassemblers = AceComm.multipart_reassemblers or {} -- e.g. "Prefix\001"="OnReceiveMultipartFirst"
+else
+ AceComm.multipart_origprefixes = nil
+ AceComm.multipart_reassemblers = nil
+end
+
+
+-- the multipart message spool: indexed by a combination of sender+distribution+
+AceComm.multipart_spool = AceComm.multipart_spool or {}
+
+--- Register for Addon Traffic on a specified prefix
+-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent), max 16 characters
+-- @param method Callback to call on message reception: Function reference, or method name (string) to call on self. Defaults to "OnCommReceived"
+function AceComm:RegisterComm(prefix, method)
+ if method == nil then
+ method = "OnCommReceived"
+ end
+
+ if RegisterAddonMessagePrefix then
+ if #prefix>16 then -- TODO: 15?
+ error("AceComm:RegisterComm(prefix,method): prefix length is limited to 16 characters")
+ end
+ RegisterAddonMessagePrefix(prefix)
+ end
+ return AceComm._RegisterComm(self, prefix, method) -- created by CallbackHandler
+end
+
+local warnedPrefix=false
+
+--- Send a message over the Addon Channel
+-- @param prefix A printable character (\032-\255) classification of the message (typically AddonName or AddonNameEvent)
+-- @param text Data to send, nils (\000) not allowed. Any length.
+-- @param distribution Addon channel, e.g. "RAID", "GUILD", etc; see SendAddonMessage API
+-- @param target Destination for some distributions; see SendAddonMessage API
+-- @param prio OPTIONAL: ChatThrottleLib priority, "BULK", "NORMAL" or "ALERT". Defaults to "NORMAL".
+-- @param callbackFn OPTIONAL: callback function to be called as each chunk is sent. receives 3 args: the user supplied arg (see next), the number of bytes sent so far, and the number of bytes total to send.
+-- @param callbackArg: OPTIONAL: first arg to the callback function. nil will be passed if not specified.
+function AceComm:SendCommMessage(prefix, text, distribution, target, prio, callbackFn, callbackArg)
+ prio = prio or "NORMAL" -- pasta's reference implementation had different prio for singlepart and multipart, but that's a very bad idea since that can easily lead to out-of-sequence delivery!
+ if not( type(prefix)=="string" and
+ type(text)=="string" and
+ type(distribution)=="string" and
+ (target==nil or type(target)=="string") and
+ (prio=="BULK" or prio=="NORMAL" or prio=="ALERT")
+ ) then
+ error('Usage: SendCommMessage(addon, "prefix", "text", "distribution"[, "target"[, "prio"[, callbackFn, callbackarg]]])', 2)
+ end
+
+ if not RegisterAddonMessagePrefix then
+ if strfind(prefix, "[\001-\009]") then
+ if strfind(prefix, "[\001-\003]") then
+ error("SendCommMessage: Characters \\001--\\003 in prefix are reserved for AceComm metadata", 2)
+ elseif not warnedPrefix then
+ -- I have some ideas about future extensions that require more control characters /mikk, 20090808
+ geterrorhandler()("SendCommMessage: Heads-up developers: Characters \\004--\\009 in prefix are reserved for AceComm future extension")
+ warnedPrefix = true
+ end
+ end
+ end
+
+ local textlen = #text
+ local maxtextlen;
+ if not RegisterAddonMessagePrefix then
+ maxtextlen = 254 - #prefix -- 254 is the max length of prefix + text that can be sent in one message (there's an internal separator char)
+ else
+ maxtextlen = 255 -- Yes, the max is 255 even if the dev post said 256. I tested. Char 256+ get silently truncated. /Mikk, 20110327
+ end
+ local queueName = prefix..distribution..(target or "")
+
+ local ctlCallback = nil
+ if callbackFn then
+ ctlCallback = function(sent)
+ return callbackFn(callbackArg, sent, textlen)
+ end
+ end
+
+ local forceMultipart
+ if RegisterAddonMessagePrefix and match(text, "^[\001-\009]") then -- 4.1+: see if the first character is a control character
+ -- we need to escape the first character with a \004
+ if textlen+1 > maxtextlen then -- would we go over the size limit?
+ forceMultipart = true -- just make it multipart, no escape problems then
+ else
+ text = "\004" .. text
+ end
+ end
+
+ if not forceMultipart and textlen <= maxtextlen then
+ -- fits all in one message
+ CTL:SendAddonMessage(prio, prefix, text, distribution, target, queueName, ctlCallback, textlen)
+ else
+ maxtextlen = maxtextlen - 1 -- 1 extra byte for part indicator in prefix(4.0)/start of message(4.1)
+
+ -- first part
+ local chunk = strsub(text, 1, maxtextlen)
+ if not RegisterAddonMessagePrefix then
+ CTL:SendAddonMessage(prio, prefix..MSG_MULTI_FIRST, chunk, distribution, target, queueName, ctlCallback, maxtextlen)
+ else
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_FIRST..chunk, distribution, target, queueName, ctlCallback, maxtextlen)
+ end
+
+ -- continuation
+ local pos = 1+maxtextlen
+
+ while pos+maxtextlen <= textlen do
+ chunk = strsub(text, pos, pos+maxtextlen-1)
+ if not RegisterAddonMessagePrefix then
+ CTL:SendAddonMessage(prio, prefix..MSG_MULTI_NEXT, chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1)
+ else
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_NEXT..chunk, distribution, target, queueName, ctlCallback, pos+maxtextlen-1)
+ end
+ pos = pos + maxtextlen
+ end
+
+ -- final part
+ chunk = strsub(text, pos)
+ if not RegisterAddonMessagePrefix then
+ CTL:SendAddonMessage(prio, prefix..MSG_MULTI_LAST, chunk, distribution, target, queueName, ctlCallback, textlen)
+ else
+ CTL:SendAddonMessage(prio, prefix, MSG_MULTI_LAST..chunk, distribution, target, queueName, ctlCallback, textlen)
+ end
+ end
+end
+
+
+----------------------------------------
+-- Message receiving
+----------------------------------------
+
+do
+ local compost = setmetatable({}, {__mode = "k"})
+ local function new()
+ local t = next(compost)
+ if t then
+ compost[t]=nil
+ for i=#t,3,-1 do -- faster than pairs loop. don't even nil out 1/2 since they'll be overwritten
+ t[i]=nil
+ end
+ return t
+ end
+
+ return {}
+ end
+
+ local function lostdatawarning(prefix,sender,where)
+ DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: lost network data regarding '"..tostring(prefix).."' from '"..tostring(sender).."' (in "..where..")")
+ end
+
+ function AceComm:OnReceiveMultipartFirst(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+
+ --[[
+ if spool[key] then
+ lostdatawarning(prefix,sender,"First")
+ -- continue and overwrite
+ end
+ --]]
+
+ spool[key] = message -- plain string for now
+ end
+
+ function AceComm:OnReceiveMultipartNext(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+ local olddata = spool[key]
+
+ if not olddata then
+ --lostdatawarning(prefix,sender,"Next")
+ return
+ end
+
+ if type(olddata)~="table" then
+ -- ... but what we have is not a table. So make it one. (Pull a composted one if available)
+ local t = new()
+ t[1] = olddata -- add old data as first string
+ t[2] = message -- and new message as second string
+ spool[key] = t -- and put the table in the spool instead of the old string
+ else
+ tinsert(olddata, message)
+ end
+ end
+
+ function AceComm:OnReceiveMultipartLast(prefix, message, distribution, sender)
+ local key = prefix.."\t"..distribution.."\t"..sender -- a unique stream is defined by the prefix + distribution + sender
+ local spool = AceComm.multipart_spool
+ local olddata = spool[key]
+
+ if not olddata then
+ --lostdatawarning(prefix,sender,"End")
+ return
+ end
+
+ spool[key] = nil
+
+ if type(olddata) == "table" then
+ -- if we've received a "next", the spooled data will be a table for rapid & garbage-free tconcat
+ tinsert(olddata, message)
+ AceComm.callbacks:Fire(prefix, tconcat(olddata, ""), distribution, sender)
+ compost[olddata] = true
+ else
+ -- if we've only received a "first", the spooled data will still only be a string
+ AceComm.callbacks:Fire(prefix, olddata..message, distribution, sender)
+ end
+ end
+end
+
+
+
+
+
+
+----------------------------------------
+-- Embed CallbackHandler
+----------------------------------------
+
+if not AceComm.callbacks then
+ AceComm.callbacks = CallbackHandler:New(AceComm,
+ "_RegisterComm",
+ "UnregisterComm",
+ "UnregisterAllComm")
+end
+
+local OnEvent
+
+if not RegisterAddonMessagePrefix then -- 4.0: per-prefix callbacks per part type
+
+ function AceComm.callbacks:OnUsed(target, prefix)
+ AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = prefix
+ AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = "OnReceiveMultipartFirst"
+
+ AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = prefix
+ AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = "OnReceiveMultipartNext"
+
+ AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = prefix
+ AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = "OnReceiveMultipartLast"
+ end
+
+ function AceComm.callbacks:OnUnused(target, prefix)
+ AceComm.multipart_origprefixes[prefix..MSG_MULTI_FIRST] = nil
+ AceComm.multipart_reassemblers[prefix..MSG_MULTI_FIRST] = nil
+
+ AceComm.multipart_origprefixes[prefix..MSG_MULTI_NEXT] = nil
+ AceComm.multipart_reassemblers[prefix..MSG_MULTI_NEXT] = nil
+
+ AceComm.multipart_origprefixes[prefix..MSG_MULTI_LAST] = nil
+ AceComm.multipart_reassemblers[prefix..MSG_MULTI_LAST] = nil
+ end
+
+ function OnEvent(this, event, ...)
+ if event == "CHAT_MSG_ADDON" then
+ local prefix,message,distribution,sender = ...
+ local reassemblername = AceComm.multipart_reassemblers[prefix]
+ if reassemblername then
+ -- multipart: reassemble
+ local aceCommReassemblerFunc = AceComm[reassemblername]
+ local origprefix = AceComm.multipart_origprefixes[prefix]
+ aceCommReassemblerFunc(AceComm, origprefix, message, distribution, sender)
+ else
+ -- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
+ AceComm.callbacks:Fire(prefix, message, distribution, sender)
+ end
+ else
+ assert(false, "Received "..tostring(event).." event?!")
+ end
+ end
+
+else -- 4.1+: only one prefix for all
+
+ AceComm.callbacks.OnUsed = nil
+ AceComm.callbacks.OnUnused = nil
+
+ function OnEvent(this, event, ...)
+ if event == "CHAT_MSG_ADDON" then
+ local prefix,message,distribution,sender = ...
+ local control, rest = match(message, "^([\001-\009])(.*)")
+ if control then
+ if control==MSG_MULTI_FIRST then
+ AceComm:OnReceiveMultipartFirst(prefix, rest, distribution, sender)
+ elseif control==MSG_MULTI_NEXT then
+ AceComm:OnReceiveMultipartNext(prefix, rest, distribution, sender)
+ elseif control==MSG_MULTI_LAST then
+ AceComm:OnReceiveMultipartLast(prefix, rest, distribution, sender)
+ elseif control==MSG_ESCAPE then
+ AceComm.callbacks:Fire(prefix, rest, distribution, sender)
+ else
+ -- unknown control character, ignore SILENTLY (dont warn unnecessarily about future extensions!)
+ end
+ else
+ -- single part: fire it off immediately and let CallbackHandler decide if it's registered or not
+ AceComm.callbacks:Fire(prefix, message, distribution, sender)
+ end
+ else
+ assert(false, "Received "..tostring(event).." event?!")
+ end
+ end
+
+end
+
+AceComm.frame = AceComm.frame or CreateFrame("Frame", "AceComm30Frame")
+AceComm.frame:SetScript("OnEvent", OnEvent)
+AceComm.frame:UnregisterAllEvents()
+AceComm.frame:RegisterEvent("CHAT_MSG_ADDON")
+
+
+----------------------------------------
+-- Base library stuff
+----------------------------------------
+
+local mixins = {
+ "RegisterComm",
+ "UnregisterComm",
+ "UnregisterAllComm",
+ "SendCommMessage",
+}
+
+-- Embeds AceComm-3.0 into the target object making the functions from the mixins list available on target:..
+-- @param target target object to embed AceComm-3.0 in
+function AceComm:Embed(target)
+ for k, v in pairs(mixins) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+function AceComm:OnEmbedDisable(target)
+ target:UnregisterAllComm()
+end
+
+-- Update embeds
+for target, v in pairs(AceComm.embeds) do
+ AceComm:Embed(target)
+end
diff --git a/Libs/AceComm-3.0/AceComm-3.0.xml b/Libs/AceComm-3.0/AceComm-3.0.xml
new file mode 100644
index 00000000..c2e1bdfd
--- /dev/null
+++ b/Libs/AceComm-3.0/AceComm-3.0.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/Libs/AceComm-3.0/ChatThrottleLib.lua b/Libs/AceComm-3.0/ChatThrottleLib.lua
new file mode 100644
index 00000000..c465f34e
--- /dev/null
+++ b/Libs/AceComm-3.0/ChatThrottleLib.lua
@@ -0,0 +1,510 @@
+--
+-- ChatThrottleLib by Mikk
+--
+-- Manages AddOn chat output to keep player from getting kicked off.
+--
+-- ChatThrottleLib:SendChatMessage/:SendAddonMessage functions that accept
+-- a Priority ("BULK", "NORMAL", "ALERT") as well as prefix for SendChatMessage.
+--
+-- Priorities get an equal share of available bandwidth when fully loaded.
+-- Communication channels are separated on extension+chattype+destination and
+-- get round-robinned. (Destination only matters for whispers and channels,
+-- obviously)
+--
+-- Will install hooks for SendChatMessage and SendAddonMessage to measure
+-- bandwidth bypassing the library and use less bandwidth itself.
+--
+--
+-- Fully embeddable library. Just copy this file into your addon directory,
+-- add it to the .toc, and it's done.
+--
+-- Can run as a standalone addon also, but, really, just embed it! :-)
+--
+
+local CTL_VERSION = 22
+
+local _G = _G
+
+if _G.ChatThrottleLib then
+ if _G.ChatThrottleLib.version >= CTL_VERSION then
+ -- There's already a newer (or same) version loaded. Buh-bye.
+ return
+ elseif not _G.ChatThrottleLib.securelyHooked then
+ print("ChatThrottleLib: Warning: There's an ANCIENT ChatThrottleLib.lua (pre-wow 2.0, =v16) in it!")
+ -- ATTEMPT to unhook; this'll behave badly if someone else has hooked...
+ -- ... and if someone has securehooked, they can kiss that goodbye too... >.<
+ _G.SendChatMessage = _G.ChatThrottleLib.ORIG_SendChatMessage
+ if _G.ChatThrottleLib.ORIG_SendAddonMessage then
+ _G.SendAddonMessage = _G.ChatThrottleLib.ORIG_SendAddonMessage
+ end
+ end
+ _G.ChatThrottleLib.ORIG_SendChatMessage = nil
+ _G.ChatThrottleLib.ORIG_SendAddonMessage = nil
+end
+
+if not _G.ChatThrottleLib then
+ _G.ChatThrottleLib = {}
+end
+
+ChatThrottleLib = _G.ChatThrottleLib -- in case some addon does "local ChatThrottleLib" above us and we're copypasted (AceComm-2, sigh)
+local ChatThrottleLib = _G.ChatThrottleLib
+
+ChatThrottleLib.version = CTL_VERSION
+
+
+
+------------------ TWEAKABLES -----------------
+
+ChatThrottleLib.MAX_CPS = 800 -- 2000 seems to be safe if NOTHING ELSE is happening. let's call it 800.
+ChatThrottleLib.MSG_OVERHEAD = 40 -- Guesstimate overhead for sending a message; source+dest+chattype+protocolstuff
+
+ChatThrottleLib.BURST = 4000 -- WoW's server buffer seems to be about 32KB. 8KB should be safe, but seen disconnects on _some_ servers. Using 4KB now.
+
+ChatThrottleLib.MIN_FPS = 20 -- Reduce output CPS to half (and don't burst) if FPS drops below this value
+
+
+local setmetatable = setmetatable
+local table_remove = table.remove
+local tostring = tostring
+local GetTime = GetTime
+local math_min = math.min
+local math_max = math.max
+local next = next
+local strlen = string.len
+local GetFrameRate = GetFrameRate
+
+
+
+-----------------------------------------------------------------------
+-- Double-linked ring implementation
+
+local Ring = {}
+local RingMeta = { __index = Ring }
+
+function Ring:New()
+ local ret = {}
+ setmetatable(ret, RingMeta)
+ return ret
+end
+
+function Ring:Add(obj) -- Append at the "far end" of the ring (aka just before the current position)
+ if self.pos then
+ obj.prev = self.pos.prev
+ obj.prev.next = obj
+ obj.next = self.pos
+ obj.next.prev = obj
+ else
+ obj.next = obj
+ obj.prev = obj
+ self.pos = obj
+ end
+end
+
+function Ring:Remove(obj)
+ obj.next.prev = obj.prev
+ obj.prev.next = obj.next
+ if self.pos == obj then
+ self.pos = obj.next
+ if self.pos == obj then
+ self.pos = nil
+ end
+ end
+end
+
+
+
+-----------------------------------------------------------------------
+-- Recycling bin for pipes
+-- A pipe is a plain integer-indexed queue, which also happens to be a ring member
+
+ChatThrottleLib.PipeBin = nil -- pre-v19, drastically different
+local PipeBin = setmetatable({}, {__mode="k"})
+
+local function DelPipe(pipe)
+ for i = #pipe, 1, -1 do
+ pipe[i] = nil
+ end
+ pipe.prev = nil
+ pipe.next = nil
+
+ PipeBin[pipe] = true
+end
+
+local function NewPipe()
+ local pipe = next(PipeBin)
+ if pipe then
+ PipeBin[pipe] = nil
+ return pipe
+ end
+ return {}
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Recycling bin for messages
+
+ChatThrottleLib.MsgBin = nil -- pre-v19, drastically different
+local MsgBin = setmetatable({}, {__mode="k"})
+
+local function DelMsg(msg)
+ msg[1] = nil
+ -- there's more parameters, but they're very repetetive so the string pool doesn't suffer really, and it's faster to just not delete them.
+ MsgBin[msg] = true
+end
+
+local function NewMsg()
+ local msg = next(MsgBin)
+ if msg then
+ MsgBin[msg] = nil
+ return msg
+ end
+ return {}
+end
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib:Init
+-- Initialize queues, set up frame for OnUpdate, etc
+
+
+function ChatThrottleLib:Init()
+
+ -- Set up queues
+ if not self.Prio then
+ self.Prio = {}
+ self.Prio["ALERT"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ self.Prio["NORMAL"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ self.Prio["BULK"] = { ByName = {}, Ring = Ring:New(), avail = 0 }
+ end
+
+ -- v4: total send counters per priority
+ for _, Prio in pairs(self.Prio) do
+ Prio.nTotalSent = Prio.nTotalSent or 0
+ end
+
+ if not self.avail then
+ self.avail = 0 -- v5
+ end
+ if not self.nTotalSent then
+ self.nTotalSent = 0 -- v5
+ end
+
+
+ -- Set up a frame to get OnUpdate events
+ if not self.Frame then
+ self.Frame = CreateFrame("Frame")
+ self.Frame:Hide()
+ end
+ self.Frame:SetScript("OnUpdate", self.OnUpdate)
+ self.Frame:SetScript("OnEvent", self.OnEvent) -- v11: Monitor P_E_W so we can throttle hard for a few seconds
+ self.Frame:RegisterEvent("PLAYER_ENTERING_WORLD")
+ self.OnUpdateDelay = 0
+ self.LastAvailUpdate = GetTime()
+ self.HardThrottlingBeginTime = GetTime() -- v11: Throttle hard for a few seconds after startup
+
+ -- Hook SendChatMessage and SendAddonMessage so we can measure unpiped traffic and avoid overloads (v7)
+ if not self.securelyHooked then
+ -- Use secure hooks as of v16. Old regular hook support yanked out in v21.
+ self.securelyHooked = true
+ --SendChatMessage
+ hooksecurefunc("SendChatMessage", function(...)
+ return ChatThrottleLib.Hook_SendChatMessage(...)
+ end)
+ --SendAddonMessage
+ hooksecurefunc("SendAddonMessage", function(...)
+ return ChatThrottleLib.Hook_SendAddonMessage(...)
+ end)
+ end
+ self.nBypass = 0
+end
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib.Hook_SendChatMessage / .Hook_SendAddonMessage
+
+local bMyTraffic = false
+
+function ChatThrottleLib.Hook_SendChatMessage(text, chattype, language, destination, ...)
+ if bMyTraffic then
+ return
+ end
+ local self = ChatThrottleLib
+ local size = strlen(tostring(text or "")) + strlen(tostring(destination or "")) + self.MSG_OVERHEAD
+ self.avail = self.avail - size
+ self.nBypass = self.nBypass + size -- just a statistic
+end
+function ChatThrottleLib.Hook_SendAddonMessage(prefix, text, chattype, destination, ...)
+ if bMyTraffic then
+ return
+ end
+ local self = ChatThrottleLib
+ local size = tostring(text or ""):len() + tostring(prefix or ""):len();
+ size = size + tostring(destination or ""):len() + self.MSG_OVERHEAD
+ self.avail = self.avail - size
+ self.nBypass = self.nBypass + size -- just a statistic
+end
+
+
+
+-----------------------------------------------------------------------
+-- ChatThrottleLib:UpdateAvail
+-- Update self.avail with how much bandwidth is currently available
+
+function ChatThrottleLib:UpdateAvail()
+ local now = GetTime()
+ local MAX_CPS = self.MAX_CPS;
+ local newavail = MAX_CPS * (now - self.LastAvailUpdate)
+ local avail = self.avail
+
+ if now - self.HardThrottlingBeginTime < 5 then
+ -- First 5 seconds after startup/zoning: VERY hard clamping to avoid irritating the server rate limiter, it seems very cranky then
+ avail = math_min(avail + (newavail*0.1), MAX_CPS*0.5)
+ self.bChoking = true
+ elseif GetFramerate() < self.MIN_FPS then -- GetFrameRate call takes ~0.002 secs
+ avail = math_min(MAX_CPS, avail + newavail*0.5)
+ self.bChoking = true -- just a statistic
+ else
+ avail = math_min(self.BURST, avail + newavail)
+ self.bChoking = false
+ end
+
+ avail = math_max(avail, 0-(MAX_CPS*2)) -- Can go negative when someone is eating bandwidth past the lib. but we refuse to stay silent for more than 2 seconds; if they can do it, we can.
+
+ self.avail = avail
+ self.LastAvailUpdate = now
+
+ return avail
+end
+
+
+-----------------------------------------------------------------------
+-- Despooling logic
+
+function ChatThrottleLib:Despool(Prio)
+ local ring = Prio.Ring
+ while ring.pos and Prio.avail > ring.pos[1].nSize do
+ local msg = table_remove(Prio.Ring.pos, 1)
+ if not Prio.Ring.pos[1] then
+ local pipe = Prio.Ring.pos
+ Prio.Ring:Remove(pipe)
+ Prio.ByName[pipe.name] = nil
+ DelPipe(pipe)
+ else
+ Prio.Ring.pos = Prio.Ring.pos.next
+ end
+ Prio.avail = Prio.avail - msg.nSize
+ bMyTraffic = true
+ msg.f(unpack(msg, 1, msg.n))
+ bMyTraffic = false
+ Prio.nTotalSent = Prio.nTotalSent + msg.nSize
+ DelMsg(msg)
+ if msg.callbackFn then
+ msg.callbackFn (msg.callbackArg)
+ end
+ end
+end
+
+
+function ChatThrottleLib.OnEvent(this,event)
+ -- v11: We know that the rate limiter is touchy after login. Assume that it's touchy after zoning, too.
+ local self = ChatThrottleLib
+ if event == "PLAYER_ENTERING_WORLD" then
+ self.HardThrottlingBeginTime = GetTime() -- Throttle hard for a few seconds after zoning
+ self.avail = 0
+ end
+end
+
+
+function ChatThrottleLib.OnUpdate(this,delay)
+ local self = ChatThrottleLib
+
+ self.OnUpdateDelay = self.OnUpdateDelay + delay
+ if self.OnUpdateDelay < 0.08 then
+ return
+ end
+ self.OnUpdateDelay = 0
+
+ self:UpdateAvail()
+
+ if self.avail < 0 then
+ return -- argh. some bastard is spewing stuff past the lib. just bail early to save cpu.
+ end
+
+ -- See how many of our priorities have queued messages (we only have 3, don't worry about the loop)
+ local n = 0
+ for prioname,Prio in pairs(self.Prio) do
+ if Prio.Ring.pos or Prio.avail < 0 then
+ n = n + 1
+ end
+ end
+
+ -- Anything queued still?
+ if n<1 then
+ -- Nope. Move spillover bandwidth to global availability gauge and clear self.bQueueing
+ for prioname, Prio in pairs(self.Prio) do
+ self.avail = self.avail + Prio.avail
+ Prio.avail = 0
+ end
+ self.bQueueing = false
+ self.Frame:Hide()
+ return
+ end
+
+ -- There's stuff queued. Hand out available bandwidth to priorities as needed and despool their queues
+ local avail = self.avail/n
+ self.avail = 0
+
+ for prioname, Prio in pairs(self.Prio) do
+ if Prio.Ring.pos or Prio.avail < 0 then
+ Prio.avail = Prio.avail + avail
+ if Prio.Ring.pos and Prio.avail > Prio.Ring.pos[1].nSize then
+ self:Despool(Prio)
+ -- Note: We might not get here if the user-supplied callback function errors out! Take care!
+ end
+ end
+ end
+
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Spooling logic
+
+
+function ChatThrottleLib:Enqueue(prioname, pipename, msg)
+ local Prio = self.Prio[prioname]
+ local pipe = Prio.ByName[pipename]
+ if not pipe then
+ self.Frame:Show()
+ pipe = NewPipe()
+ pipe.name = pipename
+ Prio.ByName[pipename] = pipe
+ Prio.Ring:Add(pipe)
+ end
+
+ pipe[#pipe + 1] = msg
+
+ self.bQueueing = true
+end
+
+
+
+function ChatThrottleLib:SendChatMessage(prio, prefix, text, chattype, language, destination, queueName, callbackFn, callbackArg)
+ if not self or not prio or not prefix or not text or not self.Prio[prio] then
+ error('Usage: ChatThrottleLib:SendChatMessage("{BULK||NORMAL||ALERT}", "prefix", "text"[, "chattype"[, "language"[, "destination"]]]', 2)
+ end
+ if callbackFn and type(callbackFn)~="function" then
+ error('ChatThrottleLib:ChatMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
+ end
+
+ local nSize = text:len()
+
+ if nSize>255 then
+ error("ChatThrottleLib:SendChatMessage(): message length cannot exceed 255 bytes", 2)
+ end
+
+ nSize = nSize + self.MSG_OVERHEAD
+
+ -- Check if there's room in the global available bandwidth gauge to send directly
+ if not self.bQueueing and nSize < self:UpdateAvail() then
+ self.avail = self.avail - nSize
+ bMyTraffic = true
+ _G.SendChatMessage(text, chattype, language, destination)
+ bMyTraffic = false
+ self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
+ if callbackFn then
+ callbackFn (callbackArg)
+ end
+ return
+ end
+
+ -- Message needs to be queued
+ local msg = NewMsg()
+ msg.f = _G.SendChatMessage
+ msg[1] = text
+ msg[2] = chattype or "SAY"
+ msg[3] = language
+ msg[4] = destination
+ msg.n = 4
+ msg.nSize = nSize
+ msg.callbackFn = callbackFn
+ msg.callbackArg = callbackArg
+
+ self:Enqueue(prio, queueName or (prefix..(chattype or "SAY")..(destination or "")), msg)
+end
+
+
+function ChatThrottleLib:SendAddonMessage(prio, prefix, text, chattype, target, queueName, callbackFn, callbackArg)
+ if not self or not prio or not prefix or not text or not chattype or not self.Prio[prio] then
+ error('Usage: ChatThrottleLib:SendAddonMessage("{BULK||NORMAL||ALERT}", "prefix", "text", "chattype"[, "target"])', 2)
+ end
+ if callbackFn and type(callbackFn)~="function" then
+ error('ChatThrottleLib:SendAddonMessage(): callbackFn: expected function, got '..type(callbackFn), 2)
+ end
+
+ local nSize = text:len();
+
+ if RegisterAddonMessagePrefix then
+ if nSize>255 then
+ error("ChatThrottleLib:SendAddonMessage(): message length cannot exceed 255 bytes", 2)
+ end
+ else
+ nSize = nSize + prefix:len() + 1
+ if nSize>255 then
+ error("ChatThrottleLib:SendAddonMessage(): prefix + message length cannot exceed 254 bytes", 2)
+ end
+ end
+
+ nSize = nSize + self.MSG_OVERHEAD;
+
+ -- Check if there's room in the global available bandwidth gauge to send directly
+ if not self.bQueueing and nSize < self:UpdateAvail() then
+ self.avail = self.avail - nSize
+ bMyTraffic = true
+ _G.SendAddonMessage(prefix, text, chattype, target)
+ bMyTraffic = false
+ self.Prio[prio].nTotalSent = self.Prio[prio].nTotalSent + nSize
+ if callbackFn then
+ callbackFn (callbackArg)
+ end
+ return
+ end
+
+ -- Message needs to be queued
+ local msg = NewMsg()
+ msg.f = _G.SendAddonMessage
+ msg[1] = prefix
+ msg[2] = text
+ msg[3] = chattype
+ msg[4] = target
+ msg.n = (target~=nil) and 4 or 3;
+ msg.nSize = nSize
+ msg.callbackFn = callbackFn
+ msg.callbackArg = callbackArg
+
+ self:Enqueue(prio, queueName or (prefix..chattype..(target or "")), msg)
+end
+
+
+
+
+-----------------------------------------------------------------------
+-- Get the ball rolling!
+
+ChatThrottleLib:Init()
+
+--[[ WoWBench debugging snippet
+if(WOWB_VER) then
+ local function SayTimer()
+ print("SAY: "..GetTime().." "..arg1)
+ end
+ ChatThrottleLib.Frame:SetScript("OnEvent", SayTimer)
+ ChatThrottleLib.Frame:RegisterEvent("CHAT_MSG_SAY")
+end
+]]
+
+
diff --git a/Libs/AceLocale-3.0/AceLocale-3.0.lua b/Libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 00000000..2ecc0cb8
--- /dev/null
+++ b/Libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/Libs/AceLocale-3.0/AceLocale-3.0.xml b/Libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 00000000..d69dbb13
--- /dev/null
+++ b/Libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Libs/AceSerializer-3.0/AceSerializer-3.0.lua b/Libs/AceSerializer-3.0/AceSerializer-3.0.lua
new file mode 100644
index 00000000..0df27803
--- /dev/null
+++ b/Libs/AceSerializer-3.0/AceSerializer-3.0.lua
@@ -0,0 +1,283 @@
+--- **AceSerializer-3.0** can serialize any variable (except functions or userdata) into a string format,
+-- that can be send over the addon comm channel. AceSerializer was designed to keep all data intact, especially
+-- very large numbers or floating point numbers, and table structures. The only caveat currently is, that multiple
+-- references to the same table will be send individually.
+--
+-- **AceSerializer-3.0** can be embeded into your addon, either explicitly by calling AceSerializer:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceSerializer itself.\\
+-- It is recommended to embed AceSerializer, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceSerializer.
+-- @class file
+-- @name AceSerializer-3.0
+-- @release $Id: AceSerializer-3.0.lua 1038 2011-10-03 01:39:58Z mikk $
+local MAJOR,MINOR = "AceSerializer-3.0", 4
+local AceSerializer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceSerializer then return end
+
+-- Lua APIs
+local strbyte, strchar, gsub, gmatch, format = string.byte, string.char, string.gsub, string.gmatch, string.format
+local assert, error, pcall = assert, error, pcall
+local type, tostring, tonumber = type, tostring, tonumber
+local pairs, select, frexp = pairs, select, math.frexp
+local tconcat = table.concat
+
+-- quick copies of string representations of wonky numbers
+local inf = math.huge
+
+local serNaN -- can't do this in 4.3, see ace3 ticket 268
+local serInf = tostring(inf)
+local serNegInf = tostring(-inf)
+
+
+-- Serialization functions
+
+local function SerializeStringHelper(ch) -- Used by SerializeValue for strings
+ -- We use \126 ("~") as an escape character for all nonprints plus a few more
+ local n = strbyte(ch)
+ if n==30 then -- v3 / ticket 115: catch a nonprint that ends up being "~^" when encoded... DOH
+ return "\126\122"
+ elseif n<=32 then -- nonprint + space
+ return "\126"..strchar(n+64)
+ elseif n==94 then -- value separator
+ return "\126\125"
+ elseif n==126 then -- our own escape character
+ return "\126\124"
+ elseif n==127 then -- nonprint (DEL)
+ return "\126\123"
+ else
+ assert(false) -- can't be reached if caller uses a sane regex
+ end
+end
+
+local function SerializeValue(v, res, nres)
+ -- We use "^" as a value separator, followed by one byte for type indicator
+ local t=type(v)
+
+ if t=="string" then -- ^S = string (escaped to remove nonprints, "^"s, etc)
+ res[nres+1] = "^S"
+ res[nres+2] = gsub(v,"[%c \94\126\127]", SerializeStringHelper)
+ nres=nres+2
+
+ elseif t=="number" then -- ^N = number (just tostring()ed) or ^F (float components)
+ local str = tostring(v)
+ if tonumber(str)==v --[[not in 4.3 or str==serNaN]] or str==serInf or str==serNegInf then
+ -- translates just fine, transmit as-is
+ res[nres+1] = "^N"
+ res[nres+2] = str
+ nres=nres+2
+ else
+ local m,e = frexp(v)
+ res[nres+1] = "^F"
+ res[nres+2] = format("%.0f",m*2^53) -- force mantissa to become integer (it's originally 0.5--0.9999)
+ res[nres+3] = "^f"
+ res[nres+4] = tostring(e-53) -- adjust exponent to counteract mantissa manipulation
+ nres=nres+4
+ end
+
+ elseif t=="table" then -- ^T...^t = table (list of key,value pairs)
+ nres=nres+1
+ res[nres] = "^T"
+ for k,v in pairs(v) do
+ nres = SerializeValue(k, res, nres)
+ nres = SerializeValue(v, res, nres)
+ end
+ nres=nres+1
+ res[nres] = "^t"
+
+ elseif t=="boolean" then -- ^B = true, ^b = false
+ nres=nres+1
+ if v then
+ res[nres] = "^B" -- true
+ else
+ res[nres] = "^b" -- false
+ end
+
+ elseif t=="nil" then -- ^Z = nil (zero, "N" was taken :P)
+ nres=nres+1
+ res[nres] = "^Z"
+
+ else
+ error(MAJOR..": Cannot serialize a value of type '"..t.."'") -- can't produce error on right level, this is wildly recursive
+ end
+
+ return nres
+end
+
+
+
+local serializeTbl = { "^1" } -- "^1" = Hi, I'm data serialized by AceSerializer protocol rev 1
+
+--- Serialize the data passed into the function.
+-- Takes a list of values (strings, numbers, booleans, nils, tables)
+-- and returns it in serialized form (a string).\\
+-- May throw errors on invalid data types.
+-- @param ... List of values to serialize
+-- @return The data in its serialized form (string)
+function AceSerializer:Serialize(...)
+ local nres = 1
+
+ for i=1,select("#", ...) do
+ local v = select(i, ...)
+ nres = SerializeValue(v, serializeTbl, nres)
+ end
+
+ serializeTbl[nres+1] = "^^" -- "^^" = End of serialized data
+
+ return tconcat(serializeTbl, "", 1, nres+1)
+end
+
+-- Deserialization functions
+local function DeserializeStringHelper(escape)
+ if escape<"~\122" then
+ return strchar(strbyte(escape,2,2)-64)
+ elseif escape=="~\122" then -- v3 / ticket 115: special case encode since 30+64=94 ("^") - OOPS.
+ return "\030"
+ elseif escape=="~\123" then
+ return "\127"
+ elseif escape=="~\124" then
+ return "\126"
+ elseif escape=="~\125" then
+ return "\94"
+ end
+ error("DeserializeStringHelper got called for '"..escape.."'?!?") -- can't be reached unless regex is screwed up
+end
+
+local function DeserializeNumberHelper(number)
+ --[[ not in 4.3 if number == serNaN then
+ return 0/0
+ else]]if number == serNegInf then
+ return -inf
+ elseif number == serInf then
+ return inf
+ else
+ return tonumber(number)
+ end
+end
+
+-- DeserializeValue: worker function for :Deserialize()
+-- It works in two modes:
+-- Main (top-level) mode: Deserialize a list of values and return them all
+-- Recursive (table) mode: Deserialize only a single value (_may_ of course be another table with lots of subvalues in it)
+--
+-- The function _always_ works recursively due to having to build a list of values to return
+--
+-- Callers are expected to pcall(DeserializeValue) to trap errors
+
+local function DeserializeValue(iter,single,ctl,data)
+
+ if not single then
+ ctl,data = iter()
+ end
+
+ if not ctl then
+ error("Supplied data misses AceSerializer terminator ('^^')")
+ end
+
+ if ctl=="^^" then
+ -- ignore extraneous data
+ return
+ end
+
+ local res
+
+ if ctl=="^S" then
+ res = gsub(data, "~.", DeserializeStringHelper)
+ elseif ctl=="^N" then
+ res = DeserializeNumberHelper(data)
+ if not res then
+ error("Invalid serialized number: '"..tostring(data).."'")
+ end
+ elseif ctl=="^F" then -- ^F^f
+ local ctl2,e = iter()
+ if ctl2~="^f" then
+ error("Invalid serialized floating-point number, expected '^f', not '"..tostring(ctl2).."'")
+ end
+ local m=tonumber(data)
+ e=tonumber(e)
+ if not (m and e) then
+ error("Invalid serialized floating-point number, expected mantissa and exponent, got '"..tostring(m).."' and '"..tostring(e).."'")
+ end
+ res = m*(2^e)
+ elseif ctl=="^B" then -- yeah yeah ignore data portion
+ res = true
+ elseif ctl=="^b" then -- yeah yeah ignore data portion
+ res = false
+ elseif ctl=="^Z" then -- yeah yeah ignore data portion
+ res = nil
+ elseif ctl=="^T" then
+ -- ignore ^T's data, future extensibility?
+ res = {}
+ local k,v
+ while true do
+ ctl,data = iter()
+ if ctl=="^t" then break end -- ignore ^t's data
+ k = DeserializeValue(iter,true,ctl,data)
+ if k==nil then
+ error("Invalid AceSerializer table format (no table end marker)")
+ end
+ ctl,data = iter()
+ v = DeserializeValue(iter,true,ctl,data)
+ if v==nil then
+ error("Invalid AceSerializer table format (no table end marker)")
+ end
+ res[k]=v
+ end
+ else
+ error("Invalid AceSerializer control code '"..ctl.."'")
+ end
+
+ if not single then
+ return res,DeserializeValue(iter)
+ else
+ return res
+ end
+end
+
+--- Deserializes the data into its original values.
+-- Accepts serialized data, ignoring all control characters and whitespace.
+-- @param str The serialized data (from :Serialize)
+-- @return true followed by a list of values, OR false followed by an error message
+function AceSerializer:Deserialize(str)
+ str = gsub(str, "[%c ]", "") -- ignore all control characters; nice for embedding in email and stuff
+
+ local iter = gmatch(str, "(^.)([^^]*)") -- Any ^x followed by string of non-^
+ local ctl,data = iter()
+ if not ctl or ctl~="^1" then
+ -- we purposefully ignore the data portion of the start code, it can be used as an extension mechanism
+ return false, "Supplied data is not AceSerializer data (rev 1)"
+ end
+
+ return pcall(DeserializeValue, iter)
+end
+
+
+----------------------------------------
+-- Base library stuff
+----------------------------------------
+
+AceSerializer.internals = { -- for test scripts
+ SerializeValue = SerializeValue,
+ SerializeStringHelper = SerializeStringHelper,
+}
+
+local mixins = {
+ "Serialize",
+ "Deserialize",
+}
+
+AceSerializer.embeds = AceSerializer.embeds or {}
+
+function AceSerializer:Embed(target)
+ for k, v in pairs(mixins) do
+ target[v] = self[v]
+ end
+ self.embeds[target] = true
+ return target
+end
+
+-- Update embeds
+for target, v in pairs(AceSerializer.embeds) do
+ AceSerializer:Embed(target)
+end
\ No newline at end of file
diff --git a/Libs/AceSerializer-3.0/AceSerializer-3.0.xml b/Libs/AceSerializer-3.0/AceSerializer-3.0.xml
new file mode 100644
index 00000000..477ac0b8
--- /dev/null
+++ b/Libs/AceSerializer-3.0/AceSerializer-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Libs/AceTimer-3.0/AceTimer-3.0.lua b/Libs/AceTimer-3.0/AceTimer-3.0.lua
new file mode 100644
index 00000000..62f6ee36
--- /dev/null
+++ b/Libs/AceTimer-3.0/AceTimer-3.0.lua
@@ -0,0 +1,475 @@
+--- **AceTimer-3.0** provides a central facility for registering timers.
+-- AceTimer supports one-shot timers and repeating timers. All timers are stored in an efficient
+-- data structure that allows easy dispatching and fast rescheduling. Timers can be registered, rescheduled
+-- or canceled at any time, even from within a running timer, without conflict or large overhead.\\
+-- AceTimer is currently limited to firing timers at a frequency of 0.1s. This constant may change
+-- in the future, but for now it seemed like a good compromise in efficiency and accuracy.
+--
+-- All `:Schedule` functions will return a handle to the current timer, which you will need to store if you
+-- need to cancel or reschedule the timer you just registered.
+--
+-- **AceTimer-3.0** can be embeded into your addon, either explicitly by calling AceTimer:Embed(MyAddon) or by
+-- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
+-- and can be accessed directly, without having to explicitly call AceTimer itself.\\
+-- It is recommended to embed AceTimer, otherwise you'll have to specify a custom `self` on all calls you
+-- make into AceTimer.
+-- @class file
+-- @name AceTimer-3.0
+-- @release $Id: AceTimer-3.0.lua 1037 2011-09-02 16:24:08Z mikk $
+
+--[[
+ Basic assumptions:
+ * In a typical system, we do more re-scheduling per second than there are timer pulses per second
+ * Regardless of timer implementation, we cannot guarantee timely delivery due to FPS restriction (may be as low as 10)
+
+ This implementation:
+ CON: The smallest timer interval is constrained by HZ (currently 1/10s).
+ PRO: It will still correctly fire any timer slower than HZ over a length of time, e.g. 0.11s interval -> 90 times over 10 seconds
+ PRO: In lag bursts, the system simly skips missed timer intervals to decrease load
+ CON: Algorithms depending on a timer firing "N times per minute" will fail
+ PRO: (Re-)scheduling is O(1) with a VERY small constant. It's a simple linked list insertion in a hash bucket.
+ CAUTION: The BUCKETS constant constrains how many timers can be efficiently handled. With too many hash collisions, performance will decrease.
+
+ Major assumptions upheld:
+ - ALLOWS scheduling multiple timers with the same funcref/method
+ - ALLOWS scheduling more timers during OnUpdate processing
+ - ALLOWS unscheduling ANY timer (including the current running one) at any time, including during OnUpdate processing
+]]
+
+local MAJOR, MINOR = "AceTimer-3.0", 6
+local AceTimer, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceTimer then return end -- No upgrade needed
+
+AceTimer.hash = AceTimer.hash or {} -- Array of [0..BUCKET-1] = linked list of timers (using .next member)
+ -- Linked list gets around ACE-88 and ACE-90.
+AceTimer.selfs = AceTimer.selfs or {} -- Array of [self]={[handle]=timerobj, [handle2]=timerobj2, ...}
+AceTimer.frame = AceTimer.frame or CreateFrame("Frame", "AceTimer30Frame")
+
+-- Lua APIs
+local assert, error, loadstring = assert, error, loadstring
+local setmetatable, rawset, rawget = setmetatable, rawset, rawget
+local select, pairs, type, next, tostring = select, pairs, type, next, tostring
+local floor, max, min = math.floor, math.max, math.min
+local tconcat = table.concat
+
+-- WoW APIs
+local GetTime = GetTime
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: DEFAULT_CHAT_FRAME, geterrorhandler
+
+-- Simple ONE-SHOT timer cache. Much more efficient than a full compost for our purposes.
+local timerCache = nil
+
+--[[
+ Timers will not be fired more often than HZ-1 times per second.
+ Keep at intended speed PLUS ONE or we get bitten by floating point rounding errors (n.5 + 0.1 can be n.599999)
+ If this is ever LOWERED, all existing timers need to be enforced to have a delay >= 1/HZ on lib upgrade.
+ If this number is ever changed, all entries need to be rehashed on lib upgrade.
+ ]]
+local HZ = 11
+
+--[[
+ Prime for good distribution
+ If this number is ever changed, all entries need to be rehashed on lib upgrade.
+]]
+local BUCKETS = 131
+
+local hash = AceTimer.hash
+for i=1,BUCKETS do
+ hash[i] = hash[i] or false -- make it an integer-indexed array; it's faster than hashes
+end
+
+--[[
+ xpcall safecall implementation
+]]
+local xpcall = xpcall
+
+local function errorhandler(err)
+ return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+ local code = [[
+ local xpcall, eh = ... -- our arguments are received as unnamed values in "..." since we don't have a proper function declaration
+ local method, ARGS
+ local function call() return method(ARGS) end
+
+ local function dispatch(func, ...)
+ method = func
+ if not method then return end
+ ARGS = ...
+ return xpcall(call, eh)
+ end
+
+ return dispatch
+ ]]
+
+ local ARGS = {}
+ for i = 1, argCount do ARGS[i] = "arg"..i end
+ code = code:gsub("ARGS", tconcat(ARGS, ", "))
+ return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {
+ __index=function(self, argCount)
+ local dispatcher = CreateDispatcher(argCount)
+ rawset(self, argCount, dispatcher)
+ return dispatcher
+ end
+})
+Dispatchers[0] = function(func)
+ return xpcall(func, errorhandler)
+end
+
+local function safecall(func, ...)
+ return Dispatchers[select('#', ...)](func, ...)
+end
+
+local lastint = floor(GetTime() * HZ)
+
+-- --------------------------------------------------------------------
+-- OnUpdate handler
+--
+-- traverse buckets, always chasing "now", and fire timers that have expired
+
+local function OnUpdate()
+ local now = GetTime()
+ local nowint = floor(now * HZ)
+
+ -- Have we passed into a new hash bucket?
+ if nowint == lastint then return end
+
+ local soon = now + 1 -- +1 is safe as long as 1 < HZ < BUCKETS/2
+
+ -- Pass through each bucket at most once
+ -- Happens on e.g. instance loads, but COULD happen on high local load situations also
+ for curint = (max(lastint, nowint - BUCKETS) + 1), nowint do -- loop until we catch up with "now", usually only 1 iteration
+ local curbucket = (curint % BUCKETS)+1
+ -- Yank the list of timers out of the bucket and empty it. This allows reinsertion in the currently-processed bucket from callbacks.
+ local nexttimer = hash[curbucket]
+ hash[curbucket] = false -- false rather than nil to prevent the array from becoming a hash
+
+ while nexttimer do
+ local timer = nexttimer
+ nexttimer = timer.next
+ local when = timer.when
+
+ if when < soon then
+ -- Call the timer func, either as a method on given object, or a straight function ref
+ local callback = timer.callback
+ if type(callback) == "string" then
+ safecall(timer.object[callback], timer.object, timer.arg)
+ elseif callback then
+ safecall(callback, timer.arg)
+ else
+ -- probably nilled out by CancelTimer
+ timer.delay = nil -- don't reschedule it
+ end
+
+ local delay = timer.delay -- NOW make a local copy, can't do it earlier in case the timer cancelled itself in the callback
+
+ if not delay then
+ -- single-shot timer (or cancelled)
+ AceTimer.selfs[timer.object][tostring(timer)] = nil
+ timerCache = timer
+ else
+ -- repeating timer
+ local newtime = when + delay
+ if newtime < now then -- Keep lag from making us firing a timer unnecessarily. (Note that this still won't catch too-short-delay timers though.)
+ newtime = now + delay
+ end
+ timer.when = newtime
+
+ -- add next timer execution to the correct bucket
+ local bucket = (floor(newtime * HZ) % BUCKETS) + 1
+ timer.next = hash[bucket]
+ hash[bucket] = timer
+ end
+ else -- if when>=soon
+ -- reinsert (yeah, somewhat expensive, but shouldn't be happening too often either due to hash distribution)
+ timer.next = hash[curbucket]
+ hash[curbucket] = timer
+ end -- if whenhandle->timer registry
+ local handle = tostring(timer)
+
+ local selftimers = AceTimer.selfs[self]
+ if not selftimers then
+ selftimers = {}
+ AceTimer.selfs[self] = selftimers
+ end
+ selftimers[handle] = timer
+ selftimers.__ops = (selftimers.__ops or 0) + 1
+
+ return handle
+end
+
+--- Schedule a new one-shot timer.
+-- The timer will fire once in `delay` seconds, unless canceled before.
+-- @param callback Callback function for the timer pulse (funcref or method name).
+-- @param delay Delay for the timer, in seconds.
+-- @param arg An optional argument to be passed to the callback function.
+-- @usage
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
+--
+-- function MyAddon:OnEnable()
+-- self:ScheduleTimer("TimerFeedback", 5)
+-- end
+--
+-- function MyAddon:TimerFeedback()
+-- print("5 seconds passed")
+-- end
+function AceTimer:ScheduleTimer(callback, delay, arg)
+ return Reg(self, callback, delay, arg)
+end
+
+--- Schedule a repeating timer.
+-- The timer will fire every `delay` seconds, until canceled.
+-- @param callback Callback function for the timer pulse (funcref or method name).
+-- @param delay Delay for the timer, in seconds.
+-- @param arg An optional argument to be passed to the callback function.
+-- @usage
+-- MyAddon = LibStub("AceAddon-3.0"):NewAddon("TimerTest", "AceTimer-3.0")
+--
+-- function MyAddon:OnEnable()
+-- self.timerCount = 0
+-- self.testTimer = self:ScheduleRepeatingTimer("TimerFeedback", 5)
+-- end
+--
+-- function MyAddon:TimerFeedback()
+-- self.timerCount = self.timerCount + 1
+-- print(("%d seconds passed"):format(5 * self.timerCount))
+-- -- run 30 seconds in total
+-- if self.timerCount == 6 then
+-- self:CancelTimer(self.testTimer)
+-- end
+-- end
+function AceTimer:ScheduleRepeatingTimer(callback, delay, arg)
+ return Reg(self, callback, delay, arg, true)
+end
+
+--- Cancels a timer with the given handle, registered by the same addon object as used for `:ScheduleTimer`
+-- Both one-shot and repeating timers can be canceled with this function, as long as the `handle` is valid
+-- and the timer has not fired yet or was canceled before.
+-- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
+-- @param silent If true, no error is raised if the timer handle is invalid (expired or already canceled)
+-- @return True if the timer was successfully cancelled.
+function AceTimer:CancelTimer(handle, silent)
+ if not handle then return end -- nil handle -> bail out without erroring
+ if type(handle) ~= "string" then
+ error(MAJOR..": CancelTimer(handle): 'handle' - expected a string", 2) -- for now, anyway
+ end
+ local selftimers = AceTimer.selfs[self]
+ local timer = selftimers and selftimers[handle]
+ if silent then
+ if timer then
+ timer.callback = nil -- don't run it again
+ timer.delay = nil -- if this is the currently-executing one: don't even reschedule
+ -- The timer object is removed in the OnUpdate loop
+ end
+ return not not timer -- might return "true" even if we double-cancel. we'll live.
+ else
+ if not timer then
+ geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - no such timer registered")
+ return false
+ end
+ if not timer.callback then
+ geterrorhandler()(MAJOR..": CancelTimer(handle[, silent]): '"..tostring(handle).."' - timer already cancelled or expired")
+ return false
+ end
+ timer.callback = nil -- don't run it again
+ timer.delay = nil -- if this is the currently-executing one: don't even reschedule
+ return true
+ end
+end
+
+--- Cancels all timers registered to the current addon object ('self')
+function AceTimer:CancelAllTimers()
+ if not(type(self) == "string" or type(self) == "table") then
+ error(MAJOR..": CancelAllTimers(): 'self' - must be a string or a table",2)
+ end
+ if self == AceTimer then
+ error(MAJOR..": CancelAllTimers(): supply a meaningful 'self'", 2)
+ end
+
+ local selftimers = AceTimer.selfs[self]
+ if selftimers then
+ for handle,v in pairs(selftimers) do
+ if type(v) == "table" then -- avoid __ops, etc
+ AceTimer.CancelTimer(self, handle, true)
+ end
+ end
+ end
+end
+
+--- Returns the time left for a timer with the given handle, registered by the current addon object ('self').
+-- This function will raise a warning when the handle is invalid, but not stop execution.
+-- @param handle The handle of the timer, as returned by `:ScheduleTimer` or `:ScheduleRepeatingTimer`
+-- @return The time left on the timer, or false if the handle is invalid.
+function AceTimer:TimeLeft(handle)
+ if not handle then return end
+ if type(handle) ~= "string" then
+ error(MAJOR..": TimeLeft(handle): 'handle' - expected a string", 2) -- for now, anyway
+ end
+ local selftimers = AceTimer.selfs[self]
+ local timer = selftimers and selftimers[handle]
+ if not timer then
+ geterrorhandler()(MAJOR..": TimeLeft(handle): '"..tostring(handle).."' - no such timer registered")
+ return false
+ end
+ return timer.when - GetTime()
+end
+
+
+-- ---------------------------------------------------------------------
+-- PLAYER_REGEN_ENABLED: Run through our .selfs[] array step by step
+-- and clean it out - otherwise the table indices can grow indefinitely
+-- if an addon starts and stops a lot of timers. AceBucket does this!
+--
+-- See ACE-94 and tests/AceTimer-3.0-ACE-94.lua
+
+local lastCleaned = nil
+
+local function OnEvent(this, event)
+ if event~="PLAYER_REGEN_ENABLED" then
+ return
+ end
+
+ -- Get the next 'self' to process
+ local selfs = AceTimer.selfs
+ local self = next(selfs, lastCleaned)
+ if not self then
+ self = next(selfs)
+ end
+ lastCleaned = self
+ if not self then -- should only happen if .selfs[] is empty
+ return
+ end
+
+ -- Time to clean it out?
+ local list = selfs[self]
+ if (list.__ops or 0) < 250 then -- 250 slosh indices = ~10KB wasted (worst case!). For one 'self'.
+ return
+ end
+
+ -- Create a new table and copy all members over
+ local newlist = {}
+ local n=0
+ for k,v in pairs(list) do
+ newlist[k] = v
+ if type(v)=="table" and v.callback then -- if the timer is actually live: count it
+ n=n+1
+ end
+ end
+ newlist.__ops = 0 -- Reset operation count
+
+ -- And since we now have a count of the number of live timers, check that it's reasonable. Emit a warning if not.
+ if n>BUCKETS then
+ DEFAULT_CHAT_FRAME:AddMessage(MAJOR..": Warning: The addon/module '"..tostring(self).."' has "..n.." live timers. Surely that's not intended?")
+ end
+
+ selfs[self] = newlist
+end
+
+-- ---------------------------------------------------------------------
+-- Embed handling
+
+AceTimer.embeds = AceTimer.embeds or {}
+
+local mixins = {
+ "ScheduleTimer", "ScheduleRepeatingTimer",
+ "CancelTimer", "CancelAllTimers",
+ "TimeLeft"
+}
+
+function AceTimer:Embed(target)
+ AceTimer.embeds[target] = true
+ for _,v in pairs(mixins) do
+ target[v] = AceTimer[v]
+ end
+ return target
+end
+
+-- AceTimer:OnEmbedDisable( target )
+-- target (object) - target object that AceTimer is embedded in.
+--
+-- cancel all timers registered for the object
+function AceTimer:OnEmbedDisable( target )
+ target:CancelAllTimers()
+end
+
+
+for addon in pairs(AceTimer.embeds) do
+ AceTimer:Embed(addon)
+end
+
+-- ---------------------------------------------------------------------
+-- Debug tools (expose copies of internals to test suites)
+AceTimer.debug = AceTimer.debug or {}
+AceTimer.debug.HZ = HZ
+AceTimer.debug.BUCKETS = BUCKETS
+
+-- ---------------------------------------------------------------------
+-- Finishing touchups
+
+AceTimer.frame:SetScript("OnUpdate", OnUpdate)
+AceTimer.frame:SetScript("OnEvent", OnEvent)
+AceTimer.frame:RegisterEvent("PLAYER_REGEN_ENABLED")
+
+-- In theory, we could hide&show the frame based on there being timers or not.
+-- However, this job is fairly expensive, and the chance that there will
+-- actually be zero timers running is diminuitive to say the least.
diff --git a/Libs/AceTimer-3.0/AceTimer-3.0.xml b/Libs/AceTimer-3.0/AceTimer-3.0.xml
new file mode 100644
index 00000000..7c478a45
--- /dev/null
+++ b/Libs/AceTimer-3.0/AceTimer-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua b/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
new file mode 100644
index 00000000..e0fe1af0
--- /dev/null
+++ b/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
@@ -0,0 +1,240 @@
+--[[ $Id: CallbackHandler-1.0.lua 14 2010-08-09 00:43:38Z mikk $ ]]
+local MAJOR, MINOR = "CallbackHandler-1.0", 6
+local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not CallbackHandler then return end -- No upgrade needed
+
+local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
+
+-- Lua APIs
+local tconcat = table.concat
+local assert, error, loadstring = assert, error, loadstring
+local setmetatable, rawset, rawget = setmetatable, rawset, rawget
+local next, select, pairs, type, tostring = next, select, pairs, type, tostring
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: geterrorhandler
+
+local xpcall = xpcall
+
+local function errorhandler(err)
+ return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+ local code = [[
+ local next, xpcall, eh = ...
+
+ local method, ARGS
+ local function call() method(ARGS) end
+
+ local function dispatch(handlers, ...)
+ local index
+ index, method = next(handlers)
+ if not method then return end
+ local OLD_ARGS = ARGS
+ ARGS = ...
+ repeat
+ xpcall(call, eh)
+ index, method = next(handlers, index)
+ until not method
+ ARGS = OLD_ARGS
+ end
+
+ return dispatch
+ ]]
+
+ local ARGS, OLD_ARGS = {}, {}
+ for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
+ code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", "))
+ return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {__index=function(self, argCount)
+ local dispatcher = CreateDispatcher(argCount)
+ rawset(self, argCount, dispatcher)
+ return dispatcher
+end})
+
+--------------------------------------------------------------------------
+-- CallbackHandler:New
+--
+-- target - target object to embed public APIs in
+-- RegisterName - name of the callback registration API, default "RegisterCallback"
+-- UnregisterName - name of the callback unregistration API, default "UnregisterCallback"
+-- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
+
+function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
+ -- TODO: Remove this after beta has gone out
+ assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
+
+ RegisterName = RegisterName or "RegisterCallback"
+ UnregisterName = UnregisterName or "UnregisterCallback"
+ if UnregisterAllName==nil then -- false is used to indicate "don't want this method"
+ UnregisterAllName = "UnregisterAllCallbacks"
+ end
+
+ -- we declare all objects and exported APIs inside this closure to quickly gain access
+ -- to e.g. function names, the "target" parameter, etc
+
+
+ -- Create the registry object
+ local events = setmetatable({}, meta)
+ local registry = { recurse=0, events=events }
+
+ -- registry:Fire() - fires the given event/message into the registry
+ function registry:Fire(eventname, ...)
+ if not rawget(events, eventname) or not next(events[eventname]) then return end
+ local oldrecurse = registry.recurse
+ registry.recurse = oldrecurse + 1
+
+ Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
+
+ registry.recurse = oldrecurse
+
+ if registry.insertQueue and oldrecurse==0 then
+ -- Something in one of our callbacks wanted to register more callbacks; they got queued
+ for eventname,callbacks in pairs(registry.insertQueue) do
+ local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
+ for self,func in pairs(callbacks) do
+ events[eventname][self] = func
+ -- fire OnUsed callback?
+ if first and registry.OnUsed then
+ registry.OnUsed(registry, target, eventname)
+ first = nil
+ end
+ end
+ end
+ registry.insertQueue = nil
+ end
+ end
+
+ -- Registration of a callback, handles:
+ -- self["method"], leads to self["method"](self, ...)
+ -- self with function ref, leads to functionref(...)
+ -- "addonId" (instead of self) with function ref, leads to functionref(...)
+ -- all with an optional arg, which, if present, gets passed as first argument (after self if present)
+ target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
+ if type(eventname) ~= "string" then
+ error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
+ end
+
+ method = method or eventname
+
+ local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten.
+
+ if type(method) ~= "string" and type(method) ~= "function" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
+ end
+
+ local regfunc
+
+ if type(method) == "string" then
+ -- self["method"] calling style
+ if type(self) ~= "table" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
+ elseif self==target then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
+ elseif type(self[method]) ~= "function" then
+ error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
+ end
+
+ if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
+ local arg=select(1,...)
+ regfunc = function(...) self[method](self,arg,...) end
+ else
+ regfunc = function(...) self[method](self,...) end
+ end
+ else
+ -- function ref with self=object or self="addonId" or self=thread
+ if type(self)~="table" and type(self)~="string" and type(self)~="thread" then
+ error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread expected.", 2)
+ end
+
+ if select("#",...)>=1 then -- this is not the same as testing for arg==nil!
+ local arg=select(1,...)
+ regfunc = function(...) method(arg,...) end
+ else
+ regfunc = method
+ end
+ end
+
+
+ if events[eventname][self] or registry.recurse<1 then
+ -- if registry.recurse<1 then
+ -- we're overwriting an existing entry, or not currently recursing. just set it.
+ events[eventname][self] = regfunc
+ -- fire OnUsed callback?
+ if registry.OnUsed and first then
+ registry.OnUsed(registry, target, eventname)
+ end
+ else
+ -- we're currently processing a callback in this registry, so delay the registration of this new entry!
+ -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
+ registry.insertQueue = registry.insertQueue or setmetatable({},meta)
+ registry.insertQueue[eventname][self] = regfunc
+ end
+ end
+
+ -- Unregister a callback
+ target[UnregisterName] = function(self, eventname)
+ if not self or self==target then
+ error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
+ end
+ if type(eventname) ~= "string" then
+ error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
+ end
+ if rawget(events, eventname) and events[eventname][self] then
+ events[eventname][self] = nil
+ -- Fire OnUnused callback?
+ if registry.OnUnused and not next(events[eventname]) then
+ registry.OnUnused(registry, target, eventname)
+ end
+ end
+ if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
+ registry.insertQueue[eventname][self] = nil
+ end
+ end
+
+ -- OPTIONAL: Unregister all callbacks for given selfs/addonIds
+ if UnregisterAllName then
+ target[UnregisterAllName] = function(...)
+ if select("#",...)<1 then
+ error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
+ end
+ if select("#",...)==1 and ...==target then
+ error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
+ end
+
+
+ for i=1,select("#",...) do
+ local self = select(i,...)
+ if registry.insertQueue then
+ for eventname, callbacks in pairs(registry.insertQueue) do
+ if callbacks[self] then
+ callbacks[self] = nil
+ end
+ end
+ end
+ for eventname, callbacks in pairs(events) do
+ if callbacks[self] then
+ callbacks[self] = nil
+ -- Fire OnUnused callback?
+ if registry.OnUnused and not next(callbacks) then
+ registry.OnUnused(registry, target, eventname)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ return registry
+end
+
+
+-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
+-- try to upgrade old implicit embeds since the system is selfcontained and
+-- relies on closures to work.
+
diff --git a/Libs/CallbackHandler-1.0/CallbackHandler-1.0.xml b/Libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
new file mode 100644
index 00000000..1aad3a2e
--- /dev/null
+++ b/Libs/CallbackHandler-1.0/CallbackHandler-1.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Libs/LibGraph-2.0/1-1.tga b/Libs/LibGraph-2.0/1-1.tga
new file mode 100644
index 00000000..bbf8393b
Binary files /dev/null and b/Libs/LibGraph-2.0/1-1.tga differ
diff --git a/Libs/LibGraph-2.0/1-128.tga b/Libs/LibGraph-2.0/1-128.tga
new file mode 100644
index 00000000..f6f417a5
Binary files /dev/null and b/Libs/LibGraph-2.0/1-128.tga differ
diff --git a/Libs/LibGraph-2.0/1-16.tga b/Libs/LibGraph-2.0/1-16.tga
new file mode 100644
index 00000000..720ba193
Binary files /dev/null and b/Libs/LibGraph-2.0/1-16.tga differ
diff --git a/Libs/LibGraph-2.0/1-2.tga b/Libs/LibGraph-2.0/1-2.tga
new file mode 100644
index 00000000..723269d4
Binary files /dev/null and b/Libs/LibGraph-2.0/1-2.tga differ
diff --git a/Libs/LibGraph-2.0/1-32.tga b/Libs/LibGraph-2.0/1-32.tga
new file mode 100644
index 00000000..78f507d5
Binary files /dev/null and b/Libs/LibGraph-2.0/1-32.tga differ
diff --git a/Libs/LibGraph-2.0/1-4.tga b/Libs/LibGraph-2.0/1-4.tga
new file mode 100644
index 00000000..5976672f
Binary files /dev/null and b/Libs/LibGraph-2.0/1-4.tga differ
diff --git a/Libs/LibGraph-2.0/1-64.tga b/Libs/LibGraph-2.0/1-64.tga
new file mode 100644
index 00000000..24700474
Binary files /dev/null and b/Libs/LibGraph-2.0/1-64.tga differ
diff --git a/Libs/LibGraph-2.0/1-8.tga b/Libs/LibGraph-2.0/1-8.tga
new file mode 100644
index 00000000..f16926f4
Binary files /dev/null and b/Libs/LibGraph-2.0/1-8.tga differ
diff --git a/Libs/LibGraph-2.0/LibGraph-2.0.lua b/Libs/LibGraph-2.0/LibGraph-2.0.lua
new file mode 100644
index 00000000..e855e0fa
--- /dev/null
+++ b/Libs/LibGraph-2.0/LibGraph-2.0.lua
@@ -0,0 +1,2288 @@
+--[[
+Name: LibGraph-2.0
+Revision: $Rev: 49 $
+Author(s): Cryect (cryect@gmail.com), Xinhuan
+Website: http://www.wowace.com/
+Documentation: http://www.wowace.com/wiki/GraphLib
+SVN: http://svn.wowace.com/root/trunk/GraphLib/
+Description: Allows for easy creation of graphs
+]]
+
+--Thanks to Nelson Minar for catching several errors where width was being used instead of height (damn copy and paste >_>)
+
+local major = "LibGraph-2.0"
+local minor = 90000 + tonumber(("$Revision: 50 $"):match("(%d+)"))
+
+--Search for just Addon\\ at the front since the interface part often gets trimmed
+--Do this before anything else, so if it errors, any existing loaded copy of LibGraph-2.0
+--doesn't get modified with a newer revision (this one)
+
+--change log:
+ -- 10/07/2013 added new methods (tercioo):
+ --SetLineTexture (texture path or 'line', 'smalline', 'thinline') for line graphics.
+ --SetBorderSize (border side, length) border side can be left right top bottom, done to line graph atm.
+
+local TextureDirectory
+do
+ local path = string.match(debugstack(1,1,0), "AddOns\\(.+)LibGraph%-2%.0%.lua")
+ if path then
+ TextureDirectory = "Interface\\AddOns\\"..path
+ else
+ error(major.." cannot determine the folder it is located in because the path is too long and got truncated in the debugstack(1,1,0) function call")
+ end
+end
+
+
+if not LibStub then error(major .. " requires LibStub") end
+
+local lib, oldLibMinor = LibStub:NewLibrary(major, minor)
+if not lib then return end
+
+local GraphFunctions={}
+
+local tinsert, tremove = tinsert, tremove
+local pairs, ipairs = pairs, ipairs
+local math_max = math.max
+local math_min = math.min
+local math_ceil = math.ceil
+local math_pi = math.pi
+local math_floor = math.floor
+local math_pow = math.pow
+local math_random = math.random
+local math_cos = math.cos
+local math_sin = math.sin
+local math_deg = math.deg
+local math_atan = math.atan
+local math_abs = math.abs
+local math_fmod = math.fmod
+local math_huge = math.huge
+local GetTime = GetTime
+
+-- lib upgrade stuff
+lib.RegisteredGraphRealtime = lib.RegisteredGraphRealtime or {}
+lib.RegisteredGraphLine = lib.RegisteredGraphLine or {}
+lib.RegisteredGraphScatterPlot = lib.RegisteredGraphScatterPlot or {}
+lib.RegisteredGraphPieChart = lib.RegisteredGraphPieChart or {}
+
+
+
+--------------------------------------------------------------------------------
+--Graph Creation Functions
+--------------------------------------------------------------------------------
+
+--Realtime Graph
+local function SetupGraphRealtimeFunctions(graph, upgrade)
+ local self = lib
+
+ --Set the various functions
+ graph.SetXAxis=GraphFunctions.SetXAxis
+ graph.SetYMax=GraphFunctions.SetYMax
+ graph.AddTimeData=GraphFunctions.AddTimeData
+ graph.OnUpdate=GraphFunctions.OnUpdateGraphRealtime
+ graph.CreateGridlines=GraphFunctions.CreateGridlines
+ graph.RefreshGraph=GraphFunctions.RefreshRealtimeGraph
+ graph.SetAxisDrawing=GraphFunctions.SetAxisDrawing
+ graph.SetGridSpacing=GraphFunctions.SetGridSpacing
+ graph.SetAxisColor=GraphFunctions.SetAxisColor
+ graph.SetGridColor=GraphFunctions.SetGridColor
+ graph.SetGridColorSecondary=GraphFunctions.SetGridColorSecondary
+ graph.SetGridSecondaryMultiple=GraphFunctions.SetGridSecondaryMultiple
+ graph.SetFilterRadius=GraphFunctions.SetFilterRadius
+ --graph.SetAutoscaleYAxis=GraphFunctions.SetAutoscaleYAxis
+ graph.SetBarColors=GraphFunctions.SetBarColors
+ graph.SetMode=GraphFunctions.SetMode
+ graph.SetAutoScale=GraphFunctions.SetAutoScale
+ if not upgrade then
+ -- This is the original frame:SetWidth() and frame:SetHeight()
+ -- standard frame functions
+ graph.OldSetWidth=graph.SetWidth
+ graph.OldSetHeight=graph.SetHeight
+ end
+ graph.SetWidth=GraphFunctions.RealtimeSetWidth
+ graph.SetHeight=GraphFunctions.RealtimeSetHeight
+ graph.SetBarColors=GraphFunctions.RealtimeSetColors
+ graph.GetMaxValue=GraphFunctions.GetMaxValue
+ graph.GetValue=GraphFunctions.RealtimeGetValue
+ graph.SetUpdateLimit=GraphFunctions.SetUpdateLimit
+ graph.SetDecay=GraphFunctions.SetDecay
+ graph.SetMinMaxY=GraphFunctions.SetMinMaxY
+ graph.AddBar=GraphFunctions.AddBar
+ graph.SetYLabels=GraphFunctions.SetYLabels
+
+
+
+ graph.DrawLine=self.DrawLine
+ graph.DrawHLine=self.DrawHLine
+ graph.DrawVLine=self.DrawVLine
+ graph.HideLines=self.HideLines
+ graph.HideFontStrings=GraphFunctions.HideFontStrings
+ graph.FindFontString=GraphFunctions.FindFontString
+ graph.SetBars=GraphFunctions.SetBars
+
+
+ --Set the update function
+ graph:SetScript("OnUpdate", graph.OnUpdate)
+end
+
+function lib:CreateGraphRealtime(name,parent,relative,relativeTo,offsetX,offsetY,Width,Height)
+ local graph
+ local i
+ graph = CreateFrame("Frame",name,parent)
+
+ Width=math_floor(Width)
+
+
+ graph:SetPoint(relative,parent,relativeTo,offsetX,offsetY)
+ graph:SetWidth(Width)
+ graph:SetHeight(Height)
+ graph:Show()
+
+ --Create the bars
+ graph.Bars={}
+ graph.BarsUsing={}
+ graph.BarNum=Width
+ graph.Height=Height
+ for i=1,Width do
+ local bar
+ bar = CreateFrame("StatusBar",name.."Bar"..i,graph)--graph:CreateTexture(nil,"ARTWORK")
+ bar:SetPoint("BOTTOMLEFT",graph,"BOTTOMLEFT",i-1,0)
+ bar:SetHeight(Height)
+ bar:SetWidth(1)
+ bar:SetOrientation("VERTICAL")
+ bar:SetMinMaxValues(0,1)
+ bar:SetStatusBarTexture("Interface\\Buttons\\WHITE8X8.blp")
+ bar:GetStatusBarTexture():SetHorizTile(false)
+ bar:GetStatusBarTexture():SetVertTile(false)
+
+ local t=bar:GetStatusBarTexture()
+ t:SetGradientAlpha("VERTICAL",0.2,0.0,0.0,0.5,1.0,0.0,0.0,1.0)
+
+ bar:Show()
+ tinsert(graph.Bars,bar)
+ tinsert(graph.BarsUsing,bar)
+ end
+
+
+ SetupGraphRealtimeFunctions(graph)
+
+
+ --Initialize Data
+ graph.GraphType="REALTIME"
+ graph.YMax=60
+ graph.YMin=0
+ graph.XMax=-0.75
+ graph.XMin=-10
+ graph.TimeRadius=0.5
+ graph.Mode="FAST"
+ graph.Filter="RECT"
+ graph.AxisColor={1.0,1.0,1.0,1.0}
+ graph.GridColor={0.5,0.5,0.5,0.5}
+ graph.BarColorTop={1.0,0.0,0.0,1.0}
+ graph.BarColorBot={0.2,0.0,0.0,0.5}
+ graph.AutoScale=false
+ graph.Data={}
+ graph.MinMaxY=0
+ graph.CurVal=0
+ graph.LastDataTime=GetTime()
+
+ graph.Textures={}
+ graph.TexturesUsed={}
+
+ graph.LimitUpdates=0
+ graph.NextUpdate=0
+
+ graph.BarHeight={}
+ graph.LastShift=GetTime()
+ graph.BarWidth=(graph.XMax-graph.XMin)/graph.BarNum
+ graph.DecaySet=0.8
+ graph.Decay=math_pow(graph.DecaySet,graph.BarWidth)
+ graph.ExpNorm=1/(1-graph.Decay)
+
+ graph.FilterOverlap=math_max(math_ceil((graph.TimeRadius+graph.XMax)/graph.BarWidth),0)
+ for i=1,graph.BarNum do
+ graph.BarHeight[i]=0
+ end
+
+ graph.TextFrame = CreateFrame("Frame",nil,graph)
+ graph.TextFrame:SetAllPoints(graph)
+ graph.TextFrame:SetFrameLevel(graph:GetFrameLevel()+2)
+
+ tinsert(self.RegisteredGraphRealtime, graph)
+ return graph
+end
+
+--Line Graph
+local function SetupGraphLineFunctions(graph)
+ local self = lib
+
+ --Set the various functions
+ graph.SetXAxis=GraphFunctions.SetXAxis
+ graph.SetYAxis=GraphFunctions.SetYAxis
+ graph.AddDataSeries=GraphFunctions.AddDataSeries
+ graph.AddFilledDataSeries=GraphFunctions.AddFilledDataSeries
+ graph.ResetData=GraphFunctions.ResetData
+ graph.RefreshGraph=GraphFunctions.RefreshLineGraph
+ graph.CreateGridlines=GraphFunctions.CreateGridlines
+ graph.SetAxisDrawing=GraphFunctions.SetAxisDrawing
+ graph.SetGridSpacing=GraphFunctions.SetGridSpacing
+ graph.SetAxisColor=GraphFunctions.SetAxisColor
+ graph.SetGridColor=GraphFunctions.SetGridColor
+ graph.SetGridColorSecondary=GraphFunctions.SetGridColorSecondary
+ graph.SetGridSecondaryMultiple=GraphFunctions.SetGridSecondaryMultiple
+ graph.SetAutoScale=GraphFunctions.SetAutoScale
+ graph.SetYLabels=GraphFunctions.SetYLabels
+ graph.SetLineTexture=GraphFunctions.SetLineTexture
+ graph.SetBorderSize=GraphFunctions.SetBorderSize
+ graph.OnUpdate=GraphFunctions.OnUpdateGraph
+
+ graph.LockXMin=GraphFunctions.LockXMin
+ graph.LockXMax=GraphFunctions.LockXMax
+ graph.LockYMin=GraphFunctions.LockYMin
+ graph.LockYMax=GraphFunctions.LockYMax
+
+ graph.DrawLine=self.DrawLine
+ graph.DrawHLine=self.DrawHLine
+ graph.DrawVLine=self.DrawVLine
+ graph.HideLines=self.HideLines
+ graph.DrawBar=self.DrawBar
+ graph.HideBars=self.HideBars
+ graph.HideFontStrings=GraphFunctions.HideFontStrings
+ graph.FindFontString=GraphFunctions.FindFontString
+
+ --Set the update function
+ graph:SetScript("OnUpdate", graph.OnUpdate)
+end
+
+--TODO: Clip lines with the bounds
+function lib:CreateGraphLine(name,parent,relative,relativeTo,offsetX,offsetY,Width,Height)
+ local graph
+ local i
+ graph = CreateFrame("Frame",name,parent)
+
+
+ graph:SetPoint(relative,parent,relativeTo,offsetX,offsetY)
+ graph:SetWidth(Width)
+ graph:SetHeight(Height)
+ graph:Show()
+
+
+ SetupGraphLineFunctions(graph)
+
+
+ graph.NeedsUpdate=false
+
+
+ --Initialize Data
+ graph.GraphType="LINE"
+ graph.YMax=1
+ graph.YMin=-1
+ graph.XMax=1
+ graph.XMin=-1
+ graph.AxisColor={1.0,1.0,1.0,1.0}
+ graph.GridColor={0.5,0.5,0.5,0.5}
+ graph.XGridInterval=0.25
+ graph.YGridInterval=0.25
+ graph.XAxisDrawn=true
+ graph.YAxisDrawn=true
+
+ graph.LockOnXMin=false
+ graph.LockOnXMax=false
+ graph.LockOnYMin=false
+ graph.LockOnYMax=false
+ graph.Data={}
+ graph.FilledData={}
+ graph.Textures={}
+ graph.TexturesUsed={}
+ graph.TextFrame = CreateFrame("Frame",nil,graph)
+ graph.TextFrame:SetAllPoints(graph)
+
+
+ tinsert(self.RegisteredGraphLine, graph)
+ return graph
+end
+
+
+--Scatter Plot
+local function SetupGraphScatterPlotFunctions(graph)
+ local self = lib
+
+ --Set the various functions
+ graph.SetXAxis=GraphFunctions.SetXAxis
+ graph.SetYAxis=GraphFunctions.SetYAxis
+ graph.AddDataSeries=GraphFunctions.AddDataSeries
+ graph.ResetData=GraphFunctions.ResetData
+ graph.RefreshGraph=GraphFunctions.RefreshScatterPlot
+ graph.CreateGridlines=GraphFunctions.CreateGridlines
+ graph.OnUpdate=GraphFunctions.OnUpdateGraph
+
+ graph.LinearRegression=GraphFunctions.LinearRegression
+ graph.SetAxisDrawing=GraphFunctions.SetAxisDrawing
+ graph.SetGridSpacing=GraphFunctions.SetGridSpacing
+ graph.SetAxisColor=GraphFunctions.SetAxisColor
+ graph.SetGridColor=GraphFunctions.SetGridColor
+ graph.SetGridColorSecondary=GraphFunctions.SetGridColorSecondary
+ graph.SetGridSecondaryMultiple=GraphFunctions.SetGridSecondaryMultiple
+ graph.SetLinearFit=GraphFunctions.SetLinearFit
+ graph.SetAutoScale=GraphFunctions.SetAutoScale
+ graph.SetYLabels=GraphFunctions.SetYLabels
+
+ graph.LockXMin=GraphFunctions.LockXMin
+ graph.LockXMax=GraphFunctions.LockXMax
+ graph.LockYMin=GraphFunctions.LockYMin
+ graph.LockYMax=GraphFunctions.LockYMax
+
+ graph.DrawLine=self.DrawLine
+ graph.DrawHLine=self.DrawHLine
+ graph.DrawVLine=self.DrawVLine
+ graph.HideLines=self.HideLines
+ graph.HideTextures=GraphFunctions.HideTextures
+ graph.FindTexture=GraphFunctions.FindTexture
+ graph.HideFontStrings=GraphFunctions.HideFontStrings
+ graph.FindFontString=GraphFunctions.FindFontString
+
+ --Set the update function
+ graph:SetScript("OnUpdate", graph.OnUpdate)
+end
+
+function lib:CreateGraphScatterPlot(name,parent,relative,relativeTo,offsetX,offsetY,Width,Height)
+ local graph
+ local i
+ graph = CreateFrame("Frame",name,parent)
+
+
+ graph:SetPoint(relative,parent,relativeTo,offsetX,offsetY)
+ graph:SetWidth(Width)
+ graph:SetHeight(Height)
+ graph:Show()
+
+
+ SetupGraphScatterPlotFunctions(graph)
+
+
+ graph.NeedsUpdate=false
+
+ --Initialize Data
+ graph.GraphType="SCATTER"
+ graph.YMax=1
+ graph.YMin=-1
+ graph.XMax=1
+ graph.XMin=-1
+ graph.AxisColor={1.0,1.0,1.0,1.0}
+ graph.GridColor={0.5,0.5,0.5,0.5}
+ graph.XGridInterval=0.25
+ graph.YGridInterval=0.25
+ graph.XAxisDrawn=true
+ graph.YAxisDrawn=true
+ graph.AutoScale=false
+ graph.LinearFit=false
+ graph.LockOnXMin=false
+ graph.LockOnXMax=false
+ graph.LockOnYMin=false
+ graph.LockOnYMax=false
+ graph.Data={}
+ graph.Textures={}
+ graph.TexturesUsed={}
+
+ graph.TextFrame = CreateFrame("Frame",nil,graph)
+ graph.TextFrame:SetAllPoints(graph)
+
+ tinsert(self.RegisteredGraphScatterPlot, graph)
+ return graph
+end
+
+--Pie Chart
+local function SetupGraphPieChartFunctions(graph)
+ local self = lib
+
+ --Set the various functions
+ graph.AddPie=GraphFunctions.AddPie
+ graph.CompletePie=GraphFunctions.CompletePie
+ graph.ResetPie=GraphFunctions.ResetPie
+
+ graph.DrawLine=self.DrawLine
+ graph.DrawHLine=self.DrawHLine
+ graph.DrawVLine=self.DrawVLine
+ graph.DrawLinePie=GraphFunctions.DrawLinePie
+ graph.HideLines=self.HideLines
+ graph.HideTextures=GraphFunctions.HideTextures
+ graph.FindTexture=GraphFunctions.FindTexture
+ graph.OnUpdate=GraphFunctions.PieChart_OnUpdate
+ graph.SetSelectionFunc=GraphFunctions.SetSelectionFunc
+
+ graph:SetScript("OnUpdate", graph.OnUpdate)
+end
+
+function lib:CreateGraphPieChart(name,parent,relative,relativeTo,offsetX,offsetY,Width,Height)
+ local graph
+ local i
+ graph = CreateFrame("Frame",name,parent)
+
+
+ graph:SetPoint(relative,parent,relativeTo,offsetX,offsetY)
+ graph:SetWidth(Width)
+ graph:SetHeight(Height)
+ graph:Show()
+
+
+ SetupGraphPieChartFunctions(graph)
+
+
+
+ --Initialize Data
+ graph.GraphType="PIE"
+ graph.PieUsed=0
+ graph.PercentOn=0
+ graph.Remaining=0
+ graph.Textures={}
+ graph.Ratio=Width/Height
+ graph.Radius=0.88*(Width/2)
+ graph.Radius=graph.Radius*graph.Radius
+ graph.Sections={}
+ graph.Textures={}
+ graph.TexturesUsed={}
+ graph.LastSection=nil
+ graph.onColor=1
+ graph.TotalSections=0
+
+ tinsert(self.RegisteredGraphPieChart, graph)
+ return graph
+end
+
+
+
+
+
+
+
+
+
+
+-------------------------------------------------------------------------------
+--Functions for Realtime Graphs
+-------------------------------------------------------------------------------
+
+--AddTimeData - Adds a data value to the realtime graph at this moment in time
+function GraphFunctions:AddTimeData(value)
+ if type(value)~="number" then
+ return
+ end
+
+ local t={}
+ t.Time=GetTime()
+ self.LastDataTime=t.Time
+ t.Value=value
+ tinsert(self.Data,t)
+end
+
+--RefreshRealtimeGraph - Refreshes the gridlines for the realtime graph
+function GraphFunctions:RefreshRealtimeGraph()
+ self:HideLines(self)
+ self:CreateGridlines()
+end
+
+--SetFilterRadius - controls the radius of the filter
+function GraphFunctions:SetFilterRadius(radius)
+ self.TimeRadius=radius
+end
+
+--SetAutoscaleYAxis - If enabled the maximum y axis is adjusted to be 25% more than the max value
+function GraphFunctions:SetAutoscaleYAxis(scale)
+ self.AutoScale=scale
+end
+
+--SetBarColors -
+function GraphFunctions:SetBarColors(BotColor,TopColor)
+ local Temp
+ if BotColor.r then
+ Temp=BotColor
+ BotColor={Temp.r,Temp.g,Temp.b,Temp.a}
+ end
+ if TopColor.r then
+ Temp=TopColor
+ TopColor={Temp.r,Temp.g,Temp.b,Temp.a}
+ end
+ for i=1,self.BarNum do
+ local t=self.Bars[i]:GetStatusBarTexture()
+ t:SetGradientAlpha("VERTICAL",BotColor[1],BotColor[2],BotColor[3],BotColor[4],TopColor[1],TopColor[2],TopColor[3],TopColor[4])
+ end
+end
+
+function GraphFunctions:SetMode(mode)
+ self.Mode=mode
+
+ if mode~="SLOW" then
+ self.LastShift=GetTime()+self.XMin
+ end
+end
+
+function GraphFunctions:RealtimeSetColors(BotColor,TopColor)
+ local Temp
+ if BotColor.r then
+ Temp=BotColor
+ BotColor={Temp.r,Temp.g,Temp.b,Temp.a}
+ end
+ if TopColor.r then
+ Temp=TopColor
+ TopColor={Temp.r,Temp.g,Temp.b,Temp.a}
+ end
+ self.BarColorBot=BotColor
+ self.BarColorTop=TopColor
+ for _,v in pairs(self.Bars) do
+ v:GetStatusBarTexture():SetGradientAlpha("VERTICAL",self.BarColorBot[1],self.BarColorBot[2],self.BarColorBot[3],self.BarColorBot[4],self.BarColorTop[1],self.BarColorTop[2],self.BarColorTop[3],self.BarColorTop[4])
+ end
+end
+
+function GraphFunctions:RealtimeSetWidth(Width)
+ Width=math_floor(Width)
+
+ if Width==self.BarNum then
+ return
+ end
+
+ self.BarNum=Width
+ for i=1,Width do
+ if type(self.Bars[i])=="nil" then
+ local bar
+ bar = CreateFrame("StatusBar",self:GetName().."Bar"..i,self)
+ bar:SetPoint("BOTTOMLEFT",self,"BOTTOMLEFT",i-1,0)
+ bar:SetHeight(self.Height)
+ bar:SetWidth(1)
+ bar:SetOrientation("VERTICAL")
+ bar:SetMinMaxValues(0,1)
+ bar:SetStatusBarTexture("Interface\\Buttons\\WHITE8X8.blp")
+ bar:GetStatusBarTexture():SetHorizTile(false)
+ bar:GetStatusBarTexture():SetVertTile(false)
+
+ local t=bar:GetStatusBarTexture()
+ t:SetGradientAlpha("VERTICAL",self.BarColorBot[1],self.BarColorBot[2],self.BarColorBot[3],self.BarColorBot[4],self.BarColorTop[1],self.BarColorTop[2],self.BarColorTop[3],self.BarColorTop[4])
+
+ tinsert(self.Bars,bar)
+ else
+ self.Bars[i]:SetPoint("BOTTOMLEFT",self,"BOTTOMLEFT",i-1,0)
+ end
+ self.BarHeight[i]=0
+ end
+
+ local SizeOfBarsUsed=table.maxn(self.BarsUsing)
+
+ if Width>SizeOfBarsUsed then
+ for i=SizeOfBarsUsed+1,Width do
+ tinsert(self.BarsUsing,self.Bars[i])
+ self.Bars[i]:Show()
+ end
+ elseif Widthself.XMax then
+ return 0
+ end
+
+ Bar=math_min(math_max(math_floor(self.BarNum*(Time-self.XMin)/(self.XMax-self.XMin)+0.5),1),self.BarNum)
+
+ return self.BarHeight[Bar]
+end
+
+function GraphFunctions:SetUpdateLimit(Time)
+ self.LimitUpdates=Time
+end
+
+function GraphFunctions:SetDecay(decay)
+ self.DecaySet=decay
+ self.Decay=math_pow(self.DecaySet,self.BarWidth)
+ self.ExpNorm=1/(1-self.Decay)/0.95 --Actually a finite geometric series (divide 0.96 instead of 1 since seems doesn't quite work right)
+end
+
+function GraphFunctions:AddBar(value)
+ for i=1,self.BarNum-1 do
+ self.BarHeight[i]=self.BarHeight[i+1]
+ end
+ self.BarHeight[self.BarNum]=value
+ self.AddedBar=true
+end
+
+function GraphFunctions:SetBars()
+ local YHeight=self.YMax-self.YMin
+
+ for i,bar in pairs(self.BarsUsing) do
+ local h
+ h=(self.BarHeight[i]-self.YMin)/YHeight
+
+ bar:SetValue(h)
+ end
+end
+
+-------------------------------------------------------------------------------
+--Functions for Line Graph Data
+-------------------------------------------------------------------------------
+
+function GraphFunctions:AddDataSeries(points,color,n2)
+ local data
+ --Make sure there is data points
+ if not points then
+ return
+ end
+
+ data=points
+ if n2==nil then
+ n2=false
+ end
+ if n2 or (table.getn(points)==2 and table.getn(points[1])~=2) then
+ data={}
+ for k,v in ipairs(points[1]) do
+ tinsert(data,{v,points[2][k]})
+ end
+ end
+
+ tinsert(self.Data,{Points=data;Color=color})
+
+ self.NeedsUpdate=true
+end
+
+function GraphFunctions:AddFilledDataSeries(points,color,n2)
+ local data
+ --Make sure there is data points
+ if not points or #points==0 then
+ return
+ end
+
+ data=points
+ if n2==nil then
+ n2=false
+ end
+
+ if n2 or (table.getn(points)==2 and table.getn(points[1])~=2) then
+ data={}
+ for k,v in ipairs(points[1]) do
+ tinsert(data,{v,points[2][k]})
+ end
+ end
+
+ tinsert(self.FilledData,{Points=data;Color=color})
+
+ self.NeedsUpdate=true
+end
+
+
+function GraphFunctions:ResetData()
+ self.Data={}
+
+ if self.FilledData then
+ self.FilledData={}
+ end
+
+ self.NeedsUpdate=true
+end
+
+function GraphFunctions:SetLinearFit(fit)
+ self.LinearFit=fit
+
+ self.NeedsUpdate=true
+end
+
+
+
+function GraphFunctions:HideTextures()
+ local k=#self.TexturesUsed
+ while k>0 do
+ self.Textures[#self.Textures+1]=self.TexturesUsed[k]
+ self.TexturesUsed[k]:Hide()
+ self.TexturesUsed[k]=nil
+ k=k-1
+ end
+end
+
+--Make sure to show a texture after you grab it or its free for anyone else to grab
+function GraphFunctions:FindTexture()
+ local t
+ if #self.Textures>0 then
+ t=self.Textures[#self.Textures]
+ self.TexturesUsed[#self.TexturesUsed+1]=t
+ self.Textures[#self.Textures]=nil
+ return t
+ end
+ local g=self:CreateTexture(nil,"BACKGROUND")
+ self.TexturesUsed[#self.TexturesUsed+1]=g
+ return g
+end
+
+function GraphFunctions:HideFontStrings()
+ if not self.FontStrings then
+ self.FontStrings={}
+ end
+ for k, t in pairs(self.FontStrings) do
+ t:Hide()
+ end
+end
+
+--Make sure to show a fontstring after you grab it or its free for anyone else to grab
+function GraphFunctions:FindFontString()
+ for k, t in pairs(self.FontStrings) do
+ if not t:IsShown() then
+ return t
+ end
+ end
+ local g
+
+ if self.TextFrame then
+ g=self.TextFrame:CreateFontString(nil,"OVERLAY")
+ else
+ g=self:CreateFontString(nil,"OVERLAY")
+ end
+ tinsert(self.FontStrings,g)
+ return g
+end
+
+--Linear Regression via Least Squares
+function GraphFunctions:LinearRegression(data)
+ local alpha, beta
+ local n, SX,SY,SXX, SXY = 0,0,0,0,0
+
+ for k,v in pairs(data) do
+ n=n+1
+
+ SX=SX+v[1]
+ SXX=SXX+v[1]*v[1]
+ SY=SY+v[2]
+ SXY=SXY+v[1]*v[2]
+ end
+
+ beta=(n*SXY-SX*SY)/(n*SXX-SX*SX)
+ alpha=(SY-beta*SX)/n
+
+ return alpha, beta
+end
+
+
+
+
+-------------------------------------------------------------------------------
+--Functions for Pie Chart
+-------------------------------------------------------------------------------
+local PiePieces={"1-2",
+ "1-4",
+ "1-8",
+ "1-16",
+ "1-32",
+ "1-64",
+ "1-128"}
+
+--26 Colors
+local ColorTable={
+ {0.9,0.1,0.1},
+ {0.1,0.9,0.1},
+ {0.1,0.1,0.9},
+ {0.9,0.9,0.1},
+ {0.9,0.1,0.9},
+ {0.1,0.9,0.9},
+ {0.9,0.9,0.9},
+ {0.5,0.1,0.1},
+ {0.1,0.5,0.1},
+ {0.1,0.1,0.5},
+ {0.5,0.5,0.1},
+ {0.5,0.1,0.5},
+ {0.1,0.5,0.5},
+ {0.5,0.5,0.5},
+ {0.75,0.15,0.15},
+ {0.15,0.75,0.15},
+ {0.15,0.15,0.75},
+ {0.75,0.75,0.15},
+ {0.75,0.15,0.75},
+ {0.15,0.75,0.75},
+ {0.9,0.5,0.1},
+ {0.1,0.5,0.9},
+ {0.9,0.1,0.5},
+ {0.5,0.9,0.1},
+ {0.5,0.1,0.9},
+ {0.1,0.9,0.5},
+}
+function GraphFunctions:AddPie(Percent, Color)
+ local k,v
+ local PiePercent=self.PercentOn
+
+ local CurPiece=50
+ local Angle=180
+ local CurAngle=PiePercent*360/100
+
+ self.TotalSections=self.TotalSections+1
+ if type(self.Sections[self.TotalSections])~="table" then
+ self.Sections[self.TotalSections]={}
+ end
+
+ local Section=self.Sections[self.TotalSections]
+ Section.Textures={}
+
+ if type(Color)~="table" then
+ if self.onColor<=table.maxn(ColorTable) then
+ Color=ColorTable[self.onColor]
+ else
+ Color={math_random(),math_random(),math_random()}
+ end
+ self.onColor=self.onColor+1
+ end
+
+ if PiePercent==0 then
+ self:DrawLinePie(0)
+ end
+
+ Percent=Percent+self.Remaining
+ local LastPiece=0
+ for k,v in pairs(PiePieces) do
+ if (Percent+0.1)>CurPiece then
+ local t=self:FindTexture()
+ t:SetTexture(TextureDirectory..v)
+ t:ClearAllPoints()
+ t:SetPoint("CENTER",self,"CENTER",0,0)
+ t:SetHeight(self:GetHeight())
+ t:SetWidth(self:GetWidth())
+ GraphFunctions:RotateTexture(t,CurAngle)
+ t:Show()
+
+ t:SetVertexColor(Color[1],Color[2],Color[3],1.0)
+ Percent=Percent-CurPiece
+ PiePercent=PiePercent+CurPiece
+ CurAngle=CurAngle+Angle
+
+ tinsert(Section.Textures,t)
+
+ if k == 7 then
+ LastPiece=0.09
+ end
+ end
+ CurPiece=CurPiece/2
+ Angle=Angle/2
+ end
+
+ --Finish adding section data
+ Section.Color=Color
+ Section.Angle=CurAngle
+
+ self:DrawLinePie((PiePercent+LastPiece)*360/100)
+ self.PercentOn=PiePercent
+ self.Remaining=Percent
+
+ return Color
+end
+
+function GraphFunctions:CompletePie(Color)
+ local Percent=100-self.PercentOn
+ local k,v
+ local PiePercent=self.PercentOn
+
+ local CurPiece=50
+ local Angle=180
+ local CurAngle=PiePercent*360/100
+
+ self.TotalSections=self.TotalSections+1
+ if not self.Sections[self.TotalSections] then
+ self.Sections[self.TotalSections]={}
+ end
+
+ local Section=self.Sections[self.TotalSections]
+ Section.Textures={}
+
+ if type(Color)~="table" then
+ if self.onColor<=table.maxn(ColorTable) then
+ Color=ColorTable[self.onColor]
+ else
+ Color={math_random(),math_random(),math_random()}
+ end
+ self.onColor=self.onColor+1
+ end
+
+
+
+ Percent=Percent+self.Remaining
+ if PiePercent~=0 then
+ for k,v in pairs(PiePieces) do
+ if (Percent+0.1)>CurPiece then
+ local t=self:FindTexture()
+ t:SetTexture(TextureDirectory..v)
+ t:ClearAllPoints()
+ t:SetPoint("CENTER",self,"CENTER",0,0)
+ t:SetHeight(self:GetHeight())
+ t:SetWidth(self:GetWidth())
+ GraphFunctions:RotateTexture(t,CurAngle)
+ t:Show()
+
+ t:SetVertexColor(Color[1],Color[2],Color[3],1.0)
+ Percent=Percent-CurPiece
+ PiePercent=PiePercent+CurPiece
+ CurAngle=CurAngle+Angle
+
+ tinsert(Section.Textures,t)
+ end
+ CurPiece=CurPiece/2
+ Angle=Angle/2
+ end
+ else--Special case if its by itself
+ local t=self:FindTexture()
+ t:SetTexture(TextureDirectory.."1-1")
+ t:ClearAllPoints()
+ t:SetPoint("CENTER",self,"CENTER",0,0)
+ t:SetHeight(self:GetHeight())
+ t:SetWidth(self:GetWidth())
+ GraphFunctions:RotateTexture(t,CurAngle)
+ t:Show()
+
+ t:SetVertexColor(Color[1],Color[2],Color[3],1.0)
+ tinsert(Section.Textures,t)
+ end
+
+ --Finish adding section data
+ Section.Color=Color
+ Section.Angle=360
+
+ self.PercentOn=PiePercent
+ self.Remaining=Percent
+
+ return Color
+end
+
+function GraphFunctions:ResetPie()
+ self:HideTextures()
+ self:HideLines(self)
+
+ self.PieUsed=0
+ self.PercentOn=0
+ self.Remaining=0
+ self.onColor=1
+ self.LastSection=nil
+ self.TotalSections=0
+ --self.Sections={}
+end
+
+function GraphFunctions:DrawLinePie(angle)
+ local sx,sy,ex,ey
+ local Radian=math_pi*(90-angle)/180
+ local w,h
+ w=self:GetWidth()/2
+ h=self:GetHeight()/2
+
+
+ sx=w
+ sy=h
+
+ ex=sx+0.88*w*math_cos(Radian)
+ ey=sx+0.88*h*math_sin(Radian)
+
+ self:DrawLine(self,sx,sy,ex,ey,34,{0.0,0.0,0.0,1.0},"OVERLAY")
+end
+
+--Used to rotate the pie slices
+function GraphFunctions:RotateTexture(texture,angle)
+ local Radian=math_pi*(45-angle)/180
+ local Radian2=math_pi*(45+90-angle)/180
+ local Radius=0.70710678118654752440084436210485
+
+ local tx,ty,tx2,ty2
+ tx=Radius*math_cos(Radian)
+ ty=Radius*math_sin(Radian)
+ tx2=-ty
+ ty2=tx
+
+ texture:SetTexCoord(0.5-tx,0.5-ty,0.5+tx2,0.5+ty2,0.5-tx2,0.5-ty2,0.5+tx,0.5+ty)
+end
+
+function GraphFunctions:SetSelectionFunc(f)
+ self.SelectionFunc=f
+end
+
+--TODO: Pie chart pieces need to be clickable
+function GraphFunctions:PieChart_OnUpdate()
+ if (MouseIsOver(self)) then
+ local sX,sY=self:GetCenter()
+ local Scale=self:GetEffectiveScale()
+ local mX,mY=GetCursorPosition()
+ local dX,dY
+
+ dX=mX/Scale-sX
+ dY=mY/Scale-sY
+
+ local Angle=90-math_deg(math_atan(dY/dX))
+ dY=dY*self.Ratio
+ local Dist=dX*dX+dY*dY
+
+ if dX<0 then
+ Angle=Angle+180
+ end
+
+ local k,v
+ --Are we on the Pie Chart?
+ if Dist added 10/07/2013 (tercioo)
+function GraphFunctions:SetLineTexture (texture)
+
+ if (type (texture) ~= "string") then
+ return assert (false, "Parameter 1 for SetLineTexture must be a string")
+ end
+
+ --> full path
+ if (texture:find ("\\") or texture:find ("//")) then
+ self.CustomLine = texture
+ --> using an image inside lib-graph folder
+ else
+ self.CustomLine = TextureDirectory..texture
+ end
+end
+
+--> added 10/07/2013 (tercioo)
+function GraphFunctions:SetBorderSize (border, size)
+ border = string.lower (border)
+
+ if (type (size) ~= "number") then
+ return assert (false, "Parameter 2 for SetBorderSize must be a number")
+ end
+
+ if (border == "left") then
+ self.CustomLeftBorder = size
+ return true
+ elseif (border == "right") then
+ self.CustomRightBorder = size
+ return true
+ elseif (border == "top") then
+ self.CustomTopBorder = size
+ return true
+ elseif (border == "bottom") then
+ self.CustomBottomBorder = size
+ return true
+ end
+
+ return assert (false, "Usage: GraphObject:SetBorderSize (LEFT RIGHT TOP BOTTOM, SIZE)")
+end
+
+function GraphFunctions:CreateGridlines()
+ local Width=self:GetWidth()
+ local Height=self:GetHeight()
+ local NoSecondary=(self.GridSecondaryY==nil) or (self.GridSecondaryX==nil) or (type(self.GridColorSecondary)~="table")
+ self:HideLines(self)
+ self:HideFontStrings()
+
+ if self.YGridInterval then
+ local LowerYGridLine,UpperYGridLine,TopSpace
+ LowerYGridLine=self.YMin/self.YGridInterval
+ LowerYGridLine=math_max(math_floor(LowerYGridLine),math_ceil(LowerYGridLine))
+ UpperYGridLine=self.YMax/self.YGridInterval
+ UpperYGridLine=math_min(math_floor(UpperYGridLine),math_ceil(UpperYGridLine))
+ TopSpace=Height*(1-(UpperYGridLine*self.YGridInterval-self.YMin)/(self.YMax-self.YMin))
+ for i=LowerYGridLine,UpperYGridLine do
+ if i~=0 or not self.YAxisDrawn then
+ local YPos,T,F
+ YPos=Height*(i*self.YGridInterval-self.YMin)/(self.YMax-self.YMin)
+ if NoSecondary or math_fmod(i,self.GridSecondaryY)==0 then
+ T=self:DrawLine(self,0,YPos,Width,YPos,24,self.GridColor,"BACKGROUND")
+ else
+ T=self:DrawLine(self,0,YPos,Width,YPos,24,self.GridColorSecondary,"BACKGROUND")
+ end
+
+ if ((i~=UpperYGridLine) or (TopSpace>12)) and (NoSecondary or math_fmod(i,self.GridSecondaryY)==0) then
+ if self.YLabelsLeft then
+ F=self:FindFontString()
+ F:SetFontObject("GameFontHighlightSmall")
+ F:SetTextColor(1,1,1)
+ F:ClearAllPoints()
+ F:SetPoint("BOTTOMLEFT",T,"LEFT",2,2)
+ F:SetText(i*self.YGridInterval)
+ F:Show()
+ end
+
+ if self.YLabelsRight then
+ F=self:FindFontString()
+ F:SetFontObject("GameFontHighlightSmall")
+ F:SetTextColor(1,1,1)
+ F:ClearAllPoints()
+ F:SetPoint("BOTTOMRIGHT",T,"RIGHT",-2,2)
+ F:SetText(i*self.YGridInterval)
+ F:Show()
+ end
+ end
+ end
+ end
+ end
+
+ if self.XGridInterval then
+ local LowerXGridLine,UpperXGridLine
+ LowerXGridLine=self.XMin/self.XGridInterval
+ LowerXGridLine=math_max(math_floor(LowerXGridLine),math_ceil(LowerXGridLine))
+ UpperXGridLine=self.XMax/self.XGridInterval
+ UpperXGridLine=math_min(math_floor(UpperXGridLine),math_ceil(UpperXGridLine))
+
+ for i=LowerXGridLine,UpperXGridLine do
+ if i~=0 or not self.XAxisDrawn then
+ local XPos
+ XPos=Width*(i*self.XGridInterval-self.XMin)/(self.XMax-self.XMin)
+ if NoSecondary or math_fmod(i,self.GridSecondaryX)==0 then
+ self:DrawLine(self,XPos,0,XPos,Height,24,self.GridColor,"BACKGROUND")
+ else
+ self:DrawLine(self,XPos,0,XPos,Height,24,self.GridColorSecondary,"BACKGROUND")
+ end
+ end
+ end
+ end
+
+ if self.YAxisDrawn and self.YMax>=0 and self.YMin<=0 then
+ local YPos,T
+
+ YPos=Height*(-self.YMin)/(self.YMax-self.YMin)
+ T=self:DrawLine(self,0,YPos,Width,YPos,24,self.AxisColor,"BACKGROUND")
+
+ if self.YLabelsLeft then
+ F=self:FindFontString()
+ F:SetFontObject("GameFontHighlightSmall")
+ F:SetTextColor(1,1,1)
+ F:ClearAllPoints()
+ F:SetPoint("BOTTOMLEFT",T,"LEFT",2,2)
+ F:SetText(0)
+ F:Show()
+ end
+ if self.YLabelsRight then
+ F=self:FindFontString()
+ F:SetFontObject("GameFontHighlightSmall")
+ F:SetTextColor(1,1,1)
+ F:ClearAllPoints()
+ F:SetPoint("BOTTOMRIGHT",T,"RIGHT",-2,2)
+ F:SetText(0)
+ F:Show()
+ end
+ end
+
+ if self.XAxisDrawn and self.XMax>=0 and self.XMin<=0 then
+ local XPos;
+
+ XPos=Width*(-self.XMin)/(self.XMax-self.XMin)
+ self:DrawLine(self,XPos,0,XPos,Height,24,self.AxisColor,"BACKGROUND")
+ end
+end
+
+
+
+
+
+
+
+--------------------------------------------------------------------------------
+--Refresh functions
+--------------------------------------------------------------------------------
+
+function GraphFunctions:OnUpdateGraph()
+ if self.NeedsUpdate and self.RefreshGraph then
+ self:RefreshGraph()
+ self.NeedsUpdate=false
+ end
+end
+
+--Performs a convolution in realtime allowing to graph Framerate, DPS, or any other data you want graphed in realtime
+function GraphFunctions:OnUpdateGraphRealtime()
+ local i,j
+ local CurTime=GetTime()
+ local BarsChanged
+
+ if self.NextUpdate>CurTime or (self.Mode=="RAW" and not (self.NeedsUpdate or self.AddedBar)) then
+ return
+ end
+
+ self.NextUpdate=CurTime+self.LimitUpdates
+
+ --Slow Mode performs an entire convolution every frame
+ if self.Mode=="SLOW" then
+ --Initialize Bar Data
+ self.BarHeight={}
+ for i=1,self.BarNum do
+ self.BarHeight[i]=0
+ end
+ local k,v
+ local BarTimeRadius=(self.XMax-self.XMin)/self.BarNum
+ local DataValue=1/(2*self.TimeRadius)
+
+ if self.Filter=="RECT" then
+ --Take the convolution of the dataset on to the bars wtih a rectangular filter
+ local DataValue=1/(2*self.TimeRadius)
+ for k,v in pairs(self.Data) do
+ if v.Time<(CurTime+self.XMin-self.TimeRadius) then
+ tremove(self.Data,k)
+ else
+ local DataTime=v.Time-CurTime
+ local LowestBar=math_max(math_floor((DataTime-self.XMin-self.TimeRadius)/BarTimeRadius),1)
+ local HighestBar=math_min(math_ceil((DataTime-self.XMin+self.TimeRadius)/BarTimeRadius),self.BarNum)
+ for i=LowestBar,HighestBar do
+ self.BarHeight[i]=self.BarHeight[i]+v.Value*DataValue
+ end
+ end
+ end
+ elseif self.Filter=="TRI" then
+ --Needs optimization badly
+ --Take the convolution of the dataset on to the bars wtih a triangular filter
+ local DataValue=1/(self.TimeRadius)
+ for k,v in pairs(self.Data) do
+ local Temp
+ if v.Time<(CurTime+self.XMin-self.TimeRadius) then
+ tremove(self.Data,k)
+ else
+ local DataTime=v.Time-CurTime
+ local LowestBar=math_max(math_floor((DataTime-self.XMin-self.TimeRadius)/BarTimeRadius),1)
+ local HighestBar=math_min(math_ceil((DataTime-self.XMin+self.TimeRadius)/BarTimeRadius),self.BarNum)
+
+
+ for i=LowestBar,HighestBar do
+ self.BarHeight[i]=self.BarHeight[i]+v.Value*DataValue*math_abs(BarTimeRadius*i+self.XMin-DataTime)
+ end
+ end
+ end
+ end
+ BarsChanged=true
+ elseif self.Mode=="FAST" then
+ local ShiftBars=math_floor((CurTime-self.LastShift)/self.BarWidth)
+
+ if ShiftBars>0 and not (self.LastDataTime<(self.LastShift+self.XMin-self.TimeRadius*2)) then
+ local RecalcBars=self.BarNum-(ShiftBars+self.FilterOverlap)+1
+
+ for i=1,self.BarNum do
+ if i0 then
+ local RecalcBars=self.BarNum-ShiftBars+1
+
+ for i=1,self.BarNum do
+ if i0 and not (self.LastDataTime<(self.LastShift+self.XMin-self.TimeRadius)) then
+ for i=1,self.BarNum do
+ if i0.01 then
+ self.YMax=MaxY
+ self.NeedsUpdate=true
+ end
+ end
+ self:SetBars()
+ end
+
+ if self.NeedsUpdate then
+ self.NeedsUpdate=false
+ self:RefreshGraph()
+ end
+end
+
+--Line Graph
+function GraphFunctions:RefreshLineGraph()
+ local k1, k2, series
+ self:HideLines(self)
+ self:HideBars(self)
+
+ if self.AutoScale and self.Data then
+ local MinX, MaxX, MinY, MaxY = math_huge, -math_huge, math_huge, -math_huge
+ --Go through line data first
+ for k1, series in pairs(self.Data) do
+ for k2, point in pairs(series.Points) do
+ MinX=math_min(point[1],MinX)
+ MaxX=math_max(point[1],MaxX)
+ MinY=math_min(point[2],MinY)
+ MaxY=math_max(point[2],MaxY)
+ end
+ end
+
+ --Now through the Filled Lines
+ for k1, series in pairs(self.FilledData) do
+ for k2, point in pairs(series.Points) do
+ MinX=math_min(point[1],MinX)
+ MaxX=math_max(point[1],MaxX)
+ MinY=math_min(point[2],MinY)
+ MaxY=math_max(point[2],MaxY)
+ end
+ end
+
+ local XBorder, YBorder
+
+ XBorder=0.1*(MaxX-MinX)
+ YBorder=0.1*(MaxY-MinY)
+
+ --> changed 10/07/2013 (tercioo)
+ --> add four new members to the line graphic object: CustomLeftBorder CustomRightBorder CustomBottomBorder CustomTopBorder
+
+ if not self.LockOnXMin then
+ if (self.CustomLeftBorder) then
+ self.XMin=MinX+self.CustomLeftBorder --> custom size of left border
+ else
+ self.XMin=MinX-XBorder
+ end
+ end
+
+ if not self.LockOnXMax then
+ if (self.CustomRightBorder) then
+ self.XMax=MaxX+self.CustomRightBorder --> custom size of right border
+ else
+ self.XMax=MaxX+XBorder
+ end
+ end
+
+ if not self.LockOnYMin then
+ if (self.CustomBottomBorder) then
+ self.YMin=MinY+self.CustomBottomBorder --> custom size of bottom border
+ else
+ self.YMin=MinY-YBorder
+ end
+ end
+
+ if not self.LockOnYMax then
+ if (self.CustomTopBorder) then
+ self.YMax=MaxY+self.CustomTopBorder --> custom size of top border
+ else
+ self.YMax=MaxY+YBorder
+ end
+ end
+
+ end
+
+ self:CreateGridlines()
+
+ local Width=self:GetWidth()
+ local Height=self:GetHeight()
+
+ for k1, series in pairs(self.Data) do
+ local LastPoint
+ LastPoint=nil
+
+ for k2, point in pairs(series.Points) do
+ if LastPoint then
+ local TPoint={x=point[1];y=point[2]}
+
+ TPoint.x=Width*(TPoint.x-self.XMin)/(self.XMax-self.XMin)
+ TPoint.y=Height*(TPoint.y-self.YMin)/(self.YMax-self.YMin)
+
+ self:DrawLine(self,LastPoint.x,LastPoint.y,TPoint.x,TPoint.y,32,series.Color)
+
+ LastPoint=TPoint
+ else
+ LastPoint={x=point[1];y=point[2]}
+ LastPoint.x=Width*(LastPoint.x-self.XMin)/(self.XMax-self.XMin)
+ LastPoint.y=Height*(LastPoint.y-self.YMin)/(self.YMax-self.YMin)
+ end
+ end
+ end
+
+ --Filled Line Graphs
+ for k1, series in pairs(self.FilledData) do
+ local LastPoint
+ LastPoint=nil
+
+ for k2, point in pairs(series.Points) do
+ if LastPoint then
+ local TPoint={x=point[1];y=point[2]}
+
+ TPoint.x=Width*(TPoint.x-self.XMin)/(self.XMax-self.XMin)
+ TPoint.y=Height*(TPoint.y-self.YMin)/(self.YMax-self.YMin)
+
+ self:DrawBar(self,LastPoint.x,LastPoint.y,TPoint.x,TPoint.y,series.Color,k1)
+
+ LastPoint=TPoint
+ else
+ LastPoint={x=point[1];y=point[2]}
+ LastPoint.x=Width*(LastPoint.x-self.XMin)/(self.XMax-self.XMin)
+ LastPoint.y=Height*(LastPoint.y-self.YMin)/(self.YMax-self.YMin)
+ end
+ end
+ end
+end
+
+--Scatter Plot Refresh
+function GraphFunctions:RefreshScatterPlot()
+ local k1, k2, series, point
+ self:HideLines(self)
+
+ if self.AutoScale and self.Data then
+ local MinX, MaxX, MinY, MaxY = math_huge, -math_huge, math_huge, -math_huge
+ for k1, series in pairs(self.Data) do
+ for k2, point in pairs(series.Points) do
+ MinX=math_min(point[1],MinX)
+ MaxX=math_max(point[1],MaxX)
+ MinY=math_min(point[2],MinY)
+ MaxY=math_max(point[2],MaxY)
+ end
+ end
+
+ local XBorder, YBorder
+
+ XBorder=0.1*(MaxX-MinX)
+ YBorder=0.1*(MaxY-MinY)
+
+ if not self.LockOnXMin then
+ self.XMin=MinX-XBorder
+ end
+ if not self.LockOnXMax then
+ self.XMax=MaxX+XBorder
+ end
+ if not self.LockOnYMin then
+ self.YMin=MinY-YBorder
+ end
+ if not self.LockOnYMax then
+ self.YMax=MaxY+YBorder
+ end
+ end
+
+ self:CreateGridlines()
+
+ local Width=self:GetWidth()
+ local Height=self:GetHeight()
+
+ self:HideTextures()
+ for k1, series in pairs(self.Data) do
+ local MinX,MaxX = self.XMax, self.XMin
+ for k2, point in pairs(series.Points) do
+ local x,y
+ MinX=math_min(point[1],MinX)
+ MaxX=math_max(point[1],MaxX)
+ x=Width*(point[1]-self.XMin)/(self.XMax-self.XMin)
+ y=Height*(point[2]-self.YMin)/(self.YMax-self.YMin)
+
+ local g=self:FindTexture()
+ g:SetTexture("Spells\\GENERICGLOW2_64.blp")
+ g:SetWidth(6)
+ g:SetHeight(6)
+ g:ClearAllPoints()
+ g:SetPoint("CENTER",self,"BOTTOMLEFT",x,y)
+ g:SetVertexColor(series.Color[1],series.Color[2],series.Color[3],series.Color[4]);
+ g:Show()
+ end
+
+ if self.LinearFit then
+ local alpha, beta = self:LinearRegression(series.Points)
+ local sx,sy,ex,ey
+
+ sx=MinX
+ sy=beta*sx+alpha
+ ex=MaxX
+ ey=beta*ex+alpha
+
+ sx=Width*(sx-self.XMin)/(self.XMax-self.XMin)
+ sy=Height*(sy-self.YMin)/(self.YMax-self.YMin)
+ ex=Width*(ex-self.XMin)/(self.XMax-self.XMin)
+ ey=Height*(ey-self.YMin)/(self.YMax-self.YMin)
+
+ self:DrawLine(self,sx,sy,ex,ey,32,series.Color)
+ end
+ end
+end
+
+
+
+
+
+
+
+
+
+--Copied from Blizzard's TaxiFrame code and modifed for IMBA then remodified for GraphLib
+
+-- The following function is used with permission from Daniel Stephens
+local TAXIROUTE_LINEFACTOR = 128/126; -- Multiplying factor for texture coordinates
+local TAXIROUTE_LINEFACTOR_2 = TAXIROUTE_LINEFACTOR / 2; -- Half of that
+
+-- T - Texture
+-- C - Canvas Frame (for anchoring)
+-- sx,sy - Coordinate of start of line
+-- ex,ey - Coordinate of end of line
+-- w - Width of line
+-- relPoint - Relative point on canvas to interpret coords (Default BOTTOMLEFT)
+function lib:DrawLine(C, sx, sy, ex, ey, w, color, layer)
+ local relPoint = "BOTTOMLEFT"
+
+ if sx==ex then
+ if sy==ey then
+ return
+ else
+ return self:DrawVLine(C,sx,sy,ey,w, color, layer)
+ end
+ elseif sy==ey then
+ return self:DrawHLine(C,sx,ex,sy,w, color, layer)
+ end
+
+ if not C.GraphLib_Lines then
+ C.GraphLib_Lines={}
+ C.GraphLib_Lines_Used={}
+ end
+
+ local T = tremove(C.GraphLib_Lines) or C:CreateTexture(nil, "ARTWORK")
+
+ --> changed 10/07/2013 (tercioo)
+ --> graph:SetLineTexture (texture)
+ if (not C.CustomLine) then
+ T:SetTexture(TextureDirectory.."line")
+ else
+ T:SetTexture(C.CustomLine)
+ end
+
+ tinsert(C.GraphLib_Lines_Used,T)
+
+ T:SetDrawLayer(layer or "ARTWORK")
+
+ T:SetVertexColor(color[1],color[2],color[3],color[4]);
+ -- Determine dimensions and center point of line
+ local dx,dy = ex - sx, ey - sy;
+ local cx,cy = (sx + ex) / 2, (sy + ey) / 2;
+
+ -- Normalize direction if necessary
+ if (dx < 0) then
+ dx,dy = -dx,-dy;
+ end
+
+ -- Calculate actual length of line
+ local l = sqrt((dx * dx) + (dy * dy));
+
+ -- Sin and Cosine of rotation, and combination (for later)
+ local s,c = -dy / l, dx / l;
+ local sc = s * c;
+
+ -- Calculate bounding box size and texture coordinates
+ local Bwid, Bhgt, BLx, BLy, TLx, TLy, TRx, TRy, BRx, BRy;
+ if (dy >= 0) then
+ Bwid = ((l * c) - (w * s)) * TAXIROUTE_LINEFACTOR_2;
+ Bhgt = ((w * c) - (l * s)) * TAXIROUTE_LINEFACTOR_2;
+ BLx, BLy, BRy = (w / l) * sc, s * s, (l / w) * sc;
+ BRx, TLx, TLy, TRx = 1 - BLy, BLy, 1 - BRy, 1 - BLx;
+ TRy = BRx;
+ else
+ Bwid = ((l * c) + (w * s)) * TAXIROUTE_LINEFACTOR_2;
+ Bhgt = ((w * c) + (l * s)) * TAXIROUTE_LINEFACTOR_2;
+ BLx, BLy, BRx = s * s, -(l / w) * sc, 1 + (w / l) * sc;
+ BRy, TLx, TLy, TRy = BLx, 1 - BRx, 1 - BLx, 1 - BLy;
+ TRx = TLy;
+ end
+
+ -- Thanks Blizzard for adding (-)10000 as a hard-cap and throwing errors!
+ -- The cap was added in 3.1.0 and I think it was upped in 3.1.1
+ -- (way less chance to get the error)
+ if TLx > 10000 then TLx = 10000 elseif TLx < -10000 then TLx = -10000 end
+ if TLy > 10000 then TLy = 10000 elseif TLy < -10000 then TLy = -10000 end
+ if BLx > 10000 then BLx = 10000 elseif BLx < -10000 then BLx = -10000 end
+ if BLy > 10000 then BLy = 10000 elseif BLy < -10000 then BLy = -10000 end
+ if TRx > 10000 then TRx = 10000 elseif TRx < -10000 then TRx = -10000 end
+ if TRy > 10000 then TRy = 10000 elseif TRy < -10000 then TRy = -10000 end
+ if BRx > 10000 then BRx = 10000 elseif BRx < -10000 then BRx = -10000 end
+ if BRy > 10000 then BRy = 10000 elseif BRy < -10000 then BRy = -10000 end
+
+ -- Set texture coordinates and anchors
+ T:ClearAllPoints();
+ T:SetTexCoord(TLx, TLy, BLx, BLy, TRx, TRy, BRx, BRy);
+ T:SetPoint("BOTTOMLEFT", C, relPoint, cx - Bwid, cy - Bhgt);
+ T:SetPoint("TOPRIGHT", C, relPoint, cx + Bwid, cy + Bhgt);
+ T:Show()
+ return T
+end
+
+--Thanks to Celandro
+function lib:DrawVLine(C, x, sy, ey, w, color, layer)
+ local relPoint = "BOTTOMLEFT"
+
+ if not C.GraphLib_Lines then
+ C.GraphLib_Lines={}
+ C.GraphLib_Lines_Used={}
+ end
+
+ local T = tremove(C.GraphLib_Lines) or C:CreateTexture(nil, "ARTWORK")
+ T:SetTexture(TextureDirectory.."sline");
+ tinsert(C.GraphLib_Lines_Used,T);
+
+ T:SetDrawLayer(layer or "ARTWORK")
+
+ T:SetVertexColor(color[1],color[2],color[3],color[4]);
+
+ if sy>ey then
+ sy, ey = ey, sy
+ end
+
+ -- Set texture coordinates and anchors
+ T:ClearAllPoints();
+ T:SetTexCoord(1, 0, 0, 0, 1, 1, 0, 1);
+ T:SetPoint("BOTTOMLEFT", C, relPoint, x-w/2, sy);
+ T:SetPoint("TOPRIGHT", C, relPoint, x+w/2, ey);
+ T:Show()
+ return T
+end
+
+function lib:DrawHLine(C, sx, ex, y, w, color, layer)
+ local relPoint = "BOTTOMLEFT"
+
+ if not C.GraphLib_Lines then
+ C.GraphLib_Lines={}
+ C.GraphLib_Lines_Used={}
+ end
+
+ local T = tremove(C.GraphLib_Lines) or C:CreateTexture(nil, "ARTWORK")
+ T:SetTexture(TextureDirectory.."sline");
+ tinsert(C.GraphLib_Lines_Used,T);
+
+ T:SetDrawLayer(layer or "ARTWORK")
+
+ T:SetVertexColor(color[1],color[2],color[3],color[4]);
+
+ if sx>ex then
+ sx, ex = ex, sx
+ end
+
+ -- Set texture coordinates and anchors
+ T:ClearAllPoints();
+ T:SetTexCoord(0, 0, 0, 1, 1, 0, 1, 1);
+ T:SetPoint("BOTTOMLEFT", C, relPoint, sx, y-w/2);
+ T:SetPoint("TOPRIGHT", C, relPoint, ex, y+w/2);
+ T:Show()
+ return T
+end
+
+function lib:HideLines(C)
+ if C.GraphLib_Lines then
+ for i = #C.GraphLib_Lines_Used, 1, -1 do
+ C.GraphLib_Lines_Used[i]:Hide()
+ tinsert(C.GraphLib_Lines,tremove(C.GraphLib_Lines_Used))
+ end
+ end
+end
+
+--Two parts to each bar
+function lib:DrawBar(C, sx, sy, ex, ey, color, level)
+ local Bar, Tri, barNum, MinY, MaxY
+
+ --Want sx<=ex if not then flip them
+ if sx>ex then
+ sx, ex = ex, sx
+ sy, ey = ey, sy
+ end
+
+ if not C.GraphLib_Bars then
+ C.GraphLib_Bars={}
+ C.GraphLib_Tris={}
+ C.GraphLib_Bars_Used={}
+ C.GraphLib_Tris_Used={}
+ C.GraphLib_Frames={}
+ end
+
+ if (#C.GraphLib_Bars)>0 then
+ Bar=C.GraphLib_Bars[#C.GraphLib_Bars]
+ tremove(C.GraphLib_Bars,#C.GraphLib_Bars)
+ Bar:Show()
+
+ Tri=C.GraphLib_Tris[#C.GraphLib_Tris]
+ tremove(C.GraphLib_Tris,#C.GraphLib_Tris)
+ Tri:Show()
+ end
+
+ if not Bar then
+ Bar=C:CreateTexture(nil, "ARTWORK")
+ Bar:SetTexture(1,1,1,1)
+
+ Tri=C:CreateTexture(nil, "ARTWORK")
+ Tri:SetTexture(TextureDirectory.."triangle")
+ end
+
+ tinsert(C.GraphLib_Bars_Used,Bar)
+ tinsert(C.GraphLib_Tris_Used,Tri)
+
+ if level then
+ if type(C.GraphLib_Frames[level])=="nil" then
+ local newLevel=C:GetFrameLevel()+level
+ C.GraphLib_Frames[level]=CreateFrame("Frame",nil,C)
+ C.GraphLib_Frames[level]:SetFrameLevel(newLevel)
+ C.GraphLib_Frames[level]:SetAllPoints(C)
+
+ if C.TextFrame and C.TextFrame:GetFrameLevel()<=newLevel then
+ C.TextFrame:SetFrameLevel(newLevel+1)
+ self.NeedsUpdate=true
+ end
+ end
+
+ Bar:SetParent(C.GraphLib_Frames[level])
+ Tri:SetParent(C.GraphLib_Frames[level])
+ end
+
+ Bar:SetVertexColor(color[1],color[2],color[3],color[4])
+ Tri:SetVertexColor(color[1],color[2],color[3],color[4])
+
+
+
+ if sy=1 then
+ Tri:ClearAllPoints()
+ Tri:SetPoint("BOTTOMLEFT", C, "BOTTOMLEFT", sx, MinY)
+ Tri:SetWidth(Width)
+ Tri:SetHeight(MaxY-MinY)
+ else
+ Tri:Hide()
+ end
+end
+
+
+function lib:HideBars(C)
+ if not C.GraphLib_Bars then
+ return
+ end
+
+ while (#C.GraphLib_Bars_Used)>0 do
+ C.GraphLib_Bars[#C.GraphLib_Bars+1]=C.GraphLib_Bars_Used[#C.GraphLib_Bars_Used]
+ C.GraphLib_Bars[#C.GraphLib_Bars]:Hide()
+ C.GraphLib_Bars_Used[#C.GraphLib_Bars_Used]=nil
+
+ C.GraphLib_Tris[#C.GraphLib_Tris+1]=C.GraphLib_Tris_Used[#C.GraphLib_Tris_Used]
+ C.GraphLib_Tris[#C.GraphLib_Tris]:Hide()
+ C.GraphLib_Tris_Used[#C.GraphLib_Tris_Used]=nil
+ end
+end
+
+
+
+
+
+
+-- lib upgrade stuff, overwrite the old function references in
+-- existing graphs with the ones in this newer library
+for _, graph in ipairs(lib.RegisteredGraphRealtime) do
+ SetupGraphRealtimeFunctions(graph, true)
+end
+for _, graph in ipairs(lib.RegisteredGraphLine) do
+ SetupGraphLineFunctions(graph)
+end
+for _, graph in ipairs(lib.RegisteredGraphScatterPlot) do
+ SetupGraphScatterPlotFunctions(graph)
+end
+for _, graph in ipairs(lib.RegisteredGraphPieChart) do
+ SetupGraphPieChartFunctions(graph)
+end
+
+
+
+
+
+
+
+---------------------------------------------------
+--Test Functions, for reference for addon authors to test, use and copy
+--To test the library do /script LibStub("LibGraph-2.0"):TestGraph2Lib()
+local function TestRealtimeGraph()
+ local Graph=LibStub(major)
+ local g=Graph:CreateGraphRealtime("TestRealtimeGraph",UIParent,"CENTER","CENTER",-90,90,150,150)
+ g:SetAutoScale(true)
+ g:SetGridSpacing(1.0,10.0)
+ g:SetYMax(120)
+ g:SetXAxis(-11,-1)
+ g:SetFilterRadius(1)
+ g:SetBarColors({0.2,0.0,0.0,0.4},{1.0,0.0,0.0,1.0})
+
+ local f = CreateFrame("Frame")
+ f:SetScript("OnUpdate",function() g:AddTimeData(1) end)
+ f:Show()
+ DEFAULT_CHAT_FRAME:AddMessage("Testing Reattime Graph")
+end
+
+local function TestRealtimeGraphRaw()
+ local Graph=LibStub(major)
+ local g=Graph:CreateGraphRealtime("TestRealtimeGraph",UIParent,"TOP","TOP",0,0,150,150)
+ g:SetAutoScale(true)
+ g:SetGridSpacing(1.0,10.0)
+ g:SetYMax(120)
+ g:SetXAxis(-10,0)
+ g:SetMode("RAW")
+ g:SetBarColors({0.2,0.0,0.0,0.4},{1.0,0.0,0.0,1.0})
+
+ local f = CreateFrame("Frame")
+ f.frames=0
+ f.NextUpdate=GetTime()
+ f:SetScript("OnUpdate",function()
+ if f.NextUpdate>GetTime() then
+ return
+ end
+
+ g:AddBar(UnitHealth("player"))
+ f.NextUpdate=f.NextUpdate+g.BarWidth
+ end)
+ f:Show()
+ DEFAULT_CHAT_FRAME:AddMessage("Testing 0")
+end
+
+
+
+local function TestLineGraph()
+ local Graph=LibStub(major)
+ local g=Graph:CreateGraphLine("TestLineGraph",UIParent,"CENTER","CENTER",90,90,150,150)
+ g:SetXAxis(-1,1)
+ g:SetYAxis(-1,1)
+ g:SetGridSpacing(0.25,0.25)
+ g:SetGridColor({0.5,0.5,0.5,0.5})
+ g:SetAxisDrawing(true,true)
+ g:SetAxisColor({1.0,1.0,1.0,1.0})
+ g:SetAutoScale(true)
+
+ local Data1={{0.05,0.05},{0.2,0.3},{0.4,0.2},{0.9,0.6}}
+ local Data2={{0.05,0.8},{0.3,0.1},{0.5,0.4},{0.95,0.05}}
+
+ g:AddDataSeries(Data1,{1.0,0.0,0.0,0.8})
+ g:AddDataSeries(Data2,{0.0,1.0,0.0,0.8})
+ DEFAULT_CHAT_FRAME:AddMessage("Testing Line Graph")
+end
+
+local function TestScatterPlot()
+ local Graph=LibStub(major)
+ local g=Graph:CreateGraphScatterPlot("TestScatterPlot",UIParent,"CENTER","CENTER",90,-90,150,150)
+ g:SetXAxis(-1,1)
+ g:SetYAxis(-1,1)
+ g:SetGridSpacing(0.25,0.25)
+ g:SetGridColor({0.5,0.5,0.5,0.5})
+ g:SetAxisDrawing(true,true)
+ g:SetAxisColor({1.0,1.0,1.0,1.0})
+ g:SetLinearFit(true)
+ g:SetAutoScale(true)
+
+ local Data1={{0.05,0.05},{0.2,0.3},{0.4,0.2},{0.9,0.6}}
+ local Data2={{0.05,0.8},{0.3,0.1},{0.5,0.4},{0.95,0.05}}
+
+ g:AddDataSeries(Data1,{1.0,0.0,0.0,0.8})
+ g:AddDataSeries(Data2,{0.0,1.0,0.0,0.8})
+ DEFAULT_CHAT_FRAME:AddMessage("Testing Scatter Plot")
+end
+
+local function TestPieChart()
+ local Graph=LibStub(major)
+ local g=Graph:CreateGraphPieChart("TestPieChart",UIParent,"CENTER","CENTER",-90,-90,150,150)
+ g:AddPie(35,{1.0,0.0,0.0})
+ g:AddPie(21,{0.0,1.0,0.0})
+ g:AddPie(10,{1.0,1.0,1.0})
+ g:CompletePie({0.2,0.2,1.0})
+ DEFAULT_CHAT_FRAME:AddMessage("Testing Pie Chart")
+end
+
+function lib:TestGraph2Lib()
+ DEFAULT_CHAT_FRAME:AddMessage("Testing "..major..", "..gsub(minor, "%$", ""))
+ TestRealtimeGraph()
+ TestLineGraph()
+ TestScatterPlot()
+ TestPieChart()
+end
diff --git a/Libs/LibGraph-2.0/line.tga b/Libs/LibGraph-2.0/line.tga
new file mode 100644
index 00000000..68fc74da
Binary files /dev/null and b/Libs/LibGraph-2.0/line.tga differ
diff --git a/Libs/LibGraph-2.0/sline.tga b/Libs/LibGraph-2.0/sline.tga
new file mode 100644
index 00000000..cf018cec
Binary files /dev/null and b/Libs/LibGraph-2.0/sline.tga differ
diff --git a/Libs/LibGraph-2.0/smallline.tga b/Libs/LibGraph-2.0/smallline.tga
new file mode 100644
index 00000000..95b75ff9
Binary files /dev/null and b/Libs/LibGraph-2.0/smallline.tga differ
diff --git a/Libs/LibGraph-2.0/thinline.tga b/Libs/LibGraph-2.0/thinline.tga
new file mode 100644
index 00000000..dcf45daf
Binary files /dev/null and b/Libs/LibGraph-2.0/thinline.tga differ
diff --git a/Libs/LibGraph-2.0/triangle.tga b/Libs/LibGraph-2.0/triangle.tga
new file mode 100644
index 00000000..0ccce337
Binary files /dev/null and b/Libs/LibGraph-2.0/triangle.tga differ
diff --git a/Libs/LibSharedMedia-3.0/LibSharedMedia-3.0.lua b/Libs/LibSharedMedia-3.0/LibSharedMedia-3.0.lua
new file mode 100644
index 00000000..2a81d7d7
--- /dev/null
+++ b/Libs/LibSharedMedia-3.0/LibSharedMedia-3.0.lua
@@ -0,0 +1,237 @@
+--[[
+Name: LibSharedMedia-3.0
+Revision: $Revision: 69 $
+Author: Elkano (elkano@gmx.de)
+Inspired By: SurfaceLib by Haste/Otravi (troeks@gmail.com)
+Website: http://www.wowace.com/projects/libsharedmedia-3-0/
+Description: Shared handling of media data (fonts, sounds, textures, ...) between addons.
+Dependencies: LibStub, CallbackHandler-1.0
+License: LGPL v2.1
+]]
+
+local MAJOR, MINOR = "LibSharedMedia-3.0", 4030402 -- increase manualy on changes
+local lib = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not lib then return end
+
+local _G = getfenv(0)
+
+local pairs = _G.pairs
+local type = _G.type
+
+local band = _G.bit.band
+
+local table_insert = _G.table.insert
+local table_sort = _G.table.sort
+
+local locale = GetLocale()
+local locale_is_western
+local LOCALE_MASK = 0
+lib.LOCALE_BIT_koKR = 1
+lib.LOCALE_BIT_ruRU = 2
+lib.LOCALE_BIT_zhCN = 4
+lib.LOCALE_BIT_zhTW = 8
+lib.LOCALE_BIT_western = 128
+
+local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
+
+lib.callbacks = lib.callbacks or CallbackHandler:New(lib)
+
+lib.DefaultMedia = lib.DefaultMedia or {}
+lib.MediaList = lib.MediaList or {}
+lib.MediaTable = lib.MediaTable or {}
+lib.MediaType = lib.MediaType or {}
+lib.OverrideMedia = lib.OverrideMedia or {}
+
+local defaultMedia = lib.DefaultMedia
+local mediaList = lib.MediaList
+local mediaTable = lib.MediaTable
+local overrideMedia = lib.OverrideMedia
+
+
+-- create mediatype constants
+lib.MediaType.BACKGROUND = "background" -- background textures
+lib.MediaType.BORDER = "border" -- border textures
+lib.MediaType.FONT = "font" -- fonts
+lib.MediaType.STATUSBAR = "statusbar" -- statusbar textures
+lib.MediaType.SOUND = "sound" -- sound files
+
+-- populate lib with default Blizzard data
+-- BACKGROUND
+if not lib.MediaTable.background then lib.MediaTable.background = {} end
+lib.MediaTable.background["None"] = [[]]
+lib.MediaTable.background["Blizzard Dialog Background"] = [[Interface\DialogFrame\UI-DialogBox-Background]]
+lib.MediaTable.background["Blizzard Dialog Background Dark"] = [[Interface\DialogFrame\UI-DialogBox-Background-Dark]]
+lib.MediaTable.background["Blizzard Dialog Background Gold"] = [[Interface\DialogFrame\UI-DialogBox-Gold-Background]]
+lib.MediaTable.background["Blizzard Low Health"] = [[Interface\FullScreenTextures\LowHealth]]
+lib.MediaTable.background["Blizzard Marble"] = [[Interface\FrameGeneral\UI-Background-Marble]]
+lib.MediaTable.background["Blizzard Out of Control"] = [[Interface\FullScreenTextures\OutOfControl]]
+lib.MediaTable.background["Blizzard Parchment"] = [[Interface\AchievementFrame\UI-Achievement-Parchment-Horizontal]]
+lib.MediaTable.background["Blizzard Parchment 2"] = [[Interface\AchievementFrame\UI-GuildAchievement-Parchment-Horizontal]]
+lib.MediaTable.background["Blizzard Rock"] = [[Interface\FrameGeneral\UI-Background-Rock]]
+lib.MediaTable.background["Blizzard Tabard Background"] = [[Interface\TabardFrame\TabardFrameBackground]]
+lib.MediaTable.background["Blizzard Tooltip"] = [[Interface\Tooltips\UI-Tooltip-Background]]
+lib.MediaTable.background["Solid"] = [[Interface\Buttons\WHITE8X8]]
+lib.DefaultMedia.background = "None"
+
+-- BORDER
+if not lib.MediaTable.border then lib.MediaTable.border = {} end
+lib.MediaTable.border["None"] = [[]]
+lib.MediaTable.border["Blizzard Achievement Wood"] = [[Interface\AchievementFrame\UI-Achievement-WoodBorder]]
+lib.MediaTable.border["Blizzard Chat Bubble"] = [[Interface\Tooltips\ChatBubble-Backdrop]]
+lib.MediaTable.border["Blizzard Dialog"] = [[Interface\DialogFrame\UI-DialogBox-Border]]
+lib.MediaTable.border["Blizzard Dialog Gold"] = [[Interface\DialogFrame\UI-DialogBox-Gold-Border]]
+lib.MediaTable.border["Blizzard Party"] = [[Interface\CHARACTERFRAME\UI-Party-Border]]
+lib.MediaTable.border["Blizzard Tooltip"] = [[Interface\Tooltips\UI-Tooltip-Border]]
+lib.DefaultMedia.border = "None"
+
+-- FONT
+if not lib.MediaTable.font then lib.MediaTable.font = {} end
+local SML_MT_font = lib.MediaTable.font
+if locale == "koKR" then
+ LOCALE_MASK = lib.LOCALE_BIT_koKR
+--
+ SML_MT_font["êµµì€ ê¸€ê¼´"] = [[Fonts\2002B.TTF]]
+ SML_MT_font["기본 글꼴"] = [[Fonts\2002.TTF]]
+ SML_MT_font["ë°ë¯¸ì§€ 글꼴"] = [[Fonts\K_Damage.TTF]]
+ SML_MT_font["퀘스트 글꼴"] = [[Fonts\K_Pagetext.TTF]]
+--
+ lib.DefaultMedia["font"] = "기본 글꼴" -- someone from koKR please adjust if needed
+--
+elseif locale == "zhCN" then
+ LOCALE_MASK = lib.LOCALE_BIT_zhCN
+--
+ SML_MT_font["伤害数å—"] = [[Fonts\ARKai_C.ttf]]
+ SML_MT_font["默认"] = [[Fonts\ARKai_T.ttf]]
+ SML_MT_font["èŠå¤©"] = [[Fonts\ARHei.ttf]]
+--
+ lib.DefaultMedia["font"] = "默认" -- someone from zhCN please adjust if needed
+--
+elseif locale == "zhTW" then
+ LOCALE_MASK = lib.LOCALE_BIT_zhTW
+--
+ SML_MT_font["æç¤ºè¨Šæ¯"] = [[Fonts\bHEI00M.ttf]]
+ SML_MT_font["èŠå¤©"] = [[Fonts\bHEI01B.ttf]]
+ SML_MT_font["傷害數å—"] = [[Fonts\bKAI00M.ttf]]
+ SML_MT_font["é è¨"] = [[Fonts\bLEI00D.ttf]]
+--
+ lib.DefaultMedia["font"] = "é è¨" -- someone from zhTW please adjust if needed
+
+elseif locale == "ruRU" then
+ LOCALE_MASK = lib.LOCALE_BIT_ruRU
+--
+ SML_MT_font["Arial Narrow"] = [[Fonts\ARIALN.TTF]]
+ SML_MT_font["Friz Quadrata TT"] = [[Fonts\FRIZQT__.TTF]]
+ SML_MT_font["Morpheus"] = [[Fonts\MORPHEUS.TTF]]
+ SML_MT_font["Nimrod MT"] = [[Fonts\NIM_____.ttf]]
+ SML_MT_font["Skurri"] = [[Fonts\SKURRI.TTF]]
+--
+ lib.DefaultMedia.font = "Friz Quadrata TT"
+--
+else
+ LOCALE_MASK = lib.LOCALE_BIT_western
+ locale_is_western = true
+--
+ SML_MT_font["Arial Narrow"] = [[Fonts\ARIALN.TTF]]
+ SML_MT_font["Friz Quadrata TT"] = [[Fonts\FRIZQT__.TTF]]
+ SML_MT_font["Morpheus"] = [[Fonts\MORPHEUS.TTF]]
+ SML_MT_font["Skurri"] = [[Fonts\SKURRI.TTF]]
+--
+ lib.DefaultMedia.font = "Friz Quadrata TT"
+--
+end
+
+-- STATUSBAR
+if not lib.MediaTable.statusbar then lib.MediaTable.statusbar = {} end
+lib.MediaTable.statusbar["Blizzard"] = [[Interface\TargetingFrame\UI-StatusBar]]
+lib.MediaTable.statusbar["Blizzard Character Skills Bar"] = [[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]]
+lib.DefaultMedia.statusbar = "Blizzard"
+
+-- SOUND
+if not lib.MediaTable.sound then lib.MediaTable.sound = {} end
+lib.MediaTable.sound["None"] = [[Interface\Quiet.ogg]] -- Relies on the fact that PlaySound[File] doesn't error on non-existing input.
+lib.DefaultMedia.sound = "None"
+
+local function rebuildMediaList(mediatype)
+ local mtable = mediaTable[mediatype]
+ if not mtable then return end
+ if not mediaList[mediatype] then mediaList[mediatype] = {} end
+ local mlist = mediaList[mediatype]
+ -- list can only get larger, so simply overwrite it
+ local i = 0
+ for k in pairs(mtable) do
+ i = i + 1
+ mlist[i] = k
+ end
+ table_sort(mlist)
+end
+
+function lib:Register(mediatype, key, data, langmask)
+ if type(mediatype) ~= "string" then
+ error(MAJOR..":Register(mediatype, key, data, langmask) - mediatype must be string, got "..type(mediatype))
+ end
+ if type(key) ~= "string" then
+ error(MAJOR..":Register(mediatype, key, data, langmask) - key must be string, got "..type(key))
+ end
+ mediatype = mediatype:lower()
+ if mediatype == lib.MediaType.FONT and ((langmask and band(langmask, LOCALE_MASK) == 0) or not (langmask or locale_is_western)) then return false end
+ if not mediaTable[mediatype] then mediaTable[mediatype] = {} end
+ local mtable = mediaTable[mediatype]
+ if mtable[key] then return false end
+
+ mtable[key] = data
+ rebuildMediaList(mediatype)
+ self.callbacks:Fire("LibSharedMedia_Registered", mediatype, key)
+ return true
+end
+
+function lib:Fetch(mediatype, key, noDefault)
+ local mtt = mediaTable[mediatype]
+ local overridekey = overrideMedia[mediatype]
+ local result = mtt and ((overridekey and mtt[overridekey] or mtt[key]) or (not noDefault and defaultMedia[mediatype] and mtt[defaultMedia[mediatype]])) or nil
+ return result ~= "" and result or nil
+end
+
+function lib:IsValid(mediatype, key)
+ return mediaTable[mediatype] and (not key or mediaTable[mediatype][key]) and true or false
+end
+
+function lib:HashTable(mediatype)
+ return mediaTable[mediatype]
+end
+
+function lib:List(mediatype)
+ if not mediaTable[mediatype] then
+ return nil
+ end
+ if not mediaList[mediatype] then
+ rebuildMediaList(mediatype)
+ end
+ return mediaList[mediatype]
+end
+
+function lib:GetGlobal(mediatype)
+ return overrideMedia[mediatype]
+end
+
+function lib:SetGlobal(mediatype, key)
+ if not mediaTable[mediatype] then
+ return false
+ end
+ overrideMedia[mediatype] = (key and mediaTable[mediatype][key]) and key or nil
+ self.callbacks:Fire("LibSharedMedia_SetGlobal", mediatype, overrideMedia[mediatype])
+ return true
+end
+
+function lib:GetDefault(mediatype)
+ return defaultMedia[mediatype]
+end
+
+function lib:SetDefault(mediatype, key)
+ if mediaTable[mediatype] and mediaTable[mediatype][key] and not defaultMedia[mediatype] then
+ defaultMedia[mediatype] = key
+ return true
+ else
+ return false
+ end
+end
diff --git a/Libs/LibSharedMedia-3.0/lib.xml b/Libs/LibSharedMedia-3.0/lib.xml
new file mode 100644
index 00000000..5b4a5c87
--- /dev/null
+++ b/Libs/LibSharedMedia-3.0/lib.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/Libs/LibStub/LibStub.lua b/Libs/LibStub/LibStub.lua
new file mode 100644
index 00000000..f5fc9192
--- /dev/null
+++ b/Libs/LibStub/LibStub.lua
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ -- LibStub:NewLibrary(major, minor)
+ -- major (string) - the major version of the library
+ -- minor (string or number ) - the minor version of the library
+ --
+ -- returns nil if a newer or same version of the lib is already present
+ -- returns empty library object or old library object if upgrade is needed
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ -- LibStub:GetLibrary(major, [silent])
+ -- major (string) - the major version of the library
+ -- silent (boolean) - if true, library is optional, silently return nil if its not found
+ --
+ -- throws an error if the library can not be found (except silent is set)
+ -- returns the library object if found
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ -- LibStub:IterateLibraries()
+ --
+ -- Returns an iterator for the currently registered libraries
+ function LibStub:IterateLibraries()
+ return pairs(self.libs)
+ end
+
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/Libs/LibStub/LibStub.toc b/Libs/LibStub/LibStub.toc
new file mode 100644
index 00000000..c3dc3656
--- /dev/null
+++ b/Libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 40200
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: r95
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/Libs/LibStub/tests/test.lua b/Libs/LibStub/tests/test.lua
new file mode 100644
index 00000000..645a08b1
--- /dev/null
+++ b/Libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/Libs/LibStub/tests/test2.lua b/Libs/LibStub/tests/test2.lua
new file mode 100644
index 00000000..af431dd3
--- /dev/null
+++ b/Libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib doesn't exist yet, by iterating through all the libraries
+ assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+ if major == "MyLib" then -- we found it!
+ count = count +1
+ assert(rawequal(library, lib)) -- verify that the references are equal
+ end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/Libs/LibStub/tests/test3.lua b/Libs/LibStub/tests/test3.lua
new file mode 100644
index 00000000..01aabb8d
--- /dev/null
+++ b/Libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/Libs/LibStub/tests/test4.lua b/Libs/LibStub/tests/test4.lua
new file mode 100644
index 00000000..15a9c9cd
--- /dev/null
+++ b/Libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/boot.lua b/boot.lua
new file mode 100644
index 00000000..a0012fc2
--- /dev/null
+++ b/boot.lua
@@ -0,0 +1,208 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> global name declaration
+ _detalhes = LibStub("AceAddon-3.0"):NewAddon("_detalhes", "AceTimer-3.0", "AceComm-3.0")
+ _detalhes.version = "Alpha 001"
+ _detalhes.realversion = 1
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> initialization stuff
+
+do
+
+ local _detalhes = _G._detalhes
+
+ --> startup
+ _detalhes.initializing = true
+ _detalhes.enabled = true
+ _detalhes.__index = _detalhes
+ _detalhes._tempo = time()
+ _detalhes.debug = false
+
+ --> containers
+ --> armazenas as funções do parser - All parse functions
+ _detalhes.parser = {}
+ --> armazena os escudos - Shields information for absorbs
+ _detalhes.escudos = {}
+ --> armazena os overwirtes de spells pelo usuario
+ _detalhes.SpellOverwriteUser = {}
+ --> armazena as funções dos frames - Frames functions
+ _detalhes.gump = {}
+ --> armazena as funções para inicialização dos dados - Metatable functions
+ _detalhes.refresh = {}
+ --> armazena as funções para limpar e guardas os dados - Metatable functions
+ _detalhes.clear = {}
+ --> armazena as fontstring usadas no addon - Store labels (fontstrings)
+ _detalhes.font_pool = {}
+ --> armazena a config do painel de fast switch
+ _detalhes.switch = {}
+ --> armazena os estilos salvos
+ _detalhes.savedStyles = {}
+ --> armazena quais atributos possue janela de atributos - contain attributes and sub attributos wich have a detailed window (left click on a row)
+ _detalhes.row_singleclick_overwrite = {}
+ --> report
+ _detalhes.ReportOptions = {}
+ --> armazena os buffs registrados - store buffs ids and functions
+ _detalhes.Buffs = {} --> initialize buff table
+
+ --> Plugins
+ --> raid -------------------------------------------------------------------
+ --> general function for raid mode plugins
+ _detalhes.RaidTables = {}
+ --> menu for raid modes
+ _detalhes.RaidTables.Menu = {}
+ --> plugin objects for raid mode
+ _detalhes.RaidTables.Plugins = {}
+ --> name to plugin object
+ _detalhes.RaidTables.NameTable = {}
+
+ --> solo -------------------------------------------------------------------
+ --> general functions for solo mode plugins
+ _detalhes.SoloTables = {}
+ --> maintain plugin menu
+ _detalhes.SoloTables.Menu = {}
+ --> plugins objects for solo mode
+ _detalhes.SoloTables.Plugins = {}
+ --> name to plugin object
+ _detalhes.SoloTables.NameTable = {}
+
+ --> toolbar -------------------------------------------------------------------
+ --> plugins container
+ _detalhes.ToolBar = {}
+ --> current showing icons
+ _detalhes.ToolBar.Shown = {}
+ --> plugin objects
+ _detalhes.ToolBar.Plugins = {}
+ --> name to plugin object
+ _detalhes.ToolBar.NameTable = {}
+
+ --> statusbar -------------------------------------------------------------------
+ --> plugins container
+ _detalhes.StatusBar = {}
+ --> maintain plugin menu
+ _detalhes.StatusBar.Menu = {}
+ --> plugins object
+ _detalhes.StatusBar.Plugins = {}
+ --> name to plugin object
+ _detalhes.StatusBar.NameTable = {}
+
+ --> constants
+ _detalhes._detalhes_props = {
+ DATA_TYPE_START = 1, --> Something on start
+ DATA_TYPE_END = 2, --> Something on end
+
+ MODO_ALONE = 1, --> Solo
+ MODO_GROUP = 2, --> Group
+ MODO_ALL = 3, --> Everything
+ MODO_RAID = 4, --> Raid
+ }
+ _detalhes.modos = {
+ alone = 1, --> Solo
+ group = 2, --> Group
+ all = 3, --> Everything
+ raid = 4 --> Raid
+ }
+ _detalhes.flags = {
+ --> Player and Pet
+ player = 0x00000001,--> player character
+ pet = 0x00000002, --> pet mobile
+ --> Group
+ in_group = 0x00000100,--> in group
+ player_in_group = 0x00000101, --> player in group
+ --> Friendship
+ friend = 0x00000010,--> friend (same faction)
+ friend_in_group = 0x00000110, --> friend in group
+ --> Enemies
+ neutral = 0x00000020,--> neutral
+ enemy = 0x00000040--> enemy
+ }
+
+ _detalhes.divisores = {
+ abre = "(", --> open
+ fecha = ")", --> close
+ colocacao = ". " --> dot
+ }
+
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ("Details")
+
+ _detalhes.segmentos = {
+ label = Loc ["STRING_SEGMENT"]..": ",
+ overall = Loc ["STRING_TOTAL"],
+ overall_standard = Loc ["STRING_OVERALL"],
+ current = Loc ["STRING_CURRENT"],
+ current_standard = Loc ["STRING_CURRENTFIGHT"],
+ past = Loc ["STRING_FIGHTNUMBER"]
+ }
+
+ _detalhes._detalhes_props["modo_nome"] = {
+ [_detalhes._detalhes_props["MODO_ALONE"]] = Loc ["STRING_MODE_SELF"],
+ [_detalhes._detalhes_props["MODO_GROUP"]] = Loc ["STRING_MODE_GROUP"],
+ [_detalhes._detalhes_props["MODO_ALL"]] = Loc ["STRING_MODE_ALL"],
+ [_detalhes._detalhes_props["MODO_RAID"]] = Loc ["STRING_MODE_RAID"]
+ }
+
+ _detalhes.icones = {
+ --> report window
+ report = {
+ up = "Interface\\FriendsFrame\\UI-Toast-FriendOnlineIcon",
+ down = "Interface\\ItemAnimations\\MINIMAP\\TRACKING\\Profession",
+ disabled = "Interface\\ItemAnimations\\MINIMAP\\TRACKING\\Profession",
+ highlight = nil
+ }
+ }
+
+ _detalhes.missTypes = {"ABSORB", "BLOCK", "DEFLECT", "DODGE", "EVADE", "IMMUNE", "MISS", "PARRY", "REFLECT", "RESIST"} --> do not localize-me
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> frames
+
+ local _CreateFrame = CreateFrame --api locals
+ local _UIParent = UIParent --api locals
+
+ --> Info Window
+ _detalhes.janela_info = _CreateFrame ("Frame", "Details_JanelaInfo", _UIParent)
+
+ --> Event Frame
+ _detalhes.listener = _CreateFrame ("Frame", nil, _UIParent)
+ _detalhes.listener:RegisterEvent ("ADDON_LOADED")
+ _detalhes.listener:RegisterEvent ("PLAYER_LOGOUT")
+ _detalhes.listener:SetFrameStrata ("LOW")
+ _detalhes.listener:SetFrameLevel (9)
+ _detalhes.listener.FrameTime = 0
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> functions
+
+ --> register textures and fonts for shared media
+ local SharedMedia = LibStub:GetLibrary ("LibSharedMedia-3.0")
+ SharedMedia:Register ("statusbar", "Details D'ictum", [[Interface\AddOns\Details\images\bar4]])
+
+ --> global 'vardump' for dump table contents over chat panel
+ function vardump (t)
+ if (type (t) ~= "table") then
+ return
+ end
+ for a,b in pairs (t) do
+ print (a,b)
+ end
+ end
+
+ --> delay messages
+ function _detalhes:DelayMsg (msg)
+ _detalhes.delaymsgs = _detalhes.delaymsgs or {}
+ _detalhes.delaymsgs [#_detalhes.delaymsgs+1] = msg
+ end
+ function _detalhes:ShowDelayMsg()
+ if (_detalhes.delaymsgs and #_detalhes.delaymsgs > 0) then
+ for _, msg in ipairs (_detalhes.delaymsgs) do
+ print (msg)
+ end
+ end
+ _detalhes.delaymsgs = {}
+ end
+
+end
diff --git a/classes/classe_combate.lua b/classes/classe_combate.lua
new file mode 100644
index 00000000..e31608a8
--- /dev/null
+++ b/classes/classe_combate.lua
@@ -0,0 +1,459 @@
+--[[
+-------Details! Addon
+-------Class Combat
+ -------This file control combat class. A combat is a object wich hold combat attributes.
+ -------The numeric part of table is compost by 4 indexes: [1] damage, [2] heal, [3] energies and [4] misc
+]]
+
+local _detalhes = _G._detalhes
+
+--shortcuts
+local combate = _detalhes.combate
+local container_combatentes = _detalhes.container_combatentes
+
+--flags
+local REACTION_HOSTILE = 0x00000040
+local CONTROL_PLAYER = 0x00000100
+
+--locals
+local _setmetatable = setmetatable --> lua api
+local _ipairs = ipairs --> lua api
+local _pairs = pairs --> lua api
+local _bit_band = bit.band --> lua api
+local _date = date --> lua api
+local _UnitName = UnitName --> wow api
+
+--time hold
+local _tempo = time()
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+--[[ __call function, get an actor from current combat.
+ combatTable ( index, actorName )
+ index: container number [1] damage, [2] heal, [3] energies and [4] misc
+ actorName: name of an actor (player, npc, pet, etc) --]]
+
+_detalhes.call_combate = function (self, class_type, name)
+ local container = self[class_type]
+ local index_mapa = container._NameIndexTable [name]
+ local actor = container._ActorTable [index_mapa]
+ return actor
+end
+
+combate.__call = _detalhes.call_combate
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+--[[ Class Constructor ]]
+function combate:NovaTabela (iniciada, _tabela_overall, combatId, ...)
+
+ local esta_tabela = {}
+
+ esta_tabela [1] = container_combatentes:NovoContainer (_detalhes.container_type.CONTAINER_DAMAGE_CLASS, esta_tabela, combatId) --> Damage
+ esta_tabela [2] = container_combatentes:NovoContainer (_detalhes.container_type.CONTAINER_HEAL_CLASS, esta_tabela, combatId) --> Healing
+ esta_tabela [3] = container_combatentes:NovoContainer (_detalhes.container_type.CONTAINER_ENERGY_CLASS, esta_tabela, combatId) --> Energies
+ esta_tabela [4] = container_combatentes:NovoContainer (_detalhes.container_type.CONTAINER_MISC_CLASS, esta_tabela, combatId) --> Misc
+ esta_tabela [5] = container_combatentes:NovoContainer (_detalhes.container_type.CONTAINER_DAMAGE_CLASS, esta_tabela, combatId) --> place holder for customs
+
+ _setmetatable (esta_tabela, combate)
+
+ --> debug
+ esta_tabela.meu_tipo = "classe_combate"
+
+ --> try discover if is a pvp combat
+ local who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags = ...
+ if (who_serial) then --> aqui irá identificar o boss ou o oponente
+ if (alvo_name and _bit_band (alvo_flags, REACTION_HOSTILE) ~= 0) then --> tentando pegar o inimigo pelo alvo
+ esta_tabela.contra = alvo_name
+ if (_bit_band (alvo_flags, CONTROL_PLAYER) ~= 0) then
+ esta_tabela.pvp = true --> o alvo é da facção oposta ou foi dado mind control
+ end
+ elseif (who_name and _bit_band (who_flags, REACTION_HOSTILE) ~= 0) then --> tentando pegar o inimigo pelo who caso o mob é quem deu o primeiro hit
+ esta_tabela.contra = who_name
+ if (_bit_band (who_flags, CONTROL_PLAYER) ~= 0) then
+ esta_tabela.pvp = true --> o who é da facção oposta ou foi dado mind control
+ end
+ else
+ esta_tabela.pvp = true --> se ambos são friendly, seria isso um PVP entre jogadores da mesma facções?
+ end
+ end
+
+ --> start/end time (duration)
+ esta_tabela.data_fim = 0
+ esta_tabela.data_inicio = 0
+ --esta_tabela.last_event = 0
+
+ --> record last event before dead
+ esta_tabela.last_events_tables = {}
+
+ --> record damage data
+ --esta_tabela.DpsGraphic = {max = 0}
+
+ --> time data container
+ esta_tabela.TimeData = _detalhes.timeContainer:CreateTimeTable()
+
+ --> Skill cache (not used)
+ esta_tabela.CombatSkillCache = {}
+
+ -- a tabela sem o tempo de inicio é a tabela descartavel do inicio do addon
+ if (iniciada) then
+ esta_tabela.start_time = _tempo
+ esta_tabela.end_time = nil
+ else
+ esta_tabela.start_time = 0
+ esta_tabela.end_time = nil
+ end
+
+ -- o container irá armazenar as classes de dano -- cria um novo container de indexes de seriais de jogadores --parâmetro 1 classe armazenada no container, parâmetro 2 = flag da classe
+ esta_tabela[1].need_refresh = true
+ esta_tabela[2].need_refresh = true
+ esta_tabela[3].need_refresh = true
+ esta_tabela[4].need_refresh = true
+ esta_tabela[5].need_refresh = true
+
+ if (_tabela_overall) then --> link é a tabela de combate do overall
+ esta_tabela[1].shadow = _tabela_overall[1] --> diz ao objeto qual a shadow dele na tabela overall
+ esta_tabela[2].shadow = _tabela_overall[2] --> diz ao objeto qual a shadow dele na tabela overall
+ esta_tabela[3].shadow = _tabela_overall[3] --> diz ao objeto qual a shadow dele na tabela overall
+ esta_tabela[4].shadow = _tabela_overall[4] --> diz ao objeto qual a shadow dele na tabela overall
+ end
+
+ -- abriga a tabela contendo o total de cada atributo
+ -- esta_tabela.barra_total = barra_total:NovaBarra()
+ --> barra total movido para um simples membro do combate:
+ esta_tabela.totals = {
+ 0, --> dano
+ 0, --> cura
+ {--> e_energy
+ mana = 0, --> mana
+ e_rage = 0, --> rage
+ e_energy = 0, --> energy (rogues cat)
+ runepower = 0 --> runepower (dk)
+ },
+ {--> misc
+ cc_break = 0, --> armazena quantas quebras de CC
+ ress = 0, --> armazena quantos pessoas ele reviveu
+ interrupt = 0, --> armazena quantos interrupt a pessoa deu
+ dispell = 0, --> armazena quantos dispell esta pessoa recebeu
+ dead = 0 --> armazena quantas vezes essa oessia morreu
+ }
+ }
+
+ esta_tabela.totals_grupo = {
+ 0, --> dano
+ 0, --> cura
+ {--> e_energy
+ mana = 0, --> mana
+ e_rage = 0, --> rage
+ e_energy = 0, --> energy (rogues cat)
+ runepower = 0 --> runepower (dk)
+ },
+ {--> misc
+ cc_break = 0, --> armazena quantas quebras de CC
+ ress = 0, --> armazena quantos pessoas ele reviveu
+ interrupt = 0, --> armazena quantos interrupt a pessoa deu
+ dispell = 0, --> armazena quantos dispell esta pessoa recebeu
+ dead = 0 --> armazena quantas vezes essa oessia morreu
+ }
+ }
+
+ return esta_tabela
+end
+
+function combate:GetTimeData (dataType)
+ --if (not dataType) then
+ return self.TimeData
+ --end
+end
+
+function combate:TravarTempos()
+ --é necessário travar o tempo em todos os atributos do combate.
+ for index, container in _ipairs (self) do -- aqui ele lista os tipos de atributo listado na lista acima
+ if (index ~= 3 and index ~= 4) then --> 3 é e_energy, não possui tempo // 4 é misc tbm não possui tempo
+ for _, jogador in _ipairs (container._ActorTable) do
+ if (jogador:Iniciar()) then -- retorna se ele esta com o dps ativo
+ jogador:TerminarTempo()
+ jogador:Iniciar (false) --trava o dps do jogador
+ jogador.last_events_table = {} --> elimina a tabela dos danos --não é mais usado desta forma
+ end
+ end
+ end
+ end
+end
+
+function combate:UltimaAcao (tempo)
+ if (tempo) then
+ self.last_event = tempo
+ else
+ return self.last_event
+ end
+end
+
+function combate:seta_data (tipo)
+ if (tipo == _detalhes._detalhes_props.DATA_TYPE_START) then
+ self.data_inicio = _date ("%H:%M:%S")
+ elseif (tipo == _detalhes._detalhes_props.DATA_TYPE_END) then
+ self.data_fim = _date ("%H:%M:%S")
+ end
+end
+
+function combate:GetActorList (container)
+ return self [container]._ActorTable
+end
+
+function combate:GetCombatTime()
+ if (self.end_time) then
+ --print ("tem end time")
+ return self.end_time - self.start_time
+ elseif (self.start_time and _detalhes.in_combat) then
+ --print ("tem start time e esta em combate")
+ return _tempo - self.start_time
+ else
+ --print ("retornando zero")
+ return 0
+ end
+end
+
+function combate:GetTotal (attribute, subAttribute, onlyGroup)
+ if (attribute == 1 or attribute == 2) then
+ if (onlyGroup) then
+ return self.totals_grupo [attribute]
+ else
+ return self.totals [attribute]
+ end
+
+ elseif (attribute == 3 or attribute == 4) then
+ local subName = _detalhes:GetInternalSubAttributeName (attribute, subAttribute)
+ if (onlyGroup) then
+ return self.totals_grupo [attribute] [subName]
+ else
+ return self.totals [attribute] [subName]
+ end
+ end
+ return 0
+end
+
+function combate:seta_tempo_decorrido()
+ self.end_time = _tempo
+end
+
+function _detalhes.refresh:r_combate (tabela_combate, shadow)
+ _setmetatable (tabela_combate, _detalhes.combate)
+ tabela_combate.__index = _detalhes.combate
+ tabela_combate.shadow = shadow
+end
+
+function _detalhes.clear:c_combate (tabela_combate)
+ tabela_combate.__index = {}
+ tabela_combate.__call = {}
+ tabela_combate._combat_table = nil
+ tabela_combate.shadow = nil
+end
+
+combate.__sub = function (overall, combate)
+
+ --> foreach no dano
+ for index, classe_damage in _ipairs (combate[1]._ActorTable) do
+ local nome = classe_damage.nome
+ local no_overall = overall[1]._ActorTable [overall[1]._NameIndexTable [nome]]
+ no_overall = no_overall - classe_damage
+
+ local alvos = classe_damage.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = no_overall.targets._ActorTable [no_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+
+ local habilidades = classe_damage.spell_tables
+ for _spellid, habilidade in _pairs (habilidades._ActorTable) do
+ local habilidade_overall = no_overall.spell_tables._ActorTable [_spellid]
+ habilidade_overall = habilidade_overall - habilidade
+
+ local alvos = habilidade.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = habilidade_overall.targets._ActorTable [habilidade_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+ end
+ end
+
+ --> foreach na cura
+ for index, classe_heal in _ipairs (combate[2]._ActorTable) do
+ local nome = classe_heal.nome
+ local no_overall = overall[2]._ActorTable [overall[2]._NameIndexTable [nome]]
+ no_overall = no_overall - classe_heal
+
+ local alvos = classe_heal.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = no_overall.targets._ActorTable [no_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+
+ local habilidades = classe_heal.spell_tables
+ for _spellid, habilidade in _pairs (habilidades._ActorTable) do
+ local habilidade_overall = no_overall.spell_tables._ActorTable [_spellid]
+ habilidade_overall = habilidade_overall - habilidade
+
+ local alvos = habilidade.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = habilidade_overall.targets._ActorTable [habilidade_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+ end
+ end
+
+ --> foreach na e_energy
+ for index, classe_energy in _ipairs (combate[3]._ActorTable) do
+ local nome = classe_energy.nome
+ local no_overall = overall[3]._ActorTable [overall[3]._NameIndexTable [nome]]
+ no_overall = no_overall - classe_energy
+
+ local alvos = classe_energy.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = no_overall.targets._ActorTable [no_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+
+ local habilidades = classe_energy.spell_tables
+ for _spellid, habilidade in _pairs (habilidades._ActorTable) do
+ local habilidade_overall = no_overall.spell_tables._ActorTable [_spellid]
+ habilidade_overall = habilidade_overall - habilidade
+
+ local alvos = habilidade.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = habilidade_overall.targets._ActorTable [habilidade_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+ end
+ end
+
+ --> foreach no misc
+ for index, classe_misc in _ipairs (combate[4]._ActorTable) do
+ local nome = classe_misc.nome
+ local no_overall = overall[4]._ActorTable [overall[4]._NameIndexTable [nome]]
+ no_overall = no_overall - classe_misc
+
+ if (classe_misc.interrupt) then
+ local alvos = classe_misc.interrupt_targets
+ local habilidades = classe_misc.interrupt_spell_tables
+
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = no_overall.interrupt_targets._ActorTable [no_overall.interrupt_targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+
+ for _spellid, habilidade in _pairs (habilidades._ActorTable) do
+ local habilidade_overall = no_overall.interrupt_spell_tables._ActorTable [_spellid]
+ habilidade_overall = habilidade_overall - habilidade
+
+ local alvos = habilidade.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = habilidade_overall.targets._ActorTable [habilidade_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+ end
+ end
+
+ if (classe_misc.ress) then
+ local alvos = classe_misc.ress_targets
+ local habilidades = classe_misc.ress_spell_tables
+
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = no_overall.ress_targets._ActorTable [no_overall.ress_targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+
+ for _spellid, habilidade in _pairs (habilidades._ActorTable) do
+ local habilidade_overall = no_overall.ress_spell_tables._ActorTable [_spellid]
+ habilidade_overall = habilidade_overall - habilidade
+
+ local alvos = habilidade.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = habilidade_overall.targets._ActorTable [habilidade_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+ end
+ end
+
+ if (classe_misc.dispell) then
+ local alvos = classe_misc.dispell_targets
+ local habilidades = classe_misc.dispell_spell_tables
+
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = no_overall.dispell_targets._ActorTable [no_overall.dispell_targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+
+ for _spellid, habilidade in _pairs (habilidades._ActorTable) do
+ local habilidade_overall = no_overall.dispell_spell_tables._ActorTable [_spellid]
+ habilidade_overall = habilidade_overall - habilidade
+
+ local alvos = habilidade.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = habilidade_overall.targets._ActorTable [habilidade_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+ end
+ end
+
+ if (classe_misc.cc_break) then
+ local alvos = classe_misc.cc_break_targets
+ local habilidades = classe_misc.cc_break_spell_tables
+
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = no_overall.cc_break_targets._ActorTable [no_overall.cc_break_targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+
+ for _spellid, habilidade in _pairs (habilidades._ActorTable) do
+ local habilidade_overall = no_overall.cc_break_spell_tables._ActorTable [_spellid]
+ habilidade_overall = habilidade_overall - habilidade
+
+ local alvos = habilidade.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ local alvo_overall = habilidade_overall.targets._ActorTable [habilidade_overall.targets._NameIndexTable [alvo.nome]]
+ alvo_overall = alvo_overall - alvo
+ end
+ end
+ end
+
+ end
+
+ --> diminui o total
+ overall.totals[1] = overall.totals[1] - combate.totals[1]
+ overall.totals[2] = overall.totals[2] - combate.totals[2]
+
+ overall.totals[3].mana = overall.totals[3].mana - combate.totals[3].mana
+ overall.totals[3].e_rage = overall.totals[3].e_rage - combate.totals[3].e_rage
+ overall.totals[3].e_energy = overall.totals[3].e_energy - combate.totals[3].e_energy
+ overall.totals[3].runepower = overall.totals[3].runepower - combate.totals[3].runepower
+
+ overall.totals[4].cc_break = overall.totals[4].cc_break - combate.totals[4].cc_break
+ overall.totals[4].ress = overall.totals[4].ress - combate.totals[4].ress
+ overall.totals[4].interrupt = overall.totals[4].interrupt - combate.totals[4].interrupt
+ overall.totals[4].dispell = overall.totals[4].dispell - combate.totals[4].dispell
+ overall.totals[4].dead = overall.totals[4].dead - combate.totals[4].dead
+
+
+ overall.totals_grupo[1] = overall.totals_grupo[1] - combate.totals_grupo[1]
+ overall.totals_grupo[2] = overall.totals_grupo[2] - combate.totals_grupo[2]
+
+ overall.totals_grupo[3].mana = overall.totals_grupo[3].mana - combate.totals_grupo[3].mana
+ overall.totals_grupo[3].e_rage = overall.totals_grupo[3].e_rage - combate.totals_grupo[3].e_rage
+ overall.totals_grupo[3].e_energy = overall.totals_grupo[3].e_energy - combate.totals_grupo[3].e_energy
+ overall.totals_grupo[3].runepower = overall.totals_grupo[3].runepower - combate.totals_grupo[3].runepower
+
+ overall.totals_grupo[4].cc_break = overall.totals_grupo[4].cc_break - combate.totals_grupo[4].cc_break
+ overall.totals_grupo[4].ress = overall.totals_grupo[4].ress - combate.totals_grupo[4].ress
+ overall.totals_grupo[4].interrupt = overall.totals_grupo[4].interrupt - combate.totals_grupo[4].interrupt
+ overall.totals_grupo[4].dispell = overall.totals_grupo[4].dispell - combate.totals_grupo[4].dispell
+ overall.totals_grupo[4].dead = overall.totals_grupo[4].dead - combate.totals_grupo[4].dead
+
+
+ return overall
+end
+
+function _detalhes:UpdateCombat()
+ _tempo = _detalhes._tempo
+end
diff --git a/classes/classe_custom.lua b/classes/classe_custom.lua
new file mode 100644
index 00000000..e54f3ad8
--- /dev/null
+++ b/classes/classe_custom.lua
@@ -0,0 +1,137 @@
+local _detalhes = _G._detalhes
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ( "Details" )
+
+--lua locals
+local _cstr = string.format
+local _math_floor = math.floor
+local _table_sort = table.sort
+local _table_insert = table.insert
+local _table_size = table.getn
+local _setmetatable = setmetatable
+local _ipairs = ipairs
+local _pairs = pairs
+local _rawget= rawget
+local _math_min = math.min
+local _math_max = math.max
+local _bit_band = bit.band
+local _unpack = unpack
+local _type = type
+
+--api locals
+local _GetSpellInfo = _detalhes.getspellinfo
+local _UnitName = UnitName
+local _IsInRaid = IsInRaid
+local _IsInGroup = IsInGroup
+local _GetNumGroupMembers = GetNumGroupMembers
+local _GetNumPartyMembers = GetNumPartyMembers or GetNumSubgroupMembers
+local _GetNumRaidMembers = GetNumRaidMembers or GetNumGroupMembers
+local _GetUnitName = GetUnitName
+
+local gump = _detalhes.gump
+
+local atributo_custom = _detalhes.atributo_custom
+
+function atributo_custom:RefreshWindow (instancia, _combat, forcar, exportar)
+
+ --> partir do principio que:
+ -- sempre vai ter um SPELLID
+ -- não vai ter target ou input output
+ --> instancia.sub_atributo armazena o index da tabela de custons
+
+ local CustomObject = _detalhes.custom [instancia.sub_atributo]
+
+ _combat.totals [CustomObject.name] = 0
+ instancia.customName = CustomObject.name
+
+ --print (CustomObject)
+ --print (CustomObject.source)
+ --print ("source: " .. CustomObject.source)
+
+ if (not CustomObject.source) then
+ print ("Sem Source")
+ return
+ elseif (CustomObject.source == "") then
+ print ("Source esta em branco")
+ return
+ end
+
+ --print ("atributo " .. CustomObject.attribute)
+
+ if (CustomObject.source == "[raid]") then
+ if (_IsInRaid()) then
+ for i = 1, _GetNumGroupMembers(), 1 do
+ local nome = _GetUnitName ("raid"..i, true):gsub (("%s+"), "")
+ local Actor = _combat (CustomObject.attribute, nome)
+ if (Actor) then
+ Actor:Custom (CustomObject.name, _combat, CustomObject.sattribute, CustomObject.spell, CustomObject.target)
+ end
+ end
+ elseif (_IsInGroup()) then
+ for i = 1, _GetNumGroupMembers()-1, 1 do
+ local nome = _GetUnitName ("raid"..i, true):gsub (("%s+"), "")
+ local Actor = _combat (CustomObject.attribute, nome)
+ if (Actor) then
+ Actor:Custom (CustomObject.name, _combat, CustomObject.sattribute, CustomObject.spell, CustomObject.target)
+ end
+ end
+ local Actor = _combat (CustomObject.attribute, _detalhes.playername)
+ if (Actor) then
+ Actor:Custom (CustomObject.name, _combat, CustomObject.sattribute, CustomObject.spell, CustomObject.target)
+ end
+ else
+ local Actor = _combat (CustomObject.attribute, _detalhes.playername)
+ if (Actor) then
+ Actor:Custom (CustomObject.name, _combat, CustomObject.sattribute, CustomObject.spell, CustomObject.target)
+ end
+ end
+
+ elseif (CustomObject.source == "[all]") then
+ for _, Actor in _ipairs (_combat [CustomObject.attribute]._ActorTable) do
+ Actor:Custom (CustomObject.name, _combat, CustomObject.sattribute, CustomObject.spell, CustomObject.target)
+ end
+
+ elseif (CustomObject.source == "[player]") then
+ local Actor = _combat (CustomObject.attribute, _detalhes.playername)
+ if (Actor) then
+ Actor:Custom (CustomObject.name, _combat, CustomObject.sattribute, CustomObject.spell, CustomObject.target)
+ end
+
+ else
+ local _thisActor = _combat (CustomObject.attribute, CustomObject.source)
+ if (_thisActor) then
+ _thisActor:Custom (CustomObject.name, _combat, CustomObject.sattribute, CustomObject.spell, CustomObject.target)
+ end
+ end
+
+ --> agora result tem os atores que usaram a habilidade
+ if (CustomObject.attribute == 1) then
+ return _detalhes.atributo_damage:RefreshWindow (instancia, _combat, forcar, exportar)
+ elseif (CustomObject.attribute == 2) then
+ _detalhes.atributo_heal:RefreshWindow (instancia, _combat, forcar, exportar)
+ end
+
+ --> aqui precisa fazer algo para retornar algo pro report reconhecer a tabela
+
+end
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/classes/classe_damage.lua b/classes/classe_damage.lua
new file mode 100644
index 00000000..f8048717
--- /dev/null
+++ b/classes/classe_damage.lua
@@ -0,0 +1,1915 @@
+
+
+--lua locals
+local _cstr = string.format
+local _math_floor = math.floor
+local _table_sort = table.sort
+local _table_insert = table.insert
+local _table_size = table.getn
+local _setmetatable = setmetatable
+local _ipairs = ipairs
+local _pairs = pairs
+local _rawget= rawget
+local _math_min = math.min
+local _math_max = math.max
+local _bit_band = bit.band
+local _unpack = unpack
+local _type = type
+--api locals
+local _GetSpellInfo = _detalhes.getspellinfo
+local GameTooltip = GameTooltip
+
+local _detalhes = _G._detalhes
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local container_habilidades = _detalhes.container_habilidades
+local container_combatentes = _detalhes.container_combatentes
+local container_pets = _detalhes.container_pets
+local atributo_damage = _detalhes.atributo_damage
+local habilidade_dano = _detalhes.habilidade_dano
+local container_damage_target = _detalhes.container_type.CONTAINER_DAMAGETARGET_CLASS
+
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+local container_damage = _detalhes.container_type.CONTAINER_DAMAGE_CLASS
+local container_friendlyfire = _detalhes.container_type.CONTAINER_FRIENDLYFIRE
+
+local modo_ALONE = _detalhes.modos.alone
+local modo_GROUP = _detalhes.modos.group
+local modo_ALL = _detalhes.modos.all
+
+local class_type = _detalhes.atributos.dano
+
+local DATA_TYPE_START = _detalhes._detalhes_props.DATA_TYPE_START
+local DATA_TYPE_END = _detalhes._detalhes_props.DATA_TYPE_END
+
+local DFLAG_player = _detalhes.flags.player
+local DFLAG_group = _detalhes.flags.in_group
+local DFLAG_player_group = _detalhes.flags.player_in_group
+
+local div_abre = _detalhes.divisores.abre
+local div_fecha = _detalhes.divisores.fecha
+local div_lugar = _detalhes.divisores.colocacao
+
+local CLASS_ICON_TCOORDS = _G.CLASS_ICON_TCOORDS
+
+local info = _detalhes.janela_info
+local keyName
+
+function atributo_damage:NovaTabela (serial, nome, link)
+
+ local _new_damageActor = {}
+ _setmetatable (_new_damageActor, atributo_damage)
+
+ _new_damageActor.quem_sou = "classe_damage" --> DEBUG deleta-me
+
+ --> grava o tempo que a tabela foi criada para o garbage collector interno
+ _new_damageActor.CriadaEm = time()
+
+ --> dps do objeto inicia sempre desligado
+ _new_damageActor.dps_started = false
+
+ _new_damageActor.tipo = class_type --> atributo 1 = dano
+
+ _new_damageActor.total = 0
+ _new_damageActor.custom = 0
+ _new_damageActor.total_without_pet = 0
+
+ _new_damageActor.damage_taken = 0 --> total de dano que este jogador levou
+ _new_damageActor.damage_from = {} --> armazena os nomes que deram dano neste jogador
+
+ _new_damageActor.last_events_table = {} --> log da morte
+
+ _new_damageActor.avoidance = {["DODGE"] = 0, ["PARRY"] = 0, ["HITS"] = 0} --> avoidance
+
+ _new_damageActor.last_event = 0
+ _new_damageActor.on_hold = false
+ _new_damageActor.delay = 0
+
+ _new_damageActor.last_value = nil --> ultimo valor que este jogador teve, salvo quando a barra dele é atualizada
+
+ _new_damageActor.end_time = nil
+ _new_damageActor.start_time = 0
+
+ _new_damageActor.last_dps = 0
+
+ _new_damageActor.pets = {}
+
+ --_new_damageActor.friendlyfire = {} --> será criado no primeiro fogo amigo dado
+ _new_damageActor.friendlyfire_total = 0
+ _new_damageActor.friendlyfire = container_combatentes:NovoContainer (container_friendlyfire)
+
+ --container armazenará os seriais dos alvos que o player aplicou dano
+ _new_damageActor.targets = container_combatentes:NovoContainer (container_damage_target)
+
+ --container armazenará os IDs das habilidades usadas por este jogador
+ _new_damageActor.spell_tables = container_habilidades:NovoContainer (container_damage)
+
+ if (link) then
+ _new_damageActor.targets.shadow = link.targets
+ _new_damageActor.spell_tables.shadow = link.spell_tables
+ _new_damageActor.friendlyfire.shadow = link.friendlyfire
+ end
+
+ return _new_damageActor
+end
+
+--[[exported]] function _detalhes.SortGroup (container, keyName2)
+ keyName = keyName2
+ return _table_sort (container, _detalhes.SortKeyGroup)
+ end
+
+--[[exported]] function _detalhes.SortKeyGroup (table1, table2)
+ if (table1.grupo and table2.grupo) then
+ return table1 [keyName] > table2 [keyName]
+ elseif (table1.grupo and not table2.grupo) then
+ return true
+ elseif (not table1.grupo and table2.grupo) then
+ return false
+ else
+ return table1 [keyName] > table2 [keyName]
+ end
+ end
+
+--[[exported]] function _detalhes.SortKeySimple (table1, table2)
+ return table1 [keyName] > table2 [keyName]
+ end
+
+--[[exported]] function _detalhes:ContainerSort (container, amount, keyName2)
+ keyName = keyName2
+ _table_sort (container, _detalhes.SortKeySimple)
+
+ if (amount) then
+ for i = amount, 1, -1 do --> de trás pra frente
+ if (container[i][keyName] < 1) then
+ amount = amount-1
+ else
+ break
+ end
+ end
+
+ return amount
+ end
+ end
+
+--[[ exported]] function _detalhes:IsPlayer()
+ if (self.flags) then
+ if (_bit_band (self.flag, 0x00000001) ~= 0) then
+ return true
+ end
+ end
+ return false
+end
+
+function atributo_damage:RefreshWindow (instancia, tabela_do_combate, forcar, exportar)
+
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ --> não há barras para mostrar -- not have something to show
+ if (#showing._ActorTable < 1) then
+ --> colocado isso recentemente para fazer as barras de dano sumirem na troca de atributo
+ return _detalhes:EsconderBarrasNaoUsadas (instancia, showing)
+ end
+
+ --> total
+ local total = 0
+ --> top actor #1
+ instancia.top = 0
+
+ local sub_atributo = instancia.sub_atributo --> o que esta sendo mostrado nesta instância
+ local conteudo = showing._ActorTable --> pega a lista de jogadores -- get actors table from container
+ local amount = #conteudo
+ local modo = instancia.modo
+
+ --> pega qual a sub key que será usada --sub keys
+ if (exportar) then
+
+ if (_type (exportar) == "boolean") then
+ if (sub_atributo == 1) then --> DAMAGE DONE
+ keyName = "total"
+ elseif (sub_atributo == 2) then --> DPS
+ keyName = "last_dps"
+ elseif (sub_atributo == 3) then --> TAMAGE TAKEN
+ keyName = "damage_taken"
+ elseif (sub_atributo == 4) then --> FRIENDLY FIRE
+ keyName = "friendlyfire_total"
+ end
+ else
+ keyName = exportar.key
+ modo = exportar.modo
+ end
+ elseif (instancia.atributo == 5) then --> custom
+ keyName = "custom"
+ total = tabela_do_combate.totals [instancia.customName]
+ else
+ if (sub_atributo == 1) then --> DAMAGE DONE
+ keyName = "total"
+ elseif (sub_atributo == 2) then --> DPS
+ keyName = "last_dps"
+ elseif (sub_atributo == 3) then --> TAMAGE TAKEN
+ keyName = "damage_taken"
+ elseif (sub_atributo == 4) then --> FRIENDLY FIRE
+ keyName = "friendlyfire_total"
+ end
+ end
+
+ if (instancia.atributo == 5) then --> custom
+ --> faz o sort da categoria e retorna o amount corrigido
+ amount = _detalhes:ContainerSort (conteudo, amount, keyName)
+
+ --> grava o total
+ instancia.top = conteudo[1][keyName]
+
+ elseif (modo == modo_ALL) then --> mostrando ALL
+
+ --> faz o sort da categoria e retorna o amount corrigido
+ amount = _detalhes:ContainerSort (conteudo, amount, keyName)
+
+ --> pega o total ja aplicado na tabela do combate
+ total = tabela_do_combate.totals [class_type]
+
+ --> grava o total
+ instancia.top = conteudo[1][keyName]
+
+ elseif (modo == modo_GROUP) then --> mostrando GROUP
+
+ --> organiza as tabelas
+
+ _table_sort (conteudo, _detalhes.SortKeyGroup, keyName)
+
+ --[[
+ _table_sort (conteudo, function (a, b)
+ if (a.grupo and b.grupo) then
+ return a[keyName] > b[keyName]
+ elseif (a.grupo and not b.grupo) then
+ return true
+ elseif (not a.grupo and b.grupo) then
+ return false
+ else
+ return a[keyName] > b[keyName]
+ end
+ end)
+ --]]
+
+ for index, player in _ipairs (conteudo) do
+ if (_bit_band (player.flag, DFLAG_player_group) >= 0x101) then --> é um player e esta em grupo
+ if (player[keyName] < 1) then --> dano menor que 1, interromper o loop
+ amount = index - 1
+ break
+ elseif (index == 1) then --> esse IF aqui, precisa mesmo ser aqui? não daria pra pega-lo com uma chave [1] nad grupo == true?
+ instancia.top = conteudo[1][keyName]
+ end
+
+ total = total + player[keyName]
+ else
+ amount = index-1
+ break
+ end
+ end
+ end
+
+ --> refaz o mapa do container
+ showing:remapear()
+
+ if (exportar) then
+ return total, keyName, instancia.top
+ end
+
+ if (amount < 1) then --> não há barras para mostrar
+ if (forcar) then
+ if (instancia.modo == 2) then --> group
+ for i = 1, instancia.barrasInfo.cabem do
+ gump:Fade (instancia.barras [i], "in", 0.3)
+ end
+ end
+ end
+ instancia:EsconderScrollBar() --> precisaria esconder a scroll bar
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+ end
+
+ --estra mostrando ALL então posso seguir o padrão correto? primeiro, atualiza a scroll bar...
+ --print ("AMOUT: " .. amount)
+ instancia:AtualizarScrollBar (amount)
+
+ --depois faz a atualização normal dele através dos iterators
+ local qual_barra = 1
+ local barras_container = instancia.barras --> evita buscar N vezes a key .barras dentro da instância
+
+ if (not true) then --> follow tests, not working atm.
+ local myPos = showing._NameIndexTable [_detalhes.playername]
+ if (myPos) then
+ --testando
+
+ local cima = math.floor (instancia.barrasInfo.cabem/2)
+ local baixo = math.ceil (instancia.barrasInfo.cabem/2)
+
+ if (instancia.barrasInfo.cabem%2 == 0) then
+ cima = cima - 1
+ end
+
+ cima = math.max (myPos - cima, 1)
+ baixo = math.min (myPos + baixo, amount)
+
+ print (myPos, cima, baixo)
+
+ for i = cima, baixo, 1 do --> vai atualizar só o range que esta sendo mostrado
+ conteudo[i]:AtualizaBarra (instancia, barras_container, qual_barra, i, total, sub_atributo, forcar, keyName) --> instância, index, total, valor da 1º barra
+ qual_barra = qual_barra+1
+ end
+
+ end
+ else
+ local combat_time = instancia.showing:GetCombatTime()
+ for i = instancia.barraS[1], instancia.barraS[2], 1 do --> vai atualizar só o range que esta sendo mostrado
+ conteudo[i]:AtualizaBarra (instancia, barras_container, qual_barra, i, total, sub_atributo, forcar, keyName, combat_time) --> instância, index, total, valor da 1º barra
+ qual_barra = qual_barra+1
+ end
+ end
+
+
+
+ if (instancia.atributo == 5) then --> custom
+ --> zerar o .custom dos Actors
+ for index, player in _ipairs (conteudo) do
+ if (player.custom > 0) then
+ player.custom = 0
+ else
+ break
+ end
+ end
+ end
+
+ --> beta, hidar barras não usadas durante um refresh forçado
+ if (forcar) then
+ if (instancia.modo == 2) then --> group
+ for i = qual_barra, instancia.barrasInfo.cabem do
+ gump:Fade (instancia.barras [i], "in", 0.3)
+ end
+ end
+ end
+
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+
+end
+
+function atributo_damage:Custom (_customName, _combat, sub_atributo, spell, alvo)
+ --> vai ter só o que a spell causou em alguém
+ --print (spell)
+ --print (self.nome)
+ --print (self.spell_tables._ActorTable)
+
+ --if (self.nome == "Ditador") then
+ --for spellid, tabela in pairs (self.spell_tables._ActorTable) do
+ --print (spellid)
+ --end
+ local _Skill = self.spell_tables._ActorTable [tonumber (spell)]
+ --print (_Skill)
+ if (_Skill) then
+ local spellName = _GetSpellInfo (tonumber (spell))
+ --print (spell)
+ --print (spellName)
+
+ local SkillTargets = _Skill.targets._ActorTable
+
+ for _, TargetActor in _ipairs (SkillTargets) do
+ --print (TargetActor.nome)
+ local TargetActorSelf = _combat (class_type, TargetActor.nome)
+ --print (TargetActor.total)
+ TargetActorSelf.custom = TargetActor.total + TargetActorSelf.custom
+ --print (TargetActorSelf.custom)
+ _combat.totals [_customName] = _combat.totals [_customName] + TargetActor.total
+ --print (self.nome .. " " ..TargetActor.total)
+ end
+ end
+ --end
+end
+
+function _detalhes:FastRefreshWindow (instancia)
+ if (instancia.atributo == 1) then --> damage
+
+ end
+end
+
+--self = esta classe de dano
+function atributo_damage:AtualizaBarra (instancia, barras_container, qual_barra, lugar, total, sub_atributo, forcar, keyName, combat_time)
+ -- instância, container das barras, qual barra, colocação, total?, sub atributo, forçar refresh, key
+
+ local esta_barra = barras_container [qual_barra] --> pega a referência da barra na janela
+
+ if (not esta_barra) then
+ print ("DEBUG: problema com "..qual_barra.." "..lugar)
+ return
+ end
+
+ local tabela_anterior = esta_barra.minha_tabela
+
+ esta_barra.minha_tabela = self --> grava uma referência desse objeto na barra
+ self.minha_barra = esta_barra --> grava uma referência da barra no objeto
+
+ esta_barra.colocacao = lugar --> salva na barra qual a colocação mostrada.
+ self.colocacao = lugar --> salva no objeto qual a colocação mostrada
+
+ local damage_total = self.total --> total de dano que este jogador deu
+ local dps
+ local porcentagem = self [keyName] / total * 100
+ local esta_porcentagem
+
+ if (_detalhes.time_type == 2 and self.grupo) then
+ dps = damage_total / combat_time
+ self.last_dps = dps
+ else
+ if (not self.on_hold) then
+ dps = damage_total/self:Tempo() --calcula o dps deste objeto
+ self.last_dps = dps --salva o dps dele
+ else
+ if (self.last_dps == 0) then --> não calculou o dps dele ainda mas entrou em standby
+ dps = damage_total/self:Tempo()
+ self.last_dps = dps
+ else
+ dps = self.last_dps
+ end
+ end
+ end
+
+ -- >>>>>>>>>>>>>>> texto da direita
+ if (instancia.atributo == 5) then --> custom
+ esta_barra.texto_direita:SetText (_detalhes:ToK (self.custom) .." ".. div_abre .. _cstr ("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita
+ esta_porcentagem = _math_floor ((self.custom/instancia.top) * 100) --> determina qual o tamanho da barra
+ else
+ if (sub_atributo == 1) then --> mostrando damage done
+ esta_barra.texto_direita:SetText (_detalhes:ToK (damage_total) .." ".. div_abre .. _math_floor (dps) .. ", ".. _cstr ("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita
+ esta_porcentagem = _math_floor ((damage_total/instancia.top) * 100) --> determina qual o tamanho da barra
+
+ elseif (sub_atributo == 2) then --> mostrando dps
+ esta_barra.texto_direita:SetText (_cstr("%.1f", dps) .." ".. div_abre .. _detalhes:ToK (damage_total) .. ", ".._cstr("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita
+ esta_porcentagem = _math_floor ((dps/instancia.top) * 100) --> determina qual o tamanho da barra
+
+ elseif (sub_atributo == 3) then --> mostrando damage taken
+ esta_barra.texto_direita:SetText (_detalhes:ToK (self.damage_taken) .." ".. div_abre .._cstr("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita --_cstr("%.1f", dps) .. " - ".. DPS do damage taken não será possivel correto?
+ esta_porcentagem = _math_floor ((self.damage_taken/instancia.top) * 100) --> determina qual o tamanho da barra
+
+ elseif (sub_atributo == 4) then --> mostrando friendly fire
+ esta_barra.texto_direita:SetText (_detalhes:ToK (self.friendlyfire_total) .." ".. div_abre .._cstr("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita --_cstr("%.1f", dps) .. " - ".. DPS do damage taken não será possivel correto?
+ esta_porcentagem = _math_floor ((self.friendlyfire_total/instancia.top) * 100) --> determina qual o tamanho da barra
+
+ end
+ end
+
+ if (esta_barra.mouse_over and not instancia.baseframe.isMoving) then --> precisa atualizar o tooltip
+ gump:UpdateTooltip (qual_barra, esta_barra, instancia)
+ end
+
+ if (self.need_refresh) then
+ self.need_refresh = false
+ forcar = true
+ end
+
+ return self:RefreshBarra2 (esta_barra, instancia, tabela_anterior, forcar, esta_porcentagem, qual_barra, barras_container)
+
+end
+
+--[[ exported]] function _detalhes:RefreshBarra2 (esta_barra, instancia, tabela_anterior, forcar, esta_porcentagem, qual_barra, barras_container)
+
+ --> primeiro colocado
+ if (esta_barra.colocacao == 1) then
+ if (not tabela_anterior or tabela_anterior ~= esta_barra.minha_tabela or forcar) then
+ esta_barra.statusbar:SetValue (100)
+
+ if (esta_barra.hidden or esta_barra.fading_in or esta_barra.faded) then
+ gump:Fade (esta_barra, "out")
+ end
+
+ return self:RefreshBarra (esta_barra, instancia)
+ else
+ return
+ end
+ else
+
+ if (esta_barra.hidden or esta_barra.fading_in or esta_barra.faded) then
+
+ esta_barra.statusbar:SetValue (esta_porcentagem)
+ gump:Fade (esta_barra, "out")
+
+ if (self.classe == "PET" and self.owner) then
+ esta_barra.textura:SetVertexColor (_unpack (_detalhes.class_colors [self.owner.classe]))
+ else
+ esta_barra.textura:SetVertexColor (_unpack (_detalhes.class_colors [self.classe]))
+ end
+
+ return self:RefreshBarra (esta_barra, instancia)
+
+ else
+ --> agora esta comparando se a tabela da barra é diferente da tabela na atualização anterior
+ if (not tabela_anterior or tabela_anterior ~= esta_barra.minha_tabela or forcar) then --> aqui diz se a barra do jogador mudou de posição ou se ela apenas será atualizada
+
+ esta_barra.statusbar:SetValue (esta_porcentagem)
+
+ esta_barra.last_value = esta_porcentagem --> reseta o ultimo valor da barra
+
+ if (instancia.use_row_animations and forcar) then
+ esta_barra.tem_animacao = 0
+ esta_barra:SetScript ("OnUpdate", nil)
+ end
+
+ return self:RefreshBarra (esta_barra, instancia)
+
+ elseif (esta_porcentagem ~= esta_barra.last_value) then --> continua mostrando a mesma tabela então compara a porcentagem
+ --> apenas atualizar
+ if (instancia.use_row_animations) then
+
+ local upRow = barras_container [qual_barra-1]
+ if (upRow) then
+ if (upRow.statusbar:GetValue() < esta_barra.statusbar:GetValue()) then
+ esta_barra.statusbar:SetValue (esta_porcentagem)
+ else
+ instancia:AnimarBarra (esta_barra, esta_porcentagem)
+ end
+ else
+ instancia:AnimarBarra (esta_barra, esta_porcentagem)
+ end
+ else
+ esta_barra.statusbar:SetValue (esta_porcentagem)
+ end
+ esta_barra.last_value = esta_porcentagem
+ end
+ end
+
+ end
+
+end
+
+--[[ exported]] function _detalhes:RefreshBarra (esta_barra, instancia)
+ --print (self.classe)
+
+ if (self.classe == "PET" and self.owner) then
+ esta_barra.textura:SetVertexColor (_unpack (_detalhes.class_colors [self.owner.classe]))
+ else
+ esta_barra.textura:SetVertexColor (_unpack (_detalhes.class_colors [self.classe]))
+ end
+
+ --esta_barra.textura:SetVertexColor (_unpack (_detalhes.class_colors [self.classe]))
+
+ if (self.classe == "UNKNOW") then
+
+ --esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\Pet_Type_Undead")
+ --esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\INV_Misc_Bone_Skull_02")
+ --esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\Icon_PetFamily_Undead")
+
+ --esta_barra.icone_classe:SetTexture ("Interface\\CHARACTERFRAME\\UI-StateIcon")
+ --esta_barra.icone_classe:SetTexCoord (0.5625, 0.90625, 0.078125, 0.4375)
+
+ --esta_barra.icone_classe:SetTexture ("Interface\\LFGFRAME\\UI-LFG-ICON-HEROIC")
+ --esta_barra.icone_classe:SetTexCoord (0, 0.5625, 0, 0.5625)
+
+ esta_barra.icone_classe:SetTexture ("Interface\\LFGFRAME\\LFGROLE_BW")
+ esta_barra.icone_classe:SetTexCoord (.25, .5, 0, 1)
+ esta_barra.icone_classe:SetVertexColor (1, 1, 1)
+
+ elseif (self.classe == "UNGROUPPLAYER") then
+ if (self.enemy) then
+ if (_detalhes.faction_against == "Horde") then
+ esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\Achievement_Character_Orc_Male")
+ esta_barra.icone_classe:SetTexCoord (0, 1, 0, 1)
+ else
+ esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\Achievement_Character_Human_Male")
+ esta_barra.icone_classe:SetTexCoord (0, 1, 0, 1)
+ end
+ else
+ if (_detalhes.faction_against == "Horde") then
+ esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\Achievement_Character_Human_Male")
+ esta_barra.icone_classe:SetTexCoord (0, 1, 0, 1)
+ else
+ esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\Achievement_Character_Orc_Male")
+ esta_barra.icone_classe:SetTexCoord (0, 1, 0, 1)
+ end
+ end
+ esta_barra.icone_classe:SetVertexColor (1, 1, 1)
+
+ elseif (self.classe == "PET") then
+ --esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\Ability_Hunter_Pet_Wolf")
+ --esta_barra.icone_classe:SetTexture ("Interface\\ICONS\\Pet_Type_Beast")
+ --esta_barra.icone_classe:SetTexCoord (0, 1, 0, 1)
+ --esta_barra.icone_classe:SetTexCoord (0, 0.25, 0.75, 1)
+
+ esta_barra.icone_classe:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+ esta_barra.icone_classe:SetTexCoord (0.25, 0.49609375, 0.75, 1)
+ if (self.owner) then
+ esta_barra.icone_classe:SetVertexColor (_unpack (_detalhes.class_colors [self.owner.classe]))
+ else
+ esta_barra.icone_classe:SetVertexColor (_unpack (_detalhes.class_colors [self.classe]))
+ end
+
+
+ else
+ esta_barra.icone_classe:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+ esta_barra.icone_classe:SetTexCoord (_unpack (CLASS_ICON_TCOORDS [self.classe]))
+ esta_barra.icone_classe:SetVertexColor (1, 1, 1)
+ end
+
+ if (self.enemy) then
+ if (_detalhes.faction_against == "Horde") then
+ esta_barra.texto_esquerdo:SetText (esta_barra.colocacao..". |TInterface\\AddOns\\Details\\images\\icones_barra:"..instancia.barrasInfo.altura..":"..instancia.barrasInfo.altura..":0:0:256:32:0:32:0:32|t"..self.displayName) --seta o texto da esqueda -- HORDA
+ else
+ esta_barra.texto_esquerdo:SetText (esta_barra.colocacao..". |TInterface\\AddOns\\Details\\images\\icones_barra:"..instancia.barrasInfo.altura..":"..instancia.barrasInfo.altura..":0:0:256:32:32:64:0:32|t"..self.displayName) --seta o texto da esqueda -- ALLY
+ end
+ esta_barra.textura:SetVertexColor (240/255, 0, 5/255, 1)
+ else
+ esta_barra.texto_esquerdo:SetText (esta_barra.colocacao..". "..self.displayName) --seta o texto da esqueda
+ end
+
+ esta_barra.texto_esquerdo:SetSize (esta_barra:GetWidth() - esta_barra.texto_direita:GetStringWidth() - 20, 15)
+
+end
+
+
+--------------------------------------------- // TOOLTIPS // ---------------------------------------------
+
+--[[Exported]] function _detalhes:TooltipForCustom (barra)
+ _detalhes.popup:Close()
+
+ GameTooltip:ClearLines()
+ GameTooltip:AddLine (barra.colocacao..". "..self.nome)
+ GameTooltip:AddLine ("-> Left click for report", 1, 1, 1, 1) --> localize-me
+
+ return true
+end
+
+---------> TOOLTIPS BIFURCAÇÃO
+function atributo_damage:ToolTip (instancia, numero, barra)
+ --> seria possivel aqui colocar o icone da classe dele?
+
+ if (instancia.atributo == 5) then --> custom
+ return self:TooltipForCustom (barra)
+ else
+ if (instancia.sub_atributo == 1 or instancia.sub_atributo == 2) then --> damage done or Dps
+ return self:ToolTip_DamageDone (instancia, numero, barra)
+ elseif (instancia.sub_atributo == 3) then --> damage taken
+ return self:ToolTip_DamageTaken (instancia, numero, barra)
+ elseif (instancia.sub_atributo == 4) then --> friendly fire
+ return self:ToolTip_FriendlyFire (instancia, numero, barra)
+ end
+ end
+end
+
+--[[exported]] function _detalhes.Sort1 (table1, table2)
+ return table1 [1] > table2 [1]
+ end
+--[[exported]] function _detalhes.Sort2 (table1, table2)
+ return table1 [2] > table2 [2]
+ end
+
+---------> DAMAGE DONE & DPS
+function atributo_damage:ToolTip_DamageDone (instancia, numero, barra)
+
+ do
+
+ --> TOP HABILIDADES
+ local ActorDamage = self.total_without_pet
+ local ActorSkillsContainer = self.spell_tables._ActorTable
+ local ActorSkillsSortTable = {}
+ for _spellid, _skill in _pairs (ActorSkillsContainer) do
+ ActorSkillsSortTable [#ActorSkillsSortTable+1] = {_spellid, _skill.total}
+ end
+ _table_sort (ActorSkillsSortTable, _detalhes.Sort2)
+
+ --> TOP INIMIGOS
+ local ActorTargetsContainer = self.targets._ActorTable
+ local ActorTargetsSortTable = {}
+ for _, _target in _ipairs (ActorTargetsContainer) do
+ ActorTargetsSortTable [#ActorTargetsSortTable+1] = {_target.nome, _target.total}
+ end
+ _table_sort (ActorTargetsSortTable, _detalhes.Sort2)
+
+ --> MOSTRA HABILIDADES
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"]..":")
+ if (#ActorSkillsSortTable > 0) then
+ for i = 1, _math_min (_detalhes.tooltip_max_abilities, #ActorSkillsSortTable) do
+ local SkillTable = ActorSkillsSortTable [i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (SkillTable [1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", _detalhes:comma_value (SkillTable [2]) .." (".._cstr("%.1f", SkillTable [2]/ActorDamage*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ else
+ GameTooltip:AddLine (Loc ["STRING_NO_SPELL"])
+ end
+
+ --> MOSTRA INIMIGOS
+ GameTooltip:AddLine (Loc ["STRING_TARGETS"]..":")
+ for i = 1, _math_min (_detalhes.tooltip_max_targets, #ActorTargetsSortTable) do
+ local este_inimigo = ActorTargetsSortTable [i]
+ GameTooltip:AddDoubleLine (este_inimigo[1]..": ", _detalhes:comma_value (este_inimigo[2]) .." (".._cstr("%.1f", este_inimigo[2]/ActorDamage*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture ("Interface\\AddOns\\Details\\images\\espadas")
+ end
+ end
+
+ --> PETS
+ local meus_pets = self.pets
+ if (#meus_pets > 0) then --> teve ajudantes
+
+ local quantidade = {} --> armazena a quantidade de pets iguais
+ local danos = {} --> armazena as habilidades
+ local alvos = {} --> armazena os alvos
+ local totais = {} --> armazena o dano total de cada objeto
+
+ for index, nome in _ipairs (meus_pets) do
+ if (not quantidade [nome]) then
+ quantidade [nome] = 1
+
+ local my_self = instancia.showing[class_type]:PegarCombatente (_, nome)
+ if (my_self) then
+ local meu_total = my_self.total_without_pet
+ local tabela = my_self.spell_tables._ActorTable
+ local meus_danos = {}
+
+ totais [nome] = my_self.total_without_pet
+
+ for spellid, tabela in _pairs (tabela) do
+ local nome, rank, icone = _GetSpellInfo (spellid)
+ _table_insert (meus_danos, {spellid, tabela.total, tabela.total/meu_total*100, {nome, rank, icone}})
+ end
+ _table_sort (meus_danos, _detalhes.Sort2)
+ danos [nome] = meus_danos
+
+ local meus_inimigos = {}
+ tabela = my_self.targets._ActorTable
+ for _, tabela in _ipairs (tabela) do
+ _table_insert (meus_inimigos, {tabela.nome, tabela.total, tabela.total/meu_total*100})
+ end
+ _table_sort (meus_inimigos,_detalhes.Sort2)
+ alvos [nome] = meus_inimigos
+ end
+
+ else
+ quantidade [nome] = quantidade [nome]+1
+ end
+ end
+
+ GameTooltip:AddLine (" ")
+
+ local _quantidade = 0
+
+ for nome, meus_danos in _pairs (danos) do --> um pet de cada vez
+ local n = nome:gsub (("%s%<.*"), "")
+ --GameTooltip:AddDoubleLine ("Ajudante: ", "x"..quantidade[nome].." "..n.." (".._math_floor (totais [nome]/self.total*100).."%)", nil, nil, nil, 1, 1, 1)
+ --> pintar o nome do pet com a cor da classe do jogador
+
+ local cor = self.cor
+ GameTooltip:AddDoubleLine (Loc ["STRING_PET"]..":", n.." (".._math_floor (totais [nome]/self.total*100).."%)", nil, nil, nil, _unpack (_detalhes.class_colors [self.classe])) --> removido a quantidade
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"])
+ for i = 1, 3 do
+ if (meus_danos[i]) then
+ --> meus_danos = { [1] = spellid [2] = total [3] = % [4] = { [1] = nome [2] = rank [3] = icone } }
+ GameTooltip:AddDoubleLine (meus_danos[i][4][1]..": ", _detalhes:comma_value (meus_danos[i][2]).." (".._cstr("%.1f", meus_danos[i][3]).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (meus_danos[i][4][3])
+ end
+ end
+
+ GameTooltip:AddLine (Loc ["STRING_TARGETS"])
+ for i = 1, 3 do
+ local meus_inimigos = alvos [nome]
+ if (meus_inimigos[i]) then
+ GameTooltip:AddDoubleLine (meus_inimigos[i][1]..": ", _detalhes:comma_value (meus_inimigos[i][2]).." (".._cstr("%.1f", meus_inimigos[i][3]).."%)", 1, 1, 1, 1, 1, 1)
+ --GameTooltip:AddTexture ("Interface\\GossipFrame\\BattleMasterGossipIcon.blp")
+
+ GameTooltip:AddTexture ("Interface\\AddOns\\Details\\images\\espadas")
+ end
+ end
+
+ GameTooltip:AddLine (" ")
+
+ _quantidade = _quantidade + 1
+ if (_quantidade >= _detalhes.tooltip_max_pets) then
+ return true
+ end
+ end
+ end
+
+ return true
+end
+
+---------> DAMAGE TAKEN
+function atributo_damage:ToolTip_DamageTaken (instancia, numero, barra)
+
+ local agressores = self.damage_from
+ local damage_taken = self.damage_taken
+
+ local tabela_do_combate = instancia.showing
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ local meus_agressores = {}
+
+ for nome, _ in _pairs (agressores) do --> agressores seria a lista de nomes
+ local este_agressor = showing._ActorTable[showing._NameIndexTable[nome]]
+ if (este_agressor) then --> checagem por causa do total e do garbage collector que não limpa os nomes que deram dano
+ local alvos = este_agressor.targets
+ local este_alvo = alvos._ActorTable[alvos._NameIndexTable[self.nome]]
+ if (este_alvo) then
+ meus_agressores [#meus_agressores+1] = {nome, este_alvo.total, este_agressor.classe}
+ end
+ end
+ end
+
+ _table_sort (meus_agressores, function (a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (" ")
+
+ local max = #meus_agressores
+ if (max > 6) then
+ max = 6
+ end
+
+ for i = 1, max do
+ GameTooltip:AddDoubleLine (meus_agressores[i][1]..": ", _detalhes:comma_value (meus_agressores[i][2]).." (".._cstr("%.1f", (meus_agressores[i][2]/damage_taken) * 100).."%)", 1, 1, 1, 1, 1, 1)
+ local classe = meus_agressores[i][3]
+ if (not classe) then
+ classe = "monster"
+ end
+
+ GameTooltip:AddTexture ("Interface\\AddOns\\Details\\images\\"..classe:lower().."_small")
+ end
+
+ return true
+end
+
+---------> FRIENDLY FIRE
+function atributo_damage:ToolTip_FriendlyFire (instancia, numero, barra)
+
+ local FriendlyFire = self.friendlyfire --> container de jogadores
+ local FriendlyFireTotal = self.friendlyfire_total
+
+ local tabela_do_combate = instancia.showing
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ local DamagedPlayers = {}
+ local Skills = {}
+
+ for nome, index in _pairs (FriendlyFire._NameIndexTable) do
+ local TargetActor = FriendlyFire._ActorTable [index]
+ DamagedPlayers [#DamagedPlayers+1] = {nome, TargetActor.total}
+
+ local SkillTable = TargetActor.spell_tables --> container das habilidades
+ for spellid, tabela in _pairs (SkillTable._ActorTable) do
+ Skills [#Skills+1] = {spellid, tabela.total, tabela.counter}
+ end
+ end
+
+ _table_sort (DamagedPlayers, _detalhes.Sort2)
+ _table_sort (Skills, _detalhes.Sort2)
+
+ GameTooltip:AddLine (Loc ["STRING_TARGETS"]..":")
+ for i = 1, _math_min (_detalhes.tooltip_max_abilities, #DamagedPlayers) do
+ GameTooltip:AddDoubleLine (DamagedPlayers[i][1]..": ", _detalhes:comma_value (DamagedPlayers[i][2]).." (".._cstr("%.1f", DamagedPlayers[i][2]/FriendlyFireTotal*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture ("Interface\\AddOns\\Details\\images\\espadas")
+ end
+
+ GameTooltip:AddLine (" ")
+
+ --> Mostra as habilidades no tooltip
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"]..":")
+ for i = 1, _math_min (_detalhes.tooltip_max_abilities, #Skills) do
+ local nome, _, icone = _GetSpellInfo (Skills[i][1])
+ GameTooltip:AddDoubleLine (nome.." (x".. Skills[i][3].."): ", _detalhes:comma_value (Skills[i][2]).." (".._cstr("%.1f", Skills[i][2]/FriendlyFireTotal*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone)
+ end
+
+ return true
+end
+
+
+--------------------------------------------- // JANELA DETALHES // ---------------------------------------------
+
+
+---------> DETALHES BIFURCAÇÃO
+function atributo_damage:MontaInfo()
+ if (info.sub_atributo == 1 or info.sub_atributo == 2) then --> damage done & dps
+ return self:MontaInfoDamageDone()
+ elseif (info.sub_atributo == 3) then --> damage taken
+ return self:MontaInfoDamageTaken()
+ elseif (info.sub_atributo == 4) then --> friendly fire
+ return self:MontaInfoFriendlyFire()
+ end
+end
+
+---------> DETALHES bloco da direita BIFURCAÇÃO
+function atributo_damage:MontaDetalhes (spellid, barra)
+ if (info.sub_atributo == 1 or info.sub_atributo == 2) then
+ return self:MontaDetalhesDamageDone (spellid, barra)
+ elseif (info.sub_atributo == 3) then
+ return self:MontaDetalhesDamageTaken (spellid, barra)
+ elseif (info.sub_atributo == 4) then
+ return self:MontaDetalhesFriendlyFire (spellid, barra)
+ end
+end
+
+
+------ Friendly Fire
+function atributo_damage:MontaInfoFriendlyFire()
+
+ -- ESQUERDA -> JOGADORES ATINGIDOS - jogadores que o player atingiu com o fogo amigo
+ -- DIREITA -> MAGIAS USADAS - magias que o jogador usou para causar dano no amigo
+ -- ALVOS -> overall de todas as magias, total de dano que elas causaram
+
+ local FriendlyFireTotal = self.friendlyfire_total --> total de fogo amigo dado por este jogador
+ local conteudo = self.friendlyfire._ActorTable --> _ipairs[] com os nomes dos jogadores em que este jogador deu dano
+
+ local barras = info.barras1
+ local barras2 = info.barras2
+ local barras3 = info.barras3
+
+ local instancia = info.instancia
+
+ local DamagedPlayers = {}
+ local Skills = {}
+
+ for nome, index in _pairs (self.friendlyfire._NameIndexTable) do --> da foreach em cada spellid do container
+ local TargetActor = conteudo [index]
+ local TargetActorDamage = TargetActor.total
+ _table_insert (DamagedPlayers, {nome, TargetActorDamage, TargetActorDamage/FriendlyFireTotal*100, TargetActor.classe})
+
+ for spellid, habilidade in _pairs (TargetActor.spell_tables._ActorTable) do
+ if (not Skills [spellid]) then
+ Skills [spellid] = habilidade.total
+ else
+ Skills [spellid] = Skills [spellid] + habilidade.total
+ end
+ end
+ end
+
+ _table_sort (DamagedPlayers, _detalhes.Sort2)
+
+ local amt = #DamagedPlayers
+ gump:JI_AtualizaContainerBarras (amt)
+
+ local FirstPlaceDamage = DamagedPlayers [1][2]
+
+ for index, tabela in _ipairs (DamagedPlayers) do
+ local barra = barras [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo1 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ barra.on_focus = false
+ end
+
+ if (not info.mostrando_mouse_over) then
+ if (tabela[1] == self.detalhes) then --> tabela [1] = NOME = NOME que esta na caixa da direita
+ if (not barra.on_focus) then --> se a barra não tiver no foco
+ barra.textura:SetStatusBarColor (129/255, 125/255, 69/255, 1)
+ barra.on_focus = true
+ if (not info.mostrando) then
+ info.mostrando = barra
+ end
+ end
+ else
+ if (barra.on_focus) then
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> volta a cor antiga
+ barra:SetAlpha (.9) --> volta a alfa antiga
+ barra.on_focus = false
+ end
+ end
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/FirstPlaceDamage*100)
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ local classe = tabela[4]
+ if (not classe) then
+ classe = "monster"
+ end
+
+ barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\"..classe:lower().."_small")
+
+ barra.minha_tabela = self
+ barra.show = tabela[1]
+ barra:Show()
+
+ if (self.detalhes and self.detalhes == barra.show) then
+ self:MontaDetalhes (self.detalhes, barra)
+ end
+ end
+
+ local SkillTable = {}
+ for spellid, amt in _pairs (Skills) do
+ local nome, _, icone = _GetSpellInfo (spellid)
+ SkillTable [#SkillTable+1] = {nome, amt, amt/FriendlyFireTotal*100, icone}
+ end
+
+ _table_sort (SkillTable, _detalhes.Sort2)
+
+ amt = #SkillTable
+ if (amt < 1) then
+ return
+ end
+
+ gump:JI_AtualizaContainerAlvos (amt)
+
+ FirstPlaceDamage = SkillTable [1][2]
+
+ for index, tabela in _ipairs (SkillTable) do
+ local barra = barras2 [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo2 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/FirstPlaceDamage*100)
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .. instancia.divisores.fecha) --seta o texto da direita
+ barra.icone:SetTexture (tabela[4])
+
+ barra.minha_tabela = nil --> desativa o tooltip
+
+ barra:Show()
+ end
+
+end
+
+------ Damage Taken
+function atributo_damage:MontaInfoDamageTaken()
+
+ local damage_taken = self.damage_taken
+ local agressores = self.damage_from
+ local instancia = info.instancia
+ local tabela_do_combate = instancia.showing
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+ local barras = info.barras1
+ local meus_agressores = {}
+
+ local este_agressor
+ for nome, _ in _pairs (agressores) do
+ este_agressor = showing._ActorTable[showing._NameIndexTable[nome]]
+ if (este_agressor) then
+ local alvos = este_agressor.targets
+ local este_alvo = alvos._ActorTable[alvos._NameIndexTable[self.nome]]
+ if (este_alvo) then
+ meus_agressores [#meus_agressores+1] = {nome, este_alvo.total, este_alvo.total/damage_taken*100, este_agressor.classe}
+ end
+ end
+ end
+
+ local amt = #meus_agressores
+
+ if (amt < 1) then --> caso houve apenas friendly fire
+ return true
+ end
+
+ _table_sort (meus_agressores, function (a, b) return a[2] > b[2] end)
+
+ gump:JI_AtualizaContainerBarras (amt)
+
+ local max_ = meus_agressores [1][2]
+
+ for index, tabela in _ipairs (meus_agressores) do
+
+ local barra = barras [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo1 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+
+ barra.on_focus = false
+ end
+
+ if (not info.mostrando_mouse_over) then
+ if (tabela[1] == self.detalhes) then --> tabela [1] = NOME = NOME que esta na caixa da direita
+ if (not barra.on_focus) then --> se a barra não tiver no foco
+ barra.textura:SetStatusBarColor (129/255, 125/255, 69/255, 1)
+ barra.on_focus = true
+ if (not info.mostrando) then
+ info.mostrando = barra
+ end
+ end
+ else
+ if (barra.on_focus) then
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> volta a cor antiga
+ barra:SetAlpha (.9) --> volta a alfa antiga
+ barra.on_focus = false
+ end
+ end
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ local classe = tabela[4]
+ if (not classe) then
+ classe = "monster"
+ end
+
+ barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\"..classe:lower().."_small")
+
+ barra.minha_tabela = self
+ barra.show = tabela[1]
+ barra:Show()
+
+ if (self.detalhes and self.detalhes == barra.show) then
+ self:MontaDetalhes (self.detalhes, barra)
+ end
+
+ end
+
+end
+
+--[[
+ --> TOP HABILIDADES
+ local ActorDamage = self.total_without_pet
+ local ActorSkillsContainer = self.spell_tables._ActorTable
+ local ActorSkillsSortTable = {}
+ for _spellid, _skill in _pairs (ActorSkillsContainer) do
+ ActorSkillsSortTable [#ActorSkillsSortTable+1] = {_spellid, _skill.total}
+ end
+ _table_sort (ActorSkillsSortTable, _detalhes.Sort2)
+
+ --> TOP INIMIGOS
+ local ActorTargetsContainer = self.targets._ActorTable
+ local ActorTargetsSortTable = {}
+ for _, _target in _ipairs (ActorTargetsContainer) do
+ ActorTargetsSortTable [#ActorTargetsSortTable+1] = {_target.nome, _target.total}
+ end
+ _table_sort (ActorTargetsSortTable, _detalhes.Sort2)
+--]]
+
+--[[exported]] function _detalhes:UpdadeInfoBar (row, index, spellid, name, value, max, percent, icon, detalhes)
+ --> seta o tamanho da barra
+ if (index == 1) then
+ row.textura:SetValue (100)
+ else
+ row.textura:SetValue (value/max*100)
+ end
+
+ --> seta o texto da esqueda
+ --row.texto_esquerdo:SetText (index.."."..name)
+ --if (not) then
+
+ --end
+ row.texto_esquerdo:SetText (index.."."..name)
+ --> seta o texto da direita
+ row.texto_direita:SetText (_detalhes:comma_value (value).." (".._cstr("%.1f", percent) .."%)")
+
+ --> seta o icone
+ if (icon) then
+ row.icone:SetTexture (icon)
+ else
+ row.icone:SetTexture ("")
+ end
+
+ row.minha_tabela = self
+ row.show = spellid
+ row:Show() --> mostra a barra
+
+ if (detalhes and self.detalhes and self.detalhes == spellid) then
+ self:MontaDetalhes (spellid, row) --> poderia deixar isso pro final e montar uma tail call??
+ end
+end
+
+--[[exported]] function _detalhes:FocusLock (row, spellid)
+ if (not info.mostrando_mouse_over) then
+ if (spellid == self.detalhes) then --> tabela [1] = spellid = spellid que esta na caixa da direita
+ if (not row.on_focus) then --> se a barra não tiver no foco
+ row.textura:SetStatusBarColor (129/255, 125/255, 69/255, 1)
+ row.on_focus = true
+ if (not info.mostrando) then
+ info.mostrando = row
+ end
+ end
+ else
+ if (row.on_focus) then
+ row.textura:SetStatusBarColor (1, 1, 1, 1) --> volta a cor antiga
+ row:SetAlpha (.9) --> volta a alfa antiga
+ row.on_focus = false
+ end
+ end
+ end
+end
+
+------ Damage Done & Dps
+function atributo_damage:MontaInfoDamageDone()
+
+ local barras = info.barras1
+ local instancia = info.instancia
+ local total = self.total_without_pet --> total de dano aplicado por este jogador
+
+ local ActorTotalDamage = self.total
+ local ActorSkillsSortTable = {}
+ local ActorSkillsContainer = self.spell_tables._ActorTable
+
+ for _spellid, _skill in _pairs (ActorSkillsContainer) do --> da foreach em cada spellid do container
+ local nome, _, icone = _GetSpellInfo (_spellid)
+ _table_insert (ActorSkillsSortTable, {_spellid, _skill.total, _skill.total/ActorTotalDamage*100, nome, icone})
+ end
+
+ --> add pets
+ local ActorPets = self.pets
+ for _, PetName in _ipairs (ActorPets) do
+ local PetActor = instancia.showing (class_type, PetName)
+ if (PetActor) then
+ _table_insert (ActorSkillsSortTable, {PetName, PetActor.total, PetActor.total/ActorTotalDamage*100, PetName:gsub ((" <.*"), ""), "Interface\\ICONS\\Ability_Hunter_Pet_Wolf"})
+ end
+ end
+
+ _table_sort (ActorSkillsSortTable, _detalhes.Sort2)
+
+ gump:JI_AtualizaContainerBarras (#ActorSkillsSortTable)
+
+ local max_ = ActorSkillsSortTable[1][2] --> dano que a primeiro magia vez
+
+ local barra
+ for index, tabela in _ipairs (ActorSkillsSortTable) do
+ barra = barras [index]
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo1 (instancia, index)
+ end
+
+ self:FocusLock (barra, tabela[1])
+
+ self:UpdadeInfoBar (barra, index, tabela[1], tabela[4], tabela[2], max_, tabela[3], tabela[5], true)
+ end
+
+ --> TOP INIMIGOS
+ local meus_inimigos = {}
+ conteudo = self.targets._ActorTable
+
+ for _, tabela in _ipairs (conteudo) do
+ _table_insert (meus_inimigos, {tabela.nome, tabela.total, tabela.total/total*100})
+ end
+
+ _table_sort (meus_inimigos, function(a, b) return a[2] > b[2] end )
+
+ local amt_alvos = #meus_inimigos
+ if (amt_alvos < 1) then
+ return
+ end
+
+ gump:JI_AtualizaContainerAlvos (amt_alvos)
+
+ local max_inimigos = meus_inimigos[1][2]
+
+ local barra
+ for index, tabela in _ipairs (meus_inimigos) do
+
+ barra = info.barras2 [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo2 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_inimigos*100)
+ end
+
+ --barra.textura:SetStatusBarColor (1, 1, 1, 1)
+
+ --gump:CorBarraOnInfo2 (index, {}) --> como será o esquema de cores?
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (_detalhes:comma_value (tabela[2]) .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .. instancia.divisores.fecha) --seta o texto da direita
+
+ if (barra.mouse_over) then --> atualizar o tooltip
+ if (barra.isAlvo) then
+ GameTooltip:Hide()
+ GameTooltip:SetOwner (barra, "ANCHOR_TOPRIGHT")
+ if (not barra.minha_tabela:MontaTooltipAlvos (barra, index)) then
+ return
+ end
+ GameTooltip:Show()
+ end
+ end
+
+ --gump:TextoBarraOnInfo2 (index, , )
+ -- o que mostrar no local do ícone?
+ --barra.icone:SetTexture (tabela[4][3])
+
+ barra.minha_tabela = self --> grava o jogador na tabela
+ barra.nome_inimigo = tabela [1] --> salva o nome do inimigo na barra --> isso é necessário?
+
+ -- no lugar do spell id colocar o que?
+ barra.spellid = tabela[5]
+ barra:Show()
+
+ --if (self.detalhes and self.detalhes == barra.spellid) then
+ -- self:MontaDetalhes (self.detalhes, barra)
+ --end
+ end
+
+end
+
+
+------ Detalhe Info Friendly Fire
+function atributo_damage:MontaDetalhesFriendlyFire (nome, barra)
+
+ for _, barra in _ipairs (info.barras3) do
+ barra:Hide()
+ end
+
+ local barras = info.barras3
+ local instancia = info.instancia
+
+ local tabela_do_combate = info.instancia.showing
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ --> será apresentada as magias que deram dano no jogador alvo
+
+ local friendlyfire = self.friendlyfire
+
+ local total = friendlyfire._ActorTable [friendlyfire._NameIndexTable[nome]].total
+ local conteudo = friendlyfire._ActorTable [friendlyfire._NameIndexTable[nome]].spell_tables._ActorTable --> assumindo que nome é o nome do Alvo que tomou dano // bastaria pegar a tabela de habilidades dele
+
+ local minhas_magias = {}
+
+ for spellid, tabela in _pairs (conteudo) do --> da foreach em cada spellid do container
+ local nome, _, icone = _GetSpellInfo (spellid)
+ _table_insert (minhas_magias, {spellid, tabela.total, tabela.total/total*100, nome, icone})
+ end
+
+ _table_sort (minhas_magias, function(a, b) return a[2] > b[2] end)
+
+ --local amt = #minhas_magias
+ --gump:JI_AtualizaContainerBarras (amt)
+
+ local max_ = minhas_magias[1][2] --> dano que a primeiro magia vez
+
+ local barra
+ for index, tabela in _ipairs (minhas_magias) do
+ barra = barras [index]
+
+ if (not barra) then --> se a barra não existir, criar ela então
+ barra = gump:CriaNovaBarraInfo3 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> isso aqui é a parte da seleção e desceleção
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[4]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ barra.icone:SetTexture (tabela[5])
+
+ barra:Show() --> mostra a barra
+
+ if (index == 15) then
+ break
+ end
+ end
+
+end
+
+------ Detalhe Info Damage Taken
+function atributo_damage:MontaDetalhesDamageTaken (nome, barra)
+
+ for _, barra in _ipairs (info.barras3) do
+ barra:Hide()
+ end
+
+ local barras = info.barras3
+ local instancia = info.instancia
+
+ local tabela_do_combate = info.instancia.showing
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ local este_agressor = showing._ActorTable[showing._NameIndexTable[nome]]
+
+ if (not este_agressor ) then
+ print ("EROO este agressor eh NIL")
+ return
+ end
+
+ local conteudo = este_agressor.spell_tables._ActorTable --> _pairs[] com os IDs das magias
+
+ local actor = info.jogador.nome
+
+ local total = este_agressor.targets._ActorTable [este_agressor.targets._NameIndexTable [actor]].total
+
+ local minhas_magias = {}
+
+ for spellid, tabela in _pairs (conteudo) do --> da foreach em cada spellid do container
+
+ --> preciso pegar os alvos que esta magia atingiu
+ local alvos = tabela.targets
+ local index = alvos._NameIndexTable[actor]
+
+ if (index) then --> esta magia deu dano no actor
+ local este_alvo = alvos._ActorTable[index] --> pega a classe_target
+ local spell_nome, rank, icone = _GetSpellInfo (spellid)
+ _table_insert (minhas_magias, {spellid, este_alvo.total, este_alvo.total/total*100, spell_nome, icone})
+ end
+
+ end
+
+ _table_sort (minhas_magias, function(a, b) return a[2] > b[2] end)
+
+ --local amt = #minhas_magias
+ --gump:JI_AtualizaContainerBarras (amt)
+
+ local max_ = minhas_magias[1][2] --> dano que a primeiro magia vez
+
+ local barra
+ for index, tabela in _ipairs (minhas_magias) do
+ barra = barras [index]
+
+ if (not barra) then --> se a barra não existir, criar ela então
+ barra = gump:CriaNovaBarraInfo3 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> isso aqui é a parte da seleção e desceleção
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[4]) --seta o texto da esqueda
+ _detalhes:name_space_info (barra)
+
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ barra.icone:SetTexture (tabela[5])
+
+ barra:Show() --> mostra a barra
+
+ if (index == 15) then
+ break
+ end
+ end
+
+end
+
+------ Detalhe Info Damage Done e Dps
+function atributo_damage:MontaDetalhesDamageDone (spellid, barra)
+
+ if (_type (spellid) == "string") then
+
+ local _barra = info.grupos_detalhes [1]
+
+ if (not _barra.pet) then
+ _barra.bg.PetIcon = _barra.bg:CreateTexture (nil, "overlay")
+ _barra.bg.PetIcon:SetTexture ("Interface\\ICONS\\Ability_Druid_SkinTeeth")
+ _barra.bg.PetIcon:SetPoint ("left", _barra.bg, "left", 2, 2)
+ _barra.bg.PetIcon:SetWidth (40)
+ _barra.bg.PetIcon:SetHeight (40)
+ gump:NewLabel (_barra.bg, _barra.bg, nil, "PetText", "The Actor is a Pet", "GameFontHighlightLeft")
+ _barra.bg.PetText:SetPoint ("topleft", _barra.bg.PetIcon, "topright", 10, -2)
+ gump:NewLabel (_barra.bg, _barra.bg, nil, "PetDps", "", "GameFontHighlightSmall")
+ _barra.bg.PetDps:SetPoint ("left", _barra.bg.PetIcon, "right", 10, 2)
+ _barra.bg.PetDps:SetPoint ("top", _barra.bg.PetText, "bottom", 0, -5)
+ _barra.pet = true
+ end
+
+ _barra.IsPet = true
+ _barra.bg:SetValue (100)
+ gump:Fade (_barra.bg.overlay, "OUT")
+ _barra.bg:SetStatusBarColor (1, 1, 1)
+ _barra.bg_end:SetPoint ("LEFT", _barra.bg, "LEFT", (_barra.bg:GetValue()*2.19)-6, 0)
+ _barra.bg:Show()
+ _barra.bg.PetIcon:Show()
+ _barra.bg.PetText:Show()
+ _barra.bg.PetDps:Show()
+
+ local PetActor = info.instancia.showing (info.instancia.atributo, spellid)
+
+ if (PetActor) then
+ local OwnerActor = PetActor.ownerName
+ if (OwnerActor) then --> nor necessary
+ OwnerActor = info.instancia.showing (info.instancia.atributo, OwnerActor)
+ if (OwnerActor) then
+ local meu_tempo = OwnerActor:Tempo()
+ local normal_dmg = PetActor.total
+ local T = (meu_tempo*normal_dmg)/PetActor.total
+ _barra.bg.PetDps:SetText ("Dps: " .. _cstr("%.1f", normal_dmg/T))
+ end
+ end
+
+ end
+
+ for i = 2, 5 do
+ gump:HidaDetalheInfo (i)
+ end
+
+ local ThisBox = _detalhes.janela_info.grupos_detalhes [1]
+ ThisBox.nome:Hide()
+ ThisBox.dano:Hide()
+ ThisBox.dano_porcento:Hide()
+ ThisBox.dano_media:Hide()
+ ThisBox.dano_dps:Hide()
+ ThisBox.nome2:Hide()
+
+ return
+ end
+
+ local esta_magia = self.spell_tables._ActorTable [spellid]
+ if (not esta_magia) then
+ return
+ end
+
+ --> icone direito superior
+ local nome, rank, icone = _GetSpellInfo (spellid)
+ local infospell = {nome, rank, icone}
+
+ _detalhes.janela_info.spell_icone:SetTexture (infospell[3])
+
+ local total = self.total
+ local meu_tempo
+ if (_detalhes.time_type == 1 or not self.grupo) then
+ meu_tempo = self:Tempo()
+ elseif (_detalhes.time_type == 2) then
+ meu_tempo = self:GetCombatTime()
+ end
+
+ local total_hits = esta_magia.counter
+
+ local index = 1
+
+ local data = {}
+
+ --> GERAL
+ local media = esta_magia.total/total_hits
+
+ local this_dps = nil
+ if (esta_magia.counter > esta_magia.c_amt) then
+ this_dps = Loc ["STRING_DPS"]..": ".._cstr("%.1f", esta_magia.total/meu_tempo)
+ else
+ this_dps = Loc ["STRING_DPS"]..": "..Loc ["STRING_SEE_BELOW"]
+ end
+
+ gump:SetaDetalheInfoTexto ( index, 100,
+ Loc ["STRING_GERAL"],
+ Loc ["STRING_DAMAGE"]..": ".._detalhes:ToK (esta_magia.total),
+ Loc ["STRING_PERCENTAGE"]..": ".._cstr("%.1f", esta_magia.total/total*100) .. "%",
+ Loc ["STRING_MEDIA"]..": " .. _cstr("%.1f", media),
+ this_dps,
+ Loc ["STRING_HITS"]..": " .. total_hits)
+
+ --> NORMAL
+ local normal_hits = esta_magia.n_amt
+ if (normal_hits > 0) then
+ local normal_dmg = esta_magia.n_dmg
+ local media_normal = normal_dmg/normal_hits
+ local T = (meu_tempo*normal_dmg)/esta_magia.total
+ local P = media/media_normal*100
+ T = P*T/100
+
+ data[#data+1] = {
+ esta_magia.n_amt,
+ normal_hits/total_hits*100,
+ Loc ["STRING_NORMAL_HITS"],
+ Loc ["STRING_MINIMUM"]..": ".._detalhes:comma_value (esta_magia.n_min),
+ Loc ["STRING_MAXIMUM"]..": ".._detalhes:comma_value (esta_magia.n_max),
+ Loc ["STRING_MEDIA"]..": ".._cstr("%.1f", media_normal),
+ Loc ["STRING_DPS"]..": ".._cstr("%.1f", normal_dmg/T),
+ normal_hits.. " / ".._cstr("%.1f", normal_hits/total_hits*100).."%"
+ }
+ end
+
+ --> CRITICO
+ if (esta_magia.c_amt > 0) then
+ local media_critico = esta_magia.c_dmg/esta_magia.c_amt
+ local T = (meu_tempo*esta_magia.c_dmg)/esta_magia.total
+ local P = media/media_critico*100
+ T = P*T/100
+ local crit_dps =_cstr("%.1f", esta_magia.c_dmg/T)
+
+ data[#data+1] = {
+ esta_magia.c_amt,
+ esta_magia.c_amt/total_hits*100,
+ Loc ["STRING_CRITICAL_HITS"],
+ Loc ["STRING_MINIMUM"]..": ".._detalhes:comma_value (esta_magia.c_min),
+ Loc ["STRING_MAXIMUM"]..": ".._detalhes:comma_value (esta_magia.c_max),
+ Loc ["STRING_MEDIA"]..": ".._cstr("%.1f", media_critico),
+ Loc ["STRING_DPS"]..": ".._cstr("%.1f", crit_dps),
+ esta_magia.c_amt.. " / ".._cstr("%.1f", esta_magia.c_amt/total_hits*100).."%"
+ }
+ end
+
+ --> Outros erros: GLACING, resisted, blocked, absorbed
+ local outros_desvios = esta_magia.g_amt + esta_magia.r_amt + esta_magia.b_amt + esta_magia.a_amt
+
+ if (outros_desvios > 0) then
+ local porcentagem_defesas = outros_desvios/total_hits*100
+ data[#data+1] = {
+ outros_desvios,
+ {["p"] = porcentagem_defesas, ["c"] = {117/255, 58/255, 0/255}},
+ Loc ["STRING_DEFENSES"],
+ Loc ["STRING_GLANCING"]..": "..esta_magia.g_amt.." / ".._math_floor (esta_magia.g_amt/esta_magia.counter*100).."%", --esta_magia.g_dmg
+ Loc ["STRING_RESISTED"]..": "..esta_magia.r_dmg, --esta_magia.resisted.amt.." / "..
+ Loc ["STRING_ABSORBED"]..": "..esta_magia.a_dmg, --esta_magia.absorbed.amt.." / "..
+ Loc ["STRING_BLOCKED"]..": "..esta_magia.b_amt.." / "..esta_magia.b_dmg,
+ outros_desvios.." / ".._cstr("%.1f", porcentagem_defesas).."%"
+ }
+ end
+
+ --> Erros de Ataque --habilidade.missType -- {"ABSORB", "BLOCK", "DEFLECT", "DODGE", "EVADE", "IMMUNE", "MISS", "PARRY", "REFLECT", "RESIST"}
+ local miss = esta_magia ["MISS"] or 0
+ local parry = esta_magia ["PARRY"] or 0
+ local dodge = esta_magia ["DODGE"] or 0
+ local erros = miss + parry + dodge
+
+ if (erros > 0) then
+ local porcentagem_erros = erros/total_hits*100
+ data[#data+1] = {
+ erros,
+ {["p"] = porcentagem_erros, ["c"] = {0.5, 0.1, 0.1}},
+ Loc ["STRING_FAIL_ATTACKS"],
+ Loc ["STRING_MISS"]..": "..miss,
+ Loc ["STRING_PARRY"]..": "..parry,
+ Loc ["STRING_DODGE"]..": "..dodge,
+ "",
+ erros.." / ".._cstr("%.1f", porcentagem_erros).."%"
+ }
+ end
+
+ table.sort (data, function (a, b) return a[1] > b[1] end)
+
+ for index, tabela in _ipairs (data) do
+ gump:SetaDetalheInfoTexto (index+1, tabela[2], tabela[3], tabela[4], tabela[5], tabela[6], tabela[7], tabela[8])
+ end
+
+ for i = #data+2, 5 do
+ gump:HidaDetalheInfo (i)
+ end
+
+end
+
+
+function atributo_damage:MontaTooltipAlvos (esta_barra, index)
+ -- eu ja sei quem é o alvo a mostrar os detalhes
+ -- dar foreach no container de habilidades -- pegar os alvos da habilidade -- e ver se dentro do container tem o meu alvo.
+
+ local inimigo = esta_barra.nome_inimigo
+ local container = self.spell_tables._ActorTable
+ local habilidades = {}
+ local total = self.total_without_pet
+
+ for spellid, tabela in _pairs (container) do
+ --> tabela = classe_damage_habilidade
+ local alvos = tabela.targets._ActorTable
+ for _, tabela in _ipairs (alvos) do
+ --> tabela = classe_target
+ if (tabela.nome == inimigo) then
+ habilidades [#habilidades+1] = {spellid, tabela.total}
+ end
+ end
+ end
+
+ table.sort (habilidades, function (a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (index..". "..inimigo)
+ GameTooltip:AddLine (Loc ["STRING_DAMAGE_FROM"]..":")
+ GameTooltip:AddLine (" ")
+
+ for index, tabela in _ipairs (habilidades) do
+ local nome, rank, icone = _GetSpellInfo (tabela[1])
+ if (index < 8) then
+ GameTooltip:AddDoubleLine (index..". |T"..icone..":0|t "..nome, _detalhes:comma_value (tabela[2]).." (".._cstr("%.1f", tabela[2]/total*100).."%)", 1, 1, 1, 1, 1, 1)
+ --GameTooltip:AddTexture (icone)
+ else
+ GameTooltip:AddDoubleLine (index..". "..nome, _detalhes:comma_value (tabela[2]).." (".._cstr("%.1f", tabela[2]/total*100).."%)", .65, .65, .65, .65, .65, .65)
+ end
+ end
+
+ return true
+ --GameTooltip:AddDoubleLine (meus_danos[i][4][1]..": ", meus_danos[i][2].." (".._cstr("%.1f", meus_danos[i][3]).."%)", 1, 1, 1, 1, 1, 1)
+
+end
+
+
+--if (esta_magia.counter == esta_magia.c_amt) then --> só teve critico
+-- gump:SetaDetalheInfoTexto (1, nil, nil, nil, nil, nil, "DPS: "..crit_dps)
+--end
+
+--controla se o dps do jogador esta travado ou destravado
+function atributo_damage:Iniciar (iniciar)
+ if (iniciar == nil) then
+ return self.dps_started --retorna se o dps esta aberto ou fechado para este jogador
+ elseif (iniciar) then
+ self.dps_started = true
+ self:RegistrarNaTimeMachine() --coloca ele da timeMachine
+ if (self.shadow) then
+ self.shadow.dps_started = true --> isso foi posto recentemente
+ self.shadow:RegistrarNaTimeMachine()
+ end
+ else
+ self.dps_started = false
+ self:DesregistrarNaTimeMachine() --retira ele da timeMachine
+ if (self.shadow) then
+ self.shadow:DesregistrarNaTimeMachine()
+ self.shadow.dps_started = false --> isso foi posto recentemente
+ end
+ end
+end
+
+function atributo_damage:FF_funcao_de_criacao (_, _, link)
+ local tabela = _setmetatable ({}, _detalhes) --> mudei de _detalhes para atributo_damage
+ tabela.total = 0
+ tabela.spell_tables = container_habilidades:NovoContainer (container_damage)
+ if (link) then
+ tabela.spell_tables.shadow = link.spell_tables
+ end
+ return tabela
+end
+
+function atributo_damage:ColetarLixo()
+ return _detalhes:ColetarLixo (class_type)
+end
+
+local function ReconstroiMapa (tabela)
+ local mapa = {}
+ for i = 1, #tabela._ActorTable do
+ mapa [tabela._ActorTable[i].nome] = i
+ end
+ tabela._NameIndexTable = mapa
+end
+
+function _detalhes.refresh:r_atributo_damage (este_jogador, shadow)
+ _setmetatable (este_jogador, _detalhes.atributo_damage)
+ este_jogador.__index = _detalhes.atributo_damage
+
+ if (shadow ~= -1) then
+
+ este_jogador.shadow = shadow
+
+ _detalhes.refresh:r_container_combatentes (este_jogador.targets, shadow.targets)
+ _detalhes.refresh:r_container_combatentes (este_jogador.friendlyfire, shadow.friendlyfire)
+ _detalhes.refresh:r_container_habilidades (este_jogador.spell_tables, shadow.spell_tables)
+
+ for index, friendlyfire in _ipairs (este_jogador.friendlyfire._ActorTable) do
+
+ _setmetatable (friendlyfire, _detalhes)
+
+ local friendlyfire_shadow = shadow.friendlyfire:PegarCombatente (_, friendlyfire.nome) --> corrigido erro aqui, estava este_jogador.nome
+ _detalhes.refresh:r_container_habilidades (friendlyfire.spell_tables, friendlyfire_shadow.spell_tables) -- acho que corrigi mais um bug, estava apenas 'friendlyfire_shadow'
+
+ end
+ else
+ _detalhes.refresh:r_container_combatentes (este_jogador.targets, -1)
+ _detalhes.refresh:r_container_combatentes (este_jogador.friendlyfire, -1)
+ _detalhes.refresh:r_container_habilidades (este_jogador.spell_tables, -1)
+ _detalhes.refresh:r_container_habilidades (este_jogador.friendlyfire.spell_tables, -1)
+ end
+
+end
+
+function _detalhes.clear:c_atributo_damage (este_jogador)
+ este_jogador.__index = {}
+ este_jogador.shadow = nil
+ este_jogador.links = nil
+ este_jogador.minha_barra = nil
+
+ _detalhes.clear:c_container_combatentes (este_jogador.targets)
+ _detalhes.clear:c_container_habilidades (este_jogador.spell_tables)
+ _detalhes.clear:c_atributo_damage_FF (este_jogador.friendlyfire)
+end
+
+function _detalhes.clear:c_atributo_damage_FF (container)
+ _detalhes.clear:c_container_combatentes (container)
+
+ for _, _tabela in _ipairs (container._ActorTable) do
+ _tabela.__index = {}
+ _tabela.shadow = nil
+
+ local habilidades = _tabela.spell_tables
+ _detalhes.clear:c_container_habilidades (habilidades)
+
+ for _, habilidade in _pairs (habilidades._ActorTable) do
+ _detalhes.clear:c_habilidade_dano (habilidade)
+ --pode parar aqui, o container de alvos não é usado no friendly fire
+ end
+ end
+end
+
+atributo_damage.__add = function (shadow, tabela2)
+
+ --> tempo decorrido
+ local tempo = (tabela2.end_time or time()) - tabela2.start_time
+ shadow.start_time = shadow.start_time - tempo
+
+ --> total de dano
+ shadow.total = shadow.total + tabela2.total
+ _detalhes.tabela_overall.totals[1] = _detalhes.tabela_overall.totals[1] + tabela2.total
+
+ if (tabela2.grupo) then
+ _detalhes.tabela_overall.totals_grupo[1] = _detalhes.tabela_overall.totals_grupo[1] + tabela2.total
+ end
+
+ --> total de dano sem o pet
+ shadow.total_without_pet = shadow.total_without_pet + tabela2.total_without_pet
+ --> total de dano que o cara levou
+ shadow.damage_taken = shadow.damage_taken + tabela2.damage_taken
+
+ --> copia o damage_from
+ for nome, _ in _pairs (tabela2.damage_from) do
+ shadow.damage_from [nome] = true
+ end
+
+ --> copia o container de alvos
+ for index, alvo in _ipairs (tabela2.targets._ActorTable) do
+ local alvo_shadow = shadow.targets:PegarCombatente (alvo.serial, alvo.nome, _, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+ --> copia o container de friendly fire
+ for index, friendlyFire in _ipairs (tabela2.friendlyfire._ActorTable) do
+ -- friendlyFire é uma tabela com .total e .spell_tables -- habilidade é um container de habilidades tipo damage
+ local friendlyFire_shadow = shadow.friendlyfire:PegarCombatente (_, friendlyFire.nome)
+ --_detalhes:DelayMsg ("+ achou -> " .. friendlyFire_shadow.nome)
+
+ --friendlyFire_shadow agora tem uma tabela com .total e .spell_tables
+ friendlyFire_shadow.total = friendlyFire_shadow.total + friendlyFire.total
+
+ --> container de habilidade
+
+ local shadow_habilidades = friendlyFire_shadow.spell_tables
+
+ for spellid, habilidade in _pairs (friendlyFire.spell_tables._ActorTable) do
+
+ local habilidade_shadow = friendlyFire_shadow.spell_tables:PegaHabilidade (spellid, true, nil, true)
+
+ habilidade_shadow.counter = habilidade_shadow.counter + habilidade.counter
+ habilidade_shadow.total = habilidade_shadow.total + habilidade.total
+ habilidade.shadow = habilidade_shadow --> aqui ele linka a habilidade com a shadow dele
+
+ --> restaura a metatable das habilidades
+ _detalhes.refresh:r_habilidade_dano (habilidade, shadow_habilidades)
+
+ end
+ end
+
+ --> copia o container de habilidades
+ for spellid, habilidade in _pairs (tabela2.spell_tables._ActorTable) do
+ local habilidade_shadow = shadow.spell_tables:PegaHabilidade (spellid, true, nil, true)
+
+ for index, alvo in _ipairs (habilidade.targets._ActorTable) do
+ local alvo_shadow = habilidade_shadow.targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for key, value in _pairs (habilidade) do
+ if (_type (value) == "number") then
+ if (key ~= "id") then
+ if (not habilidade_shadow [key]) then
+ habilidade_shadow [key] = 0
+ end
+ habilidade_shadow [key] = habilidade_shadow [key] + value
+ end
+ end
+ end
+ end
+
+ return shadow
+end
+
+atributo_damage.__sub = function (tabela1, tabela2)
+
+ tabela1.total = tabela1.total - tabela2.total
+ tabela1.total_without_pet = tabela1.total_without_pet - tabela2.total_without_pet
+ tabela1.damage_taken = tabela1.damage_taken - tabela2.damage_taken
+ tabela1.friendlyfire_total = tabela1.friendlyfire_total - tabela2.friendlyfire_total
+
+ for index, friendlyfire in _ipairs (tabela2.friendlyfire._ActorTable) do
+ friendlyfire.shadow.total = friendlyfire.shadow.total - friendlyfire.total
+ for spellid, habilidade in _pairs (friendlyfire.spell_tables._ActorTable) do
+ -- eu di reload para trocar os talentos
+ habilidade.shadow.total = habilidade.shadow.total - habilidade.total -- attempt to index field 'shadow' (a nil value) -- Deu erro denovo depois de um /reload
+ end
+ end
+
+ return tabela1
+end
+
+ --local cor = self.cor
+
+ --esta_barra.statusbar:SetStatusBarColor (cor[1], cor[2], cor[3], cor[4])
+
+ --print (cor[1], cor[2], cor[3])
+ --esta_barra.textura:SetVertexColor (cor[1], cor[2], cor[3], cor[4])
+
+ --local grayscale = (cor[1] + cor[2] + cor[3]) / 3.0 -- lightness
+
+ -- local grayscale = (_math_max (cor[1], cor[2], cor[3]) + _math_min (cor[1], cor[2], cor[3])) / 2 -- average
+ -- local grayscale = cor[1]*0.21 + cor[2]*0.71 + cor[3]*0.07
+ --(max(R, G, B) + min(R, G, B)) / 2
diff --git a/classes/classe_damage_habilidade.lua b/classes/classe_damage_habilidade.lua
new file mode 100644
index 00000000..b13c2481
--- /dev/null
+++ b/classes/classe_damage_habilidade.lua
@@ -0,0 +1,364 @@
+--[[ classe do dano aplicado, usado nos eventos:
+- SPELL_PERIODIC_DAMAGE
+- SPELL_DAMAGE
+- SWING_DAMAGE
+- RANGE_DAMAGE
+
+Parents:
+ addon -> combate atual -> Npc/Player Swicth -> Container de Habilidades -> esta tabela
+ ]]
+
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local habilidade_dano = _detalhes.habilidade_dano
+local container_combatentes = _detalhes.container_combatentes
+local container_damage_target = _detalhes.container_type.CONTAINER_DAMAGETARGET_CLASS
+
+--lua locals
+local _setmetatable = setmetatable
+local _ipairs = ipairs
+local _pairs = pairs
+--api locals
+local _UnitAura = UnitAura
+--local _GetSpellInfo = _detalhes.getspellinfo
+
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+
+local _recording_ability_with_buffs = false
+
+--id, nome, type, miss, dano, cura, overkill, school, resisted, blocked, absorbed, critico, glacing, crushing
+function habilidade_dano:NovaTabela (id, link, token) --aqui eu não sei que parâmetros passar
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, habilidade_dano)
+
+ esta_tabela.quem_sou = "classe_damage_habilidade"
+
+ -- esta_tabela.jogador = serial
+
+ esta_tabela.total = 0 --total de dano aplicado por esta habilidade
+ esta_tabela.counter = 0 --conta quantas vezes a habilidade foi chamada
+ esta_tabela.id = id
+ esta_tabela.school = 0
+
+ --> normal hits
+ --esta_tabela.normal = {["min"] = 0, ["max"] = 0, ["amt"] = 0, ["dmg"] = 0}
+
+ esta_tabela.n_min = 0
+ esta_tabela.n_max = 0
+ esta_tabela.n_amt = 0
+ esta_tabela.n_dmg = 0
+
+ --> hits criticos
+ --esta_tabela.critico = {["min"] = 0, ["max"] = 0, ["amt"] = 0, ["dmg"] = 0}
+ esta_tabela.c_min = 0
+ esta_tabela.c_max = 0
+ esta_tabela.c_amt = 0
+ esta_tabela.c_dmg = 0
+
+ --> hit glacing
+ --esta_tabela.glacing = {["min"] = 0, ["max"] = 0, ["amt"] = 0, ["dmg"] = 0}
+ esta_tabela.g_min = 0
+ esta_tabela.g_max = 0
+ esta_tabela.g_amt = 0
+ esta_tabela.g_dmg = 0
+
+ --informações e detalhes gerais desta habilidade
+
+ --esta_tabela.resisted = {["min"] = 0, ["max"] = 0, ["amt"] = 0, ["dmg"] = 0}
+ esta_tabela.r_min = 0
+ esta_tabela.r_max = 0
+ esta_tabela.r_amt = 0
+ esta_tabela.r_dmg = 0
+
+ --esta_tabela.blocked = {["min"] = 0, ["max"] = 0, ["amt"] = 0, ["dmg"] = 0}
+ esta_tabela.b_min = 0
+ esta_tabela.b_max = 0
+ esta_tabela.b_amt = 0
+ esta_tabela.b_dmg = 0
+
+ --esta_tabela.absorbed = {["min"] = 0, ["max"] = 0, ["amt"] = 0, ["dmg"] = 0}
+ esta_tabela.a_min = 0
+ esta_tabela.a_max = 0
+ esta_tabela.a_amt = 0
+ esta_tabela.a_dmg = 0
+
+ esta_tabela.crushing = 0 -- ??
+
+ esta_tabela.targets = container_combatentes:NovoContainer (container_damage_target)
+
+ if (link) then
+ esta_tabela.targets.shadow = link.targets
+ end
+
+ if (token == "SPELL_PERIODIC_DAMAGE") then
+ _detalhes:SpellIsDot (id)
+ end
+
+ return esta_tabela
+end
+
+
+function habilidade_dano:AddMiss (serial, nome, flags, who_nome, missType)
+ self.counter = self.counter + 1
+
+ local miss = self [missType] or 0
+ miss = miss + 1
+ self [missType] = miss
+
+ local alvo = self.targets:PegarCombatente (serial, nome, flags, true)
+ return alvo:AddQuantidade (0)
+end
+
+function habilidade_dano:AddFF (amount)
+ self.counter = self.counter + 1
+ self.total = self.total + amount
+ if (self.shadow) then
+ return self.shadow:AddFF (amount)
+ end
+end
+
+function habilidade_dano:Add (serial, nome, flag, amount, who_nome, resisted, blocked, absorbed, critical, glacing, token)
+
+ self.counter = self.counter + 1
+
+ --local alvo = self.targets:PegarCombatente (serial, nome, flag, true)
+ local alvo = self.targets._NameIndexTable [nome]
+ if (not alvo) then
+ alvo = self.targets:PegarCombatente (serial, nome, flag, true)
+ else
+ alvo = self.targets._ActorTable [alvo]
+ end
+
+ if (resisted and resisted > 0) then
+ self.r_dmg = self.r_dmg+amount --> tabela.total é o total de dano
+ self.r_amt = self.r_amt+1 --> tabela.total é o total de dano
+ if (amount > self.r_max) then
+ self.r_max = amount
+ end
+ if (self.r_min > amount or self.r_min == 0) then
+ self.r_min = amount
+ end
+ end
+
+ if (blocked and blocked > 0) then
+ self.b_dmg = self.b_dmg+amount --> amount é o total de dano
+ self.b_amt = self.b_amt+1 --> amount é o total de dano
+ if (amount > self.b_max) then
+ self.b_max = amount
+ end
+ if (self.b_min > amount or self.b_min == 0) then
+ self.b_min = amount
+ end
+ end
+
+ if (absorbed and absorbed > 0) then
+ self.a_dmg = self.a_dmg+amount --> amount é o total de dano
+ self.a_amt = self.a_amt+1 --> amount é o total de dano
+ if (amount > self.a_max) then
+ self.a_max = amount
+ end
+ if (self.a_min > amount or self.a_min == 0) then
+ self.a_min = amount
+ end
+ end
+
+ if (amount and amount > 0) then
+
+ self.total = self.total + amount
+
+ --alvo:AddQuantidade (amount)
+ alvo.total = alvo.total + amount
+
+ if (glacing) then
+ -- esta_tabela.glacing = {["mim"] = 0, ["max"] = 0, ["total"] = 0, ["dmg"] = 0}
+ self.g_dmg = self.g_dmg+amount --> amount é o total de dano
+ self.g_amt = self.g_amt+1 --> amount é o total de dano
+ if (amount > self.g_max) then
+ self.g_max = amount
+ end
+ if (self.g_min > amount or self.g_min == 0) then
+ self.g_min = amount
+ end
+ elseif (critical) then
+ --esta_tabela.critico = {["mim"] = 0, ["max"] = 0, ["total"] = 0, ["dmg"] = 0}
+ self.c_dmg = self.c_dmg+amount --> amount é o total de dano
+ self.c_amt = self.c_amt+1 --> amount é o total de dano
+ if (amount > self.c_max) then
+ self.c_max = amount
+ end
+ if (self.c_min > amount or self.c_min == 0) then
+ self.c_min = amount
+ end
+ else
+ --esta_tabela.normal = {["mim"] = 0, ["max"] = 0, ["total"] = 0, ["dmg"] = 0}
+ self.n_dmg = self.n_dmg+amount
+ self.n_amt = self.n_amt+1
+ if (amount > self.n_max) then
+ self.n_max = amount
+ end
+ if (self.n_min > amount or self.n_min == 0) then
+ self.n_min = amount
+ end
+ end
+ end
+
+ if (self.shadow) then
+
+ if (_recording_ability_with_buffs) then
+ if (who_nome == _detalhes.playername) then --aqui ele vai detalhar tudo sobre a magia usada
+
+ local buffsNames = _detalhes.SoloTables.BuffsTableNameCache
+
+ local SpellBuffDetails = self.BuffTable
+ if (not SpellBuffDetails) then
+ self.BuffTable = {}
+ SpellBuffDetails = self.BuffTable
+ end
+
+ if (token == "SPELL_PERIODIC_DAMAGE") then
+ --> precisa ver se ele tinha na hora que aplicou
+ local SoloDebuffPower = _detalhes.tabela_vigente.SoloDebuffPower
+ if (SoloDebuffPower) then
+ local ThisDebuff = SoloDebuffPower [self.id]
+ if (ThisDebuff) then
+ local ThisDebuffOnTarget = ThisDebuff [serial]
+ if (ThisDebuffOnTarget) then
+ for index, buff_name in _ipairs (ThisDebuffOnTarget.buffs) do
+ local buff_info = SpellBuffDetails [buff_name] or {["counter"] = 0, ["total"] = 0, ["critico"] = 0, ["critico_dano"] = 0}
+ buff_info.counter = buff_info.counter+1
+ buff_info.total = buff_info.total+amount
+ if (critical ~= nil) then
+ buff_info.critico = buff_info.critico+1
+ buff_info.critico_dano = buff_info.critico_dano+amount
+ end
+ SpellBuffDetails [buff_name] = buff_info
+ end
+ end
+ end
+ end
+
+ else
+
+ for BuffName, _ in _pairs (_detalhes.Buffs.BuffsTable) do
+ local name = _UnitAura ("player", BuffName)
+ if (name ~= nil) then
+ local buff_info = SpellBuffDetails [name] or {["counter"] = 0, ["total"] = 0, ["critico"] = 0, ["critico_dano"] = 0}
+ buff_info.counter = buff_info.counter+1
+ buff_info.total = buff_info.total+amount
+ if (critical ~= nil) then
+ buff_info.critico = buff_info.critico+1
+ buff_info.critico_dano = buff_info.critico_dano+amount
+ end
+ SpellBuffDetails [name] = buff_info
+ end
+ end
+ end
+ end
+ end
+
+ return self.shadow:Add (serial, nome, flag, amount, who_nome, resisted, blocked, absorbed, critical, glacing, token)
+ end
+
+end
+
+function _detalhes.refresh:r_habilidade_dano (habilidade, shadow) --recebeu o container shadow
+ _setmetatable (habilidade, habilidade_dano)
+ habilidade.__index = habilidade_dano
+
+ if (shadow ~= -1) then
+ habilidade.shadow = shadow._ActorTable[habilidade.id]
+ _detalhes.refresh:r_container_combatentes (habilidade.targets, habilidade.shadow.targets) else
+ _detalhes.refresh:r_container_combatentes (habilidade.targets, -1)
+ end
+end
+
+function _detalhes.clear:c_habilidade_dano (habilidade)
+ habilidade.__index = {}
+ habilidade.shadow = nil
+
+ _detalhes.clear:c_container_combatentes (habilidade.targets)
+end
+
+habilidade_dano.__add = function (tabela1, tabela2)
+ tabela1.total = tabela1.total + tabela2.total
+ tabela1.counter = tabela1.counter + tabela2.counter
+
+ tabela1.n_min = tabela1.n_min + tabela2.n_min
+ tabela1.n_max = tabela1.n_max + tabela2.n_max
+ tabela1.n_amt = tabela1.n_amt + tabela2.n_amt
+ tabela1.n_dmg = tabela1.n_dmg + tabela2.n_dmg
+
+ tabela1.c_min = tabela1.c_min + tabela2.c_min
+ tabela1.c_max = tabela1.c_max + tabela2.c_max
+ tabela1.c_amt = tabela1.c_amt + tabela2.c_amt
+ tabela1.c_dmg = tabela1.c_dmg + tabela2.c_dmg
+
+ tabela1.g_min = tabela1.g_min + tabela2.g_min
+ tabela1.g_max = tabela1.g_max + tabela2.g_max
+ tabela1.g_amt = tabela1.g_amt + tabela2.g_amt
+ tabela1.g_dmg = tabela1.g_dmg + tabela2.g_dmg
+
+ tabela1.r_min = tabela1.r_min + tabela2.r_min
+ tabela1.r_max = tabela1.r_max + tabela2.r_max
+ tabela1.r_amt = tabela1.r_amt + tabela2.r_amt
+ tabela1.r_dmg = tabela1.r_dmg + tabela2.r_dmg
+
+ tabela1.b_min = tabela1.b_min + tabela2.b_min
+ tabela1.b_max = tabela1.b_max + tabela2.b_max
+ tabela1.b_amt = tabela1.b_amt + tabela2.b_amt
+ tabela1.b_dmg = tabela1.b_dmg + tabela2.b_dmg
+
+ tabela1.a_min = tabela1.a_min + tabela2.a_min
+ tabela1.a_max = tabela1.a_max + tabela2.a_max
+ tabela1.a_amt = tabela1.a_amt + tabela2.a_amt
+ tabela1.a_dmg = tabela1.a_dmg + tabela2.a_dmg
+
+ tabela1.crushing = tabela1.crushing + tabela2.crushing
+
+ return tabela1
+end
+
+habilidade_dano.__sub = function (tabela1, tabela2)
+ tabela1.total = tabela1.total - tabela2.total
+ tabela1.counter = tabela1.counter - tabela2.counter
+
+ tabela1.n_min = tabela1.n_min - tabela2.n_min
+ tabela1.n_max = tabela1.n_max - tabela2.n_max
+ tabela1.n_amt = tabela1.n_amt - tabela2.n_amt
+ tabela1.n_dmg = tabela1.n_dmg - tabela2.n_dmg
+
+ tabela1.c_min = tabela1.c_min - tabela2.c_min
+ tabela1.c_max = tabela1.c_max - tabela2.c_max
+ tabela1.c_amt = tabela1.c_amt - tabela2.c_amt
+ tabela1.c_dmg = tabela1.c_dmg - tabela2.c_dmg
+
+ tabela1.g_min = tabela1.g_min - tabela2.g_min
+ tabela1.g_max = tabela1.g_max - tabela2.g_max
+ tabela1.g_amt = tabela1.g_amt - tabela2.g_amt
+ tabela1.g_dmg = tabela1.g_dmg - tabela2.g_dmg
+
+ tabela1.r_min = tabela1.r_min - tabela2.r_min
+ tabela1.r_max = tabela1.r_max - tabela2.r_max
+ tabela1.r_amt = tabela1.r_amt - tabela2.r_amt
+ tabela1.r_dmg = tabela1.r_dmg - tabela2.r_dmg
+
+ tabela1.b_min = tabela1.b_min - tabela2.b_min
+ tabela1.b_max = tabela1.b_max - tabela2.b_max
+ tabela1.b_amt = tabela1.b_amt - tabela2.b_amt
+ tabela1.b_dmg = tabela1.b_dmg - tabela2.b_dmg
+
+ tabela1.a_min = tabela1.a_min - tabela2.a_min
+ tabela1.a_max = tabela1.a_max - tabela2.a_max
+ tabela1.a_amt = tabela1.a_amt - tabela2.a_amt
+ tabela1.a_dmg = tabela1.a_dmg - tabela2.a_dmg
+
+ tabela1.crushing = tabela1.crushing - tabela2.crushing
+
+ return tabela1
+end
+
+function _detalhes:UpdateDamageAbilityGears()
+ _recording_ability_with_buffs = _detalhes.RecordPlayerAbilityWithBuffs
+end
diff --git a/classes/classe_energy.lua b/classes/classe_energy.lua
new file mode 100644
index 00000000..cf72039f
--- /dev/null
+++ b/classes/classe_energy.lua
@@ -0,0 +1,751 @@
+--[[ Esta classe irá abrigar todo a e_energy ganha de uma habilidade
+Parents:
+ addon -> combate atual -> e_energy-> container de jogadores -> esta classe
+
+]]
+
+--lua locals
+local _cstr = string.format
+local _math_floor = math.floor
+local _table_sort = table.sort
+local _table_insert = table.insert
+local _setmetatable = setmetatable
+local _ipairs = ipairs
+local _pairs = pairs
+local _rawget= rawget
+local _math_min = math.min
+local _math_max = math.max
+local _bit_band = bit.band
+local _unpack = unpack
+local _type = type
+--api locals
+local _GetSpellInfo = _detalhes.getspellinfo
+local GameTooltip = GameTooltip
+
+local _detalhes = _G._detalhes
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local container_habilidades = _detalhes.container_habilidades
+local container_combatentes = _detalhes.container_combatentes
+local container_pets = _detalhes.container_pets
+local atributo_energy = _detalhes.atributo_energy
+local habilidade_energy = _detalhes.habilidade_energy
+
+--local container_damage_target = _detalhes.container_type.CONTAINER_DAMAGETARGET_CLASS
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+local container_energy = _detalhes.container_type.CONTAINER_ENERGY_CLASS
+local container_energy_target = _detalhes.container_type.CONTAINER_ENERGYTARGET_CLASS
+--local container_friendlyfire = _detalhes.container_type.CONTAINER_FRIENDLYFIRE
+
+--local modo_ALONE = _detalhes.modos.alone
+local modo_GROUP = _detalhes.modos.group
+local modo_ALL = _detalhes.modos.all
+
+local class_type = _detalhes.atributos.e_energy
+
+local DATA_TYPE_START = _detalhes._detalhes_props.DATA_TYPE_START
+local DATA_TYPE_END = _detalhes._detalhes_props.DATA_TYPE_END
+
+local DFLAG_player = _detalhes.flags.player
+local DFLAG_group = _detalhes.flags.in_group
+local DFLAG_player_group = _detalhes.flags.player_in_group
+
+local div_abre = _detalhes.divisores.abre
+local div_fecha = _detalhes.divisores.fecha
+local div_lugar = _detalhes.divisores.colocacao
+
+local info = _detalhes.janela_info
+local keyName
+
+function atributo_energy:NovaTabela (serial, nome, link)
+ local esta_tabela = {}
+ esta_tabela.quem_sou = "classe_energy" --> DEBUG deleta-me
+
+ --print ("CRIANDO NOVO OBJETO")
+
+ _setmetatable (esta_tabela, atributo_energy)
+
+ --> grava o tempo que a tabela foi criada para o garbage collector interno
+ esta_tabela.CriadaEm = time()
+ esta_tabela.last_event = 0
+ esta_tabela.tipo = class_type --> atributo 3 = e_energy
+
+ esta_tabela.mana = 0
+ esta_tabela.e_rage = 0
+ esta_tabela.e_energy = 0
+ esta_tabela.runepower = 0
+ esta_tabela.focus = 0
+ esta_tabela.holypower = 0
+
+ esta_tabela.mana_r = 0
+ esta_tabela.e_rage_r = 0
+ esta_tabela.e_energy_r = 0
+ esta_tabela.runepower_r = 0
+ esta_tabela.focus_r = 0
+ esta_tabela.holypower_r = 0
+
+ esta_tabela.mana_from = {}
+ esta_tabela.e_rage_from = {}
+ esta_tabela.e_energy_from = {}
+ esta_tabela.runepower_from = {}
+ esta_tabela.focus_from = {}
+ esta_tabela.holypower_from = {}
+
+ esta_tabela.last_value = nil --> ultimo valor que este jogador teve, salvo quando a barra dele é atualizada
+
+ esta_tabela.pets = {}
+
+ --container armazenará os seriais dos alvos que o player aplicou dano
+ esta_tabela.targets = container_combatentes:NovoContainer (container_energy_target)
+
+ --container armazenará os IDs das habilidades usadas por este jogador
+ esta_tabela.spell_tables = container_habilidades:NovoContainer (container_energy)
+
+ if (link) then
+ esta_tabela.targets.shadow = link.targets
+ esta_tabela.spell_tables.shadow = link.spell_tables
+ end
+
+ return esta_tabela
+end
+
+function atributo_energy:RefreshWindow (instancia, tabela_do_combate, forcar, exportar)
+
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ if (#showing._ActorTable < 1) then --> não há barras para mostrar
+ return _detalhes:EsconderBarrasNaoUsadas (instancia, showing)
+ end
+
+ local total = 0 --> total iniciado como ZERO
+ instancia.top = 0
+
+ local sub_atributo = instancia.sub_atributo --> o que esta sendo mostrado nesta instância
+ local conteudo = showing._ActorTable
+ local amount = #conteudo
+ local modo = instancia.modo
+
+ if (exportar) then
+ if (_type (exportar) == "boolean") then
+ if (sub_atributo == 1) then --> MANA RECUPERADA
+ keyName = "mana"
+ elseif (sub_atributo == 2) then --> e_rage GANHA
+ keyName = "e_rage"
+ elseif (sub_atributo == 3) then --> ENERGIA GANHA
+ keyName = "e_energy"
+ elseif (sub_atributo == 4) then --> RUNEPOWER GANHO
+ keyName = "runepower"
+ end
+ else
+ keyName = exportar.key
+ modo = exportar.modo
+ end
+
+ elseif (instancia.atributo == 5) then --> custom
+ keyName = "custom"
+ total = tabela_do_combate.totals [instancia.customName]
+
+ else
+ if (sub_atributo == 1) then --> MANA RECUPERADA
+ keyName = "mana"
+ elseif (sub_atributo == 2) then --> e_rage GANHA
+ keyName = "e_rage"
+ elseif (sub_atributo == 3) then --> ENERGIA GANHA
+ keyName = "e_energy"
+ elseif (sub_atributo == 4) then --> RUNEPOWER GANHO
+ keyName = "runepower"
+ end
+ end
+
+ if (instancia.atributo == 5) then --> custom
+ --> faz o sort da categoria e retorna o amount corrigido
+ amount = _detalhes:ContainerSort (conteudo, amount, keyName)
+
+ --> grava o total
+ instancia.top = conteudo[1][keyName]
+
+ elseif (modo == modo_ALL) then --> mostrando ALL
+
+ --> faz o sort da categoria
+ _table_sort (conteudo, function (a, b) return a[keyName] > b[keyName] end)
+
+ --> não mostrar resultados com zero
+ for i = amount, 1, -1 do --> de trás pra frente
+ if (conteudo[i][keyName] < 1) then
+ amount = amount-1
+ else
+ break
+ end
+ end
+
+ total = tabela_do_combate.totals [class_type] [keyName] --> pega o total de dano já aplicado
+
+ instancia.top = conteudo[1] [keyName]
+
+ elseif (modo == modo_GROUP) then --> mostrando GROUP
+
+ _table_sort (conteudo, function (a, b)
+ if (a.grupo and b.grupo) then
+ return a[keyName] > b[keyName]
+ elseif (a.grupo and not b.grupo) then
+ return true
+ elseif (not a.grupo and b.grupo) then
+ return false
+ else
+ return a[keyName] > b[keyName]
+ end
+ end)
+
+ for index, player in _ipairs (conteudo) do
+ if (_bit_band (player.flag, DFLAG_player_group) >= 0x101) then --> é um player e esta em grupo
+ if (player[keyName] < 1) then --> dano menor que 1, interromper o loop
+ amount = index - 1
+ break
+ elseif (index == 1) then --> esse IF aqui, precisa mesmo ser aqui? não daria pra pega-lo com uma chave [1] nad grupo == true?
+ instancia.top = conteudo[1][keyName]
+ end
+
+ total = total + player[keyName]
+ else
+ amount = index-1
+ break
+ end
+ end
+
+ end
+
+ showing:remapear()
+
+ if (exportar) then
+ return total, keyName, instancia.top
+ end
+
+ if (amount < 1) then --> não há barras para mostrar
+ instancia:EsconderScrollBar()
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+ end
+
+ instancia:AtualizarScrollBar (amount)
+
+ local qual_barra = 1
+ local barras_container = instancia.barras
+
+ for i = instancia.barraS[1], instancia.barraS[2], 1 do --> vai atualizar só o range que esta sendo mostrado
+ conteudo[i]:AtualizaBarra (instancia, barras_container, qual_barra, i, total, sub_atributo, forcar) --> instância, index, total, valor da 1º barra
+ qual_barra = qual_barra+1
+ end
+
+ if (instancia.atributo == 5) then --> custom
+ --> zerar o .custom dos Actors
+ for index, player in _ipairs (conteudo) do
+ if (player.custom > 0) then
+ player.custom = 0
+ else
+ break
+ end
+ end
+ end
+
+ --> beta, hidar barras não usadas durante um refresh forçado
+ if (forcar) then
+ if (instancia.modo == 2) then --> group
+ for i = qual_barra, instancia.barrasInfo.cabem do
+ gump:Fade (instancia.barras [i], "in", 0.3)
+ end
+ end
+ end
+
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+
+end
+
+function atributo_energy:Custom (_customName, _combat, sub_atributo, spell, alvo)
+ local _Skill = self.spell_tables._ActorTable [tonumber (spell)]
+ if (_Skill) then
+ local spellName = _GetSpellInfo (tonumber (spell))
+ local SkillTargets = _Skill.targets._ActorTable
+
+ for _, TargetActor in _ipairs (SkillTargets) do
+ local TargetActorSelf = _combat (class_type, TargetActor.nome)
+ TargetActorSelf.custom = TargetActor.total + TargetActorSelf.custom
+ _combat.totals [_customName] = _combat.totals [_customName] + TargetActor.total
+ end
+ end
+end
+
+function atributo_energy:AtualizaBarra (instancia, barras_container, qual_barra, lugar, total, sub_atributo, forcar)
+
+ local esta_barra = instancia.barras[qual_barra] --> pega a referência da barra na janela
+
+ if (not esta_barra) then
+ print ("DEBUG: problema com "..qual_barra.." "..lugar)
+ return
+ end
+
+ local tabela_anterior = esta_barra.minha_tabela
+
+ esta_barra.minha_tabela = self
+ esta_barra.colocacao = lugar
+
+ self.minha_barra = esta_barra
+ self.colocacao = lugar
+
+ local esta_e_energy_total = self [keyName] --> total de dano que este jogador deu
+ local porcentagem = esta_e_energy_total / total * 100
+ local esta_porcentagem = _math_floor ((esta_e_energy_total/instancia.top) * 100)
+
+ esta_barra.texto_direita:SetText (_detalhes:ToK (esta_e_energy_total) .. " " .. div_abre .. _cstr ("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita
+
+ if (esta_barra.mouse_over and not instancia.baseframe.isMoving) then --> precisa atualizar o tooltip
+ gump:UpdateTooltip (qual_barra, esta_barra, instancia)
+ end
+
+ return self:RefreshBarra2 (esta_barra, instancia, tabela_anterior, forcar, esta_porcentagem, qual_barra, barras_container)
+end
+
+
+
+--------------------------------------------- // TOOLTIPS // ---------------------------------------------
+function atributo_energy:KeyNames (sub_atributo)
+ if (sub_atributo == 1) then --> MANA RECUPERADA
+ return "mana", "mana_from"
+ elseif (sub_atributo == 2) then --> e_rage GANHA
+ return "e_rage", "e_rage_from"
+ elseif (sub_atributo == 3) then --> ENERGIA GANHA
+ return "e_energy", "e_energy_from"
+ elseif (sub_atributo == 4) then --> RUNEPOWER GANHO
+ return "runepower", "runepower_from"
+ end
+end
+
+function atributo_energy:Fontes_e_Habilidades (recebido_from, showing, keyName, habilidade_alvo)
+
+ local habilidades = {}
+ local fontes = {}
+ local spells_alvo = {}
+ local max = 0
+
+ for nome, _ in _pairs (recebido_from) do
+ local esta_fonte = showing._ActorTable [showing._NameIndexTable [nome]]
+ if (esta_fonte) then
+
+ local alvos = esta_fonte.targets
+ local _habilidades = esta_fonte.spell_tables
+
+ local este_alvo = alvos._ActorTable [alvos._NameIndexTable[self.nome]]
+ if (este_alvo) then
+ fontes [#fontes+1] = {nome, este_alvo [keyName], esta_fonte.classe} --> mostra QUEM deu regen, a QUANTIDADE e a CLASSE
+ --print (nome, este_alvo [keyName], esta_fonte.classe)
+ end
+
+ for spellid, habilidade in _pairs (_habilidades._ActorTable) do
+ local alvos = habilidade.targets
+ local este_alvo = alvos._ActorTable [alvos._NameIndexTable[self.nome]]
+ if (este_alvo) then
+ if (not habilidades [spellid]) then
+ habilidades [spellid] = 0 --> mostra A SPELL e a quantidade que ela deu regen
+ end
+ habilidades [spellid] = habilidades [spellid] + este_alvo [keyName]
+ if (habilidades [spellid] > max) then
+ max = habilidades [spellid]
+ end
+ if (habilidade_alvo and habilidade_alvo == spellid) then
+ spells_alvo [#spells_alvo + 1] = {nome, este_alvo [keyName], esta_fonte.classe}
+ elseif (habilidade_alvo == true) then
+ --print (nome, nome, este_alvo [keyName], spellid)
+ spells_alvo [#spells_alvo + 1] = {nome, este_alvo [keyName], spellid}
+ end
+ end
+ end
+ end
+ end
+
+ local sorted_table = {}
+ for spellid, amt in _pairs (habilidades) do
+ local nome, _, icone = _GetSpellInfo (spellid)
+ sorted_table [#sorted_table+1] = {spellid, amt, amt/max*100, nome, icone}
+ end
+ _table_sort (sorted_table, function (a, b) return a[2] > b[2] end)
+
+ _table_sort (fontes, function (a, b) return a[2] > b[2] end)
+
+ if (habilidade_alvo) then
+ _table_sort (spells_alvo, function (a, b) return a[2] > b[2] end)
+ end
+
+ return fontes, sorted_table, spells_alvo
+end
+
+
+---------> TOOLTIPS BIFURCAÇÃO
+function atributo_energy:ToolTip (instancia, numero, barra)
+ --> seria possivel aqui colocar o icone da classe dele?
+ GameTooltip:ClearLines()
+ GameTooltip:AddLine (barra.colocacao..". "..self.nome)
+ if (instancia.sub_atributo <= 4) then
+ return self:ToolTipRegenRecebido (instancia, numero, barra)
+ end
+end
+
+function atributo_energy:ToolTipRegenRecebido (instancia, numero, barra)
+
+ local tabela_do_combate = instancia.showing
+ local showing = tabela_do_combate [class_type]
+
+ local keyName, keyName_from = atributo_energy:KeyNames (instancia.sub_atributo)
+
+ local total_regenerado = self [keyName]
+ local recebido_from = self [keyName_from]
+
+ local fontes, habilidades = self:Fontes_e_Habilidades (recebido_from, showing, keyName)
+
+-----------------------------------------------------------------
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"])
+
+ local max = #habilidades
+ if (max > 3) then
+ max = 3
+ end
+
+ for i = 1, max do
+ local nome_magia, _, icone_magia = _GetSpellInfo (habilidades[i][1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", _detalhes:comma_value (habilidades[i][2]).." (".._cstr("%.1f", (habilidades[i][2]/total_regenerado) * 100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+
+-----------------------------------------------------------------
+ GameTooltip:AddLine (Loc ["STRING_PLAYERS"]..":")
+
+ max = #fontes
+ if (max > 3) then
+ max = 3
+ end
+
+ for i = 1, max do
+ GameTooltip:AddDoubleLine (fontes[i][1]..": ", _detalhes:comma_value (fontes[i][2]).." (".._cstr("%.1f", (fontes[i][2]/total_regenerado) * 100).."%)", 1, 1, 1, 1, 1, 1)
+ local classe = fontes[i][3]
+ if (not classe) then
+ classe = "monster"
+ end
+
+ GameTooltip:AddTexture ("Interface\\AddOns\\Details\\images\\"..classe:lower().."_small")
+ end
+
+ return true
+end
+
+--------------------------------------------- // JANELA DETALHES // ---------------------------------------------
+
+---------> DETALHES BIFURCAÇÃO
+function atributo_energy:MontaInfo()
+ if (info.sub_atributo <= 4) then --> damage done & dps
+ return self:MontaInfoRegenRecebido()
+ end
+end
+
+---------> DETALHES bloco da direita BIFURCAÇÃO
+function atributo_energy:MontaDetalhes (spellid, barra)
+ if (info.sub_atributo <= 4) then
+ return self:MontaDetalhesRegenRecebido (spellid, barra)
+ end
+end
+
+function atributo_energy:MontaInfoRegenRecebido()
+
+ local barras = info.barras1
+ local barras2 = info.barras2
+ local barras3 = info.barras3
+
+ local instancia = info.instancia
+
+ local keyName, keyName_from = atributo_energy:KeyNames (instancia.sub_atributo)
+
+ local tabela_do_combate = instancia.showing
+ local showing = tabela_do_combate [class_type]
+
+ local total_regenerado = self [keyName]
+ local recebido_from = self [keyName_from]
+
+ if (not recebido_from) then
+ return
+ end
+
+ local fontes, habilidades = self:Fontes_e_Habilidades (recebido_from, showing, keyName)
+
+ local amt = #habilidades
+
+ if (amt < 1) then --> caso houve apenas friendly fire
+ return true
+ end
+
+ gump:JI_AtualizaContainerBarras (amt)
+ local max_ = habilidades [1][2]
+
+ for index, tabela in _ipairs (habilidades) do
+
+ local barra = barras [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo1 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+
+ barra.on_focus = false
+ end
+
+ self:FocusLock (barra, tabela[1])
+ self:UpdadeInfoBar (barra, index, tabela[1], tabela[4], tabela[2], max_, tabela[3], tabela[5], true)
+
+ barra.minha_tabela = self
+ barra.show = tabela[1]
+ barra:Show()
+
+ if (self.detalhes and self.detalhes == barra.show) then
+ self:MontaDetalhes (self.detalhes, barra)
+ end
+
+ end
+
+
+ local amt_fontes = #fontes
+ gump:JI_AtualizaContainerAlvos (amt_fontes)
+
+ local max_fontes = fontes[1][2]
+
+ local barra
+ for index, tabela in _ipairs (fontes) do
+
+ barra = info.barras2 [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo2 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_fontes*100)
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (_detalhes:comma_value (tabela[2]) .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[2]/total_regenerado * 100) .. instancia.divisores.fecha) --seta o texto da direita
+
+ if (barra.mouse_over) then --> atualizar o tooltip
+ if (barra.isAlvo) then
+ GameTooltip:Hide()
+ GameTooltip:SetOwner (barra, "ANCHOR_TOPRIGHT")
+ if (not barra.minha_tabela:MontaTooltipAlvos (barra, index)) then
+ return
+ end
+ GameTooltip:Show()
+ end
+ end
+
+ barra.minha_tabela = self --> grava o jogador na tabela
+ barra.nome_inimigo = tabela [1] --> salva o nome do inimigo na barra --> isso é necessário?
+
+ barra:Show()
+ end
+
+end
+
+function atributo_energy:MontaDetalhesRegenRecebido (nome, barra)
+ for _, barra in _ipairs (info.barras3) do
+ barra:Hide()
+ end
+
+ local barras = info.barras3
+ local instancia = info.instancia
+
+ local tabela_do_combate = info.instancia.showing
+ local showing = tabela_do_combate [class_type]
+
+ local keyName, keyName_from = atributo_energy:KeyNames (instancia.sub_atributo)
+ local recebido_from = self [keyName_from]
+ local total_regenerado = self [keyName]
+
+ local _, _, from = self:Fontes_e_Habilidades (recebido_from, showing, keyName, nome)
+
+ if (not from [1] or not from [1][2]) then
+ return
+ end
+
+ local max_ = from [1][2]
+
+ local barra
+ for index, tabela in _ipairs (from) do
+ barra = barras [index]
+
+ if (not barra) then --> se a barra não existir, criar ela então
+ barra = gump:CriaNovaBarraInfo3 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> isso aqui é a parte da seleção e desceleção
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (_detalhes:comma_value (tabela[2]) .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[2] /total_regenerado *100) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [tabela[3]]))
+ barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+
+ barra.icone:SetTexCoord (_unpack (_detalhes.class_coords [tabela[3]]))
+
+ barra:Show() --> mostra a barra
+
+ if (index == 15) then
+ break
+ end
+ end
+end
+
+function atributo_energy:MontaTooltipAlvos (esta_barra, index)
+ local instancia = info.instancia
+ local tabela_do_combate = instancia.showing
+ local showing = tabela_do_combate [class_type]
+
+ local keyName, keyName_from = atributo_energy:KeyNames (instancia.sub_atributo)
+
+ local total_regenerado = self [keyName]
+ local recebido_from = self [keyName_from]
+
+ local _, _, spells_alvo = self:Fontes_e_Habilidades (recebido_from, showing, keyName, true)
+
+-----------------------------------------------------------------
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"]..":")
+ for _, tabela in _ipairs (spells_alvo) do
+ if (tabela[1] == esta_barra.nome_inimigo) then
+ local nome_magia, _, icone_magia = _GetSpellInfo (tabela[3])
+ GameTooltip:AddDoubleLine (nome_magia..": ", _detalhes:comma_value (tabela[2]).." (".._cstr("%.1f", (tabela[2]/total_regenerado) * 100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ end
+
+ return true
+end
+
+
+--controla se o dps do jogador esta travado ou destravado
+function atributo_energy:Iniciar (iniciar)
+ return false --retorna se o dps esta aberto ou fechado para este jogador
+end
+
+function atributo_energy:ColetarLixo()
+ return _detalhes:ColetarLixo (class_type)
+end
+
+local function ReconstroiMapa (tabela)
+ local mapa = {}
+ for i = 1, #tabela._ActorTable do
+ mapa [tabela._ActorTable[i].nome] = i
+ end
+ tabela._NameIndexTable = mapa
+end
+
+function _detalhes.refresh:r_atributo_energy (este_jogador, shadow)
+ _setmetatable (este_jogador, _detalhes.atributo_energy)
+ este_jogador.__index = _detalhes.atributo_energy
+
+ if (shadow ~= -1) then
+ este_jogador.shadow = shadow
+ _detalhes.refresh:r_container_combatentes (este_jogador.targets, shadow.targets)
+ _detalhes.refresh:r_container_habilidades (este_jogador.spell_tables, shadow.spell_tables)
+ else
+ _detalhes.refresh:r_container_combatentes (este_jogador.targets, -1)
+ _detalhes.refresh:r_container_habilidades (este_jogador.spell_tables, -1)
+ end
+end
+
+function _detalhes.clear:c_atributo_energy (este_jogador)
+ este_jogador.__index = {}
+ este_jogador.shadow = nil
+ este_jogador.links = nil
+ este_jogador.minha_barra = nil
+
+ _detalhes.clear:c_container_combatentes (este_jogador.targets)
+ _detalhes.clear:c_container_habilidades (este_jogador.spell_tables)
+end
+
+atributo_energy.__add = function (shadow, tabela2)
+
+ shadow.mana = shadow.mana + tabela2.mana
+ shadow.e_rage = shadow.e_rage + tabela2.e_rage
+ shadow.e_energy = shadow.e_energy + tabela2.e_energy
+ shadow.runepower = shadow.runepower + tabela2.runepower
+ shadow.focus = shadow.focus + tabela2.focus
+ shadow.holypower = shadow.holypower + tabela2.holypower
+
+ _detalhes.tabela_overall.totals[3]["mana"] = _detalhes.tabela_overall.totals[3]["mana"] + tabela2.mana
+ _detalhes.tabela_overall.totals[3]["e_rage"] = _detalhes.tabela_overall.totals[3]["e_rage"] + tabela2.e_rage
+ _detalhes.tabela_overall.totals[3]["e_energy"] = _detalhes.tabela_overall.totals[3]["e_energy"] + tabela2.e_energy
+ _detalhes.tabela_overall.totals[3]["runepower"] = _detalhes.tabela_overall.totals[3]["runepower"] + tabela2.runepower
+
+ if (tabela2.grupo) then
+ _detalhes.tabela_overall.totals_grupo[3]["mana"] = _detalhes.tabela_overall.totals_grupo[3]["mana"] + tabela2.mana
+ _detalhes.tabela_overall.totals_grupo[3]["e_rage"] = _detalhes.tabela_overall.totals_grupo[3]["e_rage"] + tabela2.e_rage
+ _detalhes.tabela_overall.totals_grupo[3]["e_energy"] = _detalhes.tabela_overall.totals_grupo[3]["e_energy"] + tabela2.e_energy
+ _detalhes.tabela_overall.totals_grupo[3]["runepower"] = _detalhes.tabela_overall.totals_grupo[3]["runepower"] + tabela2.runepower
+ end
+
+ shadow.mana_r = shadow.mana_r + tabela2.mana_r
+ shadow.e_rage_r = shadow.e_rage_r + tabela2.e_rage_r
+ shadow.e_energy_r = shadow.e_energy_r + tabela2.e_energy_r
+ shadow.runepower_r = shadow.runepower_r + tabela2.runepower_r
+ shadow.focus_r = shadow.focus_r + tabela2.focus_r
+ shadow.holypower_r = shadow.holypower_r + tabela2.holypower_r
+
+ for index, alvo in _ipairs (tabela2.targets._ActorTable) do
+ local alvo_shadow = shadow.targets:PegarCombatente (alvo.serial, alvo.nome, _, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ --> copia o container de habilidades
+ for spellid, habilidade in _pairs (tabela2.spell_tables._ActorTable) do
+ local habilidade_shadow = shadow.spell_tables:PegaHabilidade (spellid, true, nil, true)
+
+ for index, alvo in _ipairs (habilidade.targets._ActorTable) do
+ local alvo_shadow = habilidade_shadow.targets:PegarCombatente (alvo.serial, alvo.nome, _, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for key, value in _pairs (habilidade) do
+ if (_type (value) == "number") then
+ if (key ~= "id") then
+ if (not habilidade_shadow [key]) then
+ habilidade_shadow [key] = 0
+ end
+ habilidade_shadow [key] = habilidade_shadow [key] + value
+ end
+ end
+ end
+ end
+
+ return shadow
+end
+
+atributo_energy.__sub = function (tabela1, tabela2)
+
+ tabela1.mana = tabela1.mana - tabela2.mana
+ tabela1.e_rage = tabela1.e_rage - tabela2.e_rage
+ tabela1.e_energy = tabela1.e_energy - tabela2.e_energy
+ tabela1.runepower = tabela1.runepower - tabela2.runepower
+ tabela1.focus = tabela1.focus - tabela2.focus
+ tabela1.holypower = tabela1.holypower - tabela2.holypower
+
+ tabela1.mana_r = tabela1.mana_r - tabela2.mana_r
+ tabela1.e_rage_r = tabela1.e_rage_r - tabela2.e_rage_r
+ tabela1.e_energy_r = tabela1.e_energy_r - tabela2.e_energy_r
+ tabela1.runepower_r = tabela1.runepower_r - tabela2.runepower_r
+ tabela1.focus_r = tabela1.focus_r - tabela2.focus_r
+ tabela1.holypower_r = tabela1.holypower_r - tabela2.holypower_r
+
+ return tabela1
+end
diff --git a/classes/classe_energy_habilidade.lua b/classes/classe_energy_habilidade.lua
new file mode 100644
index 00000000..2e7392e3
--- /dev/null
+++ b/classes/classe_energy_habilidade.lua
@@ -0,0 +1,102 @@
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local habilidade_energy = _detalhes.habilidade_e_energy
+local container_combatentes = _detalhes.container_combatentes
+local container_energy_target = _detalhes.container_type.CONTAINER_ENERGYTARGET_CLASS
+
+--lua locals
+local _setmetatable = setmetatable
+local _ipairs = ipairs
+--api locals
+local _UnitAura = UnitAura
+--local _GetSpellInfo = _detalhes.getspellinfo
+
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+
+--id, nome, type, miss, dano, cura, overkill, school, resisted, blocked, absorbed, critico, glacing, crushing
+function habilidade_energy:NovaTabela (id, link, token) --aqui eu não sei que parâmetros passar
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, habilidade_energy)
+
+ esta_tabela.quem_sou = "classe_energy_habilidade"
+ esta_tabela.id = id
+ esta_tabela.counter = 0
+
+ esta_tabela.mana = 0
+ esta_tabela.e_rage = 0
+ esta_tabela.e_energy = 0
+ esta_tabela.runepower = 0
+
+ esta_tabela.targets = container_combatentes:NovoContainer (container_energy_target)
+
+ if (link) then
+ esta_tabela.targets.shadow = link.targets
+ end
+
+ return esta_tabela
+end
+
+function habilidade_energy:Add (serial, nome, flag, amount, who_nome, powertype)
+
+ self.counter = self.counter + 1
+
+ --local alvo = self.targets:PegarCombatente (serial, nome, flag, true)
+ local alvo = self.targets._NameIndexTable [nome]
+ if (not alvo) then
+ alvo = self.targets:PegarCombatente (serial, nome, flag, true)
+ else
+ alvo = self.targets._ActorTable [alvo]
+ end
+
+
+ if (powertype == 0) then --> MANA
+ self.mana = self.mana + amount
+ alvo.mana = alvo.mana + amount
+ elseif (powertype == 1) then --> e_rage
+ self.e_rage = self.e_rage + amount
+ alvo.e_rage = alvo.e_rage + amount
+ elseif (powertype == 3) then --> ENERGIA
+ self.e_energy = self.e_energy + amount
+ alvo.e_energy = alvo.e_energy + amount
+ elseif (powertype == 6) then --> RUNEPOWER
+ self.runepower = self.runepower + amount
+ alvo.runepower = alvo.runepower + amount
+ end
+
+ if (self.shadow) then
+ return self.shadow:Add (serial, nome, flag, amount, who_nome, powertype)
+ end
+end
+
+function _detalhes.refresh:r_habilidade_e_energy (habilidade, shadow) --recebeu o container shadow
+ _setmetatable (habilidade, habilidade_energy)
+ habilidade.__index = habilidade_energy
+
+ if (shadow ~= -1) then
+ habilidade.shadow = shadow._ActorTable[habilidade.id]
+ _detalhes.refresh:r_container_combatentes (habilidade.targets, habilidade.shadow.targets)
+ else
+ _detalhes.refresh:r_container_combatentes (habilidade.targets, -1)
+ end
+end
+
+function _detalhes.clear:c_habilidade_e_energy (habilidade)
+ habilidade.__index = {}
+ habilidade.shadow = nil
+
+ _detalhes.clear:c_container_combatentes (habilidade.targets)
+end
+
+habilidade_energy.__sub = function (tabela1, tabela2)
+
+ tabela1.mana = tabela1.mana - tabela2.mana
+ tabela1.e_rage = tabela1.e_rage - tabela2.e_rage
+ tabela1.e_energy = tabela1.e_energy - tabela2.e_energy
+ tabela1.runepower = tabela1.runepower - tabela2.runepower
+
+ tabela1.counter = tabela1.counter - tabela2.counter
+
+ return tabela1
+end
diff --git a/classes/classe_error.lua b/classes/classe_error.lua
new file mode 100644
index 00000000..8895b29f
--- /dev/null
+++ b/classes/classe_error.lua
@@ -0,0 +1,27 @@
+do
+ local _detalhes = _G._detalhes
+
+ local _error = {
+ ["error"] = true,
+ ["errortext"] = ""
+ }
+ _error.__index = _error
+ _error.__newindex = function()
+ assert (false, "Attempt to modify an read-only object.\nUse object() or object.errortext\n"..debugstack (2, 1 , 0))
+ return
+ end
+ _error.__tostring = function()
+ return _error.errortext
+ end
+ _error.__call = function (_this)
+ print (_this.errortext)
+ end
+
+ function _detalhes:NewError (_msg)
+ local this_error = {}
+ this_error.errortext = _msg
+ setmetatable (this_error, _error)
+ return this_error
+ end
+
+end
\ No newline at end of file
diff --git a/classes/classe_heal.lua b/classes/classe_heal.lua
new file mode 100644
index 00000000..3d889510
--- /dev/null
+++ b/classes/classe_heal.lua
@@ -0,0 +1,1232 @@
+--[[ Esta classe irá abrigar todo a cura de uma habilidade
+Parents:
+ addon -> combate atual -> cura -> container de jogadores -> esta classe
+
+]]
+
+--lua locals
+local _cstr = string.format
+local _math_floor = math.floor
+local _setmetatable = setmetatable
+local _pairs = pairs
+local _ipairs = ipairs
+local _unpack = unpack
+local _type = type
+local _table_sort = table.sort
+local _cstr = string.format
+local _table_insert = table.insert
+local _bit_band = bit.band
+local _math_min = math.min
+--api locals
+local _GetSpellInfo = _detalhes.getspellinfo
+
+
+local _detalhes = _G._detalhes
+
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local container_habilidades = _detalhes.container_habilidades
+local container_combatentes = _detalhes.container_combatentes
+local atributo_heal = _detalhes.atributo_heal
+local habilidade_cura = _detalhes.habilidade_cura
+
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+local container_heal = _detalhes.container_type.CONTAINER_HEAL_CLASS
+local container_heal_target = _detalhes.container_type.CONTAINER_HEALTARGET_CLASS
+
+local modo_ALONE = _detalhes.modos.alone
+local modo_GROUP = _detalhes.modos.group
+local modo_ALL = _detalhes.modos.all
+
+local class_type = _detalhes.atributos.cura
+
+local DATA_TYPE_START = _detalhes._detalhes_props.DATA_TYPE_START
+local DATA_TYPE_END = _detalhes._detalhes_props.DATA_TYPE_END
+
+local DFLAG_player = _detalhes.flags.player
+local DFLAG_group = _detalhes.flags.in_group
+local DFLAG_player_group = _detalhes.flags.player_in_group
+
+local div_abre = _detalhes.divisores.abre
+local div_fecha = _detalhes.divisores.fecha
+local div_lugar = _detalhes.divisores.colocacao
+
+local info = _detalhes.janela_info
+local keyName
+
+function atributo_heal:NovaTabela (serial, nome, link)
+ local esta_tabela = {}
+ esta_tabela.quem_sou = "classe_heal" --> DEBUG deleta-me
+
+ _setmetatable (esta_tabela, atributo_heal)
+
+ --> grava o tempo que a tabela foi criada para o garbage collector interno
+ esta_tabela.CriadaEm = time()
+
+ --> dps do objeto inicia sempre desligado
+ esta_tabela.iniciar_hps = false --> sera necessario isso na cura?
+
+ esta_tabela.tipo = class_type --> atributo 2 = cura
+
+ esta_tabela.total = 0
+ esta_tabela.totalover = 0
+ esta_tabela.custom = 0
+
+ esta_tabela.total_without_pet = 0 --> pet de DK cura
+ esta_tabela.totalover_without_pet = 0 --> pet de DK cura
+
+ esta_tabela.last_events_table = {} --> log da morte
+
+ esta_tabela.healing_taken = 0 --> total de cura que este jogador recebeu
+ esta_tabela.healing_from = {} --> armazena os nomes que deram cura neste jogador
+
+ esta_tabela.last_event = 0 --> mantem igual ao dano
+ esta_tabela.on_hold = false --> mantem igual ao dano
+ esta_tabela.delay = 0 --> mantem igual ao dano
+
+ esta_tabela.last_value = nil --> ultimo valor que este jogador teve, salvo quando a barra dele é atualizada
+
+ esta_tabela.end_time = nil
+ esta_tabela.start_time = 0
+
+ esta_tabela.last_hps = 0 --> cura por segundo
+ esta_tabela.last_value = 0
+
+ esta_tabela.pets = {} --cura não tem pet, okey? tem pet sim, as larvas de DK
+
+ esta_tabela.heal_enemy = {} --> quando o jogador cura um inimigo
+
+ --container armazenará os IDs das habilidades usadas por este jogador
+ esta_tabela.spell_tables = container_habilidades:NovoContainer (container_heal)
+
+ --container armazenará os seriais dos alvos que o player aplicou dano
+ esta_tabela.targets = container_combatentes:NovoContainer (container_heal_target)
+
+ if (link) then
+ esta_tabela.targets.shadow = link.targets
+ esta_tabela.spell_tables.shadow = link.spell_tables
+ end
+
+ return esta_tabela
+end
+
+
+function atributo_heal:RefreshWindow (instancia, tabela_do_combate, forcar, exportar)
+
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura
+
+ --> não há barras para mostrar -- not have something to show
+ if (#showing._ActorTable < 1) then --> não há barras para mostrar
+ --> colocado isso recentemente para fazer as barras de dano sumirem na troca de atributo
+ return _detalhes:EsconderBarrasNaoUsadas (instancia, showing)
+ end
+
+ --> total
+ local total = 0
+ --> top actor #1
+ instancia.top = 0
+
+ local sub_atributo = instancia.sub_atributo --> o que esta sendo mostrado nesta instância
+ local conteudo = showing._ActorTable
+ local amount = #conteudo
+ local modo = instancia.modo
+
+ --> pega qual a sub key que será usada
+ if (exportar) then
+
+ if (_type (exportar) == "boolean") then
+ if (sub_atributo == 1) then --> healing DONE
+ keyName = "total"
+ elseif (sub_atributo == 2) then --> HPS
+ keyName = "last_hps"
+ elseif (sub_atributo == 3) then --> overheal
+ keyName = "totalover"
+ elseif (sub_atributo == 4) then --> healing take
+ keyName = "healing_taken"
+ end
+ else
+ keyName = exportar.key
+ modo = exportar.modo
+ end
+ elseif (instancia.atributo == 5) then --> custom
+ keyName = "custom"
+ total = tabela_do_combate.totals [instancia.customName]
+ else
+ if (sub_atributo == 1) then --> healing DONE
+ keyName = "total"
+ elseif (sub_atributo == 2) then --> HPS
+ keyName = "last_hps"
+ elseif (sub_atributo == 3) then --> overheal
+ keyName = "totalover"
+ elseif (sub_atributo == 4) then --> healing take
+ keyName = "healing_taken"
+ end
+ end
+
+ if (instancia.atributo == 5) then --> custom
+ --> faz o sort da categoria e retorna o amount corrigido
+ amount = _detalhes:ContainerSort (conteudo, amount, keyName)
+
+ --> grava o total
+ instancia.top = conteudo[1][keyName]
+
+ elseif (instancia.modo == modo_ALL) then --> mostrando ALL
+
+ amount = _detalhes:ContainerSort (conteudo, amount, keyName)
+
+ --> faz o sort da categoria
+ --_table_sort (conteudo, function (a, b) return a[keyName] > b[keyName] end)
+
+ --> não mostrar resultados com zero
+ --[[for i = amount, 1, -1 do --> de trás pra frente
+ if (conteudo[i][keyName] < 1) then
+ amount = amount-1
+ else
+ break
+ end
+ end--]]
+
+ --> pega o total ja aplicado na tabela do combate
+ total = tabela_do_combate.totals [class_type]
+
+ --> grava o total
+ instancia.top = conteudo[1][keyName]
+
+ elseif (instancia.modo == modo_GROUP) then --> mostrando GROUP
+
+ --> organiza as tabelas
+
+ --print ("AQUI")
+ --print ("::"..keyName)
+
+ --_detalhes:DelayMsg ("==================")
+ --_detalhes:DelayMsg (keyName)
+
+ --_table_sort (conteudo, _detalhes.SortKeyGroup)
+ _detalhes.SortGroup (conteudo, keyName)
+
+ --[[_table_sort (conteudo, function (a, b)
+ if (a.grupo and b.grupo) then
+ return a[keyName] > b[keyName]
+ elseif (a.grupo and not b.grupo) then
+ return true
+ elseif (not a.grupo and b.grupo) then
+ return false
+ else
+ return a[keyName] > b[keyName]
+ end
+ end)--]]
+
+ for index, player in _ipairs (conteudo) do
+ if (_bit_band (player.flag, DFLAG_player_group) >= 0x101) then --> é um player e esta em grupo
+ if (player[keyName] < 1) then --> dano menor que 1, interromper o loop
+ amount = index - 1
+ break
+ elseif (index == 1) then --> esse IF aqui, precisa mesmo ser aqui? não daria pra pega-lo com uma chave [1] nad grupo == true?
+ instancia.top = conteudo[1][keyName]
+ end
+
+ total = total + player[keyName]
+ else
+ amount = index-1
+ break
+ end
+ end
+
+ end
+
+ --> refaz o mapa do container
+ showing:remapear()
+
+ if (exportar) then
+ return total, keyName, instancia.top
+ end
+
+ if (amount < 1) then --> não há barras para mostrar
+ instancia:EsconderScrollBar()
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+ end
+
+ --estra mostrando ALL então posso seguir o padrão correto? primeiro, atualiza a scroll bar...
+ instancia:AtualizarScrollBar (amount)
+
+ --depois faz a atualização normal dele através dos iterators
+ local qual_barra = 1
+ local barras_container = instancia.barras --> evita buscar N vezes a key .barras dentro da instância
+
+ local combat_time = instancia.showing:GetCombatTime()
+ for i = instancia.barraS[1], instancia.barraS[2], 1 do --> vai atualizar só o range que esta sendo mostrado
+ --conteudo[i]:AtualizaBarra (instancia, qual_barra, i, total, sub_atributo, forcar) --> instância, index, total, valor da 1º barra
+ conteudo[i]:AtualizaBarra (instancia, barras_container, qual_barra, i, total, sub_atributo, forcar, keyName, combat_time) --> instância, index, total, valor da 1º barra
+ qual_barra = qual_barra+1
+ end
+
+ if (instancia.atributo == 5) then --> custom
+ --> zerar o .custom dos Actors
+ for index, player in _ipairs (conteudo) do
+ if (player.custom > 0) then
+ player.custom = 0
+ else
+ break
+ end
+ end
+ end
+
+ --> beta, hidar barras não usadas durante um refresh forçado
+ if (forcar) then
+ if (instancia.modo == 2) then --> group
+ for i = qual_barra, instancia.barrasInfo.cabem do
+ gump:Fade (instancia.barras [i], "in", 0.3)
+ end
+ end
+ end
+
+ -- showing.need_refresh = false
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+
+end
+
+function atributo_heal:Custom (_customName, _combat, sub_atributo, spell, alvo)
+ local _Skill = self.spell_tables._ActorTable [tonumber (spell)]
+ if (_Skill) then
+ local spellName = _GetSpellInfo (tonumber (spell))
+ local SkillTargets = _Skill.targets._ActorTable
+
+ for _, TargetActor in _ipairs (SkillTargets) do
+ local TargetActorSelf = _combat (class_type, TargetActor.nome)
+ TargetActorSelf.custom = TargetActor.total + TargetActorSelf.custom
+ _combat.totals [_customName] = _combat.totals [_customName] + TargetActor.total
+ end
+ end
+end
+
+--function atributo_heal:AtualizaBarra (instancia, qual_barra, lugar, total, sub_atributo, forcar)
+function atributo_heal:AtualizaBarra (instancia, barras_container, qual_barra, lugar, total, sub_atributo, forcar, keyName, combat_time)
+
+ local esta_barra = instancia.barras[qual_barra] --> pega a referência da barra na janela
+
+ if (not esta_barra) then
+ print ("DEBUG: problema com "..qual_barra.." "..lugar)
+ return
+ end
+
+ local tabela_anterior = esta_barra.minha_tabela
+
+ esta_barra.minha_tabela = self --grava uma referência dessa classe de dano na barra
+ self.minha_barra = esta_barra --> salva uma referência da barra no objeto do jogador
+
+ esta_barra.colocacao = lugar --> salva na barra qual a colocação dela.
+ self.colocacao = lugar --> salva qual a colocação do jogador no objeto dele
+
+ local healing_total = self.total --> total de dano que este jogador deu
+ local hps
+ local porcentagem = self [keyName] / total * 100
+ local esta_porcentagem
+
+ if (_detalhes.time_type == 2 and self.grupo) then
+ hps = healing_total / combat_time
+ self.last_hps = hps
+ else
+ if (not self.on_hold) then
+ hps = healing_total/self:Tempo() --calcula o dps deste objeto
+ self.last_hps = hps --salva o dps dele
+ else
+ hps = self.last_hps
+
+ if (hps == 0) then --> não calculou o dps dele ainda mas entrou em standby
+ hps = healing_total/self:Tempo()
+ self.last_hps = hps
+ end
+ end
+ end
+
+ -- >>>>>>>>>>>>>>> texto da direita
+ if (instancia.atributo == 5) then --> custom
+ esta_barra.texto_direita:SetText (_detalhes:ToK (self.custom) .." ".. div_abre .. _cstr ("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita
+ esta_porcentagem = _math_floor ((self.custom/instancia.top) * 100) --> determina qual o tamanho da barra
+ else
+ if (sub_atributo == 1) then --> mostrando healing done
+ esta_barra.texto_direita:SetText (_detalhes:ToK (healing_total) .." ".. div_abre .. _math_floor (hps) .. ", ".. _cstr ("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita
+ esta_porcentagem = _math_floor ((healing_total/instancia.top) * 100) --> determina qual o tamanho da barra
+
+ elseif (sub_atributo == 2) then --> mostrando hps
+ esta_barra.texto_direita:SetText (_cstr("%.1f", hps) .." ".. div_abre .. _detalhes:ToK (healing_total) .. ", ".._cstr("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita
+ esta_porcentagem = _math_floor ((hps/instancia.top) * 100) --> determina qual o tamanho da barra
+
+ elseif (sub_atributo == 3) then --> mostrando overall
+ esta_barra.texto_direita:SetText (_detalhes:ToK (self.totalover) .." ".. div_abre .._cstr("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita --_cstr("%.1f", dps) .. " - ".. DPS do damage taken não será possivel correto?
+ esta_porcentagem = _math_floor ((self.totalover/instancia.top) * 100) --> determina qual o tamanho da barra
+
+ elseif (sub_atributo == 4) then --> mostrando healing take
+ esta_barra.texto_direita:SetText (_detalhes:ToK (self.healing_taken) .." ".. div_abre .._cstr("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita --_cstr("%.1f", dps) .. " - ".. DPS do damage taken não será possivel correto?
+ esta_porcentagem = _math_floor ((self.healing_taken/instancia.top) * 100) --> determina qual o tamanho da barra
+
+ end
+ end
+
+ if (esta_barra.mouse_over and not instancia.baseframe.isMoving) then --> precisa atualizar o tooltip
+ gump:UpdateTooltip (qual_barra, esta_barra, instancia)
+ end
+
+ return self:RefreshBarra2 (esta_barra, instancia, tabela_anterior, forcar, esta_porcentagem, qual_barra, barras_container)
+end
+
+--------------------------------------------- // TOOLTIPS // ---------------------------------------------
+
+
+---------> TOOLTIPS BIFURCAÇÃO
+function atributo_heal:ToolTip (instancia, numero, barra)
+ --> seria possivel aqui colocar o icone da classe dele?
+
+ if (instancia.atributo == 5) then --> custom
+ return self:TooltipForCustom (barra)
+ else
+ --GameTooltip:ClearLines()
+ --GameTooltip:AddLine (barra.colocacao..". "..self.nome)
+ if (instancia.sub_atributo <= 3) then --> healing done, HPS or Overheal
+ return self:ToolTip_HealingDone (instancia, numero, barra)
+ elseif (instancia.sub_atributo == 4) then --> healing taken
+ return self:ToolTip_HealingTaken (instancia, numero, barra)
+ end
+ end
+end
+
+
+---------> HEALING TAKEN
+function atributo_heal:ToolTip_HealingTaken (instancia, numero, barra)
+ local curadores = self.healing_from
+ local total_curado = self.healing_taken
+
+ local tabela_do_combate = instancia.showing
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ local meus_curadores = {}
+
+ for nome, _ in _pairs (curadores) do --> agressores seria a lista de nomes
+ local este_curador = showing._ActorTable[showing._NameIndexTable[nome]]
+ if (este_curador) then --> checagem por causa do total e do garbage collector que não limpa os nomes que deram dano
+ local alvos = este_curador.targets
+ local este_alvo = alvos._ActorTable[alvos._NameIndexTable[self.nome]]
+ if (este_alvo) then
+ meus_curadores [#meus_curadores+1] = {nome, este_alvo.total, este_curador.classe}
+ end
+ end
+ end
+
+ GameTooltip:AddLine (" ")
+
+ _table_sort (meus_curadores, function (a, b) return a[2] > b[2] end)
+ local max = #meus_curadores
+ if (max > 6) then
+ max = 6
+ end
+
+ for i = 1, max do
+ GameTooltip:AddDoubleLine (meus_curadores[i][1]..": ", meus_curadores[i][2].." (".._cstr ("%.1f", (meus_curadores[i][2]/total_curado) * 100).."%)", 1, 1, 1, 1, 1, 1)
+ local classe = meus_curadores[i][3]
+ if (not classe) then
+ classe = "monster"
+ end
+ GameTooltip:AddTexture ("Interface\\AddOns\\Details\\images\\"..classe:lower().."_small")
+ end
+
+ return true
+end
+
+---------> HEALING DONE / HPS / OVERHEAL
+function atributo_heal:ToolTip_HealingDone (instancia, numero, barra)
+
+ local ActorHealingTable = {}
+ local ActorHealingTargets = {}
+ local ActorSkillsContainer = self.spell_tables._ActorTable
+
+ local actor_key, skill_key = "total", "total"
+ if (instancia.sub_atributo == 3) then
+ key = "totalover", "overheal"
+ end
+
+ local ActorTotal = self [actor_key]
+ for _spellid, _skill in _pairs (ActorSkillsContainer) do
+ local SkillName, _, SkillIcon = _GetSpellInfo (_spellid)
+ _table_insert (ActorHealingTable, {_spellid, _skill [skill_key], _skill [skill_key]/ActorTotal*100, {SkillName, nil, SkillIcon}})
+ end
+ _table_sort (ActorHealingTable, _detalhes.Sort2)
+
+ --> TOP Curados
+ ActorSkillsContainer = self.targets._ActorTable
+ for _, TargetTable in _ipairs (ActorSkillsContainer) do
+ _table_insert (ActorHealingTargets, {TargetTable.nome, TargetTable.total, TargetTable.total/ActorTotal*100})
+ end
+ _table_sort (ActorHealingTargets, _detalhes.Sort2)
+
+ --> Mostra as habilidades no tooltip
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"] .. ":") --> localiza-me
+ for i = 1, _math_min (_detalhes.tooltip_max_abilities, #ActorHealingTable) do
+ if (ActorHealingTable[i][2] < 1) then
+ break
+ end
+ GameTooltip:AddDoubleLine (ActorHealingTable[i][4][1]..": ", _detalhes:comma_value (ActorHealingTable[i][2]).." (".._cstr ("%.1f", ActorHealingTable[i][3]).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (ActorHealingTable[i][4][3])
+ end
+
+ if (instancia.sub_atributo < 3) then -- 1 or 2 -> healing done or hps
+ GameTooltip:AddLine (Loc ["STRING_TARGETS"]..":") --> localiza-me
+ for i = 1, _math_min (_detalhes.tooltip_max_targets, #ActorHealingTargets) do
+ if (ActorHealingTargets[i][2] < 1) then
+ break
+ end
+ GameTooltip:AddDoubleLine (ActorHealingTargets[i][1]..": ", _detalhes:comma_value (ActorHealingTargets[i][2]) .." (".._cstr ("%.1f", ActorHealingTargets[i][3]).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture ("Interface\\AddOns\\Details\\images\\espadas")
+ end
+ end
+
+ return true
+end
+
+
+--------------------------------------------- // JANELA DETALHES // ---------------------------------------------
+---------- bifurcação
+function atributo_heal:MontaInfo()
+ if (info.sub_atributo == 1 or info.sub_atributo == 2) then
+ return self:MontaInfoHealingDone()
+ elseif (info.sub_atributo == 3) then
+ return self:MontaInfoOverHealing()
+ elseif (info.sub_atributo == 4) then
+ return self:MontaInfoHealTaken()
+ end
+end
+
+function atributo_heal:MontaInfoHealTaken()
+
+ local healing_taken = self.healing_taken
+ local curandeiros = self.healing_from
+ local instancia = info.instancia
+ local tabela_do_combate = instancia.showing
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+ local barras = info.barras1
+ local meus_curandeiros = {}
+
+ local este_curandeiro
+ for nome, _ in _pairs (curandeiros) do
+ este_curandeiro = showing._ActorTable[showing._NameIndexTable[nome]]
+ if (este_curandeiro) then
+ local alvos = este_curandeiro.targets
+ local este_alvo = alvos._ActorTable[alvos._NameIndexTable[self.nome]]
+ if (este_alvo) then
+ meus_curandeiros [#meus_curandeiros+1] = {nome, este_alvo.total, este_alvo.total/healing_taken*100, este_curandeiro.classe}
+ end
+ end
+ end
+
+ local amt = #meus_curandeiros
+
+ if (amt < 1) then
+ return true
+ end
+
+ _table_sort (meus_curandeiros, function (a, b) return a[2] > b[2] end)
+
+ gump:JI_AtualizaContainerBarras (amt)
+
+ local max_ = meus_curandeiros [1][2]
+
+ for index, tabela in _ipairs (meus_curandeiros) do
+
+ local barra = barras [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo1 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+
+ barra.on_focus = false
+ end
+
+ if (not info.mostrando_mouse_over) then
+ if (tabela[1] == self.detalhes) then --> tabela [1] = NOME = NOME que esta na caixa da direita
+ if (not barra.on_focus) then --> se a barra não tiver no foco
+ barra.textura:SetStatusBarColor (129/255, 125/255, 69/255, 1)
+ barra.on_focus = true
+ if (not info.mostrando) then
+ info.mostrando = barra
+ end
+ end
+ else
+ if (barra.on_focus) then
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> volta a cor antiga
+ barra:SetAlpha (.9) --> volta a alfa antiga
+ barra.on_focus = false
+ end
+ end
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ local classe = tabela[4]
+ if (not classe) then
+ classe = "monster"
+ end
+
+ barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\"..classe:lower().."_small")
+
+ barra.minha_tabela = self
+ barra.show = tabela[1]
+ barra:Show()
+
+ if (self.detalhes and self.detalhes == barra.show) then
+ self:MontaDetalhes (self.detalhes, barra)
+ end
+
+ end
+
+end
+
+function atributo_heal:MontaInfoOverHealing()
+--> pegar as habilidade de dar sort no heal
+
+ local instancia = info.instancia
+ local total = self.totalover
+ local tabela = self.spell_tables._ActorTable
+ local minhas_curas = {}
+ local barras = info.barras1
+
+ for spellid, tabela in _pairs (tabela) do
+ local nome, rank, icone = _GetSpellInfo (spellid)
+ _table_insert (minhas_curas, {spellid, tabela.overheal, tabela.overheal/total*100, nome, icone})
+ end
+
+ _table_sort (minhas_curas, function(a, b) return a[2] > b[2] end)
+
+ local amt = #minhas_curas
+ gump:JI_AtualizaContainerBarras (amt)
+
+ local max_ = minhas_curas[1][2]
+
+ for index, tabela in _ipairs (minhas_curas) do
+
+ local barra = barras [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo1 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ barra.on_focus = false
+ end
+
+ if (not info.mostrando_mouse_over) then
+ if (tabela[1] == self.detalhes) then --> tabela [1] = spellid = spellid que esta na caixa da direita
+ if (not barra.on_focus) then --> se a barra não tiver no foco
+ barra.textura:SetStatusBarColor (129/255, 125/255, 69/255, 1)
+ barra.on_focus = true
+ if (not info.mostrando) then
+ info.mostrando = barra
+ end
+ end
+ else
+ if (barra.on_focus) then
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> volta a cor antiga
+ barra:SetAlpha (.9) --> volta a alfa antiga
+ barra.on_focus = false
+ end
+ end
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[4]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .. _cstr ("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ barra.icone:SetTexture (tabela[5])
+
+ barra.minha_tabela = self
+ barra.show = tabela[1]
+ barra:Show()
+
+ if (self.detalhes and self.detalhes == barra.show) then
+ self:MontaDetalhes (self.detalhes, barra)
+ end
+ end
+
+ --> TOP OVERHEALED
+ local meus_inimigos = {}
+ tabela = self.targets._ActorTable
+ for _, tabela in _ipairs (tabela) do
+ _table_insert (meus_inimigos, {tabela.nome, tabela.overheal, tabela.overheal/total*100})
+ end
+ _table_sort (meus_inimigos, function(a, b) return a[2] > b[2] end )
+
+ local amt_alvos = #meus_inimigos
+ gump:JI_AtualizaContainerAlvos (amt_alvos)
+
+ local max_inimigos = meus_inimigos[1][2]
+
+ for index, tabela in _ipairs (meus_inimigos) do
+
+ local barra = info.barras2 [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo2 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .. _cstr ("%.1f", tabela[3]) .. instancia.divisores.fecha) --seta o texto da direita
+
+ -- o que mostrar no local do ícone?
+ --barra.icone:SetTexture (tabela[4][3])
+
+ barra.minha_tabela = self
+ barra.nome_inimigo = tabela [1]
+
+ -- no lugar do spell id colocar o que?
+ --barra.spellid = tabela[5]
+ barra:Show()
+
+ --if (self.detalhes and self.detalhes == barra.spellid) then
+ -- self:MontaDetalhes (self.detalhes, barra)
+ --end
+ end
+end
+
+function atributo_heal:MontaInfoHealingDone()
+
+ --> pegar as habilidade de dar sort no heal
+
+ local instancia = info.instancia
+ local total = self.total
+ local tabela = self.spell_tables._ActorTable
+ local minhas_curas = {}
+ local barras = info.barras1
+
+ for spellid, tabela in _pairs (tabela) do
+ local nome, rank, icone = _GetSpellInfo (spellid)
+ _table_insert (minhas_curas, {spellid, tabela.total, tabela.total/total*100, nome, icone})
+ end
+
+ _table_sort (minhas_curas, function(a, b) return a[2] > b[2] end)
+
+ local amt = #minhas_curas
+ gump:JI_AtualizaContainerBarras (amt)
+
+ local max_ = minhas_curas[1][2]
+
+ for index, tabela in _ipairs (minhas_curas) do
+
+ local barra = barras [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo1 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ barra.on_focus = false
+ end
+
+ self:FocusLock (barra, tabela[1])
+
+ self:UpdadeInfoBar (barra, index, tabela[1], tabela[4], tabela[2], max_, tabela[3], tabela[5], true)
+
+ barra.minha_tabela = self
+ barra.show = tabela[1]
+ barra:Show()
+
+ if (self.detalhes and self.detalhes == barra.show) then
+ self:MontaDetalhes (self.detalhes, barra)
+ end
+ end
+
+ --> SERIA TOP CURADOS
+ local meus_inimigos = {}
+ tabela = self.targets._ActorTable
+ for _, tabela in _ipairs (tabela) do
+ _table_insert (meus_inimigos, {tabela.nome, tabela.total, tabela.total/total*100})
+ end
+ _table_sort (meus_inimigos, function(a, b) return a[2] > b[2] end )
+
+ local amt_alvos = #meus_inimigos
+ gump:JI_AtualizaContainerAlvos (amt_alvos)
+
+ local max_inimigos = meus_inimigos[1][2]
+
+ for index, tabela in _ipairs (meus_inimigos) do
+
+ local barra = info.barras2 [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo2 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (_detalhes:comma_value (tabela[2]) .." ".. instancia.divisores.abre .. _cstr ("%.1f", tabela[3]) .. instancia.divisores.fecha) --seta o texto da direita
+
+ -- o que mostrar no local do ícone?
+ --barra.icone:SetTexture (tabela[4][3])
+
+ barra.minha_tabela = self
+ barra.nome_inimigo = tabela [1]
+
+ -- no lugar do spell id colocar o que?
+ --barra.spellid = tabela[5]
+ barra:Show()
+
+ --if (self.detalhes and self.detalhes == barra.spellid) then
+ -- self:MontaDetalhes (self.detalhes, barra)
+ --end
+ end
+
+end
+
+function atributo_heal:MontaTooltipAlvos (esta_barra, index)
+ -- eu ja sei quem é o alvo a mostrar os detalhes
+ -- dar foreach no container de habilidades -- pegar os alvos da habilidade -- e ver se dentro do container tem o meu alvo.
+
+ local inimigo = esta_barra.nome_inimigo
+ local container = self.spell_tables._ActorTable
+ local habilidades = {}
+ local total = self.total
+
+ if (info.instancia.sub_atributo == 3) then --> overheal
+ total = self.totalover
+ for spellid, tabela in _pairs (container) do
+ --> tabela = classe_damage_habilidade
+ local alvos = tabela.targets._ActorTable
+ for _, tabela in _ipairs (alvos) do
+ --> tabela = classe_target
+ if (tabela.nome == inimigo) then
+ habilidades [#habilidades+1] = {spellid, tabela.overheal}
+ end
+ end
+ end
+ else
+ for spellid, tabela in _pairs (container) do
+ --> tabela = classe_damage_habilidade
+ local alvos = tabela.targets._ActorTable
+ for _, tabela in _ipairs (alvos) do
+ --> tabela = classe_target
+ if (tabela.nome == inimigo) then
+ habilidades [#habilidades+1] = {spellid, tabela.total}
+ end
+ end
+ end
+
+ end
+
+ _table_sort (habilidades, function (a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (index..". "..inimigo)
+ GameTooltip:AddLine (Loc ["STRING_HEALING_FROM"]..":") --> localize-me
+ GameTooltip:AddLine (" ")
+
+ for index, tabela in _ipairs (habilidades) do
+ local nome, rank, icone = _GetSpellInfo (tabela[1])
+ if (index < 8) then
+ GameTooltip:AddDoubleLine (index..". |T"..icone..":0|t "..nome, _detalhes:comma_value (tabela[2]).." (".. _cstr ("%.1f", tabela[2]/total*100).."%)", 1, 1, 1, 1, 1, 1)
+ --GameTooltip:AddTexture (icone)
+ else
+ GameTooltip:AddDoubleLine (index..". "..nome, _detalhes:comma_value (tabela[2]).." (".. _cstr ("%.1f", tabela[2]/total*100).."%)", .65, .65, .65, .65, .65, .65)
+ end
+ end
+
+ return true
+ --GameTooltip:AddDoubleLine (minhas_curas[i][4][1]..": ", minhas_curas[i][2].." (".._cstr ("%.1f", minhas_curas[i][3]).."%)", 1, 1, 1, 1, 1, 1)
+
+end
+
+function atributo_heal:MontaDetalhes (spellid, barra)
+ --> bifurgações
+ if (info.sub_atributo == 1 or info.sub_atributo == 2 or info.sub_atributo == 3) then
+ return self:MontaDetalhesHealingDone (spellid, barra)
+ elseif (info.sub_atributo == 4) then
+ atributo_heal:MontaDetalhesHealingTaken (spellid, barra)
+ end
+end
+
+function atributo_heal:MontaDetalhesHealingTaken (nome, barra)
+
+ for _, barra in _ipairs (info.barras3) do
+ barra:Hide()
+ end
+
+ local barras = info.barras3
+ local instancia = info.instancia
+
+ local tabela_do_combate = info.instancia.showing
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ local este_curandeiro = showing._ActorTable[showing._NameIndexTable[nome]]
+ local conteudo = este_curandeiro.spell_tables._ActorTable --> _pairs[] com os IDs das magias
+
+ local actor = info.jogador.nome
+
+ local total = este_curandeiro.targets._ActorTable [este_curandeiro.targets._NameIndexTable [actor]].total
+
+ local minhas_magias = {}
+
+ for spellid, tabela in _pairs (conteudo) do --> da foreach em cada spellid do container
+
+ --> preciso pegar os alvos que esta magia atingiu
+ local alvos = tabela.targets
+ local index = alvos._NameIndexTable[actor]
+
+ if (index) then --> esta magia deu dano no actor
+ local este_alvo = alvos._ActorTable[index] --> pega a classe_target
+ local spell_nome, rank, icone = _GetSpellInfo (spellid)
+ _table_insert (minhas_magias, {spellid, este_alvo.total, este_alvo.total/total*100, spell_nome, icone})
+ end
+
+ end
+
+ _table_sort (minhas_magias, function(a, b) return a[2] > b[2] end)
+
+ --local amt = #minhas_magias
+ --gump:JI_AtualizaContainerBarras (amt)
+
+ local max_ = minhas_magias[1][2] --> dano que a primeiro magia vez
+
+ local barra
+ for index, tabela in _ipairs (minhas_magias) do
+ barra = barras [index]
+
+ if (not barra) then --> se a barra não existir, criar ela então
+ barra = gump:CriaNovaBarraInfo3 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> isso aqui é a parte da seleção e desceleção
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[4]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ barra.icone:SetTexture (tabela[5])
+
+ barra:Show() --> mostra a barra
+
+ if (index == 15) then
+ break
+ end
+ end
+end
+
+function atributo_heal:MontaDetalhesHealingDone (spellid, barra)
+ --> localize-me
+
+ local esta_magia = self.spell_tables._ActorTable [spellid]
+ if (not esta_magia) then
+ return
+ end
+
+ --> icone direito superior
+ local nome, rank, icone = _GetSpellInfo (spellid)
+ local infospell = {nome, rank, icone}
+
+ info.spell_icone:SetTexture (infospell[3])
+
+ local total = self.total
+
+ local overheal = esta_magia.overheal
+ local meu_total = esta_magia.total + overheal
+
+ local meu_tempo
+ if (_detalhes.time_type == 1 or not self.grupo) then
+ meu_tempo = self:Tempo()
+ elseif (_detalhes.time_type == 2) then
+ meu_tempo = self:GetCombatTime()
+ end
+
+ --local total_hits = esta_magia.counter
+ local total_hits = esta_magia.n_amt+esta_magia.c_amt
+
+ local index = 1
+
+ local data = {}
+
+ if (esta_magia.total > 0) then
+
+ --> GERAL
+ local media = esta_magia.total/total_hits
+
+ local this_hps = nil
+ if (esta_magia.counter > esta_magia.c_amt) then
+ this_hps = Loc ["STRING_HPS"]..": ".._cstr ("%.1f", esta_magia.total/meu_tempo) --> localiza-me
+ else
+ this_hps = Loc ["STRING_HPS"]..": 0" --> localiza-me
+ end
+
+ gump:SetaDetalheInfoTexto ( index, 100, --> Localize-me
+ Loc ["STRING_GERAL"], --> localiza-me
+ Loc ["STRING_HEAL"]..": ".._detalhes:ToK (esta_magia.total), --> localiza-me
+ Loc ["STRING_PERCENTAGE"]..": ".._cstr ("%.1f", esta_magia.total/total*100) .. "%", --> localiza-me
+ Loc ["STRING_MEDIA"]..": ".._cstr ("%.1f", media), --> localiza-me
+ this_hps,
+ Loc ["STRING_HITS"]..": " .. total_hits) --> localiza-me
+
+ --> NORMAL
+ local normal_hits = esta_magia.n_amt
+ if (normal_hits > 0) then
+ local normal_curado = esta_magia.n_curado
+ local media_normal = normal_curado/normal_hits
+ local T = (meu_tempo*normal_curado)/esta_magia.total
+ local P = media/media_normal*100
+ T = P*T/100
+
+ data[#data+1] = {
+ esta_magia.n_amt,
+ normal_hits/total_hits*100,
+ --esta_magia.n_curado/esta_magia.total*100,
+ "Curas Normais", --> localiza-me
+ "Minimo: ".._detalhes:comma_value (esta_magia.n_min), --> localiza-me
+ "Maximo: ".._detalhes:comma_value (esta_magia.n_max), --> localiza-me
+ "Media: ".._cstr ("%.1f", media_normal), --> localiza-me
+ "HPS: ".._cstr ("%.1f", normal_curado/T), --> localiza-me
+ --normal_hits.. " / ".. _cstr ("%.1f", normal_hits/total_hits*100).."%"
+ --normal_hits.. " / ".. _cstr ("%.1f", esta_magia.n_curado/total*100).."%"
+ --esta_magia.n_curado.. " / " .. normal_hits .. " / ".. _cstr ("%.1f", esta_magia.n_curado/esta_magia.total*100).."%"
+ --esta_magia.n_curado.. " / " .. normal_hits .. " / ".. _cstr ("%.1f", normal_hits/total_hits*100).."%"
+ normal_hits .. " / ".. _cstr ("%.1f", normal_hits/total_hits*100).."%"
+ }
+ end
+
+ --> CRITICO
+ if (esta_magia.c_amt > 0) then
+ local media_critico = esta_magia.c_curado/esta_magia.c_amt
+ local T = (meu_tempo*esta_magia.c_curado)/esta_magia.total
+ local P = media/media_critico*100
+ T = P*T/100
+ local crit_dps = _cstr ("%.1f", esta_magia.c_curado/T)
+
+ data[#data+1] = {
+ esta_magia.c_amt,
+ esta_magia.c_amt/total_hits*100,
+ --esta_magia.c_curado/esta_magia.total*100,
+ "Curas Criticas", --> localiza-me
+ "Minimo: ".._detalhes:comma_value (esta_magia.c_min), --> localiza-me
+ "Maximo: ".._detalhes:comma_value (esta_magia.c_max), --> localiza-me
+ "Media: ".._cstr ("%.1f", media_critico), --> localiza-me
+ "HPS: ".._cstr ("%.1f", crit_dps), --> localiza-me
+ --esta_magia.c_amt.. " / ".._cstr ("%.1f", esta_magia.c_amt/total_hits*100).."%"
+ --esta_magia.c_amt.. " / ".._cstr ("%.1f", esta_magia.c_curado/total*100).."%"
+ --esta_magia.c_curado.. " / " .. esta_magia.c_amt .. " / ".._cstr ("%.1f", esta_magia.c_curado/esta_magia.total*100).."%"
+ --esta_magia.c_curado.. " / " .. esta_magia.c_amt .. " / ".._cstr ("%.1f", esta_magia.c_amt/total_hits*100).."%"
+ esta_magia.c_amt .. " / ".._cstr ("%.1f", esta_magia.c_amt/total_hits*100).."%"
+ }
+ end
+
+ end
+
+ _table_sort (data, function (a, b) return a[1] > b[1] end)
+
+ --> Aqui pode vir a cura absorvida
+
+ local absorbed = esta_magia.absorbed
+
+ if (absorbed > 0) then
+ local porcentagem_absorbed = absorbed/esta_magia.total*100
+ data[#data+1] = {
+ absorbed,
+ {["p"] = porcentagem_absorbed, ["c"] = {117/255, 58/255, 0/255}},
+ "Cura Absorvida", --> localiza-me
+ "", --esta_magia.glacing.curado
+ "",
+ "",
+ "",
+ absorbed.." / ".._cstr ("%.1f", porcentagem_absorbed).."%"
+ }
+ end
+
+ for i = #data+1, 3 do --> para o overheal aparecer na ultima barra
+ data[i] = nil
+ end
+
+ --> overhealing
+
+ if (overheal > 0) then
+ local porcentagem_overheal = overheal/meu_total*100
+ data[4] = {
+ overheal,
+ {["p"] = porcentagem_overheal, ["c"] = {0.5, 0.1, 0.1}},
+ "Sobrecura", --> localiza-me
+ "",
+ "",
+ "",
+ "",
+ _detalhes:comma_value (overheal).." / ".._cstr ("%.1f", porcentagem_overheal).."%"
+ }
+ end
+
+ for index = 1, 4 do
+ local tabela = data[index]
+ if (not tabela) then
+ gump:HidaDetalheInfo (index+1)
+ else
+ gump:SetaDetalheInfoTexto (index+1, tabela[2], tabela[3], tabela[4], tabela[5], tabela[6], tabela[7], tabela[8])
+ end
+ end
+
+ --for i = #data+2, 5 do
+ -- gump:HidaDetalheInfo (i)
+ --end
+
+end
+
+--if (esta_magia.counter == esta_magia.c_amt) then --> só teve critico
+-- gump:SetaDetalheInfoTexto (1, nil, nil, nil, nil, nil, "DPS: "..crit_dps)
+--end
+
+--controla se o dps do jogador esta travado ou destravado
+function atributo_heal:Iniciar (iniciar)
+ if (iniciar == nil) then
+ return self.iniciar_hps --retorna se o dps esta aberto ou fechado para este jogador
+ elseif (iniciar) then
+ self.iniciar_hps = true
+ self:RegistrarNaTimeMachine() --coloca ele da timeMachine
+ if (self.shadow) then
+ self.shadow.iniciar_hps = true --> isso foi posto recentemente
+ self.shadow:RegistrarNaTimeMachine()
+ end
+ else
+ self.iniciar_hps = false
+ self:DesregistrarNaTimeMachine() --retira ele da timeMachine
+ if (self.shadow) then
+ self.shadow:DesregistrarNaTimeMachine()
+ self.shadow.iniciar_hps = false --> isso foi posto recentemente
+ end
+ end
+end
+
+function atributo_heal:ColetarLixo()
+ return _detalhes:ColetarLixo (class_type)
+end
+
+function _detalhes.refresh:r_atributo_heal (este_jogador, shadow)
+ _setmetatable (este_jogador, atributo_heal)
+ este_jogador.__index = atributo_heal
+
+ if (shadow ~= -1) then
+ este_jogador.shadow = shadow
+ _detalhes.refresh:r_container_combatentes (este_jogador.targets, shadow.targets)
+ _detalhes.refresh:r_container_habilidades (este_jogador.spell_tables, shadow.spell_tables)
+ else
+ _detalhes.refresh:r_container_combatentes (este_jogador.targets, -1)
+ _detalhes.refresh:r_container_habilidades (este_jogador.spell_tables, -1)
+ end
+end
+
+function _detalhes.clear:c_atributo_heal (este_jogador)
+ este_jogador.__index = {}
+ este_jogador.shadow = nil
+ este_jogador.links = nil
+ este_jogador.minha_barra = nil
+
+ _detalhes.clear:c_container_combatentes (este_jogador.targets)
+ _detalhes.clear:c_container_habilidades (este_jogador.spell_tables)
+end
+
+atributo_heal.__add = function (shadow, tabela2)
+
+ --> tempo decorrido
+ local tempo = (tabela2.end_time or time()) - tabela2.start_time
+ shadow.start_time = shadow.start_time - tempo
+
+ shadow.total = shadow.total - tabela2.total
+ _detalhes.tabela_overall.totals[2] = _detalhes.tabela_overall.totals[2] + tabela2.total
+
+ if (tabela2.grupo) then
+ _detalhes.tabela_overall.totals_grupo[2] = _detalhes.tabela_overall.totals_grupo[2] + tabela2.total
+ end
+
+ shadow.totalover = shadow.totalover - tabela2.totalover
+
+ shadow.total_without_pet = shadow.total_without_pet - tabela2.total_without_pet
+ shadow.totalover_without_pet = shadow.totalover_without_pet - tabela2.totalover_without_pet
+
+ shadow.healing_taken = shadow.healing_taken - tabela2.healing_taken
+
+ --> copia o healing_from
+ for nome, _ in _pairs (tabela2.healing_from) do
+ shadow.healing_from [nome] = true
+ end
+
+ --> copiar o heal_enemy
+ if (tabela2.heal_enemy) then
+ for spellid, amount in _pairs (tabela2.heal_enemy) do
+ if (shadow.heal_enemy [spellid]) then
+ shadow.heal_enemy [spellid] = shadow.heal_enemy [spellid] + amount
+ else
+ shadow.heal_enemy [spellid] = amount
+ end
+ end
+ end
+
+ --> copia o container de alvos
+ for index, alvo in _ipairs (tabela2.targets._ActorTable) do
+ local alvo_shadow = shadow.targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ alvo_shadow.overheal = alvo_shadow.overheal + alvo.overheal
+ alvo_shadow.absorbed = alvo_shadow.absorbed + alvo.absorbed
+ end
+
+ --> copia o container de habilidades
+ for spellid, habilidade in _pairs (tabela2.spell_tables._ActorTable) do
+ local habilidade_shadow = shadow.spell_tables:PegaHabilidade (spellid, true, nil, true)
+
+ for index, alvo in _ipairs (habilidade.targets._ActorTable) do
+ local alvo_shadow = habilidade_shadow.targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ alvo_shadow.overheal = alvo_shadow.overheal + alvo.overheal
+ alvo_shadow.absorbed = alvo_shadow.absorbed + alvo.absorbed
+ end
+
+ for key, value in _pairs (habilidade) do
+ if (_type (value) == "number") then
+ if (key ~= "id") then
+ if (not habilidade_shadow [key]) then
+ habilidade_shadow [key] = 0
+ end
+ habilidade_shadow [key] = habilidade_shadow [key] + value
+ end
+ end
+ end
+ end
+
+ return shadow
+end
+
+atributo_heal.__sub = function (tabela1, tabela2)
+ tabela1.total = tabela1.total - tabela2.total
+ tabela1.totalover = tabela1.totalover - tabela2.totalover
+
+ tabela1.total_without_pet = tabela1.total_without_pet - tabela2.total_without_pet
+ tabela1.totalover_without_pet = tabela1.totalover_without_pet - tabela2.totalover_without_pet
+
+ tabela1.healing_taken = tabela1.healing_taken - tabela2.healing_taken
+
+ return tabela1
+end
diff --git a/classes/classe_heal_habilidade.lua b/classes/classe_heal_habilidade.lua
new file mode 100644
index 00000000..8c2d5243
--- /dev/null
+++ b/classes/classe_heal_habilidade.lua
@@ -0,0 +1,154 @@
+--[[ classe do dano aplicado, usado nos eventos:
+- SPELL_HEAL
+- SPELL_PERIODIC_HEAL
+Parents:
+ addon -> combate atual -> Npc/Player Swicth -> Container de Habilidades -> esta tabela
+ ]]
+
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local habilidade_cura = _detalhes.habilidade_cura
+local container_combatentes = _detalhes.container_combatentes
+local container_heal_target = _detalhes.container_type.CONTAINER_HEALTARGET_CLASS
+
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+
+--lua locals
+local _setmetatable = setmetatable
+--api locals
+
+function habilidade_cura:NovaTabela (id, link) --aqui eu não sei que parâmetros passar
+
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, habilidade_cura)
+
+ esta_tabela.CriadaEm = time()
+ esta_tabela.quem_sou = "classe_heal_habilidade"
+
+ -- esta_tabela.jogador = serial
+
+ esta_tabela.total = 0 --total de dano aplicado por esta habilidade
+ esta_tabela.counter = 0 --conta quantas vezes a habilidade foi chamada
+ esta_tabela.id = id
+
+ --> normal hits
+
+ esta_tabela.n_min = 0
+ esta_tabela.n_max = 0
+ esta_tabela.n_amt = 0
+ esta_tabela.n_curado = 0
+
+ --> critical hits
+
+ esta_tabela.c_min = 0
+ esta_tabela.c_max = 0
+ esta_tabela.c_amt = 0
+ esta_tabela.c_curado = 0
+
+ esta_tabela.absorbed = 0
+ esta_tabela.overheal = 0
+
+ esta_tabela.targets = container_combatentes:NovoContainer (container_heal_target)
+ if (link) then
+ esta_tabela.targets.shadow = link.targets
+ end
+
+ return esta_tabela
+end
+
+function habilidade_cura:Add (serial, nome, flag, amount, who_nome, absorbed, critical, overhealing, is_shield)
+
+ self.counter = self.counter + 1
+
+ --local alvo = self.targets:PegarCombatente (serial, nome, flag, true)
+ local alvo = self.targets._NameIndexTable [nome]
+ if (not alvo) then
+ alvo = self.targets:PegarCombatente (serial, nome, flag, true)
+ else
+ alvo = self.targets._ActorTable [alvo]
+ end
+
+ if (absorbed and absorbed > 0) then
+ self.absorbed = self.absorbed + absorbed
+ alvo.absorbed = alvo.absorbed + absorbed
+ end
+
+ if (overhealing and overhealing > 0) then
+ self.overheal = self.overheal + overhealing
+ alvo.overheal = alvo.overheal + overhealing
+ end
+
+ if (amount and amount > 0) then
+
+ self.total = self.total + amount
+
+ alvo:AddQuantidade (amount)
+
+ if (critical) then
+ self.c_curado = self.c_curado+amount --> amount é o total de dano
+ self.c_amt = self.c_amt+1 --> amount é o total de dano
+ if (amount > self.c_max) then
+ self.c_max = amount
+ end
+ if (self.c_min > amount or self.c_min == 0) then
+ self.c_min = amount
+ end
+ else
+ self.n_curado = self.n_curado+amount
+ self.n_amt = self.n_amt+1
+ if (amount > self.n_max) then
+ self.n_max = amount
+ end
+ if (self.n_min > amount or self.n_min == 0) then
+ self.n_min = amount
+ end
+ end
+ else
+ alvo:AddQuantidade (0)
+ end
+
+ if (self.shadow) then
+ return self.shadow:Add (serial, nome, flag, amount, who_nome, absorbed, critical, overhealing)
+ end
+end
+
+function _detalhes.refresh:r_habilidade_cura (habilidade, shadow)
+ _setmetatable (habilidade, habilidade_cura)
+ habilidade.__index = habilidade_cura
+
+ if (shadow ~= -1) then
+ habilidade.shadow = shadow._ActorTable[habilidade.id]
+ _detalhes.refresh:r_container_combatentes (habilidade.targets, habilidade.shadow.targets)
+ else
+ _detalhes.refresh:r_container_combatentes (habilidade.targets, -1)
+ end
+end
+
+function _detalhes.clear:c_habilidade_cura (habilidade)
+ habilidade.__index = {}
+ habilidade.shadow = nil
+
+ _detalhes.clear:c_container_combatentes (habilidade.targets)
+end
+
+habilidade_cura.__sub = function (tabela1, tabela2)
+ tabela1.total = tabela1.total - tabela2.total
+ tabela1.counter = tabela1.counter - tabela2.counter
+
+ tabela1.n_min = tabela1.n_min - tabela2.n_min
+ tabela1.n_max = tabela1.n_max - tabela2.n_max
+ tabela1.n_amt = tabela1.n_amt - tabela2.n_amt
+ tabela1.n_curado = tabela1.n_curado - tabela2.n_curado
+
+ tabela1.c_min = tabela1.c_min - tabela2.c_min
+ tabela1.c_max = tabela1.c_max - tabela2.c_max
+ tabela1.c_amt = tabela1.c_amt - tabela2.c_amt
+ tabela1.c_curado = tabela1.c_curado - tabela2.c_curado
+
+ tabela1.absorbed = tabela1.absorbed - tabela2.absorbed
+ tabela1.overheal = tabela1.overheal - tabela2.overheal
+
+ return tabela1
+end
diff --git a/classes/classe_instancia.lua b/classes/classe_instancia.lua
new file mode 100644
index 00000000..6a7a826a
--- /dev/null
+++ b/classes/classe_instancia.lua
@@ -0,0 +1,1747 @@
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ( "Details" )
+local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0")
+
+local _type= type --> lua local
+local _ipairs = ipairs --> lua local
+local _pairs = pairs --> lua local
+local _math_floor = math.floor --> lua local
+local _math_abs = math.abs --> lua local
+local _table_remove = table.remove --> lua local
+local _getmetatable = getmetatable --> lua local
+local _setmetatable = setmetatable --> lua local
+local _string_len = string.len --> lua local
+local _unpack = unpack --> lua local
+local _cstr = string.format --> lua local
+local _SendChatMessage = SendChatMessage --> wow api locals
+local _GetChannelName = GetChannelName --> wow api locals
+local _UnitExists = UnitExists --> wow api locals
+local _UnitName = UnitName --> wow api locals
+local _UnitIsPlayer = UnitIsPlayer --> wow api locals
+
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local historico = _detalhes.historico
+
+local modo_raid = _detalhes._detalhes_props["MODO_RAID"]
+local modo_alone = _detalhes._detalhes_props["MODO_ALONE"]
+local modo_grupo = _detalhes._detalhes_props["MODO_GROUP"]
+local modo_all = _detalhes._detalhes_props["MODO_ALL"]
+
+local atributos = _detalhes.atributos
+local sub_atributos = _detalhes.sub_atributos
+local segmentos = _detalhes.segmentos
+
+--> STARTUP reativa as instancias e regenera as tabelas das mesmas
+ function _detalhes:ReativarInstancias()
+ _detalhes.opened_windows = 0
+ for index = #_detalhes.tabela_instancias, 1, -1 do
+ local instancia = _detalhes.tabela_instancias [index]
+ if (not _getmetatable (instancia)) then
+ _setmetatable (_detalhes.tabela_instancias[index], _detalhes)
+ end
+ if (instancia:IsAtiva()) then --> só reabre se ela estiver ativa
+ instancia:RestauraJanela (index)
+ if (not _detalhes.initializing) then
+ _detalhes:SendEvent ("DETAILS_INSTANCE_OPEN", _, instancia)
+ end
+ else
+ instancia.iniciada = false
+ end
+ end
+ --print ("Abertas: " .. _detalhes.opened_windows)
+ end
+
+------------------------------------------------------------------------------------------------------------------------
+
+--> chama a função para ser executada em todas as instâncias
+function _detalhes:InstanciaCallFunction (funcao, ...)
+ for index, instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (instancia:IsAtiva()) then --> só reabre se ela estiver ativa
+ funcao (_, instancia, ...) -- > ? seria isso?
+ end
+ end
+end
+
+--> chama a função para ser executada em todas as instâncias
+function _detalhes:InstanciaCallFunctionOffline (funcao, ...)
+ for index, instancia in _ipairs (_detalhes.tabela_instancias) do
+ funcao (_, instancia, ...)
+ end
+end
+
+function _detalhes:GetLowerInstanceNumber()
+ local lower = 999
+ for index, instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (instancia.ativa and instancia.baseframe) then
+ if (instancia.meu_id < lower) then
+ lower = instancia.meu_id
+ end
+ end
+ end
+ if (lower == 999) then
+ _detalhes.lower_instance = 0
+ return nil
+ else
+ _detalhes.lower_instance = lower
+ return lower
+ end
+end
+
+function _detalhes:GetMode()
+ return self.modo
+end
+
+function _detalhes:GetInstance (id)
+ return _detalhes.tabela_instancias [id]
+end
+
+function _detalhes:GetInstanceId()
+ return self.meu_id
+end
+
+function _detalhes:GetSegment()
+ return self.segmento
+end
+
+function _detalhes:GetSoloMode()
+ return _detalhes.tabela_instancias [_detalhes.solo]
+end
+function _detalhes:GetRaidMode()
+ return _detalhes.tabela_instancias [_detalhes.raid]
+end
+
+function _detalhes:IsSoloMode()
+ if (not _detalhes.solo) then
+ return false
+ else
+ return _detalhes.solo == self:GetInstanceId()
+ end
+end
+
+function _detalhes:IsRaidMode()
+ if (not _detalhes.raid) then
+ return false
+ else
+ return _detalhes.raid == self:GetInstanceId()
+ end
+end
+
+function _detalhes:IsNormalMode()
+ if (self:GetInstanceId() == 2 or self:GetInstanceId() == 3) then
+ return true
+ else
+ return false
+ end
+end
+
+------------------------------------------------------------------------------------------------------------------------
+
+--> retorna se a instância esta ou não ativa
+function _detalhes:IsAtiva()
+ return self.ativa
+end
+--> english alias
+function _detalhes:IsEnabled()
+ return self.ativa
+end
+
+
+------------------------------------------------------------------------------------------------------------------------
+
+--> desativando a instância ela fica em stand by e apenas hida a janela
+ function _detalhes:DesativarInstancia()
+
+ self.ativa = false
+ _detalhes:GetLowerInstanceNumber()
+
+ _detalhes.opened_windows = _detalhes.opened_windows-1
+ self:ResetaGump()
+ gump:Fade (self.baseframe.cabecalho.atributo_icon, _unpack (_detalhes.windows_fade_in))
+ gump:Fade (self.baseframe.cabecalho.ball, _unpack (_detalhes.windows_fade_in))
+ gump:Fade (self.baseframe, _unpack (_detalhes.windows_fade_in))
+ self:Desagrupar (-1)
+
+ if (self.modo == modo_raid) then
+ _detalhes.RaidTables:switch()
+ _detalhes.raid = nil
+
+ elseif (self.modo == modo_alone) then
+ _detalhes.SoloTables:switch()
+ self.atualizando = false
+ _detalhes.solo = nil
+ end
+
+ --print ("Abertas: " .. _detalhes.opened_windows)
+ if (not _detalhes.initializing) then
+ _detalhes:SendEvent ("DETAILS_INSTANCE_CLOSE", _, self)
+ end
+
+ end
+------------------------------------------------------------------------------------------------------------------------
+
+function _detalhes:InstanciaFadeBarras (instancia, segmento)
+ local _fadeType, _fadeSpeed = _unpack (_detalhes.row_fade_in)
+ if (segmento) then
+ if (instancia.segmento == segmento) then
+ return gump:Fade (instancia, _fadeType, _fadeSpeed, "barras")
+ end
+ else
+ return gump:Fade (instancia, _fadeType, _fadeSpeed, "barras")
+ end
+end
+
+--> oposto do desativar, ela apenas volta a mostrar a janela
+ function _detalhes:AtivarInstancia (temp)
+
+ self.ativa = true
+ _detalhes:GetLowerInstanceNumber()
+
+ if (not self.iniciada) then
+ self:RestauraJanela (self.meu_id)
+ else
+ _detalhes.opened_windows = _detalhes.opened_windows+1
+ end
+
+ _detalhes:TrocaTabela (self, nil, nil, nil, true)
+
+ --gump:Fade (self.baseframe.cabecalho.atributo_icon, _unpack (_detalhes.windows_fade_out))
+ --gump:Fade (self.baseframe.cabecalho.ball, _unpack (_detalhes.windows_fade_out))
+ --gump:Fade (self.baseframe, _unpack (_detalhes.windows_fade_out))
+
+ gump:Fade (self.baseframe.cabecalho.atributo_icon, 0)
+ gump:Fade (self.baseframe.cabecalho.ball, 0)
+ gump:Fade (self.baseframe, 0)
+
+ self.baseframe.cabecalho.fechar:Enable()
+
+ self:ChangeIcon()
+
+ if (not temp) then
+ if (self.modo == modo_raid) then
+ _detalhes:RaidMode (true, self)
+
+ elseif (self.modo == modo_alone) then
+ self:SoloMode (true)
+ end
+ end
+
+ if (not temp and not _detalhes.initializing) then
+ _detalhes:SendEvent ("DETAILS_INSTANCE_OPEN", nil, self)
+ end
+ end
+------------------------------------------------------------------------------------------------------------------------
+
+--> apaga de vez um instância
+ function _detalhes:ApagarInstancia (ID)
+ return _table_remove (_detalhes.tabela_instancias, ID)
+ end
+------------------------------------------------------------------------------------------------------------------------
+
+--> retorna quantas instância há no momento
+ function _detalhes:QuantasInstancias()
+ return #_detalhes.tabela_instancias
+ end
+------------------------------------------------------------------------------------------------------------------------
+
+--> cria uma nova instância e a joga para o container de instâncias
+ function _detalhes:CriarInstancia (_, id)
+
+ if (id and _type (id) == "boolean") then
+ local nova_instancia = _detalhes:NovaInstancia (#_detalhes.tabela_instancias+1)
+ _detalhes.tabela_instancias [#_detalhes.tabela_instancias+1] = nova_instancia
+ return nova_instancia
+ elseif (id) then
+ local instancia = _detalhes.tabela_instancias [id]
+ if (instancia and not instancia:IsAtiva()) then
+ instancia:AtivarInstancia()
+ return
+ end
+ end
+
+ --> antes de criar uma nova, ver se não há alguma para reativar
+ for index, instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (not instancia:IsAtiva()) then
+ instancia:AtivarInstancia()
+ return
+ end
+ end
+
+ local nova_instancia = _detalhes:NovaInstancia (#_detalhes.tabela_instancias+1)
+ _detalhes.tabela_instancias [#_detalhes.tabela_instancias+1] = nova_instancia
+
+ if (not _detalhes.initializing) then
+ _detalhes:SendEvent ("DETAILS_INSTANCE_OPEN", nil, nova_instancia)
+ end
+
+ _detalhes:GetLowerInstanceNumber()
+
+ return nova_instancia
+ end
+------------------------------------------------------------------------------------------------------------------------
+
+--> self é a instância que esta sendo movida.. instancia é a que esta parada
+function _detalhes:EstaAgrupada (esta_instancia, lado) --> lado //// 1 = encostou na esquerda // 2 = escostou emaixo // 3 = encostou na direita // 4 = encostou em cima
+ --local meu_snap = self.snap --> pegou a tabela com {side, side, side, side}
+
+ if (esta_instancia.snap [lado]) then
+ return true --> ha possui uma janela grudapa neste lado
+ elseif (lado == 1) then
+ if (self.snap [3]) then
+ return true
+ end
+ elseif (lado == 2) then
+ if (self.snap [4]) then
+ return true
+ end
+ elseif (lado == 3) then
+ if (self.snap [1]) then
+ return true
+ end
+ elseif (lado == 4) then
+ if (self.snap [2]) then
+ return true
+ end
+ end
+
+ return false --> do contrário retorna false
+end
+
+function _detalhes:BaseFrameSnap()
+
+ for meu_id, instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (instancia:IsAtiva()) then
+ instancia.baseframe:ClearAllPoints()
+ end
+ end
+
+ local my_baseframe = self.baseframe
+ for lado, snap_to in _pairs (self.snap) do
+ --print ("DEBUG instancia " .. snap_to .. " lado "..lado)
+ local instancia_alvo = _detalhes.tabela_instancias [snap_to]
+
+ if (lado == 1) then --> a esquerda
+ instancia_alvo.baseframe:SetPoint ("TOPRIGHT", my_baseframe, "TOPLEFT")
+ elseif (lado == 2) then --> em baixo
+ instancia_alvo.baseframe:SetPoint ("TOPLEFT", my_baseframe, "BOTTOMLEFT", 0, -34)
+ elseif (lado == 3) then --> a direita
+ instancia_alvo.baseframe:SetPoint ("BOTTOMLEFT", my_baseframe, "BOTTOMRIGHT")
+ elseif (lado == 4) then --> em cima
+ instancia_alvo.baseframe:SetPoint ("BOTTOMLEFT", my_baseframe, "TOPLEFT", 0, 34)
+ end
+ end
+
+ --[
+ --> aqui precisa de um efeito reverso
+ local reverso = self.meu_id - 2 --> se existir
+ if (reverso > 0) then --> se tiver uma instância lá trás
+ --> aqui faz o efeito reverso:
+ local inicio_retro = self.meu_id - 1
+ for meu_id = inicio_retro, 1, -1 do
+ local instancia = _detalhes.tabela_instancias [meu_id]
+ for lado, snap_to in _pairs (instancia.snap) do
+ if (snap_to < instancia.meu_id and snap_to ~= self.meu_id) then --> se o lado que esta grudado for menor que o meu id... EX instnacia #2 grudada na #1
+
+ --> então tenho que pegar a instância do snap
+
+ local instancia_alvo = _detalhes.tabela_instancias [snap_to]
+ local lado_reverso
+ if (lado == 1) then
+ lado_reverso = 3
+ elseif (lado == 2) then
+ lado_reverso = 4
+ elseif (lado == 3) then
+ lado_reverso = 1
+ elseif (lado == 4) then
+ lado_reverso = 2
+ end
+
+ --> fazer os setpoints
+ if (lado_reverso == 1) then --> a esquerda
+ instancia_alvo.baseframe:SetPoint ("BOTTOMLEFT", instancia.baseframe, "BOTTOMRIGHT")
+ elseif (lado_reverso == 2) then --> em baixo
+ instancia_alvo.baseframe:SetPoint ("BOTTOMLEFT", instancia.baseframe, "TOPLEFT", 0, 34)
+ elseif (lado_reverso == 3) then --> a direita
+ instancia_alvo.baseframe:SetPoint ("TOPRIGHT", instancia.baseframe, "TOPLEFT")
+ elseif (lado_reverso == 4) then --> em cima
+ instancia_alvo.baseframe:SetPoint ("TOPLEFT", instancia.baseframe, "BOTTOMLEFT", 0, -34)
+ end
+ end
+ end
+ end
+ end
+ --]]
+
+ for meu_id, instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (meu_id > self.meu_id) then
+ for lado, snap_to in _pairs (instancia.snap) do
+ if (snap_to > instancia.meu_id and snap_to ~= self.meu_id) then
+ local instancia_alvo = _detalhes.tabela_instancias [snap_to]
+
+ if (lado == 1) then --> a esquerda
+ instancia_alvo.baseframe:SetPoint ("TOPRIGHT", instancia.baseframe, "TOPLEFT")
+ elseif (lado == 2) then --> em baixo
+ instancia_alvo.baseframe:SetPoint ("TOPLEFT", instancia.baseframe, "BOTTOMLEFT", 0, -34)
+ elseif (lado == 3) then --> a direita
+ instancia_alvo.baseframe:SetPoint ("BOTTOMLEFT", instancia.baseframe, "BOTTOMRIGHT")
+ elseif (lado == 4) then --> em cima
+ instancia_alvo.baseframe:SetPoint ("BOTTOMLEFT", instancia.baseframe, "TOPLEFT", 0, 34)
+ end
+ end
+ end
+ end
+ end
+end
+
+function _detalhes:agrupar_janelas (lados)
+
+ local instancia = self
+
+ for lado, esta_instancia in _pairs (lados) do
+ if (esta_instancia) then
+ instancia.baseframe:ClearAllPoints()
+ esta_instancia = _detalhes.tabela_instancias [esta_instancia]
+
+ if (lado == 3) then --> direita
+ --> mover frame
+ instancia.baseframe:SetPoint ("TOPRIGHT", esta_instancia.baseframe, "TOPLEFT")
+ instancia.baseframe:SetPoint ("RIGHT", esta_instancia.baseframe, "LEFT")
+ instancia.baseframe:SetPoint ("BOTTOMRIGHT", esta_instancia.baseframe, "BOTTOMLEFT")
+
+ local _, height = esta_instancia:GetSize()
+ instancia:SetSize (nil, height)
+
+ --> salva o snap
+ self.snap [3] = esta_instancia.meu_id
+ esta_instancia.snap [1] = self.meu_id
+
+ elseif (lado == 4) then --> cima
+ --> mover frame
+ instancia.baseframe:SetPoint ("TOPLEFT", esta_instancia.baseframe, "BOTTOMLEFT", 0, -34)
+ instancia.baseframe:SetPoint ("TOP", esta_instancia.baseframe, "BOTTOM", 0, -34)
+ instancia.baseframe:SetPoint ("TOPRIGHT", esta_instancia.baseframe, "BOTTOMRIGHT", 0, -34)
+
+ local _, height = esta_instancia:GetSize()
+ instancia:SetSize (nil, height)
+
+ --> salva o snap
+ self.snap [4] = esta_instancia.meu_id
+ esta_instancia.snap [2] = self.meu_id
+
+ esta_instancia.baseframe.rodape.StatusBarLeftAnchor:SetPoint ("left", esta_instancia.baseframe.rodape.top_bg, "left", 25, 10)
+ esta_instancia.baseframe.rodape.StatusBarCenterAnchor:SetPoint ("center", esta_instancia.baseframe.rodape.top_bg, "center", 20, 10)
+ esta_instancia.baseframe.rodape.esquerdo:SetTexture ("Interface\\AddOns\\Details\\images\\bar_down_left_snap")
+ esta_instancia.baseframe.rodape.esquerdo.have_snap = true
+
+ elseif (lado == 1) then --> esquerda
+ --> mover frame
+ instancia.baseframe:SetPoint ("TOPLEFT", esta_instancia.baseframe, "TOPRIGHT")
+ instancia.baseframe:SetPoint ("LEFT", esta_instancia.baseframe, "RIGHT")
+ instancia.baseframe:SetPoint ("BOTTOMLEFT", esta_instancia.baseframe, "BOTTOMRIGHT")
+
+ local _, height = esta_instancia:GetSize()
+ instancia:SetSize (nil, height)
+
+ --> salva o snap
+ self.snap [1] = esta_instancia.meu_id
+ esta_instancia.snap [3] = self.meu_id
+
+ elseif (lado == 2) then --> baixo
+ --> mover frame
+ instancia.baseframe:SetPoint ("BOTTOMLEFT", esta_instancia.baseframe, "TOPLEFT", 0, 34)
+ instancia.baseframe:SetPoint ("BOTTOM", esta_instancia.baseframe, "TOP", 0, 34)
+ instancia.baseframe:SetPoint ("BOTTOMRIGHT", esta_instancia.baseframe, "TOPRIGHT", 0, 34)
+
+ local _, height = esta_instancia:GetSize()
+ instancia:SetSize (nil, height)
+
+ --> salva o snap
+ self.snap [2] = esta_instancia.meu_id
+ esta_instancia.snap [4] = self.meu_id
+
+ self.baseframe.rodape.StatusBarLeftAnchor:SetPoint ("left", self.baseframe.rodape.top_bg, "left", 25, 10)
+ self.baseframe.rodape.StatusBarCenterAnchor:SetPoint ("center", self.baseframe.rodape.top_bg, "center", 20, 10)
+ self.baseframe.rodape.esquerdo:SetTexture ("Interface\\AddOns\\Details\\images\\bar_down_left_snap")
+ self.baseframe.rodape.esquerdo.have_snap = true
+ end
+
+ if (not esta_instancia.ativa) then
+ esta_instancia:AtivarInstancia()
+ end
+
+ end
+ end
+
+ gump:Fade (instancia.botao_separar, 0)
+
+ if (_detalhes.tutorial.unlock_button < 4) then
+
+ _detalhes.temp_table1.IconSize = 32
+ _detalhes.temp_table1.TextHeightMod = -6
+ _detalhes.popup:ShowMe (instancia.botao_separar, "tooltip", "Interface\\Buttons\\LockButton-Unlocked-Up", Loc ["STRING_UNLOCK"], 150, _detalhes.temp_table1)
+
+ UIFrameFlash (instancia.botao_separar, .5, .5, 5, false, 0, 0)
+ _detalhes.tutorial.unlock_button = _detalhes.tutorial.unlock_button + 1
+ end
+
+end
+
+local function FixSnaps (instancia)
+ --_detalhes:DelayMsg ("DEBUG verificando snaps para instancia "..instancia.meu_id)
+ for snap, esta_instancia in _pairs (instancia.snap) do
+ if (esta_instancia) then
+ esta_instancia = _detalhes.tabela_instancias [esta_instancia]
+ --_detalhes:DelayMsg ("DEBUG janela "..instancia.meu_id.." com snap "..snap.. " em " .. esta_instancia.meu_id)
+ if (snap == 2) then
+ instancia.baseframe.rodape.StatusBarLeftAnchor:SetPoint ("left", instancia.baseframe.rodape.top_bg, "left", 25, 10)
+ instancia.baseframe.rodape.StatusBarCenterAnchor:SetPoint ("center", instancia.baseframe.rodape.top_bg, "center", 20, 10)
+ instancia.baseframe.rodape.esquerdo:SetTexture ("Interface\\AddOns\\Details\\images\\bar_down_left_snap")
+ instancia.baseframe.rodape.esquerdo.have_snap = true
+ end
+ end
+ end
+end
+
+
+function _detalhes:Desagrupar (instancia, lado)
+
+ if (self.meu_id) then --> significa que self é uma instancia
+ lado = instancia
+ instancia = self
+ end
+
+ if (_type (instancia) == "number") then --> significa que passou o número da instância
+ instancia = _detalhes.tabela_instancias [instancia]
+ end
+
+ if (not lado) then
+ --print ("DEBUG: Desagrupar esta sem lado")
+ return
+ end
+
+ if (lado < 0) then --> clicou no botão para desagrupar tudo
+ local ID = instancia.meu_id
+
+ for id, esta_instancia in _ipairs (_detalhes.tabela_instancias) do
+ for index, iid in _pairs (esta_instancia.snap) do -- index = 1 left , 3 right, 2 bottom, 4 top
+ if (iid and (iid == ID or id == ID)) then -- iid = instancia.meu_id
+
+ esta_instancia.snap [index] = nil
+
+ if (instancia.verticalSnap or esta_instancia.verticalSnap) then
+ if (not esta_instancia.snap [2] and not esta_instancia.snap [4]) then
+ esta_instancia.verticalSnap = false
+ esta_instancia.horizontalSnap = false
+ end
+ elseif (instancia.horizontalSnap or esta_instancia.horizontalSnap) then
+ if (not esta_instancia.snap [1] and not esta_instancia.snap [3]) then
+ esta_instancia.horizontalSnap = false
+ esta_instancia.verticalSnap = false
+ end
+ end
+
+ if (index == 2) then -- index é o codigo do snap
+ esta_instancia.baseframe.rodape.StatusBarLeftAnchor:SetPoint ("left", esta_instancia.baseframe.rodape.top_bg, "left", 5, 10)
+ esta_instancia.baseframe.rodape.StatusBarCenterAnchor:SetPoint ("center", esta_instancia.baseframe.rodape.top_bg, "center", 0, 10)
+ esta_instancia.baseframe.rodape.esquerdo:SetTexture ("Interface\\AddOns\\Details\\images\\bar_down_left")
+ esta_instancia.baseframe.rodape.esquerdo.have_snap = nil
+ end
+
+ end
+ end
+ end
+
+ gump:Fade (instancia.botao_separar, 1)
+ instancia.verticalSnap = false
+ instancia.horizontalSnap = false
+ return
+ end
+
+ local esta_instancia = _detalhes.tabela_instancias [instancia.snap[lado]]
+
+ if (not esta_instancia) then
+ --print ("DEBUG: Erro, a instancia nao existe")
+ return
+ end
+
+ instancia.snap [lado] = nil
+
+ if (lado == 1) then
+ esta_instancia.snap [3] = nil
+ elseif (lado == 2) then
+ esta_instancia.snap [4] = nil
+ elseif (lado == 3) then
+ esta_instancia.snap [1] = nil
+ elseif (lado == 4) then
+ esta_instancia.snap [2] = nil
+ end
+
+ gump:Fade (instancia.botao_separar, 1)
+
+ if (instancia.iniciada) then
+ instancia:SaveMainWindowPosition()
+ instancia:RestoreMainWindowPosition()
+ end
+
+ if (esta_instancia.iniciada) then
+ esta_instancia:SaveMainWindowPosition()
+ esta_instancia:RestoreMainWindowPosition()
+ end
+
+ --print ("DEBUG: Details: Instancias desagrupadas")
+
+ --_detalhes:RefreshAgrupamentos()
+
+end
+
+function _detalhes:SnapTextures (remove)
+ for id, esta_instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (esta_instancia:IsAtiva()) then
+ if (esta_instancia.baseframe.rodape.esquerdo.have_snap) then
+ if (remove) then
+ esta_instancia.baseframe.rodape.esquerdo:SetTexture ("Interface\\AddOns\\Details\\images\\bar_down_left")
+ else
+ esta_instancia.baseframe.rodape.esquerdo:SetTexture ("Interface\\AddOns\\Details\\images\\bar_down_left_snap")
+ end
+ end
+ end
+ end
+end
+
+--> cria uma janela para uma nova instância
+ function _detalhes:NovaInstancia (ID)
+
+ -- Uma nova instância será uma extensão do acetimer somada com uma cópia da classe detalhes_funções
+ local nova_instancia = {}
+ _setmetatable (nova_instancia, _detalhes)
+
+ nova_instancia.meu_id = ID
+
+ --meu_nome ficará aqui pois no futuro pode ser que ponha uma opção para monitorar um jogador específico
+ nova_instancia.meu_nome = UnitName ("player")
+
+ --> quantidade de habilidades que aparece no tooltip
+
+ nova_instancia.barras = {} --container que irá armazenar todas as barras
+ nova_instancia.barraS = {nil, nil} --de x até x são as barras que estão sendo mostradas na tela
+ nova_instancia.rolagem = false --barra de rolagem não esta sendo mostrada
+
+ nova_instancia["barrasInfo"] = {
+ ["criadas"] = 0, --quantos frames de barras ja foram criados
+ ["mostrando"] = 0, --quantos jogadores que estão sendo mostrados agora
+ ["maximo"] = 50, --máximo de barras que pode ser criado
+ ["cabem"] = nil, --quantas barras cabem na janela
+ ["altura"] = 14,
+ ["fontSize"] = 10.5,
+ ["font"] = SharedMedia:Fetch ("font", "Arial Narrow"),
+ ["fontName"] = "Arial Narrow",
+ ["textura"] = _detalhes.default_texture,
+ ["textureName"] = _detalhes.default_texture_name,
+ ["textura_mouseover"] = "Interface\\FriendsFrame\\UI-FriendsList-Highlight",
+ ["animar"] = true,
+ ["fade"] = true,
+ ["espaco"] = {
+ ["esquerda"] = 3,
+ ["direita"] = -5,
+ ["entre"] = 1,
+ }
+ }
+
+ nova_instancia.largura_scroll = 26
+ nova_instancia.bar_mod = 0
+ nova_instancia.bgdisplay_loc = 0
+
+ nova_instancia.barrasInfo["alturaReal"] = nova_instancia.barrasInfo.altura+nova_instancia.barrasInfo.espaco.entre
+
+ nova_instancia.posicao = {
+ ["normal"] = {},
+ ["solo"] = {}
+ }
+
+ nova_instancia.tooltip = {
+ ["n_habilidades"] = 3,
+ ["n_inimigos"] = 3
+ }
+
+ nova_instancia.snap = {nil, nil, nil, nil}
+
+ --janela inicia no frame normal (group ou all)
+ nova_instancia.mostrando = "normal"
+ --menu consolidated
+ nova_instancia.consolidate = false
+ nova_instancia.icons = {true, true, true, true}
+
+ --cria a janela da instância
+ --local _janela, _header, _window, _slider, _footer = gump:CriaJanelaPrincipal (ID, nova_instancia, true) --gump:NovaJanelaPrincipal (ID, nova_instancia, true)
+ local _baseframe, _bgframe, _bgframe_display, _scrollframe = gump:CriaJanelaPrincipal (ID, nova_instancia, true)
+
+ nova_instancia.baseframe = _baseframe
+ nova_instancia.bgframe = _bgframe
+ nova_instancia.bgdisplay = _bgframe_display
+ nova_instancia.scroll = _scrollframe
+
+ --status bar
+ nova_instancia.StatusBar = {}
+ nova_instancia.StatusBar.left = nil
+ nova_instancia.StatusBar.center = nil
+ nova_instancia.StatusBar.right = nil
+ nova_instancia.StatusBar.options = {}
+
+ local clock = _detalhes.StatusBar:CreateStatusBarChildForInstance (nova_instancia, "DETAILS_STATUSBAR_PLUGIN_CLOCK")
+ _detalhes.StatusBar:SetCenterPlugin (nova_instancia, clock)
+
+ local segment = _detalhes.StatusBar:CreateStatusBarChildForInstance (nova_instancia, "DETAILS_STATUSBAR_PLUGIN_PSEGMENT")
+ _detalhes.StatusBar:SetLeftPlugin (nova_instancia, segment)
+
+ local dps = _detalhes.StatusBar:CreateStatusBarChildForInstance (nova_instancia, "DETAILS_STATUSBAR_PLUGIN_PDPS")
+ _detalhes.StatusBar:SetRightPlugin (nova_instancia, dps)
+ --
+
+ nova_instancia.color = {1, 1, 1, 1}
+ nova_instancia.wallpaper = {
+ enabled = false,
+ texture = nil,
+ anchor = "bottomright",
+ alpha = 0.5,
+ texcoord = {0, 1, 0, 1},
+ width = 0,
+ height = 0,
+ overlay = {1, 1, 1, 1}
+ }
+
+ --> salva a altura antiga
+ nova_instancia.alturaAntiga = _baseframe:GetHeight()
+
+ --atributo que será mostrado na criação do gump será o de dano:
+ nova_instancia.atributo = 1 --> dano
+ nova_instancia.sub_atributo = 1 --> damage done
+
+ nova_instancia.m2_last = {
+ [nova_instancia.atributo] = nova_instancia.sub_atributo
+ }
+
+ nova_instancia.segmento = -1 --> combate atual
+
+ -- atualiza tabela de historico e atributo
+ _detalhes:TrocaTabela (nova_instancia, 0, 1, 1)
+
+ nova_instancia:DefaultIcons (true, true, true, true)
+
+ --nova janela vem sempre com o modo grupo ativado
+ --nova_instancia.modo = _detalhes_props["MODO_GROUP"]
+ nova_instancia.modo = modo_grupo
+ nova_instancia.last_modo = modo_grupo
+ nova_instancia.LastModo = modo_grupo
+
+ --nova_instancia.janela.gump_cabecalho.Title:SetText (Loc [_detalhes._detalhes_props.modo_nome[nova_instancia.modo]]) --poe o nome do modo no gump
+ --_baseframe.rodape.segmento:SetText ("Segmento: Atual") --> localiza-me
+
+ --mostra o gump na tela
+ nova_instancia.iniciada = true
+
+ nova_instancia:SaveMainWindowPosition()
+ nova_instancia:ReajustaGump()
+
+ --> calcula quantas barras cabem na janela
+ nova_instancia.barrasInfo.cabem = _math_floor (nova_instancia.posicao[nova_instancia.mostrando].h / nova_instancia.barrasInfo.alturaReal)
+
+ nova_instancia:AtivarInstancia()
+
+ -- instância criada, hora de retorna-la a quem pediu
+ return nova_instancia
+ end
+------------------------------------------------------------------------------------------------------------------------
+
+--> ao reiniciar o addon esta função é rodada para recriar a janela da instância
+function _detalhes:RestauraJanela (index, temp)
+
+ --if (index ~= self.meu_id) then
+ --print ("DEBUG: Algo de errado, o index esta diferente do meu_id")
+ --end
+
+ local _baseframe, _bgframe, _bgframe_display, _scrollframe = gump:CriaJanelaPrincipal (self.meu_id, self)
+
+ self.baseframe = _baseframe
+ self.bgframe = _bgframe
+ self.bgdisplay = _bgframe_display
+ self.scroll = _scrollframe
+
+ --self.barrasInfo.textura = "Interface\\AddOns\\Details\\images\\bar44"
+ --self.barrasInfo.textura = "Interface\\AddOns\\Details\\images\\bar4"
+ --self.barrasInfo.textura = [[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]]
+ --self.barrasInfo.textura = "Interface\PaperDollInfoFrame\UI-Character-Skills-Bar"
+
+ self.barrasInfo.textura = self.barrasInfo.textura or _detalhes.default_texture
+ self.barrasInfo.textureName = self.barrasInfo.textureName or _detalhes.default_texture_name
+ self.barrasInfo.fontSize = self.barrasInfo.fontSize or 10.5
+ self.barrasInfo.font = self.barrasInfo.font or SharedMedia:Fetch ("font", "Arial Narrow")
+ self.barrasInfo.fontName = self.barrasInfo.fontName or "Arial Narrow"
+
+ _detalhes:TrocaTabela (self, self.segmento, self.atributo, self.sub_atributo, true) --> passando true no 5º valor para a função ignorar a checagem de valores iguais
+
+ --> resetando as cprops da instância:
+ self.rolagem = false
+ self.need_rolagem = false
+ _baseframe:EnableMouseWheel (false)
+
+ self.barras = {}
+ self.barraS = {nil, nil}
+ self.barrasInfo.cabem = nil
+
+ self.consolidate = self.consolidate or false
+ self.icons = self.icons or {true, true, true, true}
+
+ self.barrasInfo.mostrando = 0
+ self.barrasInfo.criadas = 0
+ self.barrasInfo.alturaReal = self.barrasInfo.altura+self.barrasInfo.espaco.entre
+
+ self.color = self.color or {1, 1, 1, 1}
+ self.wallpaper = self.wallpaper or {
+ enabled = false,
+ texture = nil,
+ anchor = "bottomright",
+ alpha = 0.5,
+ texcoord = {0, 1, 0, 1},
+ width = 0,
+ height = 0,
+ overlay = {1, 1, 1, 1}
+ }
+
+ if (self.wallpaper.enabled) then
+ self:InstanceWallpaper (true)
+ end
+
+ self:InstanceColor (self.color)
+
+ self.largura_scroll = 26
+ self.bar_mod = 0
+ self:EsconderScrollBar (true)
+
+ self.bgdisplay_loc = 0
+
+ self.snap = self.snap or {nil, nil, nil, nil}
+ FixSnaps (self)
+
+ ---> salva o tamanho antigo da janela
+ self.alturaAntiga = _baseframe:GetHeight()
+
+ -- status bar
+ self.StatusBar = {}
+ self.StatusBar.left = nil
+ self.StatusBar.center = nil
+ self.StatusBar.right = nil
+ self.StatusBar.options = self.StatusBarSaved.options
+
+ local clock = _detalhes.StatusBar:CreateStatusBarChildForInstance (self, self.StatusBarSaved.center or "DETAILS_STATUSBAR_PLUGIN_CLOCK")
+ _detalhes.StatusBar:SetCenterPlugin (self, clock)
+
+ local segment = _detalhes.StatusBar:CreateStatusBarChildForInstance (self, self.StatusBarSaved.left or "DETAILS_STATUSBAR_PLUGIN_PSEGMENT")
+ _detalhes.StatusBar:SetLeftPlugin (self, segment)
+
+ local dps = _detalhes.StatusBar:CreateStatusBarChildForInstance (self, self.StatusBarSaved.right or "DETAILS_STATUSBAR_PLUGIN_PDPS")
+ _detalhes.StatusBar:SetRightPlugin (self, dps)
+ --
+
+ if (not self.last_modo) then
+ self.last_modo = modo_all
+ end
+
+ self.barrasInfo.altura = self.barrasInfo.altura or 14
+ self.barrasInfo.alturaReal = self.barrasInfo.altura+self.barrasInfo.espaco.entre
+
+ self:DefaultIcons (true, true, true, true)
+
+ if (self.modo == modo_alone) then
+ if (_detalhes.solo and _detalhes.solo ~= self.meu_id) then --> proteção para ter apenas uma instância com a janela SOLO
+ self.modo = modo_grupo
+ self.mostrando = "normal"
+ else
+ self:SoloMode (true)
+ _detalhes.solo = self.meu_id
+ end
+ elseif (self.modo == modo_raid) then
+ _detalhes.raid = self.meu_id
+ else
+ self.mostrando = "normal"
+ end
+
+ self:RestoreMainWindowPosition()
+ self:ReajustaGump()
+ self:SaveMainWindowPosition()
+
+ self.iniciada = true
+ self:AtivarInstancia (temp)
+
+ end
+------------------------------------------------------------------------------------------------------------------------
+
+function _detalhes:RefreshBars (instance)
+ if (instance) then
+ self = instance
+ end
+ if (self.barras and self.barras[1]) then
+ for index, row in _ipairs (self.barras) do
+ row.textura:SetTexture (self.barrasInfo.textura)
+ row.texto_esquerdo:SetFont (self.barrasInfo.font or "GameFontHighlight", self.barrasInfo.fontSize or self.barrasInfo.altura*0.75)
+ row.texto_direita:SetFont (self.barrasInfo.font or "GameFontHighlight", self.barrasInfo.fontSize or self.barrasInfo.altura*0.75)
+ end
+ end
+end
+
+function _detalhes:GetSize()
+ return self.bgframe:GetWidth(), self.bgframe:GetHeight()
+end
+
+--> alias
+function _detalhes:SetSize (w, h)
+ return self:Resize (w, h)
+end
+
+function _detalhes:Resize (w, h)
+ if (w) then
+ self.baseframe:SetWidth (w)
+ end
+
+ if (h) then
+ self.baseframe:SetHeight (h)
+ end
+
+ self:SaveMainWindowPosition()
+
+ return true
+end
+
+------------------------------------------------------------------------------------------------------------------------
+
+function _detalhes:Freeze (instancia)
+
+ if (not instancia) then
+ instancia = self
+ end
+
+ if (not _detalhes.initializing) then
+ instancia:ResetaGump()
+ gump:Fade (instancia, "in", nil, "barras")
+ end
+
+ instancia.freeze_icon:Show()
+ instancia.freeze_texto:Show()
+
+ local width = instancia:GetSize()
+ instancia.freeze_texto:SetWidth (width-64)
+
+ instancia.freezed = true
+end
+
+function _detalhes:UnFreeze (instancia)
+
+ if (not instancia) then
+ instancia = self
+ end
+
+ instancia.freeze_icon:Hide()
+ instancia.freeze_texto:Hide()
+ instancia.freezed = false
+
+ if (not _detalhes.initializing) then
+ --instancia:RestoreMainWindowPosition()
+ instancia:ReajustaGump()
+ end
+end
+
+function _detalhes:AtualizaSegmentos (instancia)
+ if (instancia.iniciada) then
+ if (instancia.segmento == -1) then
+ --instancia.baseframe.rodape.segmento:SetText (segmentos.overall) --> localiza-me
+ instancia.showing = _detalhes.tabela_overall
+ elseif (instancia.segmento == 0) then
+ --instancia.baseframe.rodape.segmento:SetText (segmentos.current) --> localiza-me
+ instancia.showing = _detalhes.tabela_vigente
+ else
+ instancia.showing = _detalhes.tabela_historico.tabelas [instancia.segmento]
+ --instancia.baseframe.rodape.segmento:SetText (segmentos.past..instancia.segmento) --> localiza-me
+ end
+ end
+end
+
+function _detalhes:AtualizaSegmentos_AfterCombat (instancia, historico)
+
+ if (instancia.freezed) then
+ return --> se esta congelada não tem o que fazer
+ end
+
+ local segmento = instancia.segmento
+
+ local _fadeType, _fadeSpeed = _unpack (_detalhes.row_fade_in)
+
+ if (segmento == _detalhes.segments_amount) then --> significa que o index [5] passou a ser [6] com a entrada da nova tabela
+ instancia.showing = historico.tabelas [_detalhes.segments_amount] --> então ele volta a pegar o index [5] que antes era o index [4]
+
+ gump:Fade (instancia, _fadeType, _fadeSpeed, "barras")
+ instancia.showing[instancia.atributo].need_refresh = true
+ instancia.v_barras = true
+ instancia:ResetaGump()
+ instancia:AtualizaGumpPrincipal (true)
+
+ elseif (segmento < _detalhes.segments_amount and segmento > 0) then
+ instancia.showing = historico.tabelas [segmento]
+
+ gump:Fade (instancia, _fadeType, _fadeSpeed, "barras") --"in", nil
+ instancia.showing[instancia.atributo].need_refresh = true
+ instancia.v_barras = true
+ instancia:ResetaGump()
+ instancia:AtualizaGumpPrincipal (true)
+ end
+
+end
+
+function _detalhes:TrocaTabela (instancia, segmento, atributo, sub_atributo, iniciando_instancia, InstanceMode)
+
+ if (self and self.meu_id and not instancia) then --> self é uma instância
+ iniciando_instancia = sub_atributo
+ sub_atributo = atributo
+ atributo = segmento
+ segmento = instancia
+ instancia = self
+ end
+
+ if (_type (instancia) == "number") then
+ sub_atributo = atributo
+ atributo = segmento
+ segmento = instancia
+ instancia = self
+ end
+
+ --> não trocar de modo se tiver em combate e a janela no solo mode
+ --[[if (_detalhes.solo and _detalhes.solo == instancia.meu_id) then
+ if (UnitAffectingCombat ("player")) then
+ print (Loc ["STRING_SOLO_SWITCHINCOMBAT"])
+ return
+ end
+ end --]]
+
+ if (InstanceMode and InstanceMode ~= instancia:GetMode()) then
+ instancia:AlteraModo (instancia, InstanceMode)
+ end
+
+ local update_coolTip = false
+
+ if (segmento == -2) then --> clicou para mudar de segmento
+ segmento = instancia.segmento+1
+
+ if (segmento > _detalhes.segments_amount) then
+ segmento = -1
+ end
+ update_coolTip = true
+
+ elseif (segmento == -3) then --> clicou para mudar de atributo
+ segmento = instancia.segmento
+
+ atributo = instancia.atributo+1
+ if (atributo > atributos[0]) then
+ atributo = 1
+ end
+ update_coolTip = true
+
+ elseif (segmento == -4) then --> clicou para mudar de sub atributo
+ segmento = instancia.segmento
+
+ sub_atributo = instancia.sub_atributo+1
+ if (sub_atributo > atributos[instancia.atributo]) then
+ sub_atributo = 1
+ end
+ update_coolTip = true
+
+ end
+
+ --> pega os atributos desta instancia
+ local meu_segmento = instancia.segmento
+ local meu_atributo = instancia.atributo
+ local meu_sub_atributo = instancia.sub_atributo
+
+ --> verifica possiveis valores não passados
+ if (not segmento) then
+ segmento = instancia.segmento
+ end
+ if (not atributo) then
+ atributo = instancia.atributo
+ end
+ if (not sub_atributo) then
+ sub_atributo = instancia.sub_atributo
+ end
+
+ --print ("DEBUG: trocando para "..atributo.." "..sub_atributo)
+
+ --> já esta mostrando isso que esta pedindo
+ if (not iniciando_instancia and segmento == meu_segmento and atributo == meu_atributo and sub_atributo == meu_sub_atributo and not _detalhes.initializing) then
+ return
+ end
+
+ --> Muda o segmento caso necessário
+ if (segmento ~= meu_segmento or _detalhes.initializing or iniciando_instancia) then
+
+ --> na troca de segmento, conferir se a instancia esta frozen
+ if (instancia.freezed) then
+ if (not iniciando_instancia) then
+ instancia:UnFreeze()
+ else
+ instancia.freezed = false
+ end
+ end
+
+ instancia.segmento = segmento
+
+ if (segmento == -1) then --> overall
+ instancia.showing = _detalhes.tabela_overall
+ elseif (segmento == 0) then --> combate atual
+ instancia.showing = _detalhes.tabela_vigente
+ else --> alguma tabela do histórico
+ instancia.showing = _detalhes.tabela_historico.tabelas [segmento]
+ end
+
+ if (update_coolTip) then
+ _detalhes.popup:Select (1, segmento+2)
+ end
+
+ if (instancia.showing and instancia.showing.contra) then
+ --print ("DEBUG: contra", instancia.showing.contra)
+ end
+
+ _detalhes:SendEvent ("DETAILS_INSTANCE_CHANGESEGMENT", nil, instancia, segmento)
+
+ end
+
+ --> Muda o atributo caso necessário
+ --print ("DEBUG atributos", instancia, segmento, atributo, sub_atributo, iniciando_instancia)
+
+ if (atributo == 5) then
+ if (#_detalhes.custom < 1) then
+ atributo = 1
+ sub_atributo = 1
+ end
+ end
+
+ if (atributo ~= meu_atributo or _detalhes.initializing or iniciando_instancia or (instancia.modo == modo_alone or instancia.modo == modo_raid)) then
+
+ if (instancia.modo == modo_alone and not (_detalhes.initializing or iniciando_instancia)) then
+ if (_detalhes.SoloTables.Mode == #_detalhes.SoloTables.Plugins) then
+ _detalhes.popup:Select (1, 1)
+ else
+ if (_detalhes.PluginCount.SOLO > 0) then
+ _detalhes.popup:Select (1, _detalhes.SoloTables.Mode+1)
+ end
+ end
+ return _detalhes.SoloTables.switch (_, _, -1)
+
+ elseif ( (instancia.modo == modo_raid) and not (_detalhes.initializing or iniciando_instancia) ) then --> raid
+ if (_detalhes.RaidTables.Mode == #_detalhes.RaidTables.Plugins) then
+ _detalhes.popup:Select (1, 1)
+ else
+ if (_detalhes.PluginCount.RAID > 0) then
+ _detalhes.popup:Select (1, _detalhes.RaidTables.Mode+1)
+ end
+
+ end
+ return _detalhes.RaidTables.switch (_, _, -1)
+ end
+
+ instancia.m2_last [instancia.atributo] = instancia.sub_atributo --> salta o último sub-atributo do atributo que esta sendo mostrado na instÇancia
+ instancia.atributo = atributo
+
+ local last_sub_atributo = instancia.m2_last [atributo] --> isso aqui é invalido, pois sempre vai haver um sub atributo e nao precisa conferir se ele realmente existe.
+ if (not last_sub_atributo) then
+ last_sub_atributo = 1
+ end
+
+ instancia.sub_atributo = last_sub_atributo
+
+ --> troca icone
+ instancia:ChangeIcon()
+
+ if (update_coolTip) then
+ _detalhes.popup:Select (1, atributo)
+ _detalhes.popup:Select (2, instancia.sub_atributo, atributo)
+ end
+
+ _detalhes:SendEvent ("DETAILS_INSTANCE_CHANGEATTRIBUTE", nil, instancia, atributo, sub_atributo)
+
+ end
+
+ if (sub_atributo ~= meu_sub_atributo or _detalhes.initializing or iniciando_instancia) then
+ instancia.m2_last [instancia.atributo] = sub_atributo
+ instancia.sub_atributo = sub_atributo
+
+ if (instancia.atributo == 5) then --> custom
+ instancia:ChangeIcon()
+ end
+
+ _detalhes:SendEvent ("DETAILS_INSTANCE_CHANGEATTRIBUTE", nil, instancia, atributo, sub_atributo)
+ end
+
+ if (not instancia.showing) then
+ if (not iniciando_instancia) then
+ instancia:Freeze()
+ end
+ return
+ else
+ --> verificar relogio, precisaria dar refresh no plugin clock
+ end
+
+ instancia.v_barras = true
+
+ instancia.showing [atributo].need_refresh = true
+
+ if (not _detalhes.initializing and not iniciando_instancia) then
+ instancia:ResetaGump()
+ instancia:AtualizaGumpPrincipal (true)
+ end
+
+end
+
+function _detalhes:MontaRaidOption (instancia)
+ for index, _name_and_icon in _ipairs (_detalhes.RaidTables.Menu) do
+ GameCooltip:AddMenu (1, _detalhes.RaidTables.switch, index, nil, nil, _name_and_icon [1], _name_and_icon [2], true)
+ end
+ if (_detalhes.RaidTables.Mode) then
+ GameCooltip:SetLastSelected (1, _detalhes.RaidTables.Mode)
+ end
+ GameCooltip:SetColor (1, "black")
+end
+
+function _detalhes:MontaSoloOption (instancia)
+ for index, _name_and_icon in _ipairs (_detalhes.SoloTables.Menu) do
+ GameCooltip:AddMenu (1, _detalhes.SoloTables.switch, index, nil, nil, _name_and_icon [1], _name_and_icon [2], true)
+ end
+ if (_detalhes.SoloTables.Mode) then
+ GameCooltip:SetLastSelected (1, _detalhes.SoloTables.Mode)
+ end
+ GameCooltip:SetColor (1, "black")
+end
+
+function _detalhes:MontaAtributosOption (instancia, func)
+
+ func = func or instancia.TrocaTabela
+
+ local checked1 = instancia.atributo
+ local atributo_ativo = instancia.atributo --> pega o numero
+
+ local options
+ if (atributo_ativo == 5) then --> custom
+ options = {Loc ["STRING_CUSTOM_NEW"]}
+ for index, custom in _ipairs (_detalhes.custom) do
+ options [#options+1] = custom.name
+ end
+ else
+ options = sub_atributos [atributo_ativo].lista
+ end
+
+ local icones = {
+ "Interface\\AddOns\\Details\\images\\atributos_icones_damage",
+ "Interface\\AddOns\\Details\\images\\atributos_icones_heal",
+ "Interface\\AddOns\\Details\\images\\atributos_icones_energyze",
+ "Interface\\AddOns\\Details\\images\\atributos_icones_misc"
+ }
+
+ local CoolTip = _G.GameCooltip
+ local p = 0.125 --> 32/256
+
+ for i = 1, atributos[0] do --> [0] armazena quantos atributos existem
+ CoolTip:AddMenu (1, func, nil, i, nil, atributos.lista[i], _, true)
+ CoolTip:AddIcon ("Interface\\AddOns\\Details\\images\\atributos_icones", 1, 1, 20, 20, p*(i-1), p*(i), 0, 1)
+ local options = sub_atributos [i].lista
+ for o = 1, atributos [i] do
+ CoolTip:AddMenu (2, func, nil, i, o, options[o], _, true)
+ CoolTip:AddIcon (icones[i], 2, 1, 20, 20, p*(o-1), p*(o), 0, 1)
+ end
+ CoolTip:SetLastSelected (2, i, instancia.m2_last [i])
+ end
+
+ --> custom
+ CoolTip:AddMenu (1, func, nil, 5, nil, atributos.lista[5], _, true)
+ CoolTip:AddIcon ("Interface\\AddOns\\Details\\images\\atributos_icones", 1, 1, 20, 20, p*(5-1), p*(5), 0, 1)
+ CoolTip:AddMenu (2, _detalhes.OpenCustomWindow, nil, nil, nil, Loc ["STRING_CUSTOM_NEW"], "Interface\\PaperDollInfoFrame\\Character-Plus", true)
+
+ for index, custom in _ipairs (_detalhes.custom) do
+ CoolTip:AddMenu (2, func, nil, 5, index, custom.name, custom.icon, true)
+ end
+ CoolTip:SetLastSelected (2, 5, instancia.m2_last [5])
+
+
+ CoolTip:SetLastSelected (1, atributo_ativo)
+
+ return menu_principal, sub_menus
+end
+
+--> O Modo não vai afetar a tabela do SHOWING.
+-- o modo é apenas afetado na hora de mostrar o que na tabela
+
+function _detalhes:ChangeIcon (icon)
+
+ if (icon) then
+
+ self.baseframe.cabecalho.atributo_icon:SetTexture (icon)
+ self.baseframe.cabecalho.atributo_icon:SetTexCoord (5/64, 60/64, 3/64, 62/64)
+ self.baseframe.cabecalho.atributo_icon:SetWidth (19)
+ self.baseframe.cabecalho.atributo_icon:SetHeight (20)
+ self.baseframe.cabecalho.atributo_icon:SetPoint ("TOPRIGHT", self.baseframe.cabecalho.ball_point, "TOPRIGHT", -11, -6)
+
+ elseif (self.modo == modo_alone) then --> solo
+
+ --[[
+ self.baseframe.cabecalho.atributo_icon:SetTexture ("Interface\\AddOns\\Details\\images\\icon_mainwindow2")
+ self.baseframe.cabecalho.atributo_icon:SetTexCoord (32/256 * (1-1), 32/256 * 1, 0, 1) --> solo é o primeiro icone
+ self.baseframe.cabecalho.atributo_icon:SetPoint ("TOPRIGHT", self.baseframe.cabecalho.ball_point, "TOPRIGHT", -1, 1)
+ self.baseframe.cabecalho.atributo_icon:SetWidth (30)
+ self.baseframe.cabecalho.atributo_icon:SetHeight (30)
+ --]]
+ --print ("Icon Changed 1")
+
+ --_detalhes.SoloTables.Menu [INDEX] [2]
+
+ elseif (self.modo == modo_grupo or self.modo == modo_all) then --> grupo
+
+ if (self.atributo == 5) then
+ local icon = _detalhes.custom [self.sub_atributo].icon
+ self.baseframe.cabecalho.atributo_icon:SetTexture (icon)
+ self.baseframe.cabecalho.atributo_icon:SetTexCoord (5/64, 60/64, 3/64, 62/64)
+ self.baseframe.cabecalho.atributo_icon:SetWidth (20)
+ self.baseframe.cabecalho.atributo_icon:SetHeight (20)
+ self.baseframe.cabecalho.atributo_icon:SetPoint ("TOPRIGHT", self.baseframe.cabecalho.ball_point, "TOPRIGHT", -10, -5)
+ else
+ self.baseframe.cabecalho.atributo_icon:SetTexture ("Interface\\AddOns\\Details\\images\\icon_mainwindow")
+ self.baseframe.cabecalho.atributo_icon:SetTexCoord (32/256 * (self.atributo-1), 32/256 * self.atributo, 0, 1)
+ self.baseframe.cabecalho.atributo_icon:SetPoint ("TOPRIGHT", self.baseframe.cabecalho.ball_point, "TOPRIGHT", -1, 1)
+ self.baseframe.cabecalho.atributo_icon:SetWidth (30)
+ self.baseframe.cabecalho.atributo_icon:SetHeight (30)
+ end
+
+ elseif (self.modo == modo_raid) then --> raid
+ --[[
+ self.baseframe.cabecalho.atributo_icon:SetTexture ("Interface\\AddOns\\Details\\images\\icon_mainwindow2")
+ self.baseframe.cabecalho.atributo_icon:SetTexCoord (32/256 * (2-1), 32/256 * 2, 0, 1) --> solo é o primeiro icone
+ self.baseframe.cabecalho.atributo_icon:SetPoint ("TOPRIGHT", self.baseframe.cabecalho.ball_point, "TOPRIGHT", -1, 1)
+ self.baseframe.cabecalho.atributo_icon:SetWidth (30)
+ self.baseframe.cabecalho.atributo_icon:SetHeight (30)
+ --]]
+ end
+end
+
+function _detalhes:AlteraModo (instancia, qual)
+
+ if (_type (instancia) == "number") then
+ qual = instancia
+ instancia = self
+ end
+
+ local update_coolTip = false
+
+ if (qual == -2) then --clicou para mudar
+ local update_coolTip = true
+
+ if (instancia.modo == 1) then
+ qual = 2
+ elseif (instancia.modo == 2) then
+ qual = 3
+ elseif (instancia.modo == 3) then
+ qual = 4
+ elseif (instancia.modo == 4) then
+ qual = 1
+ end
+ end
+
+ --[[ if (_detalhes.solo and _detalhes.solo == instancia.meu_id) then --> não trocar de modo se tiver em combate e a janela no solo mode
+ if (UnitAffectingCombat ("player")) then
+ return
+ end
+ end --]]
+
+ if (instancia.showing) then
+ if (not instancia.atributo) then
+ instancia.atributo = 1
+ instancia.sub_atributo = 1
+ print ("Details found a internal probleam and fixed: 'instancia.atributo' were null, now is 1.")
+ end
+ if (not instancia.showing[instancia.atributo]) then
+ instancia.showing = _detalhes.tabela_vigente
+ print ("Details found a internal problem and fixed: container for instancia.showing were null, now is current combat.")
+ end
+ instancia.atributo = instancia.atributo or 1
+ instancia.showing[instancia.atributo].need_refresh = true
+ end
+
+ if (qual == modo_alone) then
+
+ instancia.LastModo = instancia.modo
+
+ if (instancia:IsRaidMode()) then
+ instancia:RaidMode (false, instancia)
+ end
+
+ --> verifica se ja tem alguma instancia desativada em solo e remove o solo dela
+ _detalhes:InstanciaCallFunctionOffline (_detalhes.InstanciaCheckForDisabledSolo)
+
+ instancia.modo = modo_alone
+ instancia:ChangeIcon()
+
+ instancia:SoloMode (true)
+ _detalhes:SendEvent ("DETAILS_INSTANCE_CHANGEMODE", nil, instancia, modo_alone)
+
+ elseif (qual == modo_raid) then
+
+ instancia.LastModo = instancia.modo
+
+ if (instancia:IsSoloMode()) then
+ instancia:SoloMode (false)
+ end
+
+ _detalhes:InstanciaCallFunctionOffline (_detalhes.InstanciaCheckForDisabledRaid)
+
+ instancia.modo = modo_raid
+ instancia:ChangeIcon()
+
+ _detalhes:RaidMode (true, instancia)
+ _detalhes:SendEvent ("DETAILS_INSTANCE_CHANGEMODE", nil, instancia, modo_raid)
+
+ elseif (qual == modo_grupo) then
+
+ instancia.LastModo = instancia.modo
+
+ if (instancia:IsSoloMode()) then
+ --instancia.modo = modo_grupo
+ instancia:SoloMode (false)
+ elseif (instancia:IsRaidMode()) then
+ instancia:RaidMode (false, instancia)
+ end
+
+ _detalhes:ResetaGump (instancia)
+ --gump:Fade (instancia, 1, nil, "barras")
+
+ instancia.modo = modo_grupo
+ instancia:ChangeIcon()
+
+ instancia:AtualizaGumpPrincipal (true)
+ instancia.last_modo = modo_grupo
+ _detalhes:SendEvent ("DETAILS_INSTANCE_CHANGEMODE", nil, instancia, modo_grupo)
+
+ elseif (qual == modo_all) then
+
+ instancia.LastModo = instancia.modo
+
+ if (instancia:IsSoloMode()) then
+ instancia.modo = modo_all
+ instancia:SoloMode (false)
+
+ elseif (instancia:IsRaidMode()) then
+ instancia:RaidMode (false, instancia)
+ end
+
+ instancia.modo = modo_all
+ instancia:ChangeIcon()
+
+ instancia:AtualizaGumpPrincipal (true)
+ instancia.last_modo = modo_all
+ _detalhes:SendEvent ("DETAILS_INSTANCE_CHANGEMODE", nil, instancia, modo_all)
+ end
+
+ _detalhes.popup:Select (1, qual)
+end
+
+
+--> Reportar o que esta na janela da instância
+function _detalhes:monta_relatorio (este_relatorio, custom)
+
+ if (custom) then
+ --> shrink
+ local report_lines = {}
+
+ for i = 1, _detalhes.report_lines+1, 1 do --#este_relatorio -- o +1 é pq ele conta o cabeçalho como uma linha
+ report_lines [#report_lines+1] = este_relatorio[i]
+ end
+
+ return self:envia_relatorio (report_lines, true)
+ end
+
+ local amt = _detalhes.report_lines
+
+ local report_lines = {}
+
+ if (self.atributo == 5) then --> custom
+ report_lines [#report_lines+1] = "Details! " .. Loc ["STRING_CUSTOM_REPORT"] .. " " .. self.customName
+ else
+ report_lines [#report_lines+1] = "Details! " .. Loc ["STRING_REPORT"] .. " " .. _detalhes.sub_atributos [self.atributo].lista [self.sub_atributo]
+ end
+
+ local barras = self.barras
+ local esta_barra
+
+ local is_current = _G ["Details_Report_CB_1"]:GetChecked()
+ local is_reverse = _G ["Details_Report_CB_2"]:GetChecked()
+
+ if (not is_reverse) then
+
+ if (not is_current) then
+ --> assumindo que self é sempre uma instância aqui.
+ local total, keyName, first
+ local atributo = self.atributo
+ local container = self.showing [atributo]._ActorTable
+
+ if (atributo == 1) then --> damage
+ total, keyName, first = _detalhes.atributo_damage:RefreshWindow (self, self.showing, true, true)
+ elseif (atributo == 2) then --> heal
+ total, keyName, first = _detalhes.atributo_heal:RefreshWindow (self, self.showing, true, true)
+ elseif (atributo == 3) then --> energy
+ total, keyName, first = _detalhes.atributo_energy:RefreshWindow (self, self.showing, true, true)
+ elseif (atributo == 4) then --> misc
+ if (self.sub_atributo == 5) then --> mortes
+ local mortes = self.showing.last_events_tables
+ local reportarMortes = {}
+ for index, morte in ipairs (mortes) do
+ reportarMortes [#reportarMortes+1] = {dead = morte [6], nome = morte [3]:gsub (("%-.*"), "")}
+ end
+ container = reportarMortes
+ keyName = "dead"
+ else
+ total, keyName, first = _detalhes.atributo_misc:RefreshWindow (self, self.showing, true, true)
+ end
+ elseif (atributo == 5) then --> custom
+ total, keyName, first = _detalhes.atributo_custom:RefreshWindow (self, self.showing, true, {key = "custom"})
+ total = self.showing.totals [self.customName]
+ atributo = _detalhes.custom [self.sub_atributo].attribute
+ container = self.showing [atributo]._ActorTable
+ end
+
+ for i = 1, amt do
+ local _thisActor = container [i]
+ if (_thisActor) then
+ local amount = _thisActor [keyName]
+ if (_type (amount) == "number" and amount > 0) then --1236
+ report_lines [#report_lines+1] = i..".".. _thisActor.nome.." ".. _detalhes:comma_value ( _math_floor (amount) ).." (".._cstr ("%.1f", amount/total*100).."%)"
+ elseif (_type (amount) == "string") then
+ report_lines [#report_lines+1] = i..".".. _thisActor.nome.." ".. amount
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+
+ else
+ for i = 1, amt do
+ local ROW = self.barras [i]
+ if (ROW) then
+ if (not ROW.hidden or ROW.fading_out) then --> a barra esta visivel na tela
+ report_lines [#report_lines+1] = ROW.texto_esquerdo:GetText().." ".. ROW.texto_direita:GetText()
+ else
+ break
+ end
+ else
+ break --> chegou a final, parar de pegar as linhas
+ end
+ end
+ end
+
+ else --> é reverso
+ report_lines[1] = report_lines[1].." (" .. Loc ["STRING_REPORTFRAME_REVERTED"] .. ")"
+
+ if (not is_current) then
+ --> assumindo que self é sempre uma instância aqui.
+ local total, keyName, first
+ local atributo = self.atributo
+
+ if (atributo == 1) then --> damage
+ total, keyName, first = _detalhes.atributo_damage:RefreshWindow (self, self.showing, true, true)
+ elseif (atributo == 2) then --> heal
+ total, keyName, first = _detalhes.atributo_heal:RefreshWindow (self, self.showing, true, true)
+ elseif (atributo == 3) then --> energy
+ total, keyName, first = _detalhes.atributo_energy:RefreshWindow (self, self.showing, true, true)
+ elseif (atributo == 4) then --> misc
+ total, keyName, first = _detalhes.atributo_misc:RefreshWindow (self, self.showing, true, true)
+ elseif (atributo == 5) then --> custom
+ total, keyName, first = _detalhes.atributo_custom:RefreshWindow (self, self.showing, true, {key = "custom"})
+ total = self.showing.totals [self.customName]
+ atributo = _detalhes.custom [self.sub_atributo].attribute
+ end
+
+ local container = self.showing [atributo]._ActorTable
+ local quantidade = 0
+
+ for i = #container, 1, -1 do
+ local _thisActor = container [i]
+ local amount = _thisActor [keyName]
+ if (amount > 0) then
+ report_lines [#report_lines+1] = i..".".. _thisActor.nome.." ".. _detalhes:comma_value ( _math_floor (amount) ).." (".._cstr ("%.1f", amount/total*100).."%)"
+ quantidade = quantidade + 1
+ if (quantidade == amt) then
+ break
+ end
+ end
+ end
+
+ else
+ local nova_tabela = {}
+
+ for i = 1, amt do
+ local ROW = self.barras [i]
+ if (ROW) then
+ if (not ROW.hidden or ROW.fading_out) then --> a barra esta visivel na tela
+ nova_tabela [#nova_tabela+1] = ROW.texto_esquerdo:GetText().." ".. ROW.texto_direita:GetText()
+ else
+ break
+ end
+ else
+ break
+ end
+ end
+
+ for i = #nova_tabela, 1, -1 do
+ report_lines [#report_lines+1] = nova_tabela[i]
+ end
+ end
+
+ end
+
+ return self:envia_relatorio (report_lines)
+
+end
+
+function _detalhes:envia_relatorio (linhas, custom)
+
+ local segmento = self.segmento
+ local luta = nil
+
+ if (not custom) then
+ if (segmento == -1) then --overall
+ luta = Loc ["STRING_REPORT_LAST"] .. " " .. #_detalhes.tabela_historico.tabelas .. " " .. Loc ["STRING_REPORT_FIGHTS"]
+ elseif (segmento == 0) then --current
+
+ if (_detalhes.tabela_vigente.is_boss) then
+ local encounterName = _detalhes.tabela_vigente.is_boss.name
+ if (encounterName) then
+ luta = _detalhes.segmentos.current .. " " .. Loc ["STRING_AGAINST"] .. " " .. encounterName
+ end
+ end
+
+ if (not luta) then
+ if (_detalhes.tabela_vigente.enemy) then
+ luta = _detalhes.segmentos.current .. " " .. Loc ["STRING_AGAINST"] .. " " .. _detalhes.tabela_vigente.enemy
+ end
+ end
+
+ if (not luta) then
+ luta = _detalhes.segmentos.current
+ end
+ else
+ if (segmento == 1) then
+
+ if (_detalhes.tabela_historico.tabelas[1].is_boss) then
+ local encounterName = _detalhes.tabela_historico.tabelas[1].is_boss.name
+ if (encounterName) then
+ luta = Loc ["STRING_REPORT_LASTFIGHT"] .. " " .. Loc ["STRING_AGAINST"] .. " " .. encounterName
+ end
+ end
+
+ if (not luta) then
+ if (_detalhes.tabela_historico.tabelas[1].enemy) then
+ luta = Loc ["STRING_REPORT_LASTFIGHT"] .. " " .. Loc ["STRING_AGAINST"] .. " " .. _detalhes.tabela_historico.tabelas[1].enemy
+ end
+ end
+
+ if (not luta) then
+ luta = Loc ["STRING_REPORT_LASTFIGHT"]
+ end
+
+ else
+
+ if (_detalhes.tabela_historico.tabelas[segmento].is_boss) then
+ local encounterName = _detalhes.tabela_historico.tabelas[segmento].is_boss.name
+ if (encounterName) then
+ luta = segmento .. " " .. Loc ["STRING_REPORT_PREVIOUSFIGHTS"] .. " " .. Loc ["STRING_AGAINST"] .. " " .. encounterName
+ end
+ end
+
+ if (not luta) then
+ if (_detalhes.tabela_historico.tabelas[segmento].enemy) then
+ luta = segmento .. " " .. Loc ["STRING_REPORT_PREVIOUSFIGHTS"] .. " " .. Loc ["STRING_AGAINST"] .. " " .. _detalhes.tabela_historico.tabelas[segmento].enemy
+ end
+ end
+
+ if (not luta) then
+ luta = segmento .. " " .. Loc ["STRING_REPORT_PREVIOUSFIGHTS"]
+ end
+ end
+ end
+
+ linhas[1] = linhas[1] .. ". " .. Loc ["STRING_REPORT_FIGHT"] .. ": " .. luta
+ end
+
+ local editbox = _detalhes.janela_report.editbox
+ if (editbox.focus) then --> não precionou enter antes de clicar no okey
+ local texto = _detalhes:trim (editbox:GetText())
+ if (_string_len (texto) > 0) then
+ _detalhes.report_to_who = texto
+ editbox:AddHistoryLine (texto)
+ editbox:SetText (texto)
+ else
+ _detalhes.report_to_who = ""
+ editbox:SetText ("")
+ end
+ editbox.perdeu_foco = true --> isso aqui pra quando estiver editando e clicar em outra caixa
+ editbox:ClearFocus()
+ end
+
+ local to_who = _detalhes.report_where
+ local channel = to_who:find ("|")
+
+ if (channel) then
+
+ channel = to_who:gsub ((".*|"), "")
+
+ for i = 1, #linhas do
+ _SendChatMessage (linhas[i], "CHANNEL", nil, _GetChannelName (channel))
+ end
+ return
+
+ elseif (to_who == "WHISPER") then --> whisper
+
+ local alvo = _detalhes.report_to_who
+
+ if (not alvo or alvo == "") then
+ print (Loc ["STRING_REPORT_INVALIDTARGET"])
+ return
+ end
+
+ for i = 1, #linhas do
+ _SendChatMessage (linhas[i], to_who, nil, alvo)
+ end
+ return
+
+ elseif (to_who == "WHISPER2") then --> whisper target
+ to_who = "WHISPER"
+
+ local alvo
+ if (_UnitExists ("target")) then
+ if (_UnitIsPlayer ("target")) then
+ alvo = _UnitName ("target")
+ else
+ print (Loc ["STRING_REPORT_INVALIDTARGET"])
+ return
+ end
+ else
+ print (Loc ["STRING_REPORT_INVALIDTARGET"])
+ return
+ end
+
+ for i = 1, #linhas do
+ _SendChatMessage (linhas[i], to_who, nil, alvo)
+ end
+
+ return
+ end
+
+ for i = 1, #linhas do
+ _SendChatMessage (linhas[i], to_who)
+ end
+
+end
diff --git a/classes/classe_others.lua b/classes/classe_others.lua
new file mode 100644
index 00000000..21d2f583
--- /dev/null
+++ b/classes/classe_others.lua
@@ -0,0 +1,1345 @@
+--lua locals
+local _cstr = string.format
+local _math_floor = math.floor
+local _table_sort = table.sort
+local _table_insert = table.insert
+local _table_size = table.getn
+local _setmetatable = setmetatable
+local _getmetatable = getmetatable
+local _ipairs = ipairs
+local _pairs = pairs
+local _rawget= rawget
+local _math_min = math.min
+local _math_max = math.max
+local _math_abs = math.abs
+local _bit_band = bit.band
+local _unpack = unpack
+local _type = type
+--api locals
+local _GetSpellInfo = _detalhes.getspellinfo
+local GameTooltip = GameTooltip
+
+local _detalhes = _G._detalhes
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local container_habilidades = _detalhes.container_habilidades
+local container_combatentes = _detalhes.container_combatentes
+local container_pets = _detalhes.container_pets
+local atributo_misc = _detalhes.atributo_misc
+local habilidade_misc = _detalhes.habilidade_misc
+
+--local container_damage_target = _detalhes.container_type.CONTAINER_DAMAGETARGET_CLASS
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+local container_misc = _detalhes.container_type.CONTAINER_MISC_CLASS
+local container_misc_target = _detalhes.container_type.CONTAINER_ENERGYTARGET_CLASS
+--local container_friendlyfire = _detalhes.container_type.CONTAINER_FRIENDLYFIRE
+
+--local modo_ALONE = _detalhes.modos.alone
+local modo_GROUP = _detalhes.modos.group
+local modo_ALL = _detalhes.modos.all
+
+local class_type = _detalhes.atributos.misc
+
+local DATA_TYPE_START = _detalhes._detalhes_props.DATA_TYPE_START
+local DATA_TYPE_END = _detalhes._detalhes_props.DATA_TYPE_END
+
+local DFLAG_player = _detalhes.flags.player
+local DFLAG_group = _detalhes.flags.in_group
+local DFLAG_player_group = _detalhes.flags.player_in_group
+
+local div_abre = _detalhes.divisores.abre
+local div_fecha = _detalhes.divisores.fecha
+local div_lugar = _detalhes.divisores.colocacao
+
+local info = _detalhes.janela_info
+local keyName
+
+function atributo_misc:NovaTabela (serial, nome, link)
+ local esta_tabela = {}
+ esta_tabela.quem_sou = "classe_misc" --> DEBUG deleta-me
+
+ --print ("CRIANDO NOVO OBJETO")
+
+ _setmetatable (esta_tabela, atributo_misc)
+
+ --> grava o tempo que a tabela foi criada para o garbage collector interno
+ esta_tabela.CriadaEm = time()
+ esta_tabela.last_event = 0
+ esta_tabela.tipo = class_type --> atributo 4 = misc
+
+ --esta_tabela.interrupt = 0 --> armazena quantos interrupt a pessoa deu
+
+ --[[
+ esta_tabela.cc_break = 0 --> armazena quantas quebras de CC
+ esta_tabela.ress = 0 --> armazena quantos pessoas ele reviveu
+ esta_tabela.dispelled = 0 --> armazena quantos dispells esta pessoa fez
+ esta_tabela.dispell = 0 --> armazena quantos dispell esta pessoa recebeu
+ esta_tabela.last_events_tables = 0 --> armazena quantas vezes essa oessia morreu
+ --]]
+
+ esta_tabela.pets = {} --> pets? okey pets
+
+ --container armazenará os seriais dos alvos que o player aplicou dano
+ --esta_tabela.targets = container_combatentes:NovoContainer (container_energy_target)
+
+ --container armazenará os IDs das habilidades usadas por este jogador
+ --esta_tabela.spell_tables = container_habilidades:NovoContainer (container_energy)
+
+ if (link) then
+ --esta_tabela.targets.shadow = link.targets
+ --esta_tabela.spell_tables.shadow = link.spell_tables
+ end
+
+ return esta_tabela
+end
+
+function _detalhes:ToolTipDead (instancia, morte, esta_barra)
+
+ local eventos = morte [1]
+ local hora_da_morte = morte [2]
+ local hp_max = morte [5]
+
+ local linhas = {}
+
+ local battleress = false
+
+ local GameCooltip = GameCooltip
+
+ GameCooltip:Reset()
+ GameCooltip:SetType ("tooltipbar")
+ GameCooltip:SetOwner (esta_barra)
+
+
+ for index, evento in _ipairs (eventos) do
+
+ local hp = _math_floor (evento[5]/hp_max*100)
+ if (hp > 100) then
+ hp = 100
+ end
+
+ if (evento [1]) then --> DANO
+ --print ("DANO|"..evento [4]-hora_da_morte.."|"..evento [2].."|"..evento [3]) --> {true, spellid, amount, _tempo}
+ local nome_magia, _, icone_magia = _GetSpellInfo (evento [2])
+
+ if (evento[3]) then
+ local amt_golpes = evento[7]
+ if (amt_golpes) then
+ amt_golpes = "(x"..amt_golpes..") "
+ else
+ amt_golpes = ""
+ end
+
+ --> [1] left text [2] right text [3] main 1 or sub 2 [...] color
+ GameCooltip:AddLine ("".._cstr ("%.1f", evento[4] - hora_da_morte) .."s "..amt_golpes..nome_magia.." ("..evento[6]..")", "-".._detalhes:ToK (evento[3]).." (".. hp .."%)", 1, "white", "white")
+ --> [1] icon [2] main 1 or sub 2 [3] left or right [4,5] width height [...] texcoord
+ GameCooltip:AddIcon (icone_magia)
+ --> [1] value [2] main 1 or sub 2 [...] color [4] glow
+ GameCooltip:AddStatusBar (hp, 1, "red", true)
+
+ elseif (not battleress) then --> battle ress
+ GameCooltip:AddLine ("+".._cstr ("%.1f", evento[4] - hora_da_morte) .."s "..nome_magia.." ("..evento[6]..")", "", 1, "white")
+ GameCooltip:AddIcon ("Interface\\Glues\\CharacterSelect\\Glues-AddOn-Icons", 1, 1, nil, nil, .75, 1, 0, 1)
+ GameCooltip:AddStatusBar (100, 1, "silver", false)
+ battleress = true
+
+ end
+ else
+ local nome_magia, _, icone_magia = _GetSpellInfo (evento [2])
+ GameCooltip:AddLine ("".._cstr ("%.1f", evento[4] - hora_da_morte) .."s "..nome_magia.." ("..evento[6]..")", "+".._detalhes:ToK (evento[3]).." (".. hp .."%)", 1, "white", "white")
+ GameCooltip:AddIcon (icone_magia, 1, 1)
+ GameCooltip:AddStatusBar (hp, 1, "green", true)
+ end
+ end
+
+ if (battleress) then
+ --_table_insert (linhas, 2, {{"Interface\\AddOns\\Details\\images\\small_icons", .75, 1, 0, 1}, morte [6] .. " Morreu", "-- -- -- ", 100, {75/255, 75/255, 75/255, 1}, {noglow = true}}) --> localize-me
+ GameCooltip:AddSpecial ("line", 2, nil, morte [6] .. " Morreu", "-- -- -- ", 1, "white")
+ GameCooltip:AddSpecial ("icon", 2, nil, "Interface\\AddOns\\Details\\images\\small_icons", 1, 1, nil, nil, .75, 1, 0, 1)
+ GameCooltip:AddSpecial ("statusbar", 2, nil, 100, 1, "darkgray", false)
+ else
+ GameCooltip:AddSpecial ("line", 1, nil, morte [6] .. " Morreu", "-- -- -- ", 1, "white")
+ GameCooltip:AddSpecial ("icon", 1, nil, "Interface\\AddOns\\Details\\images\\small_icons", 1, 1, nil, nil, .75, 1, 0, 1)
+ GameCooltip:AddSpecial ("statusbar", 1, nil, 100, 1, "darkgray", false)
+ --_table_insert (linhas, 1, {{, .75, 1, 0, 1}, , 100, {75/255, 75/255, 75/255, 1}, {noglow = true}}) --> localize-me
+ end
+
+ GameCooltip:SetOption ("StatusBarHeightMod", -6)
+ GameCooltip:SetOption ("FixedWidth", 300)
+ GameCooltip:SetOption ("TextSize", 9.5)
+ GameCooltip:ShowCooltip()
+
+ --_detalhes.popup:ShowMe (esta_barra, "tooltip_bars", linhas, 300, 16, 9) --> [1] ancora [2] tipo do painel [3] texto/linhas [4] largura [5] tamanho do icone e altura da barra [6] tamanho da fonte
+
+end
+
+local function RefreshBarraMorte (morte, barra, instancia)
+ atributo_misc:DeadAtualizarBarra (morte, morte.minha_barra, barra.colocacao, instancia)
+end
+
+function atributo_misc:ReportSingleDeadLine (morte, instancia)
+
+ local barra = instancia.barras [morte.minha_barra]
+
+ local reportar = {"Detalhes da morte de " .. morte [3] .. " " .. barra.texto_esquerdo:GetText()} --> localize-me
+ for i = 1, _detalhes.popup.NumLines, 1 do
+ local texto_left = _detalhes.popup.frame1.linhas[i].left_text:GetText()
+ local texto_right = _detalhes.popup.frame1.linhas[i].right_text:GetText()
+
+ if (texto_left and texto_right) then
+ texto_left = texto_left:gsub (("|T(.*)|t "), "")
+ reportar [#reportar+1] = ""..texto_left.." "..texto_right..""
+ end
+ end
+
+ return _detalhes:Reportar (reportar, {_no_current = true, _no_inverse = true, _custom = true})
+end
+
+function atributo_misc:DeadAtualizarBarra (morte, qual_barra, colocacao, instancia)
+
+ morte ["dead"] = true --> temporario (testes)
+ local esta_barra = instancia.barras[qual_barra] --> pega a referência da barra na janela
+
+ if (not esta_barra) then
+ print ("DEBUG: problema com "..qual_barra.." "..lugar)
+ return
+ end
+
+ local tabela_anterior = esta_barra.minha_tabela
+
+ esta_barra.minha_tabela = morte
+
+ morte.nome = morte [3] --> evita dar erro ao redimencionar a janela
+ morte.minha_barra = qual_barra
+ esta_barra.colocacao = colocacao
+
+ if (not _getmetatable (morte)) then
+ _setmetatable (morte, {__call = RefreshBarraMorte})
+ morte._custom = true
+ end
+
+ esta_barra.texto_esquerdo:SetText (colocacao .. ". " .. morte [3]:gsub (("%-.*"), ""))
+ esta_barra.texto_direita:SetText (morte [6])
+
+ esta_barra.statusbar:SetValue (100)
+ if (esta_barra.hidden or esta_barra.fading_in or esta_barra.faded) then
+ gump:Fade (esta_barra, "out")
+ end
+ esta_barra.textura:SetVertexColor (_unpack (_detalhes.class_colors [morte[4]]))
+ esta_barra.icone_classe:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+ esta_barra.icone_classe:SetTexCoord (_unpack (CLASS_ICON_TCOORDS [morte[4]]))
+
+ if (esta_barra.mouse_over and not instancia.baseframe.isMoving) then --> precisa atualizar o tooltip
+ gump:UpdateTooltip (qual_barra, esta_barra, instancia)
+ end
+
+ --return self:RefreshBarra2 (esta_barra, instancia, tabela_anterior, forcar, esta_porcentagem)
+end
+
+function atributo_misc:RefreshWindow (instancia, tabela_do_combate, forcar, exportar)
+
+ --print ("refresh misc...")
+
+ local total = 0 --> total iniciado como ZERO
+
+ local showing = tabela_do_combate [class_type] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ if (#showing._ActorTable < 1) then --> não há barras para mostrar
+ if (forcar) then
+ _detalhes:EsconderBarrasNaoUsadas (instancia, showing)
+ end
+ return
+ end
+
+ --print ("refresh misc... 2")
+
+ instancia.top = 0
+
+ local sub_atributo = instancia.sub_atributo --> o que esta sendo mostrado nesta instância
+ local conteudo = showing._ActorTable
+ local amount = #conteudo
+ local modo = instancia.modo
+
+ if (exportar) then
+ if (_type (exportar) == "boolean") then
+ if (sub_atributo == 1) then --> CC BREAKS
+ keyName = "cc_break"
+ elseif (sub_atributo == 2) then --> RESS
+ keyName = "ress"
+ elseif (sub_atributo == 3) then --> INTERRUPT
+ keyName = "interrupt"
+ elseif (sub_atributo == 4) then --> DISPELLS
+ keyName = "dispell"
+ elseif (sub_atributo == 5) then --> DEATHS
+ keyName = "dead"
+ end
+ else
+ keyName = exportar.key
+ modo = exportar.modo
+ end
+
+ elseif (instancia.atributo == 5) then --> custom
+ keyName = "custom"
+ total = tabela_do_combate.totals [instancia.customName]
+
+ else
+
+ --> pega qual a sub key que será usada
+ if (sub_atributo == 1) then --> CC BREAKS
+ keyName = "cc_break"
+ elseif (sub_atributo == 2) then --> RESS
+ keyName = "ress"
+ elseif (sub_atributo == 3) then --> INTERRUPT
+ keyName = "interrupt"
+ elseif (sub_atributo == 4) then --> DISPELLS
+ keyName = "dispell"
+ elseif (sub_atributo == 5) then --> DEATHS
+ keyName = "dead"
+ end
+
+ end
+
+ if (keyName == "dead") then
+ local mortes = tabela_do_combate.last_events_tables
+ --> não precisa reordenar, uma vez que sempre vai da na ordem do último a morrer até o primeiro
+ -- _table_sort (mortes, function (m1, m2) return m1[2] < m2[2] end) -- [1] = tabela com a morte [2] = tempo [3] = nome do jogador
+ instancia.top = 1
+ total = #mortes
+
+ if (exportar) then
+ return mortes
+ end
+
+ if (total < 1) then
+ instancia:EsconderScrollBar()
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+ end
+
+ --estra mostrando ALL então posso seguir o padrão correto? primeiro, atualiza a scroll bar...
+ instancia:AtualizarScrollBar (total)
+
+ --depois faz a atualização normal dele através dos iterators
+ local qual_barra = 1
+ local barras_container = instancia.barras
+
+ for i = instancia.barraS[1], instancia.barraS[2], 1 do --> vai atualizar só o range que esta sendo mostrado
+ atributo_misc:DeadAtualizarBarra (mortes[i], qual_barra, i, instancia)
+ --conteudo[i]:AtualizaBarra (instancia, barras_container, qual_barra, i, total, sub_atributo, forcar, keyName, true) --> instância, index, total, valor da 1º barra
+ qual_barra = qual_barra+1
+ end
+
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+
+ else
+
+ if (instancia.atributo == 5) then --> custom
+ --> faz o sort da categoria e retorna o amount corrigido
+ amount = _detalhes:ContainerSort (conteudo, amount, keyName)
+
+ --> grava o total
+ instancia.top = conteudo[1][keyName]
+
+ elseif (modo == modo_ALL) then --> mostrando ALL
+
+ --> faz o sort da categoria
+ _table_sort (conteudo, function (a, b)
+
+ if (a[keyName] and b[keyName]) then
+ return a[keyName] > b[keyName]
+ elseif (a[keyName] and not b[keyName]) then
+ return true
+ else
+ return false
+ end
+
+ end)
+
+ --> não mostrar resultados com zero
+ for i = amount, 1, -1 do --> de trás pra frente
+ if (not conteudo[i][keyName]) then
+ amount = amount-i
+ break
+ end
+ end
+
+ total = tabela_do_combate.totals [class_type] [keyName]
+
+ --> grava o total
+ instancia.top = conteudo[1][keyName]
+
+ elseif (modo == modo_GROUP) then --> mostrando GROUP
+
+ --> faz o sort da categoria
+ _table_sort (conteudo, function (a, b)
+
+ if (a.grupo and b.grupo) then
+ if (a[keyName] and b[keyName]) then
+ return a[keyName] > b[keyName]
+ elseif (a[keyName] and not b[keyName]) then
+ return true
+ else
+ return false
+ end
+ elseif (a.grupo and not b.grupo) then
+ return true
+ elseif (not a.grupo and b.grupo) then
+ return false
+ else
+ if (a[keyName] and b[keyName]) then
+ return a[keyName] > b[keyName]
+ elseif (a[keyName] and not b[keyName]) then
+ return true
+ else
+ return false
+ end
+ end
+ end)
+
+ for index, player in _ipairs (conteudo) do
+ if (_bit_band (player.flag, DFLAG_player_group) >= 0x101) then --> é um player e esta em grupo
+ if (not player[keyName] or player[keyName] < 1) then --> dano menor que 1, interromper o loop
+ amount = index - 1
+ break
+ elseif (index == 1) then --> esse IF aqui, precisa mesmo ser aqui? não daria pra pega-lo com uma chave [1] nad grupo == true?
+ instancia.top = conteudo[1][keyName]
+ end
+
+ total = total + player[keyName]
+ else
+ amount = index-1
+ break
+ end
+ end
+
+ end
+
+ end
+
+ --> refaz o mapa do container
+ showing:remapear()
+
+ if (exportar) then
+ return total, keyName, instancia.top
+ end
+
+ if (amount < 1) then --> não há barras para mostrar
+ instancia:EsconderScrollBar() --> precisaria esconder a scroll bar
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+ end
+
+ --estra mostrando ALL então posso seguir o padrão correto? primeiro, atualiza a scroll bar...
+ instancia:AtualizarScrollBar (amount)
+
+ --depois faz a atualização normal dele através dos iterators
+ local qual_barra = 1
+ local barras_container = instancia.barras
+
+ for i = instancia.barraS[1], instancia.barraS[2], 1 do --> vai atualizar só o range que esta sendo mostrado
+ conteudo[i]:AtualizaBarra (instancia, barras_container, qual_barra, i, total, sub_atributo, forcar, keyName) --> instância, index, total, valor da 1º barra
+ qual_barra = qual_barra+1
+ end
+
+ if (instancia.atributo == 5) then --> custom
+ --> zerar o .custom dos Actors
+ for index, player in _ipairs (conteudo) do
+ if (player.custom > 0) then
+ player.custom = 0
+ else
+ break
+ end
+ end
+ end
+
+ --> beta, hidar barras não usadas durante um refresh forçado
+ if (forcar) then
+ if (instancia.modo == 2) then --> group
+ for i = qual_barra, instancia.barrasInfo.cabem do
+ gump:Fade (instancia.barras [i], "in", 0.3)
+ end
+ end
+ end
+
+ return _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing) --> retorna a tabela que precisa ganhar o refresh
+
+end
+
+--self = esta classe de dano
+
+function atributo_misc:Custom (_customName, _combat, sub_atributo, spell, alvo)
+ local _Skill = self.spell_tables._ActorTable [tonumber (spell)]
+ if (_Skill) then
+ local spellName = _GetSpellInfo (tonumber (spell))
+ local SkillTargets = _Skill.targets._ActorTable
+
+ for _, TargetActor in _ipairs (SkillTargets) do
+ local TargetActorSelf = _combat (class_type, TargetActor.nome)
+ TargetActorSelf.custom = TargetActor.total + TargetActorSelf.custom
+ _combat.totals [_customName] = _combat.totals [_customName] + TargetActor.total
+ end
+ end
+end
+
+function atributo_misc:AtualizaBarra (instancia, barras_container, qual_barra, lugar, total, sub_atributo, forcar, keyName, is_dead)
+
+ --print (self.ress)
+
+ local esta_barra = instancia.barras[qual_barra] --> pega a referência da barra na janela
+
+ if (not esta_barra) then
+ print ("DEBUG: problema com "..qual_barra.." "..lugar)
+ return
+ end
+
+ local tabela_anterior = esta_barra.minha_tabela
+
+ esta_barra.minha_tabela = self
+ esta_barra.colocacao = lugar
+
+ self.minha_barra = esta_barra
+ self.colocacao = lugar
+
+ local meu_total = self [keyName] --> total de dano que este jogador deu
+ if (not meu_total) then
+ return
+ end
+ local porcentagem = meu_total / total * 100
+ local esta_porcentagem = _math_floor ((meu_total/instancia.top) * 100)
+
+ esta_barra.texto_direita:SetText (meu_total .." ".. div_abre .. _cstr ("%.1f", porcentagem).."%" .. div_fecha) --seta o texto da direita
+
+ if (esta_barra.mouse_over and not instancia.baseframe.isMoving) then --> precisa atualizar o tooltip
+ gump:UpdateTooltip (qual_barra, esta_barra, instancia)
+ end
+
+ return self:RefreshBarra2 (esta_barra, instancia, tabela_anterior, forcar, esta_porcentagem, qual_barra, barras_container)
+end
+
+
+
+--------------------------------------------- // TOOLTIPS // ---------------------------------------------
+
+
+---------> TOOLTIPS BIFURCAÇÃO
+function atributo_misc:ToolTip (instancia, numero, barra)
+ --> seria possivel aqui colocar o icone da classe dele?
+ GameTooltip:ClearLines()
+ GameTooltip:AddLine (barra.colocacao..". "..self.nome)
+
+ if (instancia.sub_atributo == 3) then --> interrupt
+ return self:ToolTipInterrupt (instancia, numero, barra)
+ elseif (instancia.sub_atributo == 1) then --> cc_break
+ return self:ToolTipCC (instancia, numero, barra)
+ elseif (instancia.sub_atributo == 2) then --> ress
+ return self:ToolTipRess (instancia, numero, barra)
+ elseif (instancia.sub_atributo == 4) then --> dispell
+ return self:ToolTipDispell (instancia, numero, barra)
+ elseif (instancia.sub_atributo == 5) then --> mortes
+ return self:ToolTipDead (instancia, numero, barra)
+ end
+end
+
+function atributo_misc:ToolTipDead (instancia, numero, barra)
+
+ local last_dead = self.dead_log [#self.dead_log]
+
+
+
+end
+
+function atributo_misc:ToolTipCC (instancia, numero, barra)
+
+ local meu_total = self ["cc_break"]
+ local habilidades = self.cc_break_spell_tables._ActorTable
+
+--> habilidade usada para dispelar
+ local meus_cc_breaks = {}
+ for _spellid, _tabela in _pairs (habilidades) do
+ meus_cc_breaks [#meus_cc_breaks+1] = {_spellid, _tabela.cc_break}
+ end
+ _table_sort (meus_cc_breaks, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"]..":")
+ if (#meus_cc_breaks > 0) then
+ for i = 1, _math_min (3, #meus_cc_breaks) do
+ local esta_habilidade = meus_cc_breaks[i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (esta_habilidade[1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", esta_habilidade[2].." (".._cstr("%.1f", esta_habilidade[2]/meu_total*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ else
+ GameTooltip:AddLine (Loc ["STRING_NO_SPELL"])
+ end
+
+--> quais habilidades foram dispaladas
+ local buffs_dispelados = {}
+ for _spellid, amt in _pairs (self.cc_break_oque) do
+ buffs_dispelados [#buffs_dispelados+1] = {_spellid, amt}
+ end
+ _table_sort (buffs_dispelados, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (Loc ["STRING_CCBROKE"] .. ":")
+ if (#buffs_dispelados > 0) then
+ for i = 1, _math_min (3, #buffs_dispelados) do
+ local esta_habilidade = buffs_dispelados[i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (esta_habilidade[1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", esta_habilidade[2].." (".._cstr("%.1f", esta_habilidade[2]/meu_total*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ end
+
+ return true
+end
+
+function atributo_misc:ToolTipDispell (instancia, numero, barra)
+
+ local meu_total = self ["dispell"]
+ local habilidades = self.dispell_spell_tables._ActorTable
+
+--> habilidade usada para dispelar
+ local meus_dispells = {}
+ for _spellid, _tabela in _pairs (habilidades) do
+ meus_dispells [#meus_dispells+1] = {_spellid, _tabela.dispell}
+ end
+ _table_sort (meus_dispells, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"]..":")
+ if (#meus_dispells > 0) then
+ for i = 1, _math_min (3, #meus_dispells) do
+ local esta_habilidade = meus_dispells[i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (esta_habilidade[1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", esta_habilidade[2].." (".._cstr("%.1f", esta_habilidade[2]/meu_total*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ else
+ GameTooltip:AddLine (Loc ["STRING_NO_SPELL"])
+ end
+
+--> quais habilidades foram dispaladas
+ local buffs_dispelados = {}
+ for _spellid, amt in _pairs (self.dispell_oque) do
+ buffs_dispelados [#buffs_dispelados+1] = {_spellid, amt}
+ end
+ _table_sort (buffs_dispelados, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (Loc ["STRING_DISPELLED"] .. ":")
+ if (#buffs_dispelados > 0) then
+ for i = 1, _math_min (3, #buffs_dispelados) do
+ local esta_habilidade = buffs_dispelados[i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (esta_habilidade[1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", esta_habilidade[2].." (".._cstr("%.1f", esta_habilidade[2]/meu_total*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ end
+
+ return true
+end
+
+function atributo_misc:ToolTipRess (instancia, numero, barra)
+
+ local meu_total = self ["ress"]
+ local minha_tabela = self.ress_spell_tables._ActorTable
+
+--> habilidade usada para interromper
+ local meus_ress = {}
+
+ for _spellid, _tabela in _pairs (minha_tabela) do
+ meus_ress [#meus_ress+1] = {_spellid, _tabela.ress}
+ end
+ _table_sort (meus_ress, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"]..":")
+ if (#meus_ress > 0) then
+ for i = 1, _math_min (3, #meus_ress) do
+ local esta_habilidade = meus_ress[i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (esta_habilidade[1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", esta_habilidade[2].." (".._cstr("%.1f", esta_habilidade[2]/meu_total*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ else
+ GameTooltip:AddLine (Loc ["STRING_NO_SPELL"])
+ end
+
+--> quem foi que o cara reviveu
+ local meus_alvos = self.ress_targets._ActorTable
+ local alvos = {}
+
+ for _, _tabela in _ipairs (meus_alvos) do
+ alvos [#alvos+1] = {_tabela.nome, _tabela.total}
+ end
+ _table_sort (alvos, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (Loc ["STRING_TARGETS"]..":")
+ if (#alvos > 0) then
+ for i = 1, _math_min (3, #alvos) do
+ GameTooltip:AddDoubleLine (alvos[i][1]..": ", alvos[i][2], 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture ("Interface\\Icons\\PALADIN_HOLY")
+ end
+ end
+
+ return true
+
+end
+
+function atributo_misc:ToolTipInterrupt (instancia, numero, barra)
+
+ local meu_total = self ["interrupt"]
+ local minha_tabela = self.interrupt_spell_tables._ActorTable
+
+--> habilidade usada para interromper
+ local meus_interrupts = {}
+
+ for _spellid, _tabela in _pairs (minha_tabela) do
+ meus_interrupts [#meus_interrupts+1] = {_spellid, _tabela.counter}
+ end
+ _table_sort (meus_interrupts, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (Loc ["STRING_SPELLS"]..":")
+ if (#meus_interrupts > 0) then
+ for i = 1, _math_min (3, #meus_interrupts) do
+ local esta_habilidade = meus_interrupts[i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (esta_habilidade[1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", esta_habilidade[2].." (".._cstr("%.1f", esta_habilidade[2]/meu_total*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ else
+ GameTooltip:AddLine (Loc ["STRING_NO_SPELL"])
+ end
+
+--> quais habilidades foram interrompidas
+ local habilidades_interrompidas = {}
+
+ for _spellid, amt in _pairs (self.interrompeu_oque) do
+ habilidades_interrompidas [#habilidades_interrompidas+1] = {_spellid, amt}
+ end
+ _table_sort (habilidades_interrompidas, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (Loc ["STRING_SPELL_INTERRUPTED"] .. ":")
+ if (#habilidades_interrompidas > 0) then
+ for i = 1, _math_min (3, #habilidades_interrompidas) do
+ local esta_habilidade = habilidades_interrompidas[i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (esta_habilidade[1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", esta_habilidade[2].." (".._cstr("%.1f", esta_habilidade[2]/meu_total*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ end
+
+ return true
+end
+
+
+--------------------------------------------- // JANELA DETALHES // ---------------------------------------------
+
+
+---------> DETALHES BIFURCAÇÃO
+function atributo_misc:MontaInfo()
+ if (info.sub_atributo == 3) then --> interrupt
+ return self:MontaInfoInterrupt()
+ end
+end
+
+---------> DETALHES bloco da direita BIFURCAÇÃO
+function atributo_misc:MontaDetalhes (spellid, barra)
+ if (info.sub_atributo == 3) then --> interrupt
+ return self:MontaDetalhesInterrupt (spellid, barra)
+ end
+end
+
+------ Interrupt
+function atributo_misc:MontaInfoInterrupt()
+
+--[[
+--> quais habilidades foram interrompidas
+ local habilidades_interrompidas = {}
+
+ for _spellid, amt in _pairs (self.interrompeu_oque) do
+ habilidades_interrompidas [#habilidades_interrompidas+1] = {_spellid, amt}
+ end
+ _table_sort (habilidades_interrompidas, function(a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine ("Habilidades Interrompidas:")
+ if (#habilidades_interrompidas > 0) then
+ for i = 1, _math_min (3, #habilidades_interrompidas) do
+ local esta_habilidade = habilidades_interrompidas[i]
+ local nome_magia, _, icone_magia = _GetSpellInfo (esta_habilidade[1])
+ GameTooltip:AddDoubleLine (nome_magia..": ", esta_habilidade[2].." (".._cstr("%.1f", esta_habilidade[2]/meu_total*100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+ end
+--]]
+
+ local meu_total = self ["interrupt"]
+ local minha_tabela = self.interrupt_spell_tables._ActorTable
+
+ local barras = info.barras1
+ local instancia = info.instancia
+
+ local meus_interrupts = {}
+
+ for _spellid, _tabela in _pairs (minha_tabela) do --> da foreach em cada spellid do container
+ local nome, _, icone = _GetSpellInfo (_spellid)
+ _table_insert (meus_interrupts, {_spellid, _tabela.counter, _tabela.counter/meu_total*100, nome, icone})
+ end
+
+ _table_sort (meus_interrupts, function(a, b) return a[2] > b[2] end)
+
+ local amt = #meus_interrupts
+ gump:JI_AtualizaContainerBarras (amt)
+
+ local max_ = meus_interrupts [1][2] --> dano que a primeiro magia vez
+
+ local barra
+ for index, tabela in _ipairs (meus_interrupts) do
+
+ barra = barras [index]
+
+ if (not barra) then --> se a barra não existir, criar ela então
+ barra = gump:CriaNovaBarraInfo1 (instancia, index)
+
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> isso aqui é a parte da seleção e desceleção
+ barra.on_focus = false --> isso aqui é a parte da seleção e desceleção
+ end
+
+ --> isso aqui é tudo da seleção e desceleção das barras
+
+ if (not info.mostrando_mouse_over) then
+ if (tabela[1] == self.detalhes) then --> tabela [1] = spellid = spellid que esta na caixa da direita
+ if (not barra.on_focus) then --> se a barra não tiver no foco
+ barra.textura:SetStatusBarColor (129/255, 125/255, 69/255, 1)
+ barra.on_focus = true
+ if (not info.mostrando) then
+ info.mostrando = barra
+ end
+ end
+ else
+ if (barra.on_focus) then
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> volta a cor antiga
+ barra:SetAlpha (.9) --> volta a alfa antiga
+ barra.on_focus = false
+ end
+ end
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[4]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[3]) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ barra.icone:SetTexture (tabela[5])
+
+ barra.minha_tabela = self --> grava o jogador na barrinho... é estranho pq todas as barras vão ter o mesmo valor do jogador
+ barra.show = tabela[1] --> grava o spellid na barra
+ barra:Show() --> mostra a barra
+
+ -- jogador . detalhes ??
+ if (self.detalhes and self.detalhes == barra.show) then
+ self:MontaDetalhes (self.detalhes, barra) --> poderia deixar isso pro final e montar uma tail call??
+ end
+ end
+
+
+
+ --[
+ --> Alvos do interrupt
+ local meus_alvos = {}
+ for _, tabela in _pairs (self.interrupt_targets._ActorTable) do
+ meus_alvos [#meus_alvos+1] = {tabela.nome, tabela.total}
+ end
+ _table_sort (meus_alvos, function(a, b) return a[2] > b[2] end)
+
+ local amt_alvos = #meus_alvos
+ if (amt_alvos < 1) then
+ return
+ end
+ gump:JI_AtualizaContainerAlvos (amt_alvos)
+
+ local max_alvos = meus_alvos[1][2]
+
+ local barra
+ for index, tabela in _ipairs (meus_alvos) do
+
+ barra = info.barras2 [index]
+
+ if (not barra) then
+ barra = gump:CriaNovaBarraInfo2 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1)
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_alvos*100)
+ end
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..tabela[1]) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[2]/meu_total*100) .. instancia.divisores.fecha) --seta o texto da direita
+
+ if (barra.mouse_over) then --> atualizar o tooltip
+ if (barra.isAlvo) then
+ GameTooltip:Hide()
+ GameTooltip:SetOwner (barra, "ANCHOR_TOPRIGHT")
+ if (not barra.minha_tabela:MontaTooltipAlvos (barra, index)) then
+ return
+ end
+ GameTooltip:Show()
+ end
+ end
+
+ --gump:TextoBarraOnInfo2 (index, , )
+ -- o que mostrar no local do ícone?
+ --barra.icone:SetTexture (tabela[4][3])
+
+ barra.minha_tabela = self --> grava o jogador na tabela
+ barra.nome_inimigo = tabela [1] --> salva o nome do inimigo na barra --> isso é necessário?
+
+ -- no lugar do spell id colocar o que?
+ --barra.spellid = tabela[5]
+ barra:Show()
+
+ --if (self.detalhes and self.detalhes == barra.spellid) then
+ -- self:MontaDetalhes (self.detalhes, barra)
+ --end
+ end
+ --]]
+
+end
+
+
+------ Detalhe Info Interrupt
+function atributo_misc:MontaDetalhesInterrupt (spellid, barra)
+
+ for _, barra in _ipairs (info.barras3) do
+ barra:Hide()
+ end
+
+ local esta_magia = self.interrupt_spell_tables._ActorTable [spellid]
+ if (not esta_magia) then
+ return
+ end
+
+ --> icone direito superior
+ local nome, _, icone = _GetSpellInfo (spellid)
+ local infospell = {nome, nil, icone}
+
+ _detalhes.janela_info.spell_icone:SetTexture (infospell[3])
+
+ local total = self.interrupt
+ local meu_total = esta_magia.counter
+
+ local index = 1
+
+ local data = {}
+
+ local barras = info.barras3
+ local instancia = info.instancia
+
+ local habilidades_alvos = {}
+ for spellid, amt in pairs (esta_magia.interrompeu_oque) do
+ habilidades_alvos [#habilidades_alvos+1] = {spellid, amt}
+ end
+ _table_sort (habilidades_alvos, function(a, b) return a[2] > b[2] end)
+ local max_ = habilidades_alvos[1][2]
+
+ local barra
+ for index, tabela in _ipairs (habilidades_alvos) do
+ barra = barras [index]
+
+ if (not barra) then --> se a barra não existir, criar ela então
+ barra = gump:CriaNovaBarraInfo3 (instancia, index)
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> isso aqui é a parte da seleção e desceleção
+ end
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ else
+ barra.textura:SetValue (tabela[2]/max_*100) --> muito mais rapido...
+ end
+
+ local nome, _, icone = _GetSpellInfo (tabela[1])
+
+ barra.texto_esquerdo:SetText (index..instancia.divisores.colocacao..nome) --seta o texto da esqueda
+ barra.texto_direita:SetText (tabela[2] .." ".. instancia.divisores.abre .._cstr("%.1f", tabela[2]/total*100) .."%".. instancia.divisores.fecha) --seta o texto da direita
+
+ barra.icone:SetTexture (icone)
+
+ barra:Show() --> mostra a barra
+
+ if (index == 15) then
+ break
+ end
+ end
+
+end
+
+
+function atributo_misc:MontaTooltipAlvos (esta_barra, index)
+
+ local inimigo = esta_barra.nome_inimigo
+
+ local container
+ if (info.instancia.sub_atributo == 3) then --interrupt
+ container = self.interrupt_spell_tables._ActorTable
+ end
+
+ local habilidades = {}
+ local total = self.interrupt
+
+ for spellid, tabela in _pairs (container) do
+ --> tabela = classe_damage_habilidade
+ local alvos = tabela.targets._ActorTable
+ for _, tabela in _ipairs (alvos) do
+ --> tabela = classe_target
+ if (tabela.nome == inimigo) then
+ habilidades [#habilidades+1] = {spellid, tabela.total}
+ end
+ end
+ end
+
+ table.sort (habilidades, function (a, b) return a[2] > b[2] end)
+
+ GameTooltip:AddLine (index..". "..inimigo)
+ GameTooltip:AddLine (Loc ["STRING_SPELL_INTERRUPTED"] .. ":")
+ GameTooltip:AddLine (" ")
+
+ for index, tabela in _ipairs (habilidades) do
+ local nome, rank, icone = _GetSpellInfo (tabela[1])
+ if (index < 8) then
+ GameTooltip:AddDoubleLine (index..". |T"..icone..":0|t "..nome, tabela[2].." (".._cstr("%.1f", tabela[2]/total*100).."%)", 1, 1, 1, 1, 1, 1)
+ --GameTooltip:AddTexture (icone)
+ else
+ GameTooltip:AddDoubleLine (index..". "..nome, tabela[2].." (".._cstr("%.1f", tabela[2]/total*100).."%)", .65, .65, .65, .65, .65, .65)
+ end
+ end
+
+ return true
+ --GameTooltip:AddDoubleLine (meus_danos[i][4][1]..": ", meus_danos[i][2].." (".._cstr("%.1f", meus_danos[i][3]).."%)", 1, 1, 1, 1, 1, 1)
+
+end
+
+
+--if (esta_magia.counter == esta_magia.c_amt) then --> só teve critico
+-- gump:SetaDetalheInfoTexto (1, nil, nil, nil, nil, nil, "DPS: "..crit_dps)
+--end
+
+--controla se o dps do jogador esta travado ou destravado
+function atributo_misc:Iniciar (iniciar)
+ return false --retorna se o dps esta aberto ou fechado para este jogador
+end
+
+function atributo_misc:ColetarLixo()
+ return _detalhes:ColetarLixo (class_type)
+end
+
+local function ReconstroiMapa (tabela)
+ local mapa = {}
+ for i = 1, #tabela._ActorTable do
+ mapa [tabela._ActorTable[i].nome] = i
+ end
+ tabela._NameIndexTable = mapa
+end
+
+function _detalhes.refresh:r_atributo_misc (este_jogador, shadow)
+ _setmetatable (este_jogador, _detalhes.atributo_misc)
+ este_jogador.__index = _detalhes.atributo_misc
+
+ if (shadow ~= -1) then
+ este_jogador.shadow = shadow
+
+ --> refresh interrupts
+ if (este_jogador.interrupt_targets) then
+ _detalhes.refresh:r_container_combatentes (este_jogador.interrupt_targets, shadow.interrupt_targets)
+ _detalhes.refresh:r_container_habilidades (este_jogador.interrupt_spell_tables, shadow.interrupt_spell_tables)
+ end
+
+ --> refresh ressers
+ if (este_jogador.ress_targets) then
+ _detalhes.refresh:r_container_combatentes (este_jogador.ress_targets, shadow.ress_targets)
+ _detalhes.refresh:r_container_habilidades (este_jogador.ress_spell_tables, shadow.ress_spell_tables)
+ end
+
+ --> refresh dispells
+ if (este_jogador.dispell_targets) then
+ _detalhes.refresh:r_container_combatentes (este_jogador.dispell_targets, shadow.dispell_targets)
+ _detalhes.refresh:r_container_habilidades (este_jogador.dispell_spell_tables, shadow.dispell_spell_tables)
+ end
+
+ --> refresh cc_breaks
+ if (este_jogador.cc_break_targets) then
+ _detalhes.refresh:r_container_combatentes (este_jogador.cc_break_targets, shadow.cc_break_targets)
+ _detalhes.refresh:r_container_habilidades (este_jogador.cc_break_spell_tables, shadow.cc_break_spell_tables)
+ end
+ else
+
+ --> refresh interrupts
+ if (este_jogador.interrupt_targets) then
+ _detalhes.refresh:r_container_combatentes (este_jogador.interrupt_targets, -1)
+ _detalhes.refresh:r_container_habilidades (este_jogador.interrupt_spell_tables, -1)
+ end
+
+ --> refresh ressers
+ if (este_jogador.ress_targets) then
+ _detalhes.refresh:r_container_combatentes (este_jogador.ress_targets, -1)
+ _detalhes.refresh:r_container_habilidades (este_jogador.ress_spell_tables, -1)
+ end
+
+ --> refresh dispells
+ if (este_jogador.dispell_targets) then
+ _detalhes.refresh:r_container_combatentes (este_jogador.dispell_targets, -1)
+ _detalhes.refresh:r_container_habilidades (este_jogador.dispell_spell_tables, -1)
+ end
+
+ --> refresh cc_breaks
+ if (este_jogador.cc_break_targets) then
+ _detalhes.refresh:r_container_combatentes (este_jogador.cc_break_targets, -1)
+ _detalhes.refresh:r_container_habilidades (este_jogador.cc_break_spell_tables, -1)
+ end
+ end
+end
+
+function _detalhes.clear:c_atributo_misc (este_jogador)
+
+ este_jogador.__index = {}
+ este_jogador.shadow = nil
+ este_jogador.links = nil
+ este_jogador.minha_barra = nil
+
+ if (este_jogador.interrupt_targets) then
+ _detalhes.clear:c_container_combatentes (este_jogador.interrupt_targets)
+ _detalhes.clear:c_container_habilidades (este_jogador.interrupt_spell_tables)
+ end
+
+ if (este_jogador.ress_targets) then
+ _detalhes.clear:c_container_combatentes (este_jogador.ress_targets)
+ _detalhes.clear:c_container_habilidades (este_jogador.ress_spell_tables)
+ end
+
+ if (este_jogador.cc_break_targets) then
+ _detalhes.clear:c_container_combatentes (este_jogador.cc_break_targets)
+ _detalhes.clear:c_container_habilidades (este_jogador.cc_break_spell_tables)
+ end
+
+ if (este_jogador.dispell_targets) then
+ _detalhes.clear:c_container_combatentes (este_jogador.dispell_targets)
+ _detalhes.clear:c_container_habilidades (este_jogador.dispell_spell_tables)
+ end
+
+end
+
+atributo_misc.__add = function (shadow, tabela2)
+
+ if (tabela2.interrupt) then
+
+ shadow.interrupt = shadow.interrupt + tabela2.interrupt
+ _detalhes.tabela_overall.totals[4]["interrupt"] = _detalhes.tabela_overall.totals[4]["interrupt"] + tabela2.interrupt
+
+ if (tabela2.grupo) then
+ _detalhes.tabela_overall.totals_grupo[4]["interrupt"] = _detalhes.tabela_overall.totals_grupo[4]["interrupt"] + tabela2.interrupt
+ end
+
+ for index, alvo in _ipairs (tabela2.interrupt_targets._ActorTable) do
+ local alvo_shadow = shadow.interrupt_targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for spellid, habilidade in _pairs (tabela2.interrupt_spell_tables._ActorTable) do
+ local habilidade_shadow = shadow.interrupt_spell_tables:PegaHabilidade (spellid, true, nil, true)
+
+ habilidade_shadow.interrompeu_oque = {}
+ for _spellid, amount in _pairs (habilidade.interrompeu_oque) do
+ habilidade_shadow.interrompeu_oque [_spellid] = amount
+ end
+
+ for index, alvo in _ipairs (habilidade.targets._ActorTable) do
+ local alvo_shadow = habilidade_shadow.targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for key, value in _pairs (habilidade) do
+ if (_type (value) == "number") then
+ if (key ~= "id") then
+ if (not habilidade_shadow [key]) then
+ habilidade_shadow [key] = 0
+ end
+ habilidade_shadow [key] = habilidade_shadow [key] + value
+ end
+ end
+ end
+ end
+
+ for spellid, amount in _pairs (tabela2.interrompeu_oque) do
+ if (not shadow.interrompeu_oque [spellid]) then
+ shadow.interrompeu_oque [spellid] = 0
+ end
+ shadow.interrompeu_oque [spellid] = shadow.interrompeu_oque [spellid] + amount
+ end
+
+ end
+
+ if (tabela2.ress) then
+
+ shadow.ress = shadow.ress + tabela2.ress
+ _detalhes.tabela_overall.totals[4]["ress"] = _detalhes.tabela_overall.totals[4]["ress"] + tabela2.ress
+
+ if (tabela2.grupo) then
+ _detalhes.tabela_overall.totals_grupo[4]["ress"] = _detalhes.tabela_overall.totals_grupo[4]["ress"] + tabela2.ress
+ end
+
+ for index, alvo in _ipairs (tabela2.ress_targets._ActorTable) do
+ local alvo_shadow = shadow.ress_targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for spellid, habilidade in _pairs (tabela2.ress_spell_tables._ActorTable) do
+ local habilidade_shadow = shadow.ress_spell_tables:PegaHabilidade (spellid, true, nil, true)
+
+ for index, alvo in _ipairs (habilidade.targets._ActorTable) do
+ local alvo_shadow = habilidade_shadow.targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for key, value in _pairs (habilidade) do
+ if (_type (value) == "number") then
+ if (key ~= "id") then
+ if (not habilidade_shadow [key]) then
+ habilidade_shadow [key] = 0
+ end
+ habilidade_shadow [key] = habilidade_shadow [key] + value
+ end
+ end
+ end
+ end
+
+ end
+
+ if (tabela2.dispell) then
+
+ shadow.dispell = shadow.dispell + tabela2.dispell
+ _detalhes.tabela_overall.totals[4]["dispell"] = _detalhes.tabela_overall.totals[4]["dispell"] + tabela2.dispell
+
+ if (tabela2.grupo) then
+ _detalhes.tabela_overall.totals_grupo[4]["dispell"] = _detalhes.tabela_overall.totals_grupo[4]["dispell"] + tabela2.dispell
+ end
+
+ for index, alvo in _ipairs (tabela2.dispell_targets._ActorTable) do
+ local alvo_shadow = shadow.dispell_targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for spellid, habilidade in _pairs (tabela2.dispell_spell_tables._ActorTable) do
+ local habilidade_shadow = shadow.dispell_spell_tables:PegaHabilidade (spellid, true, nil, true)
+
+ habilidade_shadow.dispell_oque = {}
+
+ if (habilidade.dispell_oque) then
+ for _spellid, amount in _pairs (habilidade.dispell_oque) do
+ habilidade_shadow.dispell_oque [_spellid] = amount
+ end
+ end
+
+ for index, alvo in _ipairs (habilidade.targets._ActorTable) do
+ local alvo_shadow = habilidade_shadow.targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for key, value in _pairs (habilidade) do
+ if (_type (value) == "number") then
+ if (key ~= "id") then
+ if (not habilidade_shadow [key]) then
+ habilidade_shadow [key] = 0
+ end
+ habilidade_shadow [key] = habilidade_shadow [key] + value
+ end
+ end
+ end
+ end
+
+ for spellid, amount in _pairs (tabela2.dispell_oque) do
+ if (not shadow.dispell_oque [spellid]) then
+ shadow.dispell_oque [spellid] = 0
+ end
+ shadow.dispell_oque [spellid] = shadow.dispell_oque [spellid] + amount
+ end
+
+ end
+
+ if (tabela2.cc_break) then
+
+ shadow.cc_break = shadow.cc_break + tabela2.cc_break
+ _detalhes.tabela_overall.totals[4]["cc_break"] = _detalhes.tabela_overall.totals[4]["cc_break"] + tabela2.cc_break
+
+ if (tabela2.grupo) then
+ _detalhes.tabela_overall.totals_grupo[4]["cc_break"] = _detalhes.tabela_overall.totals_grupo[4]["cc_break"] + tabela2.cc_break
+ end
+
+ for index, alvo in _ipairs (tabela2.cc_break_targets._ActorTable) do
+ local alvo_shadow = shadow.cc_break_targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for spellid, habilidade in _pairs (tabela2.cc_break_spell_tables._ActorTable) do
+ local habilidade_shadow = shadow.cc_break_spell_tables:PegaHabilidade (spellid, true, nil, true)
+
+ habilidade_shadow.cc_break_oque = {}
+ for _spellid, amount in _pairs (habilidade.cc_break_oque) do
+ habilidade_shadow.cc_break_oque [_spellid] = amount
+ end
+
+ for index, alvo in _ipairs (habilidade.targets._ActorTable) do
+ local alvo_shadow = habilidade_shadow.targets:PegarCombatente (alvo.serial, alvo.nome, alvo.flag_original, true)
+ alvo_shadow.total = alvo_shadow.total + alvo.total
+ end
+
+ for key, value in _pairs (habilidade) do
+ if (_type (value) == "number") then
+ if (key ~= "id") then
+ if (not habilidade_shadow [key]) then
+ habilidade_shadow [key] = 0
+ end
+ habilidade_shadow [key] = habilidade_shadow [key] + value
+ end
+ end
+ end
+ end
+
+ for spellid, amount in _pairs (tabela2.cc_break_oque) do
+ if (not shadow.cc_break_oque [spellid]) then
+ shadow.cc_break_oque [spellid] = 0
+ end
+ shadow.cc_break_oque [spellid] = shadow.cc_break_oque [spellid] + amount
+ end
+ end
+
+ return shadow
+end
+
+atributo_misc.__sub = function (tabela1, tabela2)
+
+ if (tabela1.interrupt and tabela2.interrupt) then
+ tabela1.interrupt = tabela1.interrupt - tabela2.interrupt
+
+ --> reduz o interrompeu_oque
+ for spellid, amt in _pairs (tabela2.interrompeu_oque) do
+ tabela1.interrompeu_oque [spellid] = tabela1.interrompeu_oque [spellid] - amt
+ end
+ end
+
+ if (tabela1.ress and tabela2.ress) then
+ tabela1.ress = tabela1.ress - tabela2.ress
+ end
+
+ if (tabela1.dispell and tabela2.dispell) then
+ tabela1.dispell = tabela1.dispell - tabela2.dispell
+ end
+
+ if (tabela1.cc_break and tabela2.cc_break) then
+ tabela1.cc_break = tabela1.cc_break - tabela2.cc_break
+ end
+
+ return tabela1
+end
diff --git a/classes/classe_others_habilidade.lua b/classes/classe_others_habilidade.lua
new file mode 100644
index 00000000..5e3a8c24
--- /dev/null
+++ b/classes/classe_others_habilidade.lua
@@ -0,0 +1,160 @@
+local _detalhes = _G._detalhes
+--local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local habilidade_misc = _detalhes.habilidade_misc
+local container_combatentes = _detalhes.container_combatentes
+local container_misc_target = _detalhes.container_type.CONTAINER_MISCTARGET_CLASS
+
+--lua locals
+local _setmetatable = setmetatable
+local _ipairs = ipairs
+--api locals
+local _UnitAura = UnitAura
+
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+
+function habilidade_misc:NovaTabela (id, link, token) --aqui eu não sei que parâmetros passar
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, habilidade_misc)
+
+ esta_tabela.quem_sou = "classe_others_habilidade"
+
+ esta_tabela.id = id
+
+ --print ("token: " .. token)
+
+ if (token == "SPELL_INTERRUPT") then
+ --print ("token de interrupt")
+ esta_tabela.interrompeu_oque = {}
+ end
+
+ if (token == "SPELL_DISPEL" or token == "SPELL_STOLEN") then
+ --print ("token de interrupt")
+ esta_tabela.dispell_oque = {}
+ end
+
+ if (token == "SPELL_AURA_BROKEN" or token == "SPELL_AURA_BROKEN_SPELL") then
+ --print ("token de interrupt")
+ esta_tabela.cc_break_oque = {}
+ end
+
+ -- isso aqui não pode ser assim... ou pode?
+ esta_tabela.counter = 0
+ --esta_tabela.res = 0
+
+ esta_tabela.targets = container_combatentes:NovoContainer (container_misc_target)
+
+ if (link) then
+ esta_tabela.targets.shadow = link.targets
+ end
+
+ return esta_tabela
+end
+
+function habilidade_misc:Add (serial, nome, flag, who_nome, token, spellID, spellName)
+
+ --local alvo = self.targets:PegarCombatente (serial, nome, flag, true)
+ local alvo = self.targets._NameIndexTable [nome]
+ if (not alvo) then
+ alvo = self.targets:PegarCombatente (serial, nome, flag, true)
+ else
+ alvo = self.targets._ActorTable [alvo]
+ end
+
+ alvo.total = alvo.total + 1
+
+ --alvo:AddQuantidade (1)
+
+ if (token == "SPELL_INTERRUPT") then
+ self.counter = self.counter + 1
+
+ if (not self.interrompeu_oque [spellID]) then --> interrompeu_oque a NIL value
+ self.interrompeu_oque [spellID] = 1
+ else
+ self.interrompeu_oque [spellID] = self.interrompeu_oque [spellID] + 1
+ end
+
+ elseif (token == "SPELL_RESURRECT") then
+ if (not self.ress) then
+ self.ress = 1
+ else
+ self.ress = self.ress + 1
+ end
+
+ elseif (token == "SPELL_DISPEL" or token == "SPELL_STOLEN") then
+ if (not self.dispell) then
+ self.dispell = 1
+ else
+ self.dispell = self.dispell + 1
+ end
+
+ if (not self.dispell_oque [spellID]) then
+ self.dispell_oque [spellID] = 1
+ else
+ self.dispell_oque [spellID] = self.dispell_oque [spellID] + 1
+ end
+
+ elseif (token == "SPELL_AURA_BROKEN_SPELL" or token == "SPELL_AURA_BROKEN") then
+
+ if (not self.cc_break) then
+ self.cc_break = 1
+ else
+ self.cc_break = self.cc_break + 1
+ end
+
+ if (not self.cc_break_oque [spellID]) then
+ self.cc_break_oque [spellID] = 1
+ else
+ self.cc_break_oque [spellID] = self.cc_break_oque [spellID] + 1
+ end
+ end
+
+ if (self.shadow) then
+ return self.shadow:Add (serial, nome, flag, who_nome, token, spellID, spellName)
+ end
+
+end
+
+--> habilidade atual e o container de habilidades da shadow
+function _detalhes.refresh:r_habilidade_misc (habilidade, shadow) --recebeu o container shadow
+ _setmetatable (habilidade, habilidade_misc)
+ habilidade.__index = habilidade_misc
+
+ if (shadow ~= -1) then
+ habilidade.shadow = shadow._ActorTable[habilidade.id]
+ _detalhes.refresh:r_container_combatentes (habilidade.targets, habilidade.shadow.targets)
+ else
+ _detalhes.refresh:r_container_combatentes (habilidade.targets, -1)
+ end
+end
+
+function _detalhes.clear:c_habilidade_misc (habilidade)
+ habilidade.__index = {}
+ habilidade.shadow = nil
+
+ _detalhes.clear:c_container_combatentes (habilidade.targets)
+end
+
+habilidade_misc.__sub = function (tabela1, tabela2)
+
+ --interrupts
+ tabela1.counter = tabela1.counter - tabela2.counter
+
+ --ressesrs
+ if (tabela1.ress and tabela2.ress) then
+ tabela1.ress = tabela1.ress - tabela2.ress
+ end
+
+ --dispells
+ if (tabela1.dispell and tabela2.dispell) then
+ tabela1.dispell = tabela1.dispell - tabela2.dispell
+ end
+
+ --cc_breaks
+ if (tabela1.cc_break and tabela2.cc_break) then
+ tabela1.cc_break = tabela1.cc_break - tabela2.cc_break
+ end
+
+ return tabela1
+end
diff --git a/classes/classe_target.lua b/classes/classe_target.lua
new file mode 100644
index 00000000..236789cf
--- /dev/null
+++ b/classes/classe_target.lua
@@ -0,0 +1,55 @@
+
+local _detalhes = _G._detalhes
+--local AceLocale = LibStub ("AceLocale-3.0")
+--local Loc = AceLocale:GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+
+--lua locals
+local _setmetatable = setmetatable
+--api locals
+
+--esta tabela irá ser usada por todas os tipos? tipo dano, cura, interrupts?
+
+function alvo_da_habilidade:NovaTabela (link)
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, alvo_da_habilidade)
+
+ esta_tabela.quem_sou = "classe_alvo_da_habilidade"
+
+ esta_tabela.total = 0 --total que a habilidade fez.
+
+ return esta_tabela
+end
+
+function alvo_da_habilidade:AddQuantidade (amt)
+ self.total = self.total + amt
+ if (self.shadow) then
+ return self.shadow:AddQuantidade (amt)
+ end
+end
+
+function _detalhes.refresh:r_alvo_da_habilidade (este_alvo, shadow)
+ --print (shadow)
+ --print (este_alvo.shadow)
+ _setmetatable (este_alvo, alvo_da_habilidade)
+ este_alvo.__index = alvo_da_habilidade
+ if (shadow ~= -1) then
+ este_alvo.shadow = shadow._ActorTable [shadow._NameIndexTable[este_alvo.nome]]
+ end
+end
+
+function _detalhes.clear:c_alvo_da_habilidade (este_alvo)
+ este_alvo.shadow = nil
+ este_alvo.__index = {}
+end
+
+alvo_da_habilidade.__sub = function (tabela1, tabela2)
+ tabela1.total = tabela1.total - tabela2.total
+ if (tabela1.overheal) then
+ tabela1.overheal = tabela1.overheal - tabela2.overheal
+ tabela1.absorbed = tabela1.absorbed - tabela2.absorbed
+ end
+end
diff --git a/classes/container_combatentes.lua b/classes/container_combatentes.lua
new file mode 100644
index 00000000..bb00d41d
--- /dev/null
+++ b/classes/container_combatentes.lua
@@ -0,0 +1,531 @@
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local combatente = _detalhes.combatente
+local container_combatentes = _detalhes.container_combatentes
+local alvo_da_habilidade = _detalhes.alvo_da_habilidade
+local atributo_damage = _detalhes.atributo_damage
+local atributo_heal = _detalhes.atributo_heal
+local atributo_energy = _detalhes.atributo_energy
+local atributo_misc = _detalhes.atributo_misc
+
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+local container_damage = _detalhes.container_type.CONTAINER_DAMAGE_CLASS
+local container_heal = _detalhes.container_type.CONTAINER_HEAL_CLASS
+local container_heal_target = _detalhes.container_type.CONTAINER_HEALTARGET_CLASS
+local container_friendlyfire = _detalhes.container_type.CONTAINER_FRIENDLYFIRE
+local container_damage_target = _detalhes.container_type.CONTAINER_DAMAGETARGET_CLASS
+local container_energy = _detalhes.container_type.CONTAINER_ENERGY_CLASS
+local container_energy_target = _detalhes.container_type.CONTAINER_ENERGYTARGET_CLASS
+local container_misc = _detalhes.container_type.CONTAINER_MISC_CLASS
+local container_misc_target = _detalhes.container_type.CONTAINER_MISCTARGET_CLASS
+
+--api locals
+local _UnitClass = UnitClass
+local _GetPlayerInfoByGUID = GetPlayerInfoByGUID
+--lua locals
+local _setmetatable = setmetatable
+local _getmetatable = getmetatable
+local _bit_band = bit.band
+local _ipairs = ipairs
+local _pairs = pairs
+
+--local table_insert = table.insert
+
+--> FLAGS <== qual o tipo do objeto
+local OBJECT_TYPE_MASK = 0x0000FC00
+local OBJECT_TYPE_OBJECT = 0x00004000
+local OBJECT_TYPE_PETGUARDIAN = 0x00003000
+local OBJECT_TYPE_GUARDIAN = 0x00002000
+local OBJECT_TYPE_PET = 0x00001000
+local OBJECT_TYPE_NPC = 0x00000800
+local OBJECT_TYPE_PLAYER = 0x00000400
+local OBJECT_TYPE_PETS = OBJECT_TYPE_PET + OBJECT_TYPE_GUARDIAN
+
+local REACTION_HOSTILE = COMBATLOG_OBJECT_REACTION_HOSTILE or 0x00000040
+
+function container_combatentes:NovoContainer (tipo_do_container, combatTable, combatId)
+
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, container_combatentes)
+
+ esta_tabela.funcao_de_criacao = container_combatentes:FuncaoDeCriacao (tipo_do_container)
+ if (not esta_tabela.funcao_de_criacao) then
+ print ("Debug: Container criado mas sem funcao de criacao. TIPO: ")
+ print (tipo_do_container)
+ print (debugstack(2))
+ return
+ end
+
+ esta_tabela.tipo = tipo_do_container
+
+ esta_tabela.combatId = combatId
+
+ esta_tabela._ActorTable = {}
+ esta_tabela._NameIndexTable = {}
+ esta_tabela.meu_tipo = "container_combatentes"
+
+ return esta_tabela
+end
+
+local function get_class_ (novo_objeto, nome, flag)
+ local _, engClass = _UnitClass (nome)
+
+ if (engClass) then
+ novo_objeto.classe = engClass
+ return
+ else
+ if (flag) then
+ --print ("tem flag: " .. flag)
+ --> conferir se o jogador é um player
+ if (_bit_band (flag, OBJECT_TYPE_PLAYER) ~= 0) then
+ --print ("eh um player sem grupo: "..novo_objeto.nome)
+ novo_objeto.classe = "UNGROUPPLAYER"
+ return
+ elseif (_bit_band (flag, OBJECT_TYPE_PETGUARDIAN) ~= 0) then
+ --print ("eh um pet: "..novo_objeto.nome)
+ novo_objeto.classe = "PET"
+ return
+ end
+ end
+ novo_objeto.classe = "UNKNOW"
+ return
+ end
+end
+
+local EM_GRUPO = 0x00000007
+
+function container_combatentes:Dupe (who)
+ local novo_objeto = {}
+ if (_getmetatable (who)) then
+ _setmetatable (novo_objeto, _getmetatable (who))
+ end
+
+ for cprop, value in _pairs (who) do
+ novo_objeto[cprop] = value
+ end
+
+ return novo_objeto
+end
+
+function container_combatentes:CriarShadow (who)
+ --> o self é o container no combate_overall -- who é o objeto na tabela do historico [1 2 3]
+ local mapa = self._NameIndexTable
+ local conteudo = self._ActorTable
+
+ local novo_objeto = self.funcao_de_criacao (_, who.serial, who.nome)
+ novo_objeto.nome = who.nome
+
+ novo_objeto.flag = who.flag
+ novo_objeto.classe = who.classe
+
+ for _, pet in _ipairs (who.pets) do
+ novo_objeto.pets [#novo_objeto.pets+1] = pet
+ end
+
+ if (who.enemy) then
+ novo_objeto.enemy = true
+ end
+
+ self._ActorTable [#self._ActorTable+1] = novo_objeto
+ self._NameIndexTable[who.nome] = #self._ActorTable
+
+ return novo_objeto
+
+end
+
+function container_combatentes:GetAmount (actorName, key)
+ key = key or "total"
+ local index = self._NameIndexTable [actorName]
+ if (index) then
+ return self._ActorTable [index] [key] or 0
+ else
+ return 0
+ end
+end
+
+function container_combatentes:PegarCombatente (serial, nome, flag, criar, isOwner)
+
+ --> antes de mais nada, vamos verificar se é um pet
+ local dono_do_pet
+ if (flag and _bit_band (flag, OBJECT_TYPE_PETS) ~= 0) then --> é um pet
+
+ --> aqui ele precisaria achar as tag < > pra saber se o nome passado já não veio com o dono imbutido
+ --> se não tiver as tags, terá que ser posto aqui
+ if (not nome:find ("<") or not nome:find (">")) then --> find é lento, não teria outra forma de fazer isso?
+
+ local nome_dele, dono_nome, dono_serial, dono_flag = _detalhes.tabela_pets:PegaDono (serial, nome, flag)
+
+ if (nome_dele) then
+
+ nome = nome_dele
+ --> aqui pode ocorrer bug caso o dono tenha sido adicionado ao container de pets enquanto não estava na party ou raide
+ --[[ old debug lines
+ if (self.shadow and self.tipo == container_damage and not self._NameIndexTable [dono_nome]) then
+ print ("CONTAINER 1: Criando Actor do Dono:", dono_nome, "Pet: ", nome)
+ elseif (self.shadow and self.tipo == container_damage and self._NameIndexTable [dono_nome]) then
+ print ("CONTAINER 1: criado actor repedido",nome)
+ end
+ --]]
+ dono_do_pet = self:PegarCombatente (dono_serial, dono_nome, dono_flag, true, nome)
+
+ end
+ end
+ end
+
+ local index = self._NameIndexTable [nome] --> pega o index no mapa
+ if (index) then
+ return self._ActorTable [index], dono_do_pet, nome
+
+ elseif (criar) then
+
+ --[[ old debug lines
+ if (isOwner and self.shadow and self.tipo == container_damage) then
+ print ("CONTAINER 2: Criando actor do Dono do Pet: OWNER:", nome, "PET:", isOwner)
+ if (self._NameIndexTable [nome]) then
+ print ("Repetido")
+ end
+ end
+ --]]
+ -- rotinas de criação do objeto shadow
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ local shadow = self.shadow --> espelho do container no overall
+ local shadow_objeto = nil
+
+ if (shadow) then --> se tiver o espelho (não for a tabela overall já)
+ shadow_objeto = shadow:PegarCombatente (_, nome) --> apenas verifica se ele existe ou não
+ if (not shadow_objeto) then --> se não existir, cria-lo
+ local novo_nome = nome:gsub ((" <.*"), "") --> tira o nome do pet
+ shadow_objeto = shadow:PegarCombatente (serial, novo_nome, flag, true)
+ end
+ end
+
+ local novo_objeto = self.funcao_de_criacao (_, serial, nome, shadow_objeto) --> shadow_objeto passa para o classe_damage gravar no .targets e .spell_tables, mas não grava nele mesmo
+
+ novo_objeto.nome = nome
+
+ -- converte a flag do wow em flag do details
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> pega afiliação
+ local details_flag = 0x00000000
+ if (flag) then
+ --print ("tem flag")
+
+ if (_bit_band (flag, 0x00000400) ~= 0) then --> é um player
+ details_flag = details_flag+0x00000001
+
+ if (IsInInstance()) then
+ novo_objeto.displayName = nome:gsub (("%-.*"), "")
+ else
+ novo_objeto.displayName = nome
+ end
+
+ if (_bit_band (flag, EM_GRUPO) ~= 0) then --> faz parte do grupo
+ details_flag = details_flag+0x00000100
+ novo_objeto.grupo = true
+ if (shadow_objeto) then
+ shadow_objeto.grupo = true
+ end
+ end
+
+ elseif (dono_do_pet) then --> é um pet
+
+ details_flag = details_flag+0x00000002
+ novo_objeto.owner = dono_do_pet
+ novo_objeto.ownerName = dono_do_pet.nome
+
+ if (IsInInstance()) then
+ novo_objeto.displayName = nome:gsub (("%-.*"), ">")
+ else
+ novo_objeto.displayName = nome
+ end
+
+ --if (not novo_objeto.displayName:find (">")) then
+ -- novo_objeto.displayName = novo_objeto.displayName .. ">"
+ --end
+
+ --print ("pet -> " .. nome)
+ else
+ novo_objeto.displayName = nome
+ end
+
+ -- 0x00000060 --> inimigo neutro
+ if (_bit_band (flag, 0x00000010) ~= 0) then --> é amigo
+ details_flag = details_flag+0x00000010
+ elseif (_bit_band (flag, 0x00000020) ~= 0) then --> é neutro
+ details_flag = details_flag+0x00000020
+ --print ("neutro -> " .. nome)
+ elseif (_bit_band (flag, 0x00000040) ~= 0) then --> é inimigo
+ details_flag = details_flag+0x00000040
+ --print ("inimigos -> " .. nome)
+ end
+ else
+ --print (flag)
+ end
+
+ novo_objeto.flag = details_flag
+ novo_objeto.flag_original = flag
+ novo_objeto.serial = serial
+
+ -- tipo do container
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ if (self.tipo == container_playernpc) then --> CONTAINER COMUM
+
+ elseif (self.tipo == container_damage) then --> CONTAINER DAMAGE
+
+ get_class_ (novo_objeto, nome, flag)
+
+ if (dono_do_pet) then
+ dono_do_pet.pets [#dono_do_pet.pets+1] = nome
+ end
+
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ novo_objeto:CriaLink (shadow_objeto) --> criando o link
+ shadow_objeto.flag = details_flag
+ end
+
+ if (novo_objeto.classe == "UNGROUPPLAYER") then --> is a player
+ if (_bit_band (flag, REACTION_HOSTILE ) ~= 0) then --> is hostile
+ novo_objeto.enemy = true
+ end
+
+ --> try to guess his class
+ if (shadow) then --> não executar 2x
+ _detalhes:ScheduleTimer ("GuessClass", 1, {novo_objeto, self, 1})
+ end
+ end
+
+
+ elseif (self.tipo == container_heal) then --> CONTAINER HEALING
+
+ get_class_ (novo_objeto, nome, flag)
+
+ if (dono_do_pet) then
+ dono_do_pet.pets [#dono_do_pet.pets+1] = nome
+ end
+
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ novo_objeto:CriaLink (shadow_objeto) --> criando o link
+ shadow_objeto.flag = details_flag
+ end
+
+ if (novo_objeto.classe == "UNGROUPPLAYER") then --> is a player
+ if (_bit_band (flag, REACTION_HOSTILE ) ~= 0) then --> is hostile
+ novo_objeto.enemy = true --print (nome.." EH UM INIMIGO -> " .. engRace)
+ end
+
+ --> try to guess his class
+ if (shadow) then --> não executar 2x
+ _detalhes:ScheduleTimer ("GuessClass", 1, {novo_objeto, self, 1})
+ end
+ end
+
+
+ elseif (self.tipo == container_energy) then --> CONTAINER ENERGY
+
+ get_class_ (novo_objeto, nome, flag)
+
+ if (dono_do_pet) then
+ dono_do_pet.pets [#dono_do_pet.pets+1] = nome
+ end
+
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ novo_objeto:CriaLink (shadow_objeto) --> criando o link
+ shadow_objeto.flag = details_flag
+ end
+
+ if (novo_objeto.classe == "UNGROUPPLAYER") then --> is a player
+ if (_bit_band (flag, REACTION_HOSTILE ) ~= 0) then --> is hostile
+ novo_objeto.enemy = true --print (nome.." EH UM INIMIGO -> " .. engRace)
+ end
+
+ --> try to guess his class
+ if (shadow) then --> não executar 2x
+ _detalhes:ScheduleTimer ("GuessClass", 1, {novo_objeto, self, 1})
+ end
+ end
+
+ elseif (self.tipo == container_misc) then --> CONTAINER MISC
+
+ get_class_ (novo_objeto, nome, flag)
+
+ --local teste_classe =
+
+ if (dono_do_pet) then
+ dono_do_pet.pets [#dono_do_pet.pets+1] = nome
+ end
+
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ novo_objeto:CriaLink (shadow_objeto) --> criando o link
+ shadow_objeto.flag = details_flag
+ end
+
+ if (novo_objeto.classe == "UNGROUPPLAYER") then --> is a player
+ if (_bit_band (flag, REACTION_HOSTILE ) ~= 0) then --> is hostile
+ novo_objeto.enemy = true --print (nome.." EH UM INIMIGO -> " .. engRace)
+ end
+
+ --> try to guess his class
+ if (shadow) then --> não executar 2x
+ _detalhes:ScheduleTimer ("GuessClass", 1, {novo_objeto, self, 1})
+ end
+ end
+
+ elseif (self.tipo == container_damage_target) then --> CONTAINER ALVO DO DAMAGE
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ shadow_objeto.flag = details_flag
+ end
+
+ elseif (self.tipo == container_heal_target) then --> CONTAINER ALVOS DO HEALING
+ novo_objeto.overheal = 0
+ novo_objeto.absorbed = 0
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ shadow_objeto.flag = details_flag
+ end
+
+ elseif (self.tipo == container_energy_target) then --> CONTAINER ALVOS DO ENERGY
+
+ novo_objeto.mana = 0
+ novo_objeto.e_rage = 0
+ novo_objeto.e_energy = 0
+ novo_objeto.runepower = 0
+
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ shadow_objeto.flag = details_flag
+ end
+
+ elseif (self.tipo == container_misc_target) then --> CONTAINER ALVOS DO MISC
+
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ shadow_objeto.flag = details_flag
+ end
+
+ elseif (self.tipo == container_friendlyfire) then --> CONTAINER FRIENDLY FIRE
+
+ get_class_ (novo_objeto, nome)
+
+ if (shadow_objeto) then
+ novo_objeto.shadow = shadow_objeto
+ shadow_objeto.flag = details_flag
+ end
+ end
+
+ -- grava o objeto no mapa do container
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ -- novo_objeto.combatID = _detalhes:NumeroCombate() --> grava no objeto qual o ID do combate que ele pertence -- Não serve pra nada? melhor DELETAR
+
+ --if (self.shadow and self.tipo == container_damage and self._NameIndexTable [nome]) then
+ -- print ("CONTAINER 3: criado actor repedido",nome, isOwner)
+ --end
+
+ local size = #self._ActorTable+1
+ self._ActorTable [size] = novo_objeto --> grava na tabela de indexes
+ self._NameIndexTable [nome] = size --> grava no hash map o index deste jogador
+
+ return novo_objeto, dono_do_pet, nome
+ else
+ return nil, nil, nil
+ end
+end
+
+function container_combatentes:FuncaoDeCriacao (tipo)
+ if (tipo == container_damage_target) then
+ return alvo_da_habilidade.NovaTabela
+
+ elseif (tipo == container_damage) then
+ return atributo_damage.NovaTabela
+
+ elseif (tipo == container_heal_target) then
+ return alvo_da_habilidade.NovaTabela
+
+ elseif (tipo == container_heal) then
+ return atributo_heal.NovaTabela
+
+ elseif (tipo == container_friendlyfire) then
+ return atributo_damage.FF_funcao_de_criacao
+
+ elseif (tipo == container_energy) then
+ return atributo_energy.NovaTabela
+
+ elseif (tipo == container_energy_target) then
+ return alvo_da_habilidade.NovaTabela
+
+ elseif (tipo == container_misc) then
+ return atributo_misc.NovaTabela
+
+ elseif (tipo == container_misc_target) then
+ return alvo_da_habilidade.NovaTabela
+
+ end
+end
+
+function container_combatentes:remapear()
+ local mapa = self._NameIndexTable
+ local conteudo = self._ActorTable
+ for i = 1, #conteudo do
+ mapa [conteudo[i].nome] = i
+ end
+end
+
+local function ReparaMapa (tabela)
+ local mapa = {}
+ for i = 1, #tabela._ActorTable do
+ mapa [tabela._ActorTable[i].nome] = i
+ end
+ tabela._NameIndexTable = mapa
+end
+
+function _detalhes.refresh:r_container_combatentes (container, shadow)
+ _setmetatable (container, _detalhes.container_combatentes)
+ container.__index = _detalhes.container_combatentes
+ container.funcao_de_criacao = container_combatentes:FuncaoDeCriacao (container.tipo)
+ ReparaMapa (container)
+
+ if (shadow ~= -1) then
+ container.shadow = shadow
+ end
+end
+
+function _detalhes.clear:c_container_combatentes (container)
+ container.__index = {}
+ container.shadow = nil
+ container._NameIndexTable = nil
+ container.need_refresh = nil
+ container.funcao_de_criacao = nil
+end
+
+ --[[
+ if (not serial) then
+ print ("DEBUG: objeto sem serial: "..nome)
+ novo_objeto.classe = "UNKNOW"
+ else
+ if (_bit_band (flag, 0x00000400) ~= 0) then --> é player
+
+ local _, engClass, _, engRace = _GetPlayerInfoByGUID (serial)
+ novo_objeto.classe = engClass
+ --print (novo_objeto.classe)
+ --print ("eh um player ".. nome.." da classe "..engClass)
+ else
+ --print ("nao eh um player "..nome)
+ local _, engClass = _UnitClass (nome)
+ --print (engClass)
+
+ if (engClass) then
+ novo_objeto.classe = engClass
+ else
+ novo_objeto.classe = "UNKNOW"
+ end
+ end
+ --novo_objeto.classe = "UNKNOW"
+ end
+ --]]
diff --git a/classes/container_habilidades.lua b/classes/container_habilidades.lua
new file mode 100644
index 00000000..fdbb29c2
--- /dev/null
+++ b/classes/container_habilidades.lua
@@ -0,0 +1,130 @@
+local _detalhes = _G._detalhes
+--local AceLocale = LibStub ("AceLocale-3.0")
+--local Loc = AceLocale:GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+local _setmetatable = setmetatable
+
+local container_playernpc = _detalhes.container_type.CONTAINER_PLAYERNPC
+local container_damage = _detalhes.container_type.CONTAINER_DAMAGE_CLASS
+local container_heal = _detalhes.container_type.CONTAINER_HEAL_CLASS
+local container_heal_target = _detalhes.container_type.CONTAINER_HEALTARGET_CLASS
+local container_friendlyfire = _detalhes.container_type.CONTAINER_FRIENDLYFIRE
+local container_damage_target = _detalhes.container_type.CONTAINER_DAMAGETARGET_CLASS
+local container_energy = _detalhes.container_type.CONTAINER_ENERGY_CLASS
+local container_energy_target = _detalhes.container_type.CONTAINER_ENERGYTARGET_CLASS
+local container_misc = _detalhes.container_type.CONTAINER_MISC_CLASS
+local container_misc_target = _detalhes.container_type.CONTAINER_MISCTARGET_CLASS
+
+local habilidade_dano = _detalhes.habilidade_dano
+local habilidade_cura = _detalhes.habilidade_cura
+local habilidade_e_energy = _detalhes.habilidade_e_energy
+local habilidade_misc = _detalhes.habilidade_misc
+
+local container_habilidades = _detalhes.container_habilidades
+
+function container_habilidades:NovoContainer (tipo_do_container)
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, container_habilidades)
+
+ esta_tabela.funcao_de_criacao = container_habilidades:FuncaoDeCriacao (tipo_do_container)
+ if (not esta_tabela.funcao_de_criacao) then
+ print ("DEBUG: Sem funcao de criacao para a habilidade... TIPO: ")
+ print (tipo_do_container)
+ end
+
+ esta_tabela.tipo = tipo_do_container
+ esta_tabela._ActorTable = {}
+ return esta_tabela
+end
+
+function container_habilidades:Dupe (who)
+ local novo_objeto = {}
+ if (_getmetatable (who)) then
+ _setmetatable (novo_objeto, _getmetatable (who))
+ end
+
+ for cprop, value in _pairs (who) do
+ novo_objeto[cprop] = value
+ end
+
+ return novo_objeto
+end
+
+function container_habilidades:GetSpell (id)
+ return self._ActorTable [id]
+end
+
+function container_habilidades:PegaHabilidade (id, criar, token, cria_shadow)
+ local esta_habilidade = self._ActorTable [id]
+ if (esta_habilidade) then
+ return esta_habilidade
+ else
+ if (criar) then
+
+ if (cria_shadow) then
+ local novo_objeto = self.funcao_de_criacao (_, id, nil, "")
+ self._ActorTable [id] = novo_objeto
+ return novo_objeto
+ end
+
+ local shadow = self.shadow --> retorna o container semelhante a esta na tabela overall
+ local shadow_objeto = nil
+
+ if (shadow) then --> talvez possa mandar todos os parâmetros de criação logo no inicio
+ shadow_objeto = shadow:PegaHabilidade (id) --> apenas verifica se ele existe ou não
+ if (not shadow_objeto) then --> se não existir, cria-lo
+ shadow_objeto = shadow:PegaHabilidade (id, true, token)
+ end
+ end
+
+ --local novo_objeto = habilidade_dano:NovaTabela (id, shadow_objeto)
+ local novo_objeto = self.funcao_de_criacao (_, id, shadow_objeto, token)
+
+ if (shadow_objeto) then --> link é esta mesma tabela mas no container do overall
+ novo_objeto.shadow = shadow_objeto --> diz ao objeto qual a shadow dele na tabela overall
+ --novo_objeto:CriaLink (shadow_objeto) --> cria o link entre o objeto e a sua shadow
+ end
+
+ self._ActorTable [id] = novo_objeto
+
+ return novo_objeto
+ else
+ return nil
+ end
+ end
+end
+
+function container_habilidades:FuncaoDeCriacao (tipo)
+ if (tipo == container_damage) then
+ return habilidade_dano.NovaTabela
+
+ elseif (tipo == container_heal) then
+ return habilidade_cura.NovaTabela
+
+ elseif (tipo == container_energy) then
+ return habilidade_e_energy.NovaTabela
+
+ elseif (tipo == container_misc) then
+ return habilidade_misc.NovaTabela
+
+ end
+end
+
+function _detalhes.refresh:r_container_habilidades (container, shadow)
+ _setmetatable (container, _detalhes.container_habilidades)
+ container.__index = _detalhes.container_habilidades
+ local func_criacao = container_habilidades:FuncaoDeCriacao (container.tipo)
+ container.funcao_de_criacao = func_criacao
+
+ if (shadow ~= -1) then
+ container.shadow = shadow
+ end
+end
+
+function _detalhes.clear:c_container_habilidades (container)
+ container.__index = {}
+ container.shadow = nil
+ container.funcao_de_criacao = nil
+end
diff --git a/classes/container_historico.lua b/classes/container_historico.lua
new file mode 100644
index 00000000..99eb8d6b
--- /dev/null
+++ b/classes/container_historico.lua
@@ -0,0 +1,131 @@
+--lua api
+local _table_remove = table.remove
+local _table_insert = table.insert
+local _setmetatable = setmetatable
+local _table_wipe = table.wipe
+
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local combate = _detalhes.combate
+local historico = _detalhes.historico
+local barra_total = _detalhes.barra_total
+local container_pets = _detalhes.container_pets
+local timeMachine = _detalhes.timeMachine
+
+function historico:NovoHistorico()
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, historico)
+
+ esta_tabela.tabelas = {} --guarda as tabelas dos combates
+
+ return esta_tabela
+end
+
+--> sai do combate, chamou adicionar a tabela ao histórico
+function historico:adicionar (tabela)
+
+ local tamanho = #self.tabelas
+
+ --> verifica se precisa dar UnFreeze()
+ if (tamanho < _detalhes.segments_amount) then --> vai preencher um novo index vazio
+ local ultima_tabela = self.tabelas[tamanho]
+ if (not ultima_tabela) then --> não ha tabelas no historico, esta será a #1
+ --> pega a tabela do combate atual
+ ultima_tabela = tabela
+ end
+ _detalhes:InstanciaCallFunction (_detalhes.CheckFreeze, tamanho+1, ultima_tabela)
+ end
+
+ --> reordena as tabelas
+ _table_insert (self.tabelas, 1, tabela)
+
+ --> chama a função que irá atualizar as instâncias com segmentos no histórico
+ _detalhes:InstanciaCallFunction (_detalhes.AtualizaSegmentos_AfterCombat, self)
+
+ --> verifica se precisa apagar a última tabela do histórico
+ if (#self.tabelas > _detalhes.segments_amount) then
+
+ -- BETA subtração do combate overall
+ _detalhes.tabela_overall = _detalhes.tabela_overall - self.tabelas [#self.tabelas]
+ _detalhes.tabela_overall.start_time = _detalhes.tabela_overall.start_time + (self.tabelas[#self.tabelas].end_time-self.tabelas[#self.tabelas].start_time)
+ --print (#self.tabelas)
+
+ local amt_mortes = #self.tabelas[#self.tabelas].last_events_tables --> quantas mortes teve nessa luta
+ if (amt_mortes > 0) then
+ for i = #_detalhes.tabela_overall.last_events_tables, #_detalhes.tabela_overall.last_events_tables-amt_mortes, -1 do
+ _table_remove (_detalhes.tabela_overall.last_events_tables, #_detalhes.tabela_overall.last_events_tables)
+ end
+ end
+
+ _table_remove (self.tabelas, #self.tabelas)
+ _detalhes:SendEvent ("DETAILS_DATA_SEGMENTREMOVED", nil, nil)
+
+ end
+
+ _detalhes:InstanciaCallFunction (_detalhes.AtualizarJanela)
+end
+
+--> verifica se tem alguma instancia congelada mostrando o segmento recém liberado
+function _detalhes:CheckFreeze (instancia, index_liberado, tabela)
+ if (instancia.freezed) then --> esta congelada
+ if (instancia.segmento == index_liberado) then
+ instancia.showing = tabela
+ instancia:UnFreeze()
+ end
+ end
+end
+
+function historico:resetar()
+
+ if (_detalhes.bosswindow) then
+ _detalhes.bosswindow:Reset()
+ end
+
+ if (_detalhes.tabela_vigente.verifica_combate) then --> finaliza a checagem se esta ou não no combate
+ _detalhes:CancelTimer (_detalhes.tabela_vigente.verifica_combate)
+ end
+
+ --> fecha a janela de informações do jogador
+ _detalhes:FechaJanelaInfo()
+
+ -- novo container de historico
+ _detalhes.tabela_historico = historico:NovoHistorico() --joga fora a tabela antiga e cria uma nova
+ --novo container para armazenar pets
+ _detalhes.tabela_pets = _detalhes.container_pets:NovoContainer()
+ _detalhes.container_pets:BuscarPets()
+ -- nova tabela do overall e current
+ _detalhes.tabela_overall = combate:NovaTabela() --joga fora a tabela antiga e cria uma nova
+ -- cria nova tabela do combate atual
+ _detalhes.tabela_vigente = combate:NovaTabela (_, _detalhes.tabela_overall)
+
+ --marca o addon como fora de combate
+ _detalhes.in_combat = false
+ --zera o contador de combates
+ _detalhes:NumeroCombate (0)
+
+ --> limpa o cache de magias
+ _detalhes:ClearSpellCache()
+
+ --> limpa a tabela de escudos
+ _table_wipe (_detalhes.escudos)
+
+ --> reinicia a time machine
+ timeMachine:Reiniciar()
+
+ _detalhes:InstanciaCallFunction (_detalhes.AtualizaSegmentos) -- atualiza o instancia.showing para as novas tabelas criadas
+ _detalhes:InstanciaCallFunction (_detalhes.AtualizaSoloMode_AfertReset) -- verifica se precisa zerar as tabela da janela solo mode
+ _detalhes:InstanciaCallFunction (_detalhes.ResetaGump) --_detalhes:ResetaGump ("de todas as instancias")
+ _detalhes:InstanciaCallFunction (gump.Fade, "in", nil, "barras")
+
+ _detalhes:AtualizaGumpPrincipal (-1) --atualiza todas as instancias
+
+ _detalhes:UpdateParserGears()
+
+ _detalhes:SendEvent ("DETAILS_DATA_RESET", nil, nil)
+end
+
+function _detalhes.refresh:r_historico (este_historico)
+ _setmetatable (este_historico, historico)
+ --este_historico.__index = historico
+end
diff --git a/classes/container_pets.lua b/classes/container_pets.lua
new file mode 100644
index 00000000..095de055
--- /dev/null
+++ b/classes/container_pets.lua
@@ -0,0 +1,149 @@
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local container_pets = _detalhes.container_pets
+
+-- api locals
+local _UnitGUID = UnitGUID
+local _UnitName = UnitName
+local _GetUnitName = GetUnitName
+local _IsInRaid = IsInRaid
+local _IsInGroup = IsInGroup
+local _GetNumGroupMembers = GetNumGroupMembers
+
+-- lua locals
+local _setmetatable = setmetatable
+
+function container_pets:NovoContainer()
+ local esta_tabela = {}
+ _setmetatable (esta_tabela, _detalhes.container_pets)
+ esta_tabela.pets = {} --> armazena a pool -> uma dictionary com o [serial do pet] -> nome do dono
+ esta_tabela._ActorTable = {} --> armazena os 15 ultimos pets do jogador -> [jogador nome] -> {nil, nil, nil, ...}
+ return esta_tabela
+end
+
+function container_pets:PegaDono (pet_serial, pet_nome, pet_flags)
+
+ local busca = self.pets [pet_serial]
+ local dono_nome, dono_serial, dono_flags
+
+ if (busca) then
+ --debug: print ("achou o pet no container de donos")
+ dono_nome, dono_serial, dono_flags = busca[1], busca[2], busca[3]
+ return pet_nome .." <"..dono_nome..">", dono_nome, dono_serial, dono_flags
+ end
+
+ if (_IsInRaid()) then
+ --print ("estou em RAIDE")
+ for i = 1, _GetNumGroupMembers(), 1 do
+ if (pet_serial == _UnitGUID ("raidpet"..i)) then
+ dono_serial = _UnitGUID ("raid"..i)
+ dono_flags = 0x00000417 --> emulate sourceflag flag
+
+ local nome, realm = _UnitName ("raid"..i)
+ if (realm) then
+ nome = nome.."-"..realm
+ end
+ dono_nome = nome
+ --print ("Dono encontrado na raide")
+ end
+ end
+
+ elseif (_IsInGroup()) then
+ --print ("DEBUG estou em PARTY")
+ for i = 1, _GetNumGroupMembers()-1, 1 do
+ if (pet_serial == _UnitGUID ("partypet"..i)) then
+ dono_serial = _UnitGUID ("party"..i)
+ dono_flags = 0x00000417 --> emulate sourceflag flag
+
+ local nome, realm = _UnitName ("party"..i)
+ if (realm) then
+ nome = nome.."-"..realm
+ end
+ dono_nome = nome
+ --print ("DEBUG Dono encontrado na party")
+ end
+ end
+ end
+
+ if (not dono_nome) then
+ if (pet_serial == _UnitGUID ("pet")) then
+ dono_nome = _GetUnitName ("player")
+ dono_serial = _UnitGUID ("player")
+ if (_IsInGroup() or _IsInRaid()) then
+ dono_flags = 0x00000417 --> emulate sourceflag flag
+ else
+ dono_flags = 0x00000411 --> emulate sourceflag flag
+ end
+ end
+ end
+
+ if (dono_nome) then
+ --print ("dono encontrado, adicionando ao cache")
+ self.pets [pet_serial] = {dono_nome, dono_serial, dono_flags, _detalhes._tempo} --> adicionada a flag emulada
+ return pet_nome .." <"..dono_nome..">", dono_nome, dono_serial, dono_flags
+ else
+ --if (_GetNumGroupMembers() > 0) then
+ --print ("DEBUG: Pet sem dono: "..pet_nome)
+ --end
+ --print ("DEBUG Nao foi possivel achar o dono de "..pet_nome)
+ end
+
+ return nil, nil, nil, nil
+
+end
+
+--> ao ter raid roster update, precisa dar foreach no container de pets e verificar as flags
+--> o mesmo precisa ser feito com as tabelas de combate
+
+function container_pets:BuscarPets()
+ if (_IsInRaid()) then
+ for i = 1, _GetNumGroupMembers(), 1 do
+ local pet_serial = _UnitGUID ("raidpet"..i)
+ if (pet_serial) then
+ if (not _detalhes.tabela_pets.pets [pet_serial]) then
+ local nome, realm = _UnitName ("raid"..i)
+ if (realm) then
+ nome = nome.."-"..realm
+ end
+ _detalhes.tabela_pets:Adicionar (pet_serial, _UnitName ("raidpet"..i), 2600, _UnitGUID ("raid"..i), nome, 0x514, true)
+ --print ("PET FOUND on Buscar Pets!", _GetUnitName ("raid"..i, true), _detalhes:trim (_GetUnitName ("raid"..i, true)))
+ end
+ end
+ end
+ elseif (_IsInGroup()) then
+ for i = 1, _GetNumGroupMembers()-1, 1 do
+ local pet_serial = _UnitGUID ("partypet"..i)
+ if (pet_serial) then
+ if (not _detalhes.tabela_pets.pets [pet_serial]) then
+ local nome, realm = _UnitName ("party"..i)
+ if (realm) then
+ nome = nome.."-"..realm
+ end
+ _detalhes.tabela_pets:Adicionar (pet_serial, _UnitName ("partypet"..i), 2600, _UnitGUID ("party"..i), nome, 0x514)
+ end
+ end
+ end
+ end
+end
+
+function container_pets:Adicionar (pet_serial, pet_nome, pet_flags, dono_serial, dono_nome, dono_flags, fromSearch)
+
+ self.pets [pet_serial] = {dono_nome, dono_serial, dono_flags, _detalhes._tempo}
+
+ --if (fromSearch) then
+ -- local d = self.pets [pet_serial]
+ --print ("dono nome:",d[1], "dono serial:", d[2], "dono flags:", d[3], "tempo:", d[4])
+ --end
+
+ if (self.pets [dono_serial]) then
+ --print ("debug: a owner is a pet, Owner: ", dono_nome, " Pet: ", pet_nome)
+ end
+
+end
+
+function _detalhes.refresh:r_container_pets (container)
+ _setmetatable (container, container_pets)
+ --container.__index = container_pets
+end
+
diff --git a/core/control.lua b/core/control.lua
new file mode 100644
index 00000000..3e51d1c4
--- /dev/null
+++ b/core/control.lua
@@ -0,0 +1,481 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+ local _tempo = time()
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _math_floor = math.floor --lua local
+ local _ipairs = ipairs --lua local
+ local _pairs = pairs --lua local
+ local _table_wipe = table.wipe --lua local
+ local _bit_band = bit.band --lua local
+
+ local _GetInstanceInfo = GetInstanceInfo --wow api local
+ local _UnitExists = UnitExists --wow api local
+ local _UnitGUID = UnitGUID --wow api local
+
+ local atributo_damage = _detalhes.atributo_damage --details local
+ local atributo_heal = _detalhes.atributo_heal --details local
+ local atributo_energy = _detalhes.atributo_energy --details local
+ local atributo_misc = _detalhes.atributo_misc --details local
+ local atributo_custom = _detalhes.atributo_custom --details local
+ local info = _detalhes.janela_info --details local
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> constants
+
+ local modo_GROUP = _detalhes.modos.group
+ local modo_ALL = _detalhes.modos.all
+ local class_type_dano = _detalhes.atributos.dano
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ --> try to find the opponent of last fight, can be called during a fight as well
+ function _detalhes:FindEnemy()
+
+ for _, actor in _ipairs (_detalhes.tabela_vigente[class_type_dano]._ActorTable) do
+ if (not actor.grupo and not actor.owner and not actor.nome:find ("[*]") and _bit_band (actor.flag, 0x00000060) ~= 0) then --> 0x20+0x40 neutral + enemy reaction
+ for name, _ in _pairs (actor.targets._NameIndexTable) do
+ if (name == _detalhes.playername) then
+ return actor.nome
+ else
+ local _target_actor = _detalhes.tabela_vigente (class_type_dano, name)
+ if (_target_actor and _target_actor.grupo) then
+ return actor.nome
+ end
+ end
+ end
+ end
+ end
+
+ return Loc ["STRING_UNKNOW"]
+ end
+
+ -- try get the current encounter name during the encounter
+ function _detalhes:ReadBossFrames()
+ for index = 1, 5, 1 do
+ if (_UnitExists ("boss"..index)) then
+ local guid = _UnitGUID ("boss"..index)
+ if (guid) then
+ local serial = tonumber (guid:sub(6, 10), 16)
+
+ if (serial) then
+
+ local ZoneName, _, _, _, _, _, _, ZoneMapID = _GetInstanceInfo()
+
+ local BossIds = _detalhes:GetBossIds (ZoneMapID)
+ if (BossIds) then
+ local BossIndex = BossIds [serial]
+
+ if (BossIndex) then
+
+ if (_detalhes.in_combat) then
+ local bossFunction, bossFunctionType = _detalhes:GetBossFunction (ZoneMapID, BossIndex)
+ if (bossFunction) then
+ if (_bit_band (bossFunctionType, 0x1) ~= 0) then --realtime
+ _detalhes.bossFunction = bossFunction
+ local combat = _detalhes:GetCombat ("current")
+ combat.bossFunction = _detalhes:ScheduleTimer ("bossFunction", 1)
+ end
+ end
+ end
+
+ _detalhes.tabela_vigente.is_boss = {
+ index = BossIndex,
+ name = _detalhes:GetBossName (ZoneMapID, BossIndex),
+ zone = ZoneName,
+ mapid = ZoneMapID,
+ encounter = _detalhes:GetBossName (ZoneMapID, BossIndex)
+ }
+ _detalhes:SendEvent ("COMBAT_BOSS_FOUND", nil, _detalhes.tabela_vigente.is_boss.index, _detalhes.tabela_vigente.is_boss.name)
+ return _detalhes.tabela_vigente.is_boss
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+
+ --try to get the encounter name after the encounter (can be called during the combat as well)
+ function _detalhes:FindBoss()
+
+ local ZoneName, _, _, _, _, _, _, ZoneMapID = _GetInstanceInfo()
+ local BossIds = _detalhes:GetBossIds (ZoneMapID)
+
+ if (BossIds) then
+ local BossIndex = nil
+ local ActorsContainer = _detalhes.tabela_vigente [class_type_dano]._ActorTable
+
+ if (ActorsContainer) then
+ for index, Actor in _ipairs (ActorsContainer) do
+ if (not Actor.grupo) then
+ local serial = tonumber (Actor.serial:sub(6, 10), 16)
+ if (serial) then
+ BossIndex = BossIds [serial]
+ if (BossIndex) then
+ Actor.boss = true
+ Actor.shadow.boss = true
+ _detalhes:FlagActorsOnBossFight()
+ return {
+ index = BossIndex,
+ name =_detalhes:GetBossName (ZoneMapID, BossIndex),
+ zone = ZoneName,
+ mapid = ZoneMapID,
+ encounter = _detalhes:GetBossName (ZoneMapID, BossIndex)}
+ end
+ end
+ end
+ end
+ end
+ end
+
+ return false
+ end
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ function _detalhes:EntrarEmCombate (...)
+
+ if (_detalhes.debug) then
+ print ("Details started a new combat.")
+ end
+
+ --> não tem historico, addon foi resetado, a primeira tabela é descartada -- Erase first table is does not have a firts segment history, this occour after reset or first run
+ if (not _detalhes.tabela_historico.tabelas[1]) then
+ --> precisa zerar aqui a tabela overall
+ _table_wipe (_detalhes.tabela_overall)
+ _table_wipe (_detalhes.tabela_vigente)
+ --> aqui ele perdeu o self.showing das instâncias, precisa fazer com que elas atualizem
+ _detalhes.tabela_overall = _detalhes.combate:NovaTabela()
+
+ _detalhes:InstanciaCallFunction (_detalhes.ResetaGump, _, -1) --> reseta scrollbar, iterators, rodapé, etc
+ _detalhes:InstanciaCallFunction (_detalhes.InstanciaFadeBarras, -1) --> esconde todas as barras
+ _detalhes:InstanciaCallFunction (_detalhes.AtualizaSegmentos) --> atualiza o showing
+ end
+
+ --> conta o tempo na tabela overall -- start time at overall table
+ if (_detalhes.tabela_overall.end_time) then
+ _detalhes.tabela_overall.start_time = _tempo - (_detalhes.tabela_overall.end_time - _detalhes.tabela_overall.start_time)
+ _detalhes.tabela_overall.end_time = nil
+ else
+ _detalhes.tabela_overall.start_time = _tempo
+ end
+
+ --> re-lock nos tempos da tabela passada -- lock again last table times
+ _detalhes.tabela_vigente:TravarTempos() --> lá em cima é feito wipe, não deveria ta dando merda nisso aqui? ou ela puxa da __index e da zero jogadores no mapa e container
+
+ local n_combate = _detalhes:NumeroCombate (1) --aumenta o contador de combates -- combat number up
+
+ --> cria a nova tabela de combates -- create new table
+ _detalhes.tabela_vigente = _detalhes.combate:NovaTabela (true, _detalhes.tabela_overall, n_combate, ...) --cria uma nova tabela de combate
+
+ --> verifica se há alguma instância mostrando o segmento atual -- change segment
+ _detalhes:InstanciaCallFunction (_detalhes.TrocaSegmentoAtual)
+
+ _detalhes.tabela_vigente:seta_data (_detalhes._detalhes_props.DATA_TYPE_START) --seta na tabela do combate a data do inicio do combate -- setup time data
+ _detalhes.in_combat = true --sinaliza ao addon que há um combate em andamento -- in combat flag up
+
+ _detalhes.tabela_vigente.combat_id = n_combate --> grava o número deste combate na tabela atual -- setup combat id on new table
+
+ --> é o timer que ve se o jogador ta em combate ou não -- check if any party or raid members are in combat
+ _detalhes.tabela_vigente.verifica_combate = _detalhes:ScheduleRepeatingTimer ("EstaEmCombate", 1)
+
+ _detalhes.container_pets:BuscarPets()
+
+ _detalhes:UpdateParserGears()
+
+ _detalhes:SendEvent ("COMBAT_PLAYER_ENTER", nil, _detalhes.tabela_vigente)
+ end
+
+ function _detalhes:SairDoCombate()
+
+ --> pega a zona do jogador e vê se foi uma luta contra um Boss -- identifica se a luta foi com um boss
+ if (not _detalhes.tabela_vigente.is_boss) then
+ _detalhes.tabela_vigente.is_boss = _detalhes:FindBoss()
+ else
+ _detalhes:FlagActorsOnBossFight()
+ end
+
+ if (_detalhes.debug) then
+ print ("Details ended a combat.")
+ end
+
+ if (not _detalhes.tabela_vigente.is_boss) then
+ local inimigo = _detalhes:FindEnemy()
+ if (inimigo) then
+ if (_detalhes.debug) then
+ print ("Details last fight against: " .. inimigo)
+ end
+ end
+ _detalhes.tabela_vigente.enemy = inimigo
+ else
+ _detalhes.tabela_vigente.enemy = _detalhes.tabela_vigente.is_boss.encounter
+ _detalhes:CaptureSet (false, "damage", false, 30)
+ _detalhes:CaptureSet (false, "heal", false, 30)
+
+ if (_detalhes.debug) then
+ print ("Details found a boss on last fight, freezing parser for 30 seconds.")
+ end
+
+ local bossFunction, bossFunctionType = _detalhes:GetBossFunction (_detalhes.tabela_vigente.is_boss.mapid, _detalhes.tabela_vigente.is_boss.index)
+ if (bossFunction) then
+ if (_bit_band (bossFunctionType, 0x2) ~= 0) then --end of combat
+ bossFunction()
+ end
+ end
+ end
+
+ if (_detalhes.tabela_vigente.bossFunction) then
+ _detalhes:CancelTimer (_detalhes.tabela_vigente.bossFunction)
+ _detalhes.bossFunction = nil
+ end
+
+ --> finaliza a checagem se esta ou não no combate -- finish combat check
+ if (_detalhes.tabela_vigente.verifica_combate) then
+ _detalhes:CancelTimer (_detalhes.tabela_vigente.verifica_combate)
+ _detalhes.tabela_vigente.verifica_combate = nil
+ end
+
+ --> lock timers
+ _detalhes.tabela_vigente:TravarTempos()
+
+ _detalhes.tabela_vigente:seta_data (_detalhes._detalhes_props.DATA_TYPE_END) --> salva hora, minuto, segundo do fim da luta
+ _detalhes.tabela_overall:seta_data (_detalhes._detalhes_props.DATA_TYPE_END) --> salva hora, minuto, segundo do fim da luta
+ _detalhes.tabela_vigente:seta_tempo_decorrido() --> salva o end_time
+ _detalhes.tabela_overall:seta_tempo_decorrido() --seta o end_time
+
+ local tempo_do_combate = _detalhes.tabela_vigente.end_time - _detalhes.tabela_vigente.start_time
+
+ if (_detalhes.solo) then
+ --> debuffs need a checkup, not well functional right now
+ _detalhes.CloseSoloDebuffs()
+ end
+
+ if ( tempo_do_combate >= _detalhes.minimum_combat_time) then --> tempo minimo precisa ser 5 segundos pra acrecentar a tabela ao historico
+ _detalhes.tabela_historico:adicionar (_detalhes.tabela_vigente) --move a tabela atual para dentro do histórico
+ else
+ --> this is a little bit complicated, need a specific function for combat cancellation
+
+ if (_detalhes.tabela_overall.end_time) then --> no inicio do combate o tempo do overall vai pra NIL o.0
+ _detalhes.tabela_overall.start_time = _detalhes.tabela_overall.start_time + tempo_do_combate --> assim ele descarta o tempo de combate na tabela do everall
+ else
+ _detalhes.tabela_overall.start_time = 0 --> tempo inicio igual a zero pois se o end_time é NIL significa que é a primeira vez que ocorre o combate na tabela overall
+ end
+
+ _detalhes.tabela_overall = _detalhes.tabela_overall - _detalhes.tabela_vigente --> isso aqui é novo, ele vai subtrair da overall qualquer dado adicionado na tabela descardata
+ _table_wipe (_detalhes.tabela_vigente) --> descarta ela, não será mais usada
+
+ _detalhes.tabela_vigente = _detalhes.tabela_historico.tabelas[1] --> pega a tabela do ultimo combate
+ if (not _detalhes.tabela_vigente) then --> provavel foi o primeiro combate após um reset
+ _detalhes.tabela_vigente = _detalhes.combate:NovaTabela (false, _detalhes.tabela_overall) --cria uma nova tabela de combate caso não tenha nenhuma no historico
+ end
+
+ --> tabela foi descartada, precisa atualizar os baseframes // precisa atualizer todos ou apenas o overall?
+ _detalhes:InstanciaCallFunction (_detalhes.AtualizarJanela)
+
+ if (_detalhes.solo) then
+ local esta_instancia = _detalhes.tabela_instancias[_detalhes.solo]
+ if (_detalhes.SoloTables.CombatID == _detalhes:NumeroCombate()) then --> significa que o solo mode validou o combate, como matar um bixo muito low level com uma só porrada
+ if (_detalhes.SoloTables.CombatIDLast and _detalhes.SoloTables.CombatIDLast ~= 0) then --> volta os dados da luta anterior
+
+ _detalhes.SoloTables.CombatID = _detalhes.SoloTables.CombatIDLast
+ _detalhes:RefreshSolo()
+
+ else
+ _detalhes:RefreshSolo()
+ _detalhes.SoloTables.CombatID = nil
+ end
+ end
+ end
+
+ _detalhes:NumeroCombate (-1)
+ _detalhes:UpdateParserGears()
+ end
+
+ _detalhes.in_combat = false --sinaliza ao addon que não há combate no momento
+
+ _detalhes:UpdateParserGears()
+
+ _detalhes:SendEvent ("COMBAT_PLAYER_LEAVE", nil, _detalhes.tabela_vigente)
+ end
+
+ function _detalhes:FlagActorsOnBossFight()
+ for class_type, container in _ipairs (_detalhes.tabela_vigente) do
+ for _, actor in _ipairs (container._ActorTable) do
+ if (not actor.grupo and not actor.boss) then
+ if (_bit_band (actor.flag, _detalhes.flags.friend) == 0) then
+ actor.boss_fight_component = true
+ local shadow = _detalhes.tabela_overall (class_type, actor.nome)
+ if (shadow) then
+ shadow.boss_fight_component = true
+ else
+ print ("Nao achou a shadow em FlagActorsOnBossFight()")
+ end
+ end
+ end
+ end
+ end
+ end
+
+ function _detalhes:AtualizarJanela (instancia, _segmento)
+ if (_segmento) then --> apenas atualizar janelas que estejam mostrando o segmento solicitado
+ if (_segmento == instancia.segmento) then
+ instancia:TrocaTabela (instancia, instancia.segmento, instancia.atributo, instancia.sub_atributo, true)
+ end
+ else
+ if (instancia.modo == modo_GROUP or instancia.modo == modo_ALL) then
+ instancia:TrocaTabela (instancia, instancia.segmento, instancia.atributo, instancia.sub_atributo, true)
+ end
+ end
+ end
+
+ function _detalhes:TrocaSegmentoAtual (instancia)
+ if (instancia.segmento == 0) then --> esta mostrando a tabela Atual
+ instancia.showing =_detalhes.tabela_vigente
+ instancia:ResetaGump()
+ _detalhes.gump:Fade (instancia, "in", nil, "barras")
+ end
+ end
+
+ --> internal GetCombatId() version
+ function _detalhes:NumeroCombate (flag)
+ if (flag == 0) then
+ _detalhes.combat_id = 0
+ elseif (flag) then
+ _detalhes.combat_id = _detalhes.combat_id + flag
+ end
+ return _detalhes.combat_id
+ end
+
+ --> tooltip fork
+ function _detalhes:MontaTooltip (qual_barra)
+
+ local esta_barra = self.barras [qual_barra] --> barra que o mouse passou em cima e irá mostrar o tooltip
+ local objeto = esta_barra.minha_tabela --> pega a referencia da tabela --> retorna a classe_damage ou classe_heal
+ if (not objeto) then --> a barra não possui um objeto
+ return false
+ end
+ _detalhes.popup:Close()
+
+ --verifica por tooltips especiais:
+ if (objeto.dead) then --> é uma barra de dead
+ return _detalhes:ToolTipDead (self, objeto, esta_barra) --> instância, [morte], barra
+ end
+
+ return objeto:ToolTip (self, qual_barra, esta_barra) --> instância, nº barra, objeto barra
+ end
+
+
+ function _detalhes:EndRefresh (instancia, total, tabela_do_combate, showing)
+ _detalhes:EsconderBarrasNaoUsadas (instancia, showing)
+ end
+
+ function _detalhes:EsconderBarrasNaoUsadas (instancia, showing)
+ --> primeira atualização após uma mudança de segmento --> verifica se há mais barras sendo mostradas do que o necessário
+ --------------------
+ if (instancia.v_barras) then
+ for barra_numero = instancia.barrasInfo.mostrando+1, instancia.barrasInfo.criadas do
+ _detalhes.gump:Fade (instancia.barras[barra_numero], "in")
+ end
+ instancia.v_barras = false
+ end
+
+ return showing
+ end
+
+ --> call update functions
+ function _detalhes:AtualizarALL (forcar)
+
+ local tabela_do_combate = self.showing
+
+ --> confere se a instância possui uma tabela válida
+ if (not tabela_do_combate) then
+ if (not self.freezed) then
+ return self:Freeze()
+ end
+ return
+ end
+
+ if (not tabela_do_combate[self.atributo].need_refresh and not forcar) then
+ return --> não precisa de refresh
+ end
+
+ if (self.atributo == 1) then --> damage
+ return atributo_damage:RefreshWindow (self, tabela_do_combate, forcar)
+ elseif (self.atributo == 2) then --> heal
+ return atributo_heal:RefreshWindow (self, tabela_do_combate, forcar)
+ elseif (self.atributo == 3) then --> energy
+ return atributo_energy:RefreshWindow (self, tabela_do_combate, forcar)
+ elseif (self.atributo == 4) then --> outros
+ return atributo_misc:RefreshWindow (self, tabela_do_combate, forcar)
+ elseif (self.atributo == 5) then --> ocustom
+ return atributo_custom:RefreshWindow (self, tabela_do_combate, forcar)
+ end
+
+ end
+
+ function _detalhes:AtualizaGumpPrincipal (instancia, forcar)
+
+ if (not instancia or type (instancia) == "boolean") then --> o primeiro parâmetro não foi uma instância ou ALL
+ forcar = instancia
+ instancia = self
+ end
+
+ if (instancia == -1) then
+
+ local refresh_poll = {}
+
+ for _, esta_instancia in _ipairs (_detalhes.tabela_instancias) do
+
+ if (esta_instancia.ativa) then
+ if (esta_instancia.modo == modo_GROUP or esta_instancia.modo == modo_ALL) then
+ local atributo = esta_instancia:AtualizarALL (forcar)
+ if (atributo) then
+ refresh_poll [#refresh_poll+1] = atributo
+ end
+ end
+ end
+
+ end
+
+ for _, atributo in _ipairs (refresh_poll) do
+ atributo.need_refresh = false
+ end
+
+ if (not forcar) then --atualizar o gump de detalhes também se ele estiver aberto
+ if (info.ativo) then
+ return info.jogador:MontaInfo()
+ end
+ end
+
+ return
+
+ else
+ if (not instancia.ativa) then
+ return
+ end
+ end
+
+ if (instancia.modo == modo_ALL or instancia.modo == modo_GROUP) then
+ return instancia:AtualizarALL (forcar)
+ end
+ end
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> core
+
+ function _detalhes:UpdateControl()
+ _tempo = _detalhes._tempo
+ end
\ No newline at end of file
diff --git a/core/gears.lua b/core/gears.lua
new file mode 100644
index 00000000..36692872
--- /dev/null
+++ b/core/gears.lua
@@ -0,0 +1,9 @@
+local _detalhes = _G._detalhes
+
+function _detalhes:UpdateGears()
+
+ _detalhes:UpdateParser()
+ _detalhes:UpdateControl()
+ _detalhes:UpdateCombat()
+
+end
\ No newline at end of file
diff --git a/core/meta.lua b/core/meta.lua
new file mode 100644
index 00000000..ec9bec30
--- /dev/null
+++ b/core/meta.lua
@@ -0,0 +1,856 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local _tempo = time()
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _pairs = pairs --lua local
+ local _ipairs = ipairs --lua local
+ local _rawget = rawget --lua local
+ local _setmetatable = setmetatable --lua local
+ local _table_remove = table.remove --lua local
+ local _bit_band = bit.band --lua local
+ local _table_wipe = table.wipe --lua local
+ local _time = time --lua local
+
+ local _InCombatLockdown = InCombatLockdown --wow api local
+
+ local atributo_damage = _detalhes.atributo_damage --details local
+ local atributo_heal = _detalhes.atributo_heal --details local
+ local atributo_energy = _detalhes.atributo_energy --details local
+ local atributo_misc = _detalhes.atributo_misc --details local
+ local alvo_da_habilidade = _detalhes.alvo_da_habilidade --details local
+ local habilidade_dano = _detalhes.habilidade_dano --details local
+ local habilidade_cura = _detalhes.habilidade_cura --details local
+ local container_habilidades = _detalhes.container_habilidades --details local
+ local container_combatentes = _detalhes.container_combatentes --details local
+
+ local container_damage_target = _detalhes.container_type.CONTAINER_DAMAGETARGET_CLASS
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> constants
+
+ local class_type_dano = _detalhes.atributos.dano
+ local class_type_cura = _detalhes.atributos.cura
+ local class_type_e_energy = _detalhes.atributos.e_energy
+ local class_type_misc = _detalhes.atributos.misc
+ local DFLAG_pet = _detalhes.flags.pet
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> core
+
+ local function ReconstroiMapa (tabela)
+ local mapa = {}
+ for i = 1, #tabela._ActorTable do
+ mapa [tabela._ActorTable[i].nome] = i
+ end
+ tabela._NameIndexTable = mapa
+ end
+
+ local function ReduzTotal (_actor, _combate)
+ if (_actor.tipo == class_type_dano) then
+ _combate.totals [class_type_dano] = _combate.totals [class_type_dano] - _actor.total
+ if (_actor.grupo) then
+ _combate.totals_grupo [class_type_dano] = _combate.totals_grupo [class_type_dano] - _actor.total
+ end
+
+ elseif (_actor.tipo == class_type_cura) then
+ _combate.totals [class_type_cura] = _combate.totals [class_type_cura] - _actor.total
+ if (_actor.grupo) then
+ _combate.totals_grupo [class_type_cura] = _combate.totals_grupo [class_type_cura] - _actor.total
+ end
+
+ elseif (_actor.tipo == class_type_e_energy) then
+ _combate.totals [_actor.tipo] ["mana"] = _combate.totals [_actor.tipo] ["mana"] - _actor.mana
+ _combate.totals [_actor.tipo] ["e_rage"] = _combate.totals [_actor.tipo] ["e_rage"] - _actor.e_rage
+ _combate.totals [_actor.tipo] ["e_energy"] = _combate.totals [_actor.tipo] ["e_energy"] - _actor.e_energy
+ _combate.totals [_actor.tipo] ["runepower"] = _combate.totals [_actor.tipo] ["runepower"] - _actor.runepower
+
+ if (_actor.grupo) then
+ _combate.totals_grupo [_actor.tipo] ["runepower"] = _combate.totals_grupo [_actor.tipo] ["runepower"] - _actor.runepower
+ _combate.totals_grupo [_actor.tipo] ["e_energy"] = _combate.totals_grupo [_actor.tipo] ["e_energy"] - _actor.e_energy
+ _combate.totals_grupo [_actor.tipo] ["e_rage"] = _combate.totals_grupo [_actor.tipo] ["e_rage"] - _actor.e_rage
+ _combate.totals_grupo [_actor.tipo] ["mana"] = _combate.totals_grupo [_actor.tipo] ["mana"] - _actor.mana
+ end
+
+ elseif (_actor.tipo == class_type_misc) then
+ if (_actor.cc_break) then
+ _combate.totals [_actor.tipo] ["cc_break"] = _combate.totals [_actor.tipo] ["cc_break"] - _actor.cc_break
+ if (_actor.grupo) then
+ _combate.totals_grupo [_actor.tipo] ["cc_break"] = _combate.totals_grupo [_actor.tipo] ["cc_break"] - _actor.cc_break
+ end
+ end
+ if (_actor.ress) then
+ _combate.totals [_actor.tipo] ["ress"] = _combate.totals [_actor.tipo] ["ress"] - _actor.ress
+ if (_actor.grupo) then
+ _combate.totals_grupo [_actor.tipo] ["ress"] = _combate.totals_grupo [_actor.tipo] ["ress"] - _actor.ress
+ end
+ end
+ if (_actor.interrupt) then
+ _combate.totals [_actor.tipo] ["interrupt"] = _combate.totals [_actor.tipo] ["interrupt"] - _actor.interrupt
+ if (_actor.grupo) then
+ _combate.totals_grupo [_actor.tipo] ["interrupt"] = _combate.totals_grupo [_actor.tipo] ["interrupt"] - _actor.interrupt
+ end
+ end
+ if (_actor.dispell) then
+ _combate.totals [_actor.tipo] ["dispell"] = _combate.totals [_actor.tipo] ["dispell"] - _actor.dispell
+ if (_actor.grupo) then
+ _combate.totals_grupo [_actor.tipo] ["dispell"] = _combate.totals_grupo [_actor.tipo] ["dispell"] - _actor.dispell
+ end
+ end
+ if (_actor.dead) then
+ _combate.totals [_actor.tipo] ["dead"] = _combate.totals [_actor.tipo] ["dead"] - _actor.dead
+ if (_actor.grupo) then
+ _combate.totals_grupo [_actor.tipo] ["dead"] = _combate.totals_grupo [_actor.tipo] ["dead"] - _actor.dead
+ end
+ end
+ end
+ end
+
+ function _detalhes:RestauraMetaTables()
+
+ ----------------------------//containers principais
+ _detalhes.refresh:r_container_pets (_detalhes.tabela_pets)
+ _detalhes.refresh:r_historico (_detalhes.tabela_historico)
+
+ ----------------------------//combates
+
+ local tabela_overall = _detalhes.tabela_overall
+
+ local overall_dano = tabela_overall [class_type_dano]
+ local overall_cura = tabela_overall [class_type_cura]
+ local overall_energy = tabela_overall [class_type_e_energy]
+ local overall_misc = tabela_overall [class_type_misc]
+
+ local tabelas_de_combate = {}
+ for _, _tabela in _ipairs (_detalhes.tabela_historico.tabelas) do
+ tabelas_de_combate [#tabelas_de_combate+1] = _tabela
+ _tabela.__call = _detalhes.call_combate
+ end
+
+ tabela_overall.end_time = _tempo
+ tabela_overall.start_time = _tempo
+
+ if (#tabelas_de_combate > 0) then
+ for index, combate in _ipairs (tabelas_de_combate) do
+
+ if (combate.end_time and combate.start_time) then
+ tabela_overall.start_time = tabela_overall.start_time - (combate.end_time - combate.start_time)
+ end
+
+ _detalhes.refresh:r_combate (combate, tabela_overall)
+
+ _detalhes.refresh:r_container_combatentes (combate [class_type_dano], overall_dano)
+ _detalhes.refresh:r_container_combatentes (combate [class_type_cura], overall_cura)
+ _detalhes.refresh:r_container_combatentes (combate [class_type_e_energy], overall_energy)
+ _detalhes.refresh:r_container_combatentes (combate [class_type_misc], overall_misc)
+
+ local todos_atributos = {combate [class_type_dano]._ActorTable,
+ combate [class_type_cura]._ActorTable,
+ combate [class_type_e_energy]._ActorTable,
+ combate [class_type_misc]._ActorTable}
+
+ for class_type, atributo in _ipairs (todos_atributos) do
+ for _, esta_classe in _ipairs (atributo) do
+
+ local nome = esta_classe.nome
+ esta_classe.displayName = nome:gsub (("%-.*"), "")
+
+ local shadow
+
+ if (class_type == class_type_dano) then
+
+ shadow = overall_dano._ActorTable [overall_dano._NameIndexTable[nome]]
+ if (not shadow) then
+ --shadow = overall_dano:CriarShadow (esta_classe)
+ shadow = overall_dano:PegarCombatente (esta_classe.serial, esta_classe.nome, esta_classe.flag_original, true)
+ shadow.classe = esta_classe.classe
+ shadow.start_time = _tempo
+ shadow.end_time = _tempo
+ end
+ -- Reconstruir o container do friendly fire shadow aqui
+ for index, friendlyfire in _ipairs (esta_classe.friendlyfire._ActorTable) do
+ --> criando o objeto do friendly fire na shadow
+ local ff_shadow = shadow.friendlyfire:PegarCombatente (friendlyfire.serial, friendlyfire.nome, friendlyfire.flag_original, true)
+ friendlyfire.shadow = ff_shadow
+
+ end
+ _detalhes.refresh:r_atributo_damage (esta_classe, shadow)
+ shadow = shadow + esta_classe
+
+ elseif (class_type == class_type_cura) then
+ shadow = overall_cura._ActorTable [overall_cura._NameIndexTable[nome]]
+ if (not shadow) then
+ --shadow = overall_cura:CriarShadow (esta_classe)
+ shadow = overall_cura:PegarCombatente (esta_classe.serial, esta_classe.nome, esta_classe.flag_original, true)
+ shadow.classe = esta_classe.classe
+ shadow.start_time = _tempo
+ shadow.end_time = _tempo
+ end
+ _detalhes.refresh:r_atributo_heal (esta_classe, shadow)
+ shadow = shadow + esta_classe
+
+ elseif (class_type == class_type_e_energy) then
+ shadow = overall_energy._ActorTable [overall_energy._NameIndexTable[nome]]
+ if (not shadow) then
+ --shadow = overall_energy:CriarShadow (esta_classe)
+ shadow = overall_energy:PegarCombatente (esta_classe.serial, esta_classe.nome, esta_classe.flag_original, true)
+ shadow.classe = esta_classe.classe
+ end
+ _detalhes.refresh:r_atributo_energy (esta_classe, shadow)
+ shadow = shadow + esta_classe
+
+ elseif (class_type == class_type_misc) then
+
+ -- o problema ta na habilidade do interrupt, aqui ele só ta recriando os containers no Actor principal e não esta itinerando nas habilidades
+
+ shadow = overall_misc._ActorTable [overall_misc._NameIndexTable[nome]]
+
+ if (not shadow) then
+ --shadow = overall_misc:CriarShadow (esta_classe)
+ shadow = overall_misc:PegarCombatente (esta_classe.serial, esta_classe.nome, esta_classe.flag_original, true)
+ shadow.classe = esta_classe.classe
+ end
+
+ if (esta_classe.interrupt) then
+ if (not shadow.interrupt_targets) then
+ shadow.interrupt = 0
+ shadow.interrupt_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ shadow.interrupt_spell_tables = container_habilidades:NovoContainer (_detalhes.container_type.CONTAINER_MISC_CLASS) --> cria o container das habilidades usadas para interromper
+ shadow.interrompeu_oque = {}
+ end
+ end
+
+ if (esta_classe.ress) then
+ if (not shadow.ress_targets) then
+ shadow.ress = 0
+ shadow.ress_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ shadow.ress_spell_tables = container_habilidades:NovoContainer (_detalhes.container_type.CONTAINER_MISC_CLASS) --> cria o container das habilidades usadas para interromper
+ end
+ end
+
+ if (esta_classe.dispell) then
+ if (not shadow.dispell_targets) then
+ shadow.dispell = 0
+ shadow.dispell_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ shadow.dispell_spell_tables = container_habilidades:NovoContainer (_detalhes.container_type.CONTAINER_MISC_CLASS) --> cria o container das habilidades usadas para interromper
+ shadow.dispell_oque = {}
+ end
+ end
+
+ if (esta_classe.cc_break) then
+ if (not shadow.cc_break) then
+ shadow.cc_break = 0
+ shadow.cc_break_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ shadow.cc_break_spell_tables = container_habilidades:NovoContainer (_detalhes.container_type.CONTAINER_MISC_CLASS) --> cria o container das habilidades usadas para interromper
+ shadow.cc_break_oque = {}
+ end
+ end
+
+ _detalhes.refresh:r_atributo_misc (esta_classe, shadow)
+ shadow = shadow + esta_classe
+
+ if (esta_classe.interrupt) then
+ for _, este_alvo in _ipairs (esta_classe.interrupt_targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, shadow.interrupt_targets)
+ end
+ end
+ if (esta_classe.ress) then
+ for _, este_alvo in _ipairs (esta_classe.ress_targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, shadow.ress_targets)
+ end
+ end
+ if (esta_classe.dispell) then
+ for _, este_alvo in _ipairs (esta_classe.dispell_targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, shadow.dispell_targets)
+ end
+ end
+ if (esta_classe.cc_break) then
+ for _, este_alvo in _ipairs (esta_classe.cc_break_targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, shadow.cc_break_targets)
+ end
+ end
+ end
+
+ shadow:FazLinkagem (esta_classe)
+
+ if (class_type ~= class_type_misc) then
+ for _, este_alvo in _ipairs (esta_classe.targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, shadow.targets)
+ end
+
+ for _, habilidade in _pairs (esta_classe.spell_tables._ActorTable) do
+ if (class_type == class_type_dano) then
+ _detalhes.refresh:r_habilidade_dano (habilidade, shadow.spell_tables) --> passando o container de habilidades
+ elseif (class_type == class_type_cura) then
+ _detalhes.refresh:r_habilidade_cura (habilidade, shadow.spell_tables)
+ elseif (class_type == class_type_e_energy) then
+ _detalhes.refresh:r_habilidade_e_energy (habilidade, shadow.spell_tables)
+ end
+
+ for _, este_alvo in _ipairs (habilidade.targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, habilidade.targets.shadow)
+ end
+ end
+ else
+ if (esta_classe.interrupt) then
+ for _, habilidade in _pairs (esta_classe.interrupt_spell_tables._ActorTable) do
+ _detalhes.refresh:r_habilidade_misc (habilidade, shadow.interrupt_spell_tables)
+
+ for _, este_alvo in _ipairs (habilidade.targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, habilidade.targets.shadow)
+ end
+ end
+ end
+
+ if (esta_classe.ress) then
+ for _, habilidade in _pairs (esta_classe.ress_spell_tables._ActorTable) do
+ _detalhes.refresh:r_habilidade_misc (habilidade, shadow.ress_spell_tables)
+
+ for _, este_alvo in _ipairs (habilidade.targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, habilidade.targets.shadow)
+ end
+ end
+ end
+
+ if (esta_classe.dispell) then
+ for _, habilidade in _pairs (esta_classe.dispell_spell_tables._ActorTable) do
+ _detalhes.refresh:r_habilidade_misc (habilidade, shadow.dispell_spell_tables)
+
+ for _, este_alvo in _ipairs (habilidade.targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, habilidade.targets.shadow)
+ end
+ end
+ end
+
+ if (esta_classe.cc_break) then
+ for _, habilidade in _pairs (esta_classe.cc_break_spell_tables._ActorTable) do
+ _detalhes.refresh:r_habilidade_misc (habilidade, shadow.cc_break_spell_tables)
+
+ for _, este_alvo in _ipairs (habilidade.targets._ActorTable) do
+ _detalhes.refresh:r_alvo_da_habilidade (este_alvo, habilidade.targets.shadow)
+ end
+ end
+ end
+
+ end
+ end
+ end
+
+ --> reconstrói a tabela dos pets
+ for class_type, atributo in _ipairs (todos_atributos) do
+ for _, esta_classe in _ipairs (atributo) do
+ if (esta_classe.ownerName) then --> nome do owner
+ esta_classe.owner = combate (class_type, esta_classe.ownerName)
+ end
+ end
+ end
+
+ end
+ end
+ end
+
+
+ function _detalhes:PrepareTablesForSave()
+
+ ----------------------------//overall
+
+ local tabelas_de_combate = {}
+
+ local historico_tabelas = _detalhes.tabela_historico.tabelas or {}
+
+ --local tabela_overall = _detalhes.tabela_overall
+ _detalhes.tabela_overall = nil
+
+ local tabela_atual = _detalhes.tabela_vigente or {}
+
+ for _, _tabela in _ipairs (historico_tabelas) do
+ tabelas_de_combate [#tabelas_de_combate+1] = _tabela
+ end
+
+ tabelas_de_combate [#tabelas_de_combate+1] = tabela_atual
+ --tabelas_de_combate [#tabelas_de_combate+1] = tabela_overall
+
+ --> make sure details database exists
+ _detalhes_database = _detalhes_database or {}
+
+ for tabela_index, _combate in _ipairs (tabelas_de_combate) do
+
+ --> limpa a tabela do grafico -- clear graphic table
+ if (_detalhes.clear_graphic) then
+ _combate.TimeData = {}
+ end
+
+ local container_dano = _combate [class_type_dano] or {}
+ local container_cura = _combate [class_type_cura] or {}
+ local container_e_energy = _combate [class_type_e_energy] or {}
+ local container_misc = _combate [class_type_misc] or {}
+
+ local todos_atributos = {container_dano, container_cura, container_e_energy, container_misc}
+
+ local IsBossEncounter = _combate.is_boss
+ if (IsBossEncounter) then
+ if (_combate.pvp) then
+ IsBossEncounter = false
+ end
+ end
+
+ for class_type, _tabela in _ipairs (todos_atributos) do
+
+ local conteudo = _tabela._ActorTable
+
+ --> Limpa tabelas que não estejam em grupo
+ if (_detalhes.clear_ungrouped) then
+
+ local _iter = {index = 1, data = conteudo[1], cleaned = 0} --> ._ActorTable[1] para pegar o primeiro index
+
+ while (_iter.data) do --serach key: deletar apagar
+ local can_erase = true
+
+ if (_iter.data.grupo or _iter.data.boss or _iter.data.boss_fight_component or IsBossEncounter) then
+ can_erase = false
+ else
+ local owner = _iter.data.owner
+ if (owner) then
+ local owner_actor = _combate (class_type, owner.nome)
+ if (owner_actor) then
+ if (owner.grupo or owner.boss or owner.boss_fight_component) then
+ can_erase = false
+ end
+ end
+ end
+ end
+
+ if (can_erase) then
+
+ if (not _iter.data.owner) then --> pet (not a pet?)
+ local myself = _iter.data
+
+ if (myself.tipo == class_type_dano or myself.tipo == class_type_cura) then
+ _combate.totals [myself.tipo] = _combate.totals [myself.tipo] - myself.total
+ if (myself.grupo) then
+ _combate.totals_grupo [myself.tipo] = _combate.totals_grupo [myself.tipo] - myself.total
+ end
+ elseif (myself.tipo == class_type_e_energy) then
+ _combate.totals [myself.tipo] ["mana"] = _combate.totals [myself.tipo] ["mana"] - myself.mana
+ _combate.totals [myself.tipo] ["e_rage"] = _combate.totals [myself.tipo] ["e_rage"] - myself.e_rage
+ _combate.totals [myself.tipo] ["e_energy"] = _combate.totals [myself.tipo] ["e_energy"] - myself.e_energy
+ _combate.totals [myself.tipo] ["runepower"] = _combate.totals [myself.tipo] ["runepower"] - myself.runepower
+ if (myself.grupo) then
+ _combate.totals_grupo [myself.tipo] ["mana"] = _combate.totals_grupo [myself.tipo] ["mana"] - myself.mana
+ _combate.totals_grupo [myself.tipo] ["e_rage"] = _combate.totals_grupo [myself.tipo] ["e_rage"] - myself.e_rage
+ _combate.totals_grupo [myself.tipo] ["e_energy"] = _combate.totals_grupo [myself.tipo] ["e_energy"] - myself.e_energy
+ _combate.totals_grupo [myself.tipo] ["runepower"] = _combate.totals_grupo [myself.tipo] ["runepower"] - myself.runepower
+ end
+ elseif (myself.tipo == class_type_misc) then
+ if (myself.cc_break) then
+ _combate.totals [myself.tipo] ["cc_break"] = _combate.totals [myself.tipo] ["cc_break"] - myself.cc_break
+ if (myself.grupo) then
+ _combate.totals_grupo [myself.tipo] ["cc_break"] = _combate.totals_grupo [myself.tipo] ["cc_break"] - myself.cc_break
+ end
+ end
+ if (myself.ress) then
+ _combate.totals [myself.tipo] ["ress"] = _combate.totals [myself.tipo] ["ress"] - myself.ress
+ if (myself.grupo) then
+ _combate.totals_grupo [myself.tipo] ["ress"] = _combate.totals_grupo [myself.tipo] ["ress"] - myself.ress
+ end
+ end
+ if (myself.interrupt) then
+ _combate.totals [myself.tipo] ["interrupt"] = _combate.totals [myself.tipo] ["interrupt"] - myself.interrupt
+ if (myself.grupo) then
+ _combate.totals_grupo [myself.tipo] ["interrupt"] = _combate.totals_grupo [myself.tipo] ["interrupt"] - myself.interrupt
+ end
+ end
+ if (myself.dispell) then
+ _combate.totals [myself.tipo] ["dispell"] = _combate.totals [myself.tipo] ["dispell"] - myself.dispell
+ if (myself.grupo) then
+ _combate.totals_grupo [myself.tipo] ["dispell"] = _combate.totals_grupo [myself.tipo] ["dispell"] - myself.dispell
+ end
+ end
+ if (myself.dead) then
+ _combate.totals [myself.tipo] ["dead"] = _combate.totals [myself.tipo] ["dead"] - myself.dead
+ if (myself.grupo) then
+ _combate.totals_grupo [myself.tipo] ["dead"] = _combate.totals_grupo [myself.tipo] ["dead"] - myself.dead
+ end
+ end
+ end
+ end
+
+ _table_remove (conteudo, _iter.index)
+ _iter.cleaned = _iter.cleaned + 1
+ _iter.data = conteudo [_iter.index]
+ else
+ _iter.index = _iter.index + 1
+ _iter.data = conteudo [_iter.index]
+ end
+ end
+
+ if (_iter.cleaned > 0) then --> desencargo de consciência, reconstruir o mapa depois de excluir
+ ReconstroiMapa (_tabela)
+ end
+
+ end
+
+ for _, esta_classe in _ipairs (conteudo) do
+
+ --> limpa o displayName, não precisa salvar
+ esta_classe.displayName = nil
+ esta_classe.owner = nil
+
+ if (class_type == class_type_dano) then
+ _detalhes.clear:c_atributo_damage (esta_classe)
+ elseif (class_type == class_type_cura) then
+ _detalhes.clear:c_atributo_heal (esta_classe)
+ elseif (class_type == class_type_e_energy) then
+ _detalhes.clear:c_atributo_energy (esta_classe)
+ elseif (class_type == class_type_misc) then
+ _detalhes.clear:c_atributo_misc (esta_classe)
+
+ if (esta_classe.interrupt) then
+ for _, _alvo in _ipairs (esta_classe.interrupt_targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+
+ if (esta_classe.ress) then
+ for _, _alvo in _ipairs (esta_classe.ress_targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+
+ if (esta_classe.dispell) then
+ for _, _alvo in _ipairs (esta_classe.dispell_targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+
+ if (esta_classe.cc_break) then
+ for _, _alvo in _ipairs (esta_classe.cc_break_targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+ end
+
+ if (class_type ~= class_type_misc) then
+ for _, _alvo in _ipairs (esta_classe.targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+
+ for _, habilidade in _pairs (esta_classe.spell_tables._ActorTable) do
+ if (class_type == class_type_dano) then
+ _detalhes.clear:c_habilidade_dano (habilidade)
+ elseif (class_type == class_type_cura) then
+ _detalhes.clear:c_habilidade_cura (habilidade)
+ elseif (class_type == class_type_e_energy) then
+ _detalhes.clear:c_habilidade_e_energy (habilidade)
+ end
+
+ for _, _alvo in ipairs (habilidade.targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+ else
+ if (esta_classe.interrupt) then
+ for _, habilidade in _pairs (esta_classe.interrupt_spell_tables._ActorTable) do
+ _detalhes.clear:c_habilidade_misc (habilidade)
+
+ for _, _alvo in ipairs (habilidade.targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+ end
+
+ if (esta_classe.ress) then
+ for _, habilidade in _pairs (esta_classe.ress_spell_tables._ActorTable) do
+ _detalhes.clear:c_habilidade_misc (habilidade)
+
+ for _, _alvo in ipairs (habilidade.targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+ end
+
+ if (esta_classe.dispell) then
+ for _, habilidade in _pairs (esta_classe.dispell_spell_tables._ActorTable) do
+ _detalhes.clear:c_habilidade_misc (habilidade)
+
+ for _, _alvo in ipairs (habilidade.targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+ end
+
+ if (esta_classe.cc_break) then
+ for _, habilidade in _pairs (esta_classe.cc_break_spell_tables._ActorTable) do
+ _detalhes.clear:c_habilidade_misc (habilidade)
+
+ for _, _alvo in ipairs (habilidade.targets._ActorTable) do
+ _detalhes.clear:c_alvo_da_habilidade (_alvo)
+ end
+ end
+ end
+ end
+
+ end
+ end
+
+ end
+
+ --> Clear Containers
+ for tabela_index, _combate in _ipairs (tabelas_de_combate) do
+ local container_dano = _combate [class_type_dano]
+ local container_cura = _combate [class_type_cura]
+ local container_e_energy = _combate [class_type_e_energy]
+ local container_misc = _combate [class_type_misc]
+
+ local todos_atributos = {container_dano, container_cura, container_e_energy, container_misc}
+
+ for class_type, _tabela in _ipairs (todos_atributos) do
+ _detalhes.clear:c_combate (_combate)
+ _detalhes.clear:c_container_combatentes (container_dano)
+ _detalhes.clear:c_container_combatentes (container_cura)
+ _detalhes.clear:c_container_combatentes (container_e_energy)
+ _detalhes.clear:c_container_combatentes (container_misc)
+ end
+ end
+
+ --> Limpa instâncias
+
+ for _, esta_instancia in _ipairs (_detalhes.tabela_instancias) do
+ --> detona a janela do Solo Mode
+
+ esta_instancia.barras = nil
+ esta_instancia.showing = nil
+
+ --> apaga os frames
+ esta_instancia.scroll = nil
+ esta_instancia.baseframe = nil
+ esta_instancia.bgframe = nil
+ esta_instancia.bgdisplay = nil
+ esta_instancia.freeze_icon = nil
+ esta_instancia.freeze_texto = nil
+
+ esta_instancia.agrupada_a = nil
+ esta_instancia.grupada_pos = nil
+ esta_instancia.agrupado = nil
+
+ if (esta_instancia.StatusBar.left) then
+ esta_instancia.StatusBarSaved = {
+ ["left"] = esta_instancia.StatusBar.left.real_name or "NONE",
+ ["center"] = esta_instancia.StatusBar.center.real_name or "NONE",
+ ["right"] = esta_instancia.StatusBar.right.real_name or "NONE",
+ ["options"] = esta_instancia.StatusBar.options
+ }
+ end
+
+ esta_instancia.StatusBar = nil
+
+ end
+
+ end
+
+ function _detalhes:reset_window (instancia)
+ if (instancia.segmento == -1) then
+ instancia.showing[instancia.atributo].need_refresh = true
+ instancia.v_barras = true
+ instancia:ResetaGump()
+ instancia:AtualizaGumpPrincipal (true)
+ end
+ end
+
+
+
+ function _detalhes:IniciarColetaDeLixo()
+
+ if (_detalhes.ultima_coleta + _detalhes.intervalo_coleta > _detalhes._tempo + 1) then
+ return
+ elseif (_detalhes.in_combat or _InCombatLockdown() or _detalhes:IsInInstance()) then
+ _detalhes:ScheduleTimer ("IniciarColetaDeLixo", 5)
+ return
+ end
+
+ _detalhes:ClearParserCache()
+
+ local limpados = atributo_damage:ColetarLixo() + atributo_heal:ColetarLixo() + atributo_energy:ColetarLixo() + atributo_misc:ColetarLixo()
+
+ if (limpados > 0) then
+ _detalhes:InstanciaCallFunction (_detalhes.reset_window)
+ end
+
+ --print ("coletados: " .. limpados)
+
+ _detalhes.ultima_coleta = _detalhes._tempo
+
+ end
+
+
+
+ local function FazColeta (_combate, tipo)
+
+ local conteudo = _combate [tipo]._ActorTable
+ local _iter = {index = 1, data = conteudo[1], cleaned = 0}
+ local _tempo = _time()
+
+ while (_iter.data) do
+
+ local _actor = _iter.data
+ local can_garbage = false
+
+ if (not _actor.grupo and not _actor.boss and not _actor.boss_fight_component and _actor.last_event + _detalhes.intervalo_coleta < _tempo) then
+ local owner = _actor.owner
+ if (owner) then
+ local owner_actor = _combate (tipo, owner.nome)
+ if (not owner.grupo and not owner.boss and not owner.boss_fight_component) then
+ can_garbage = true
+ end
+ else
+ can_garbage = true
+ end
+ end
+
+ if (can_garbage) then
+ if (not _actor.owner) then --> pet
+ ReduzTotal (_actor, _combate)
+ end
+
+ --> fix para a weak table
+ local shadow = _actor.shadow
+ local _it = {index = 1, link = shadow.links [1]}
+ while (_it.link) do
+ if (_it.link == _actor) then
+ _table_remove (shadow.links, _it.index)
+ _it.link = shadow.links [_it.index]
+ else
+ _it.index = _it.index+1
+ _it.link = shadow.links [_it.index]
+ end
+ end
+
+ _iter.cleaned = _iter.cleaned+1
+ _table_remove (conteudo, _iter.index)
+ _iter.data = conteudo [_iter.index]
+ else
+ _iter.index = _iter.index + 1
+ _iter.data = conteudo [_iter.index]
+ end
+
+ end
+
+ if (_iter.cleaned > 0) then
+ ReconstroiMapa (_combate [tipo])
+ _combate [tipo].need_refresh = true
+ end
+
+ return _iter.cleaned
+ end
+
+ function _detalhes:ColetarLixo (tipo)
+
+ for index, instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (instancia:IsAtiva()) then
+ for i, barra in _ipairs (instancia.barras) do
+ if (not barra:IsShown()) then
+ barra.minha_tabela = nil
+ end
+ end
+ end
+ end
+
+ local _tempo = _time()
+ local limpados = 0
+
+ local tabelas_de_combate = {}
+ for _, _tabela in _ipairs (_detalhes.tabela_historico.tabelas) do
+ if (_tabela ~= _detalhes.tabela_vigente) then
+ tabelas_de_combate [#tabelas_de_combate+1] = _tabela
+ end
+ end
+ tabelas_de_combate [#tabelas_de_combate+1] = _detalhes.tabela_vigente
+
+ for _, _combate in _ipairs (tabelas_de_combate) do
+ limpados = limpados + FazColeta (_combate, tipo)
+ end
+
+ --> clear shadow tables
+ local _overall_combat = _detalhes.tabela_overall
+ local conteudo = _overall_combat [tipo]._ActorTable
+ _iter = {index = 1, data = conteudo[1], cleaned = 0} --> ._ActorTable[1] para pegar o primeiro index
+
+ collectgarbage()
+
+ while (_iter.data) do
+
+ local _actor = _iter.data
+
+ local meus_links = _rawget (_actor, "links")
+ local can_garbage = true
+ local new_weak_table = _setmetatable ({}, _detalhes.weaktable) --> precisa da nova weak table para remover os NILS da tabela antiga
+
+ if (meus_links) then
+ for _, ref in _pairs (meus_links) do --> trocando pairs por _ipairs
+ if (ref) then
+ can_garbage = false
+ new_weak_table [#new_weak_table+1] = ref
+ end
+ end
+ _table_wipe (meus_links)
+ end
+
+ if (tipo == 1 and #new_weak_table > 0) then
+ -- print (can_garbage, _actor.nome)
+ end
+
+
+ if (can_garbage or not meus_links) then --> não há referências a este objeto
+
+ if (not _actor.owner) then --> pet
+ ReduzTotal (_actor, _overall_combat)
+ end
+
+ --> apaga a referência deste jogador na tabela overall
+ _iter.cleaned = _iter.cleaned+1
+ _table_remove (conteudo, _iter.index)
+ _iter.data = conteudo [_iter.index]
+ else
+ _actor.links = new_weak_table
+ _iter.index = _iter.index + 1
+ _iter.data = conteudo [_iter.index]
+ end
+
+ end
+
+ --> elimina pets antigos
+ local _new_PetTable = {}
+ for PetSerial, PetTable in _pairs (_detalhes.tabela_pets.pets) do
+ if (PetTable[4] + _detalhes.intervalo_coleta > _detalhes._tempo + 1) then
+ _new_PetTable [PetSerial] = PetTable
+ end
+ end
+
+ _table_wipe (_detalhes.tabela_pets.pets)
+ _detalhes.tabela_pets.pets = _new_PetTable
+
+ --> wipa container de escudos
+ _table_wipe (_detalhes.escudos)
+
+ --> termina o coletor de lixo
+ if (_iter.cleaned > 0) then
+ _overall_combat[tipo].need_refresh = true
+ ReconstroiMapa (_overall_combat [tipo])
+ limpados = limpados + _iter.cleaned
+ end
+
+ if (limpados > 0) then
+ _detalhes:InstanciaCallFunction (_detalhes.ScheduleUpdate)
+ _detalhes:AtualizaGumpPrincipal (-1)
+ end
+
+ return limpados
+ end
diff --git a/core/parser.lua b/core/parser.lua
new file mode 100644
index 00000000..fcf12f63
--- /dev/null
+++ b/core/parser.lua
@@ -0,0 +1,1955 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+ local _tempo = time()
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _UnitAffectingCombat = UnitAffectingCombat --wow api local
+ local _UnitHealth = UnitHealth --wow api local
+ local _UnitHealthMax = UnitHealthMax --wow api local
+ local _UnitIsFeignDeath = UnitIsFeignDeath --wow api local
+ local _GetInstanceInfo = GetInstanceInfo --wow api local
+
+ local _cstr = string.format --lua local
+ local _table_insert = table.insert --lua local
+ local _select = select --lua local
+ local _bit_band = bit.band --lua local
+ local _math_floor = math.floor --lua local
+ local _table_remove = table.remove --lua local
+ local _ipairs = ipairs --lua local
+ local _pairs = pairs --lua local
+ local _table_sort = table.sort --lua local
+ local _type = type --lua local
+ local _math_ceil = math.ceil --lua local
+
+ local escudo = _detalhes.escudos --details local
+ local parser = _detalhes.parser --details local
+ local absorb_spell_list = _detalhes.AbsorbSpells --details local
+ local cc_spell_list = _detalhes.CrowdControlSpells --details local
+ local container_combatentes = _detalhes.container_combatentes --details local
+ local container_habilidades = _detalhes.container_habilidades --details local
+
+ --> current combat and overall pointers
+ local _current_combat = _detalhes.tabela_vigente or {} --> placeholder table
+ local _overall_combat = _detalhes.tabela_overall or {} --> placeholder table
+ --> total container pointers
+ local _current_total = _current_combat.totals
+ local _current_gtotal = _current_combat.totals_grupo
+ local _overall_total = _overall_combat.totals
+ local _overall_gtotal = _overall_combat.totals_grupo
+ --> actors container pointers
+ local _current_damage_container = _current_combat [1]
+ local _overall_damage_container = _overall_combat [1]
+ local _current_heal_container = _current_combat [2]
+ local _overall_heal_container = _overall_combat [2]
+ local _current_energy_container = _current_combat [3]
+ local _overall_energy_container = _overall_combat [3]
+ local _current_misc_container = _current_combat [4]
+ local _overall_misc_container = _overall_combat [4]
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> cache
+ --> damage
+ local damage_cache = {}
+ --> heaing
+ local healing_cache = {}
+ --> energy
+ local energy_cache = {}
+ --> misc
+ local misc_cache = {}
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> constants
+
+ local container_damage_target = _detalhes.container_type.CONTAINER_DAMAGETARGET_CLASS
+ local container_misc = _detalhes.container_type.CONTAINER_MISC_CLASS
+
+ local OBJECT_TYPE_PLAYER = 0x00000400
+ local OBJECT_TYPE_PETS = 0x00003000
+ local AFFILIATION_GROUP = 0x00000007
+ local REACTION_FRIENDLY = 0x00000010
+
+ --> recording data options shortcuts
+ local _recording_self_buffs = false
+ local _recording_ability_with_buffs = false
+ local _recording_took_damage = false
+ --> in combat shortcut
+ local _in_combat = false
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+ --> DAMAGE serach key: ~damage |
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+ function parser:swing (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing)
+ return parser:spell_dmg (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, 1, "Corpo-a-Corpo", 00000001, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing) --> localize-me
+ --spellid, spellname, spelltype
+ end
+
+ function parser:range (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing)
+ return parser:spell_dmg (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, 2, "Tiro-Automático", 00000001, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing) --> localize-me
+ --spellid, spellname, spelltype
+ end
+
+ function parser:spell_dmg (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, amount, overkill, school, resisted, blocked, absorbed, critical, glacing, crushing)
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ if (who_serial == "0x0000000000000000") then
+ if (who_flags and _bit_band (who_flags, OBJECT_TYPE_PETS) ~= 0) then --> é um pet
+ --> pets must have an serial
+ return
+ end
+ who_serial = nil
+ end
+
+ if (not alvo_name) then
+ --> no target name, just quit
+ return
+ elseif (not who_name) then
+ --> no actor name, use spell name instead
+ who_name = "[*] "..spellname
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> check if need start an combat
+
+ if (not _in_combat) then
+ if ( token ~= "SPELL_PERIODIC_DAMAGE" and
+ (
+ ( _bit_band (who_flags, AFFILIATION_GROUP) ~= 0 and _UnitAffectingCombat (who_name) )
+ or
+ (_bit_band (alvo_flags, AFFILIATION_GROUP) ~= 0 and _UnitAffectingCombat (alvo_name) )
+ )) then
+
+ --> não entra em combate se for DOT
+ _detalhes:EntrarEmCombate (who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags)
+ end
+ end
+
+ _current_damage_container.need_refresh = true
+ _overall_damage_container.need_refresh = true
+
+ ------------------------------------------------------------------------------------------------
+ --> get actors
+
+ --> damager
+ local este_jogador, meu_dono = damage_cache [who_name]
+
+ if (not este_jogador) then --> pode ser um desconhecido ou um pet
+
+ este_jogador, meu_dono, who_name = _current_damage_container:PegarCombatente (who_serial, who_name, who_flags, true)
+
+ if (not meu_dono) then --> se não for um pet, adicionar no cache
+ --> fazer: precisa ser com cache
+ local search = _detalhes.tabela_pets.pets [who_serial]
+ if (not search) then --> make sure isn't a pet
+ damage_cache [who_name] = este_jogador
+ end
+ end
+ end
+
+ --> his target
+ local jogador_alvo, alvo_dono = damage_cache [alvo_name]
+ if (not jogador_alvo) then
+ jogador_alvo, alvo_dono, alvo_name = _current_damage_container:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ --> fazer: precisa ser com cache
+ if (not alvo_dono and not _detalhes.tabela_pets.pets [alvo_serial]) then
+ damage_cache [alvo_name] = jogador_alvo
+ end
+ end
+
+ --> damager shadow
+ local shadow = este_jogador.shadow
+ local shadow_of_target = jogador_alvo.shadow
+
+ --> last event
+ este_jogador.last_event = _tempo
+ shadow.last_event = _tempo
+
+ ------------------------------------------------------------------------------------------------
+ --> group checks and avoidance
+
+ if (este_jogador.grupo) then
+ _current_gtotal [1] = _current_gtotal [1]+amount
+ _overall_gtotal [1] = _overall_gtotal [1]+amount
+
+ elseif (jogador_alvo.grupo) then
+ --> record death log
+ _table_insert (jogador_alvo.last_events_table, 1, {true, spellid, amount, time, _UnitHealth (alvo_name), who_name }) --: [1] true = damage, false = heal [2] spellid [3] amount
+ _table_remove (jogador_alvo.last_events_table, 20) --> max 20 spots
+
+ --> record avoidance only for player actors
+ if (spellid < 3) then --> autoshot melee
+ jogador_alvo.avoidance ["HITS"] = jogador_alvo.avoidance ["HITS"] + 1
+ end
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> damage taken
+
+ --> target
+ jogador_alvo.damage_taken = jogador_alvo.damage_taken + amount --> adiciona o dano tomado
+ if (not jogador_alvo.damage_from [who_name]) then --> adiciona a pool de dano tomado de quem
+ jogador_alvo.damage_from [who_name] = true
+ end
+
+ --> his shadow
+ shadow_of_target.damage_taken = shadow_of_target.damage_taken + amount --> adiciona o dano tomado
+ if (not shadow_of_target.damage_from [who_name]) then --> adiciona a pool de dano tomado de quem
+ shadow_of_target.damage_from [who_name] = true
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> time start
+
+ if (not este_jogador.dps_started) then
+
+ este_jogador:Iniciar (true)
+
+ if (meu_dono and not meu_dono.dps_started) then
+ meu_dono:Iniciar (true)
+ if (meu_dono.end_time) then
+ meu_dono.end_time = nil
+ meu_dono.shadow.end_time = nil
+ else
+ meu_dono:IniciarTempo (_tempo-3.0, meu_dono.shadow)
+ end
+ end
+
+ if (este_jogador.end_time) then
+ este_jogador.end_time = nil
+ shadow.end_time = nil
+ else
+ este_jogador:IniciarTempo (_tempo-3.0, shadow)
+ end
+
+ if (este_jogador.nome == _detalhes.playername and token ~= "SPELL_PERIODIC_DAMAGE") then --> iniciando o dps do "PLAYER"
+ if (_detalhes.solo) then
+ --> save solo attributes
+ _detalhes:UpdateSolo()
+ end
+
+ if (_UnitAffectingCombat ("player")) then
+ _detalhes:SendEvent ("COMBAT_PLAYER_TIMESTARTED", nil, _current_combat, este_jogador)
+ end
+ end
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> firendly fire
+
+ if (_bit_band (who_flags, REACTION_FRIENDLY) ~= 0 and _bit_band (alvo_flags, REACTION_FRIENDLY) ~= 0) then
+ este_jogador.friendlyfire_total = este_jogador.friendlyfire_total + amount
+ shadow.friendlyfire_total = shadow.friendlyfire_total + amount
+
+ local amigo = este_jogador.friendlyfire._NameIndexTable [alvo_name]
+ if (not amigo) then
+ amigo = este_jogador.friendlyfire:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ else
+ amigo = este_jogador.friendlyfire._ActorTable [amigo]
+ end
+
+ amigo.total = amigo.total + amount
+ amigo.shadow.total = amigo.shadow.total + amount
+
+ local spell = amigo.spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = amigo.spell_tables:PegaHabilidade (spellid, true, token)
+ end
+
+ return spell:AddFF (amount) --adiciona a classe da habilidade, a classe da habilidade se encarrega de adicionar aos alvos dela
+ else
+ _current_total [1] = _current_total [1]+amount
+ _overall_total [1] = _overall_total [1]+amount
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> amount add
+
+ --> actor owner (if any)
+ if (meu_dono) then --> se for dano de um Pet
+ meu_dono.total = meu_dono.total + amount --> e adiciona o dano ao pet
+ meu_dono.shadow.total = meu_dono.shadow.total + amount --> e adiciona o dano ao pet
+ end
+
+ --> actor
+ este_jogador.total = este_jogador.total + amount
+ shadow.total = shadow.total + amount
+
+ --> actor without pets
+ este_jogador.total_without_pet = este_jogador.total_without_pet + amount
+ shadow.total_without_pet = shadow.total_without_pet + amount
+
+ --> actor targets
+ local este_alvo = este_jogador.targets._NameIndexTable [alvo_name]
+ if (not este_alvo) then
+ este_alvo = este_jogador.targets:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true) --retorna o objeto classe_target -> ALVO_DA_HABILIDADE:NovaTabela()
+ else
+ este_alvo = este_jogador.targets._ActorTable [este_alvo]
+ end
+ este_alvo.total = este_alvo.total + amount
+
+ --> actor spells table
+ local spell = este_jogador.spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = este_jogador.spell_tables:PegaHabilidade (spellid, true, token)
+ end
+
+ return spell:Add (alvo_serial, alvo_name, alvo_flags, amount, who_name, resisted, blocked, absorbed, critical, glacing, token)
+ end
+
+ function parser:swingmissed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, missType, isOffHand, amountMissed)
+ return parser:missed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, 1, "Corpo-a-Corpo", 00000001, missType, isOffHand, amountMissed)
+ end
+
+ function parser:rangemissed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, missType, isOffHand, amountMissed)
+ return parser:missed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, 2, "Tiro-Automático", 00000001, missType, isOffHand, amountMissed)
+ end
+
+ function parser:missed (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, missType, isOffHand, amountMissed)
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ if (not who_name or not alvo_name) then
+ return --> just return
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> get actors
+
+ --> 'misser'
+ local este_jogador = damage_cache [who_name]
+ if (not este_jogador) then
+ este_jogador, meu_dono, who_name = _current_damage_container:PegarCombatente (_, who_name)
+ if (not este_jogador) then
+ return --> just return if actor doen't exist yet
+ end
+ end
+
+ --> 'avoider'
+ --> using this method means avoidance of pets will not be tracked
+ local TargetActor = damage_cache [alvo_name]
+ if (TargetActor) then
+ local missTable = TargetActor.avoidance [missType]
+ if (missTable) then
+ TargetActor.avoidance [missType] = missTable +1
+ end
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> amount add
+
+ --> actor spells table
+ local spell = este_jogador.spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = este_jogador.spell_tables:PegaHabilidade (spellid, true, token)
+ end
+ return spell:AddMiss (alvo_serial, alvo_name, alvo_flags, who_name, missType)
+ end
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+ --> SUMMON serach key: ~summon |
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+ function parser:summon (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellName)
+
+ local sou_pet = _detalhes.tabela_pets.pets [who_serial]
+ if (sou_pet) then --> okey, ja é um pet
+ --print ("PET sumonando PET: who_name -> " .. who_name .. " meu dono -> "..sou_pet[1])
+ who_name, who_serial, who_flags = sou_pet[1], sou_pet[2], sou_pet[3]
+ end
+
+ local alvo_pet = _detalhes.tabela_pets.pets [alvo_serial]
+ if (alvo_pet) then
+ --print ("PET ALVO sumonando PET ALVO: who_name -> " .. who_name .. " meu dono -> "..sou_pet[1])
+ who_name, who_serial, who_flags = alvo_pet[1], alvo_pet[2], alvo_pet[3]
+ end
+
+ return _detalhes.tabela_pets:Adicionar (alvo_serial, alvo_name, alvo_flags, who_serial, who_name, who_flags)
+ end
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+ --> HEALING serach key: ~heal |
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+ function parser:heal (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, amount, overhealing, absorbed, critical, is_shield)
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ --> check nil serial against pets
+ if (who_serial == "0x0000000000000000") then
+ if (who_flags and _bit_band (who_flags, OBJECT_TYPE_PETS) ~= 0) then --> é um pet
+ return
+ end
+ who_serial = nil
+ end
+
+ --> no name, use spellname
+ if (not who_name) then
+ who_name = "[*] "..spellname
+ end
+
+ --> no target, just ignore
+ if (not alvo_name) then
+ return
+ end
+
+ --> checking shield and overheals
+ local cura_efetiva = absorbed
+ if (is_shield) then
+ cura_efetiva = amount
+ else
+ cura_efetiva = amount - overhealing
+ end
+
+ _current_heal_container.need_refresh = true
+ _overall_heal_container.need_refresh = true
+
+ ------------------------------------------------------------------------------------------------
+ --> get actors
+
+ local este_jogador, meu_dono = healing_cache [who_name]
+ if (not este_jogador) then --> pode ser um desconhecido ou um pet
+ este_jogador, meu_dono, who_name = _current_heal_container:PegarCombatente (who_serial, who_name, who_flags, true)
+ if (not meu_dono) then --> se não for um pet, adicionar no cache
+ healing_cache [who_name] = este_jogador
+ end
+ end
+
+ local jogador_alvo, alvo_dono = healing_cache [alvo_name]
+ if (not jogador_alvo) then
+ jogador_alvo, alvo_dono, alvo_name = _current_heal_container:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ if (not alvo_dono) then
+ healing_cache [alvo_name] = jogador_alvo
+ end
+ end
+
+ local shadow = este_jogador.shadow
+ local shadow_of_target = jogador_alvo.shadow
+
+ este_jogador.last_event = _tempo
+ shadow.last_event = _tempo
+
+ ------------------------------------------------------------------------------------------------
+ --> an enemy healing enemy or an player actor healing a enemy
+
+ if (_bit_band (alvo_flags, REACTION_FRIENDLY) == 0) then
+ if (not este_jogador.heal_enemy [spellid]) then
+ este_jogador.heal_enemy [spellid] = cura_efetiva
+ else
+ este_jogador.heal_enemy [spellid] = este_jogador.heal_enemy [spellid] + cura_efetiva
+ end
+
+ if (not este_jogador.shadow.heal_enemy [spellid]) then
+ este_jogador.shadow.heal_enemy [spellid] = cura_efetiva
+ else
+ este_jogador.shadow.heal_enemy [spellid] = este_jogador.shadow.heal_enemy [spellid] + cura_efetiva
+ end
+
+ return
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> group checks
+
+ if (este_jogador.grupo) then
+ _current_combat.totals_grupo[2] = _current_combat.totals_grupo[2]+amount
+ _overall_combat.totals_grupo[2] = _overall_combat.totals_grupo[2]+amount
+ end
+
+ if (jogador_alvo.grupo) then
+ _table_insert (jogador_alvo.last_events_table, 1, {false, spellid, amount, time, _UnitHealth (alvo_name), who_name}) --: [1] true = damage, false = heal [2] spellid [3] amount
+ _table_remove (jogador_alvo.last_events_table, 20) --> limita a 20 spots
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> timer
+
+ if (not este_jogador.iniciar_hps) then
+ este_jogador:Iniciar (true) --inicia o dps do jogador
+ if (este_jogador.end_time) then --> o combate terminou, reabrir o tempo
+ este_jogador.end_time = nil
+ shadow.end_time = nil --> não tenho certeza se isso aqui não pode dar merda
+ else
+ este_jogador:IniciarTempo (_tempo-3.0, shadow)
+ end
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> add amount
+
+ --> actor target
+ local este_alvo = este_jogador.targets._NameIndexTable [alvo_name]
+ if (not este_alvo) then
+ este_alvo = este_jogador.targets:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ else
+ este_alvo = este_jogador.targets._ActorTable [este_alvo]
+ end
+
+ if (cura_efetiva > 0) then
+
+ --> combat total
+ _current_total [2] = _current_total [2] + cura_efetiva
+ _overall_total [2] = _overall_total [2] + cura_efetiva
+
+ --> healing taken
+ jogador_alvo.healing_taken = jogador_alvo.healing_taken + cura_efetiva --> adiciona o dano tomado
+ if (not jogador_alvo.healing_from [who_name]) then --> adiciona a pool de dano tomado de quem
+ jogador_alvo.healing_from [who_name] = true
+ end
+
+ --> healing taken shadow
+ shadow_of_target.healing_taken = shadow_of_target.healing_taken+cura_efetiva --> adiciona o dano tomado
+ if (not shadow_of_target.healing_from [who_name]) then --> adiciona a pool de dano tomado de quem
+ shadow_of_target.healing_from [who_name] = true
+ end
+
+ --> actor healing amount
+ este_jogador.total = este_jogador.total + cura_efetiva
+ shadow.total = shadow.total + cura_efetiva
+
+ este_jogador.total_without_pet = este_jogador.total_without_pet + cura_efetiva
+ shadow.total_without_pet = shadow.total_without_pet + cura_efetiva
+
+ --> pet
+ if (meu_dono) then
+ meu_dono.total = meu_dono.total + cura_efetiva --> e adiciona o dano ao pet
+ meu_dono.shadow.total = meu_dono.shadow.total + cura_efetiva --> e adiciona o dano ao pet
+ end
+
+ --> target amount
+ este_alvo.total = este_alvo.total + cura_efetiva
+ end
+
+ if (overhealing > 0) then
+ este_jogador.totalover = este_jogador.totalover + overhealing
+ shadow.totalover = shadow.totalover + overhealing
+ este_alvo.overheal = este_alvo.overheal + overhealing
+ if (meu_dono) then
+ meu_dono.totalover = meu_dono.totalover + overhealing
+ meu_dono.shadow.totalover = meu_dono.shadow.totalover + overhealing
+ end
+ end
+
+ --> actor spells table
+ local spell = este_jogador.spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = este_jogador.spell_tables:PegaHabilidade (spellid, true, token)
+ end
+
+ if (is_shield) then
+ return spell:Add (alvo_serial, alvo_name, alvo_flags, cura_efetiva, who_name, 0, nil, overhealing, true)
+ else
+ return spell:Add (alvo_serial, alvo_name, alvo_flags, cura_efetiva, who_name, absorbed, critical, overhealing)
+ end
+ end
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+ --> BUFFS & DEBUFFS serach key: ~buff |
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+ function parser:buff (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, _, tipo, amount)
+
+ --> not yet well know about unnamed buff casters
+ if (not alvo_name) then
+ alvo_name = "[*] Unknow shield target"
+ elseif (not who_name) then
+ who_name = "[*] Unknow shield caster"
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> handle shields
+
+ if (tipo == "BUFF") then
+ if (absorb_spell_list [spellid] and amount) then
+ if (not escudo [alvo_name]) then
+ escudo [alvo_name] = {}
+ escudo [alvo_name] [spellid] = {}
+ escudo [alvo_name] [spellid] [who_name] = amount
+ elseif (not escudo [alvo_name] [spellid]) then
+ escudo [alvo_name] [spellid] = {}
+ escudo [alvo_name] [spellid] [who_name] = amount
+ else
+ escudo [alvo_name] [spellid] [who_name] = amount
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> recording buffs
+
+ elseif (_recording_self_buffs) then
+ --> or alvo_name needded, seems jade spirit not send who_name correctly
+ if (who_name == _detalhes.playername or alvo_name == _detalhes.playername) then
+ local bufftable = _detalhes.Buffs.BuffsTable [spellname]
+ if (bufftable) then
+ return bufftable:UpdateBuff ("new")
+ else
+ return false
+ end
+ end
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> recording debuffs applied by player
+
+ elseif (tipo == "DEBUFF") then
+ if (_recording_ability_with_buffs and _in_combat) then
+ if (who_name == _detalhes.playername) then
+
+ --> record debuff uptime
+ local SoloDebuffUptime = _current_combat.SoloDebuffUptime
+ if (not SoloDebuffUptime) then
+ SoloDebuffUptime = {}
+ _current_combat.SoloDebuffUptime = SoloDebuffUptime
+ end
+
+ local ThisDebuff = SoloDebuffUptime [spellid]
+
+ if (not ThisDebuff) then
+ ThisDebuff = {name = spellname, duration = 0, start = _tempo, castedAmt = 1, refreshAmt = 0, droppedAmt = 0, Active = true}
+ SoloDebuffUptime [spellid] = ThisDebuff
+ else
+ ThisDebuff.castedAmt = ThisDebuff.castedAmt + 1
+ ThisDebuff.start = _tempo
+ ThisDebuff.Active = true
+ end
+
+ --> record debuff spell and attack power
+ local SoloDebuffPower = _current_combat.SoloDebuffPower
+ if (not SoloDebuffPower) then
+ SoloDebuffPower = {}
+ _current_combat.SoloDebuffPower = SoloDebuffPower
+ end
+
+ local ThisDebuff = SoloDebuffPower [spellid]
+ if (not ThisDebuff) then
+ ThisDebuff = {}
+ SoloDebuffPower [spellid] = ThisDebuff
+ end
+
+ local ThisDebuffOnTarget = ThisDebuff [alvo_serial]
+
+ local base, posBuff, negBuff = UnitAttackPower ("player")
+ local AttackPower = base+posBuff+negBuff
+ local base, posBuff, negBuff = UnitRangedAttackPower ("player")
+ local RangedAttackPower = base+posBuff+negBuff
+ local SpellPower = GetSpellBonusDamage (3)
+
+ --> record buffs active on player when the debuff was applied
+ local BuffsOn = {}
+ for BuffName, BuffTable in _pairs (_detalhes.Buffs.BuffsTable) do
+ if (BuffTable.active) then
+ BuffsOn [#BuffsOn+1] = BuffName
+ end
+ end
+
+ if (not ThisDebuffOnTarget) then --> apply
+ ThisDebuff [alvo_serial] = {power = math.max (AttackPower, RangedAttackPower, SpellPower), onTarget = true, buffs = BuffsOn}
+ else --> re applying
+ ThisDebuff [alvo_serial].power = math.max (AttackPower, RangedAttackPower, SpellPower)
+ ThisDebuff [alvo_serial].buffs = BuffsOn
+ ThisDebuff [alvo_serial].onTarget = true
+ end
+
+ --> send event for plugins
+ _detalhes:SendEvent ("BUFF_UPDATE_DEBUFFPOWER")
+
+ end
+ end
+ end
+ end
+
+ function parser:buff_refresh (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, _, tipo, amount)
+
+ ------------------------------------------------------------------------------------------------
+ --> handle shields
+
+ if (tipo == "BUFF") then
+ if (absorb_spell_list [spellid] and amount) then
+
+ if (escudo [alvo_name] and escudo [alvo_name][spellid] and escudo [alvo_name][spellid][who_name]) then
+ local absorb = escudo [alvo_name][spellid][who_name] - amount
+ escudo [alvo_name][spellid][who_name] = amount
+
+ if (absorb > 0) then
+ return parser:heal (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, _, _math_ceil (absorb), 0, 0, 0, true)
+ end
+ else
+ --> should apply aura if not found in already applied buff list?
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> recording buffs
+
+ elseif (_recording_self_buffs) then
+ if (who_name == _detalhes.playername or alvo_name == _detalhes.playername) then --> foi colocado pelo player
+
+ local bufftable = _detalhes.Buffs.BuffsTable [spellname]
+ if (bufftable) then
+ return bufftable:UpdateBuff ("refresh")
+ else
+ return false
+ end
+ end
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> recording debuffs applied by player
+
+ elseif (tipo == "DEBUFF") then
+ if (_recording_ability_with_buffs and _in_combat) then
+ if (who_name == _detalhes.playername) then
+
+ --> record debuff uptime
+ local SoloDebuffUptime = _current_combat.SoloDebuffUptime
+ if (SoloDebuffUptime) then
+ local ThisDebuff = SoloDebuffUptime [spellid]
+ if (ThisDebuff and ThisDebuff.Active) then
+ ThisDebuff.refreshAmt = ThisDebuff.refreshAmt + 1
+ ThisDebuff.duration = ThisDebuff.duration + (_tempo - ThisDebuff.start)
+ ThisDebuff.start = _tempo
+
+ --> send event for plugins
+ _detalhes:SendEvent ("BUFF_UPDATE_DEBUFFPOWER")
+ end
+ end
+
+ --> record debuff spell and attack power
+ local SoloDebuffPower = _current_combat.SoloDebuffPower
+ if (SoloDebuffPower) then
+ local ThisDebuff = SoloDebuffPower [spellid]
+ if (ThisDebuff) then
+ local ThisDebuffOnTarget = ThisDebuff [alvo_serial]
+ if (ThisDebuffOnTarget) then
+ local base, posBuff, negBuff = UnitAttackPower ("player")
+ local AttackPower = base+posBuff+negBuff
+ local base, posBuff, negBuff = UnitRangedAttackPower ("player")
+ local RangedAttackPower = base+posBuff+negBuff
+ local SpellPower = GetSpellBonusDamage (3)
+
+ local BuffsOn = {}
+ for BuffName, BuffTable in _pairs (_detalhes.Buffs.BuffsTable) do
+ if (BuffTable.active) then
+ BuffsOn [#BuffsOn+1] = BuffName
+ end
+ end
+
+ ThisDebuff [alvo_serial].power = math.max (AttackPower, RangedAttackPower, SpellPower)
+ ThisDebuff [alvo_serial].buffs = BuffsOn
+
+ --> send event for plugins
+ _detalhes:SendEvent ("BUFF_UPDATE_DEBUFFPOWER")
+ end
+ end
+ end
+
+ end
+ end
+ end
+ end
+
+ function parser:unbuff (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, _, tipo, amount)
+
+ ------------------------------------------------------------------------------------------------
+ --> handle shields
+
+ if (tipo == "BUFF") then
+ if (absorb_spell_list [spellid]) then
+ if (escudo [alvo_name] and escudo [alvo_name][spellid] and escudo [alvo_name][spellid][who_name]) then
+ if (amount) then
+ local escudo_antigo = escudo [alvo_name][spellid][who_name]
+ if (escudo_antigo and escudo_antigo > amount) then
+ local absorb = escudo_antigo - amount
+ escudo [alvo_name][spellid][who_name] = nil
+ return parser:heal (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, _, _math_ceil (absorb), _math_ceil (escudo_antigo), 0, 0, true) --> último parametro IS_SHIELD
+ end
+ end
+ escudo [alvo_name][spellid][who_name] = nil
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> recording buffs
+
+ elseif (_recording_self_buffs) then
+ if (who_name == _detalhes.playername or alvo_name == _detalhes.playername) then --> foi colocado pelo player
+
+ local bufftable = _detalhes.Buffs.BuffsTable [spellname]
+ if (bufftable) then
+ return bufftable:UpdateBuff ("remove")
+ else
+ return false
+ end
+ end
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> recording debuffs applied by player
+
+ elseif (tipo == "DEBUFF") then
+ if (_recording_ability_with_buffs and _in_combat) then
+ if (who_name == _detalhes.playername) then
+
+ --> record debuff uptime
+ local SoloDebuffUptime = _current_combat.SoloDebuffUptime
+ local sendevent = false
+ if (SoloDebuffUptime) then
+ local ThisDebuff = SoloDebuffUptime [spellid]
+ if (ThisDebuff and ThisDebuff.Active) then
+ ThisDebuff.duration = ThisDebuff.duration + (_tempo - ThisDebuff.start)
+ ThisDebuff.droppedAmt = ThisDebuff.droppedAmt + 1
+ ThisDebuff.start = nil
+ ThisDebuff.Active = false
+ sendevent = true
+ end
+ end
+
+ --> record debuff spell and attack power
+ local SoloDebuffPower = _current_combat.SoloDebuffPower
+ if (SoloDebuffPower) then
+ local ThisDebuff = SoloDebuffPower [spellid]
+ if (ThisDebuff) then
+ ThisDebuff [alvo_serial] = nil
+ sendevent = true
+ end
+ end
+
+ if (sendevent) then
+ _detalhes:SendEvent ("BUFF_UPDATE_DEBUFFPOWER")
+ end
+ end
+ end
+ end
+ end
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+ --> ENERGY serach key: ~energy |
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+ function parser:energize (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, amount, powertype, p6, p7)
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ if (not who_name) then
+ who_name = "[*] "..spellname
+ elseif (not alvo_name) then
+ return
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> get regen key name
+
+ local key_regenDone
+ local key_regenFrom
+ local key_regenType
+
+ if (powertype == 0) then --> MANA
+ key_regenDone = "mana_r"
+ key_regenFrom = "mana_from"
+ key_regenType = "mana"
+ elseif (powertype == 1) then --> RAGE
+ key_regenDone = "e_rage_r"
+ key_regenFrom = "e_rage_from"
+ key_regenType = "e_rage"
+ elseif (powertype == 3) then --> ENERGY
+ key_regenDone = "e_energy_r"
+ key_regenFrom = "e_energy_from"
+ key_regenType = "e_energy"
+ elseif (powertype == 6) then --> RUNEPOWER
+ key_regenDone = "runepower_r"
+ key_regenFrom = "runepower_from"
+ key_regenType = "runepower"
+ else
+ --> not tracking this regen type
+ return
+ end
+
+ _current_energy_container.need_refresh = true
+ _overall_energy_container.need_refresh = true
+
+ ------------------------------------------------------------------------------------------------
+ --> get actors
+
+ --> main actor
+ local este_jogador, meu_dono = energy_cache [who_name]
+ if (not este_jogador) then --> pode ser um desconhecido ou um pet
+ este_jogador, meu_dono, who_name = _current_energy_container:PegarCombatente (who_serial, who_name, who_flags, true)
+ if (not meu_dono) then --> se não for um pet, adicionar no cache
+ energy_cache [who_name] = este_jogador
+ end
+ end
+
+ --> target
+ local jogador_alvo, alvo_dono = energy_cache [alvo_name]
+ if (not jogador_alvo) then
+ jogador_alvo, alvo_dono, alvo_name = _current_energy_container:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ if (not alvo_dono) then
+ energy_cache [alvo_name] = jogador_alvo
+ end
+ end
+
+ --> actor targets
+ local este_alvo = este_jogador.targets._NameIndexTable [alvo_name]
+ if (not este_alvo) then
+ este_alvo = este_jogador.targets:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true) --retorna o objeto classe_target -> ALVO_DA_HABILIDADE:NovaTabela()
+ else
+ este_alvo = este_jogador.targets._ActorTable [este_alvo]
+ end
+
+ local shadow = este_jogador.shadow
+ local shadow_of_target = jogador_alvo.shadow
+
+ este_jogador.last_event = _tempo
+ shadow.last_event = _tempo
+
+ ------------------------------------------------------------------------------------------------
+ --> amount add
+
+ --> combat total
+ _current_total [3] [key_regenType] = _current_total [3] [key_regenType] + amount
+ _overall_total [3] [key_regenType] = _overall_total [3] [key_regenType] + amount
+
+ if (este_jogador.grupo) then
+ _current_gtotal [3] [key_regenType] = _current_gtotal [3] [key_regenType] + amount
+ _overall_gtotal [3] [key_regenType] = _overall_gtotal [3] [key_regenType] + amount
+ end
+
+ --> regen produced amount
+ este_jogador [key_regenType] = este_jogador [key_regenType] + amount
+ shadow [key_regenType] = shadow [key_regenType] + amount
+ este_alvo [key_regenType] = este_alvo [key_regenType] + amount
+
+ --> target regenerated amount
+ jogador_alvo [key_regenDone] = jogador_alvo [key_regenDone] + amount
+ shadow_of_target [key_regenDone] = shadow_of_target [key_regenDone] + amount
+
+ --> regen from
+ if (not jogador_alvo [key_regenFrom] [who_name]) then
+ jogador_alvo [key_regenFrom] [who_name] = true
+ end
+ if (not shadow_of_target [key_regenFrom] [who_name]) then
+ shadow_of_target [key_regenFrom] [who_name] = true
+ end
+
+ --> owner
+ if (meu_dono) then
+ meu_dono [key_regenType] = meu_dono [key_regenType] + amount --> e adiciona o dano ao pet
+ meu_dono.shadow [key_regenType] = meu_dono.shadow [key_regenType] + amount --> e adiciona o dano ao pet
+ end
+
+ --> actor spells table
+ local spell = este_jogador.spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = este_jogador.spell_tables:PegaHabilidade (spellid, true, token)
+ end
+
+ return spell:Add (alvo_serial, alvo_name, alvo_flags, amount, who_name, powertype)
+ end
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------
+ --> MISC |
+-----------------------------------------------------------------------------------------------------------------------------------------
+
+ --serach key: ~interrupt
+ function parser:interrupt (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, extraSpellID, extraSpellName, extraSchool)
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ if (not who_name) then
+ who_name = "[*] "..spellname
+ elseif (not alvo_name) then
+ return
+ end
+
+ _current_misc_container.need_refresh = true
+ _overall_misc_container.need_refresh = true
+
+ ------------------------------------------------------------------------------------------------
+ --> get actors
+
+ --> main actor
+ local este_jogador, meu_dono = misc_cache [who_name]
+ if (not este_jogador) then --> pode ser um desconhecido ou um pet
+ este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
+ if (not meu_dono) then --> se não for um pet, adicionar no cache
+ misc_cache [who_name] = este_jogador
+ end
+ end
+
+ local shadow = este_jogador.shadow
+
+ ------------------------------------------------------------------------------------------------
+ --> build containers on the fly
+
+ if (not este_jogador.interrupt) then
+ este_jogador.interrupt = 0
+ este_jogador.interrupt_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ este_jogador.interrupt_spell_tables = container_habilidades:NovoContainer (container_misc) --> cria o container das habilidades usadas para interromper
+ este_jogador.interrompeu_oque = {}
+
+ if (not shadow.interrupt_targets) then
+ shadow.interrupt = 0
+ shadow.interrupt_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ shadow.interrupt_spell_tables = container_habilidades:NovoContainer (container_misc) --> cria o container das habilidades usadas para interromper
+ shadow.interrompeu_oque = {}
+ end
+
+ este_jogador.interrupt_targets.shadow = shadow.interrupt_targets
+ este_jogador.interrupt_spell_tables.shadow = shadow.interrupt_spell_tables
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> add amount
+
+ --> actor interrupt amount
+ este_jogador.interrupt = este_jogador.interrupt + 1
+ shadow.interrupt = shadow.interrupt + 1
+
+ --> combat totals
+ _current_total [4].interrupt = _current_total [4].interrupt + 1
+ _overall_total [4].interrupt = _overall_total [4].interrupt + 1
+
+ if (este_jogador.grupo) then
+ _current_gtotal [4].interrupt = _current_gtotal [4].interrupt + 1
+ _overall_gtotal [4].interrupt = _overall_gtotal [4].interrupt + 1
+ end
+
+ --> update last event
+ este_jogador.last_event = _tempo
+ shadow.last_event = _tempo
+
+ --> spells interrupted
+ if (not este_jogador.interrompeu_oque [extraSpellID]) then
+ este_jogador.interrompeu_oque [extraSpellID] = 1
+ else
+ este_jogador.interrompeu_oque [extraSpellID] = este_jogador.interrompeu_oque [extraSpellID] + 1
+ end
+
+ if (not shadow.interrompeu_oque [extraSpellID]) then
+ shadow.interrompeu_oque [extraSpellID] = 1
+ else
+ shadow.interrompeu_oque [extraSpellID] = shadow.interrompeu_oque [extraSpellID] + 1
+ end
+
+ --> actor targets
+ local este_alvo = este_jogador.interrupt_targets._NameIndexTable [alvo_name]
+ if (not este_alvo) then
+ este_alvo = este_jogador.interrupt_targets:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ else
+ este_alvo = este_jogador.interrupt_targets._ActorTable [este_alvo]
+ end
+ este_alvo.total = este_alvo.total + 1
+
+ --> actor spells table
+ local spell = este_jogador.interrupt_spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = este_jogador.interrupt_spell_tables:PegaHabilidade (spellid, true, token)
+ end
+ return spell:Add (alvo_serial, alvo_name, alvo_flags, who_name, token, extraSpellID, extraSpellName)
+
+ end
+
+ --serach key: ~dispell
+ function parser:dispell (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, extraSpellID, extraSpellName, extraSchool, auraType)
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ --> esta dando erro onde o nome é NIL, fazendo um fix para isso
+ if (not who_name) then
+ print ( "DISPELL sem who_name: [*] "..extraSpellName )
+ print (alvo_name)
+ print (spellname)
+ who_name = "[*] "..extraSpellName
+ end
+ if (not alvo_name) then
+ print ("DISPELL sem alvo_name: [*] "..extraSpellName)
+ print (who_name)
+ print (spellname)
+ alvo_name = "[*] "..spellid
+ end
+
+ _current_misc_container.need_refresh = true
+ _overall_misc_container.need_refresh = true
+
+ ------------------------------------------------------------------------------------------------
+ --> get actors
+
+ --> main actor
+ local este_jogador, meu_dono = misc_cache [who_name]
+ if (not este_jogador) then --> pode ser um desconhecido ou um pet
+ este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
+ if (not meu_dono) then --> se não for um pet, adicionar no cache
+ misc_cache [who_name] = este_jogador
+ end
+ end
+
+ local shadow = este_jogador.shadow
+
+ ------------------------------------------------------------------------------------------------
+ --> build containers on the fly
+
+ if (not este_jogador.dispell) then
+ --> constrói aqui a tabela dele
+ este_jogador.dispell = 0
+ este_jogador.dispell_targets = container_combatentes:NovoContainer (container_damage_target)
+ este_jogador.dispell_spell_tables = container_habilidades:NovoContainer (container_misc)
+ este_jogador.dispell_oque = {}
+
+ if (not shadow.dispell_targets) then
+ shadow.dispell = 0
+ shadow.dispell_targets = container_combatentes:NovoContainer (container_damage_target)
+ shadow.dispell_spell_tables = container_habilidades:NovoContainer (container_misc)
+ shadow.dispell_oque = {}
+ end
+
+ este_jogador.dispell_targets.shadow = shadow.dispell_targets
+ este_jogador.dispell_spell_tables.shadow = shadow.dispell_spell_tables
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> add amount
+
+ --> last event update
+ este_jogador.last_event = _tempo
+ shadow.last_event = _tempo
+
+ --> total dispells in combat
+ _current_total [4].dispell = _current_total [4].dispell + 1
+ _overall_total [4].dispell = _overall_total [4].dispell + 1
+
+ if (este_jogador.grupo) then
+ _current_gtotal [4].dispell = _current_gtotal [4].dispell + 1
+ _overall_gtotal [4].dispell = _overall_gtotal [4].dispell + 1
+ end
+
+ --> actor dispell amount
+ este_jogador.dispell = este_jogador.dispell + 1
+ shadow.dispell = shadow.dispell + 1
+
+ --> dispell what
+ if (not este_jogador.dispell_oque [spellid]) then
+ este_jogador.dispell_oque [spellid] = 1
+ else
+ este_jogador.dispell_oque [spellid] = este_jogador.dispell_oque [spellid] + 1
+ end
+
+ if (not shadow.dispell_oque [spellid]) then
+ shadow.dispell_oque [spellid] = 1
+ else
+ shadow.dispell_oque [spellid] = shadow.dispell_oque [spellid] + 1
+ end
+
+ --> actor targets
+ local este_alvo = este_jogador.dispell_targets._NameIndexTable [alvo_name]
+ if (not este_alvo) then
+ este_alvo = este_jogador.dispell_targets:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ else
+ este_alvo = este_jogador.dispell_targets._ActorTable [este_alvo]
+ end
+ este_alvo.total = este_alvo.total + 1
+
+ --> actor spells table
+ local spell = este_jogador.dispell_spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = este_jogador.dispell_spell_tables:PegaHabilidade (spellid, true, token)
+ end
+ return spell:Add (alvo_serial, alvo_name, alvo_flags, who_name, token, extraSpellID, extraSpellName)
+ end
+
+ --serach key: ~ress
+ function parser:ress (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname)
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ if (_bit_band (who_flags, AFFILIATION_GROUP) == 0) then
+ return
+ end
+
+ _current_misc_container.need_refresh = true
+ _overall_misc_container.need_refresh = true
+
+ ------------------------------------------------------------------------------------------------
+ --> get actors
+
+ --> main actor
+ local este_jogador, meu_dono = misc_cache [who_name]
+ if (not este_jogador) then --> pode ser um desconhecido ou um pet
+ este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
+ if (not meu_dono) then --> se não for um pet, adicionar no cache
+ misc_cache [who_name] = este_jogador
+ end
+ end
+
+ local shadow = este_jogador.shadow
+
+ ------------------------------------------------------------------------------------------------
+ --> build containers on the fly
+
+ if (not este_jogador.ress) then
+ --> constrói aqui a tabela dele
+ este_jogador.ress = 0
+ este_jogador.ress_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ este_jogador.ress_spell_tables = container_habilidades:NovoContainer (container_misc) --> cria o container das habilidades usadas para interromper
+
+ if (not shadow.ress_targets) then
+ shadow.ress = 0
+ shadow.ress_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ shadow.ress_spell_tables = container_habilidades:NovoContainer (container_misc) --> cria o container das habilidades usadas para interromper
+ end
+
+ este_jogador.ress_targets.shadow = shadow.ress_targets
+ este_jogador.ress_spell_tables.shadow = shadow.ress_spell_tables
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> add amount
+
+ --> update last event
+ este_jogador.last_event = _tempo
+ shadow.last_event = _tempo
+
+ --> combat ress total
+ _current_total [4].ress = _current_total [4].ress + 1
+ _overall_total [4].ress = _overall_total [4].ress + 1
+
+ if (este_jogador.grupo) then
+ _current_combat.totals_grupo[4].ress = _current_combat.totals_grupo[4].ress+1
+ _overall_combat.totals_grupo[4].ress = _overall_combat.totals_grupo[4].ress+1
+ end
+
+ --> add ress amount
+ este_jogador.ress = este_jogador.ress + 1
+ shadow.ress = shadow.ress + 1
+
+ --> add battle ress
+ if (_UnitAffectingCombat (who_name)) then
+ --> procura a última morte do alvo na tabela do combate:
+ for i = 1, #_current_combat.last_events_tables do
+ if (_current_combat.last_events_tables [i] [3] == alvo_name) then
+ --print ("Adicionando Bres para "..alvo_name)
+ local deadLog = _current_combat.last_events_tables [i] [1]
+ local jaTem = false
+ for _, evento in _ipairs (deadLog) do
+ if (evento [1] and not evento[3]) then
+ jaTem = true
+ end
+ end
+
+ if (not jaTem) then
+ _table_insert (_current_combat.last_events_tables [i] [1], 1, {true, spellid, false, time, _UnitHealth (alvo_name), who_name })
+ break
+ end
+ end
+ end
+ end
+
+ --> actor targets
+ local este_alvo = este_jogador.ress_targets._NameIndexTable [alvo_name]
+ if (not este_alvo) then
+ este_alvo = este_jogador.ress_targets:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ else
+ este_alvo = este_jogador.ress_targets._ActorTable [este_alvo]
+ end
+ este_alvo.total = este_alvo.total + 1
+
+ --> actor spells table
+ local spell = este_jogador.ress_spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = este_jogador.ress_spell_tables:PegaHabilidade (spellid, true, token)
+ end
+ return spell:Add (alvo_serial, alvo_name, alvo_flags, who_name, token, extraSpellID, extraSpellName)
+ end
+
+ --serach key: ~cc
+ function parser:break_cc (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, spellid, spellname, spelltype, extraSpellID, extraSpellName, extraSchool, auraType)
+
+ --print ("CCBREAK: ",spellid, spellname,extraSpellID, extraSpellName, auraType)
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ if (not cc_spell_list [extraSpellID]) then
+ return
+ end
+
+ if (_bit_band (who_flags, AFFILIATION_GROUP) == 0) then
+ return
+ end
+
+ if (not spellname) then
+ spellname = "Melee"
+ end
+
+ _current_misc_container.need_refresh = true
+ _overall_misc_container.need_refresh = true
+
+ ------------------------------------------------------------------------------------------------
+ --> get actors
+
+ --> main actor
+ local este_jogador, meu_dono = misc_cache [who_name]
+ if (not este_jogador) then --> pode ser um desconhecido ou um pet
+ este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (who_serial, who_name, who_flags, true)
+ if (not meu_dono) then --> se não for um pet, adicionar no cache
+ misc_cache [who_name] = este_jogador
+ end
+ end
+
+ local shadow = este_jogador.shadow
+
+ ------------------------------------------------------------------------------------------------
+ --> build containers on the fly
+
+ if (not este_jogador.cc_break) then
+ --> constrói aqui a tabela dele
+ este_jogador.cc_break = 0
+ este_jogador.cc_break_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ este_jogador.cc_break_spell_tables = container_habilidades:NovoContainer (container_misc) --> cria o container das habilidades usadas para interromper
+ este_jogador.cc_break_oque = {}
+
+ if (not shadow.cc_break) then
+ shadow.cc_break = 0
+ shadow.cc_break_targets = container_combatentes:NovoContainer (container_damage_target) --> pode ser um container de alvo de dano, pois irá usar apenas o .total
+ shadow.cc_break_spell_tables = container_habilidades:NovoContainer (container_misc) --> cria o container das habilidades usadas para interromper
+ shadow.cc_break_oque = {}
+ end
+
+ este_jogador.cc_break_targets.shadow = shadow.cc_break_targets
+ este_jogador.cc_break_spell_tables.shadow = shadow.cc_break_spell_tables
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> add amount
+
+ --> update last event
+ este_jogador.last_event = _tempo
+ shadow.last_event = _tempo
+
+ --> combat cc break total
+ _current_total [4].cc_break = _current_total [4].cc_break + 1
+ _overall_total [4].cc_break = _overall_total [4].cc_break + 1
+
+ if (este_jogador.grupo) then
+ _current_combat.totals_grupo[4].cc_break = _current_combat.totals_grupo[4].cc_break+1
+ _overall_combat.totals_grupo[4].cc_break = _overall_combat.totals_grupo[4].cc_break+1
+ end
+
+ --> add amount
+ este_jogador.cc_break = este_jogador.cc_break + 1
+ shadow.cc_break = shadow.cc_break + 1
+
+ --> broke what
+ if (not este_jogador.cc_break_oque [extraSpellID]) then
+ este_jogador.cc_break_oque [extraSpellID] = 1
+ else
+ este_jogador.cc_break_oque [extraSpellID] = este_jogador.cc_break_oque [extraSpellID] + 1
+ end
+
+ if (not shadow.cc_break_oque [extraSpellID]) then
+ shadow.cc_break_oque [extraSpellID] = 1
+ else
+ shadow.cc_break_oque [extraSpellID] = shadow.cc_break_oque [extraSpellID] + 1
+ end
+
+ --> actor targets
+ local este_alvo = este_jogador.cc_break_targets._NameIndexTable [alvo_name]
+ if (not este_alvo) then
+ este_alvo = este_jogador.cc_break_targets:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ else
+ este_alvo = este_jogador.cc_break_targets._ActorTable [este_alvo]
+ end
+ este_alvo.total = este_alvo.total + 1
+
+ --> actor spells table
+ local spell = este_jogador.cc_break_spell_tables._ActorTable [spellid]
+ if (not spell) then
+ spell = este_jogador.cc_break_spell_tables:PegaHabilidade (spellid, true, token)
+ end
+ return spell:Add (alvo_serial, alvo_name, alvo_flags, who_name, token, extraSpellID, extraSpellName)
+ end
+
+ --serach key: ~dead ~death
+ function parser:dead (token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags)
+
+ --> not yet well cleaned, need more improvements
+
+ ------------------------------------------------------------------------------------------------
+ --> early checks and fixes
+
+ if (not alvo_name) then
+ return
+ end
+
+ ------------------------------------------------------------------------------------------------
+ --> build dead
+
+ if (not _UnitIsFeignDeath (alvo_name)) then
+ if (
+ --> player in your group
+ _bit_band (alvo_flags, AFFILIATION_GROUP) ~= 0 and
+ --> must be a player
+ _bit_band (alvo_flags, OBJECT_TYPE_PLAYER) ~= 0 and
+ --> must be in combat
+ _in_combat
+ ) then
+
+ --> true dead was a attempt to get the last hit because parser sometimes send the dead token before send the hit wich really killed the actor
+ --> but unfortunately seems parser not send at all any damage after actor dead
+ --_detalhes:ScheduleTimer ("TrueDead", 1, {time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags})
+
+ _current_misc_container.need_refresh = true
+ _overall_misc_container.need_refresh = true
+
+ --> combat totals
+ _current_total [4].dead = _current_total [4].dead + 1
+ _overall_total [4].dead = _overall_total [4].dead + 1
+ _current_gtotal [4].dead = _current_gtotal [4].dead + 1
+ _overall_gtotal [4].dead = _overall_gtotal [4].dead + 1
+
+ --> main actor
+ local este_jogador, meu_dono = misc_cache [alvo_name]
+ if (not este_jogador) then --> pode ser um desconhecido ou um pet
+ este_jogador, meu_dono, who_name = _current_misc_container:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true)
+ if (not meu_dono) then --> se não for um pet, adicionar no cache
+ misc_cache [alvo_name] = este_jogador
+ end
+ end
+
+ --> monta a estrutura da morte
+ local dano = _current_combat[1]:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true) --> container do dano
+ local cura = _current_combat[2]:PegarCombatente (alvo_serial, alvo_name, alvo_flags, true) --> container da cura
+ local esta_morte = {}
+
+ if (dano.last_events_table) then
+
+ local novaTabela = {}
+ local counter = 1
+ for i = 1, #dano.last_events_table, 1 do
+
+ local este_dano = dano.last_events_table[i]
+ local proximo_dano = dano.last_events_table[counter+1]
+
+ if (este_dano and proximo_dano) then
+
+ local spellId_this = este_dano[2]
+ local tempo_this = este_dano[4]
+
+ local spellId_next = proximo_dano[2]
+ local tempo_next = proximo_dano[4]
+
+ if (spellId_this == spellId_next and _cstr ("%.1f", tempo_this) == _cstr ("%.1f", tempo_next)) then
+ este_dano[3] = este_dano[3] + proximo_dano[3]
+ if (not este_dano [7]) then
+ este_dano[7] = 2
+ else
+ este_dano[7] = este_dano[7] + 1
+ end
+ _table_remove (dano.last_events_table, counter+1)
+ end
+
+ end
+
+ counter = counter + 1
+
+ end
+
+ local amt = 0
+ for index, tabela in _ipairs (dano.last_events_table) do
+ if (tabela [4] + 12 > time) then --> mostra apenas eventos recentes
+ esta_morte [#esta_morte+1] = tabela
+ amt = amt + 1
+ end
+ end
+ end
+
+ if (cura.last_events_table) then
+ local amt = 0
+ for index, tabela in _ipairs (cura.last_events_table) do
+ if (tabela [4] + 12 > time) then --> mostra apenas eventos recentes
+ esta_morte [#esta_morte+1] = tabela
+ amt = amt + 1
+ end
+ end
+ end
+
+ _table_sort (esta_morte, function (a, b) return a[4] > b[4] end)
+
+ if (_detalhes.deadlog_limit and #esta_morte > _detalhes.deadlog_limit) then
+ for i = #esta_morte, _detalhes.deadlog_limit+1, -1 do
+ _table_remove (esta_morte, i)
+ end
+ end
+
+ local decorrido = _tempo - _current_combat.start_time
+ local minutos, segundos = _math_floor (decorrido/60), _math_floor (decorrido%60)
+
+ local t = {esta_morte, time, este_jogador.nome, este_jogador.classe, _UnitHealthMax (alvo_name), minutos.."m "..segundos.."s", ["dead"] = true}
+
+ --print ("A morte teve "..#esta_morte.." eventos")
+
+ _table_insert (_current_combat.last_events_tables, #_current_combat.last_events_tables+1, t)
+ _table_insert (_overall_combat.last_events_tables, #_current_combat.last_events_tables+1, t)
+
+ --> reseta a pool
+ dano.last_events_table = {}
+ cura.last_events_table = {}
+
+ end
+ end
+ end
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> core
+
+ local token_list = {
+ -- neutral
+ ["SPELL_SUMMON"] = parser.summon,
+ }
+
+ --serach key: ~capture
+
+ _detalhes.capture_types = {"damage", "heal", "energy", "miscdata", "aura"}
+
+ function _detalhes:CaptureRefresh()
+ for _, _thisType in _ipairs (_detalhes.capture_types) do
+ if (_detalhes.capture_current [_thisType]) then
+ _detalhes:CaptureEnable (_thisType)
+ else
+ _detalhes:CaptureDisable (_thisType)
+ end
+ end
+ end
+
+ function _detalhes:CaptureSet (on_off, capture_type, real, time)
+
+ if (real) then
+ --> hard switch
+ _detalhes.capture_real [capture_type] = on_off
+ _detalhes.capture_current [capture_type] = on_off
+ else
+ --> soft switch
+ _detalhes.capture_current [capture_type] = on_off
+ if (time) then
+ _detalhes:ScheduleTimer ("CaptureTimeout", time, capture_type)
+ end
+ end
+
+ _detalhes:CaptureRefresh()
+ end
+
+ function _detalhes:CaptureTimeout (capture_type)
+ _detalhes.capture_current [capture_type] = _detalhes.capture_real [capture_type]
+ _detalhes:CaptureRefresh()
+ end
+
+ function _detalhes:CaptureDisable (capture_type)
+
+ capture_type = string.lower (capture_type)
+
+ if (capture_type == "damage") then
+ token_list ["SPELL_PERIODIC_DAMAGE"] = nil
+ token_list ["SPELL_EXTRA_ATTACKS"] = nil
+ token_list ["SPELL_DAMAGE"] = nil
+ token_list ["SWING_DAMAGE"] = nil
+ token_list ["RANGE_DAMAGE"] = nil
+ token_list ["DAMAGE_SHIELD"] = nil
+ token_list ["DAMAGE_SPLIT"] = nil
+ token_list ["RANGE_MISSED"] = nil
+ token_list ["SWING_MISSED"] = nil
+ token_list ["SPELL_MISSED"] = nil
+
+ elseif (capture_type == "heal") then
+ token_list ["SPELL_HEAL"] = nil
+ token_list ["SPELL_PERIODIC_HEAL"] = nil
+
+ elseif (capture_type == "aura") then
+ token_list ["SPELL_AURA_APPLIED"] = nil
+ token_list ["SPELL_AURA_REMOVED"] = nil
+ token_list ["SPELL_AURA_REFRESH"] = nil
+
+ elseif (capture_type == "energy") then
+ token_list ["SPELL_ENERGIZE"] = nil
+ token_list ["SPELL_PERIODIC_ENERGIZE"] = nil
+
+ elseif (capture_type == "miscdata") then
+ -- dispell
+ token_list ["SPELL_DISPEL"] = nil
+ token_list ["SPELL_STOLEN"] = nil
+ -- cc broke
+ token_list ["SPELL_AURA_BROKEN"] = nil
+ token_list ["SPELL_AURA_BROKEN_SPELL"] = nil
+ -- ress
+ token_list ["SPELL_RESURRECT"] = nil
+ -- interrupt
+ token_list ["SPELL_INTERRUPT"] = nil
+ -- dead
+ token_list ["UNIT_DIED"] = nil
+
+ end
+ end
+
+ function _detalhes:CaptureEnable (capture_type)
+
+ capture_type = string.lower (capture_type)
+
+ if (capture_type == "damage") then
+ token_list ["SPELL_PERIODIC_DAMAGE"] = parser.spell_dmg
+ token_list ["SPELL_EXTRA_ATTACKS"] = parser.spell_dmg
+ token_list ["SPELL_DAMAGE"] = parser.spell_dmg
+ token_list ["SWING_DAMAGE"] = parser.swing
+ token_list ["RANGE_DAMAGE"] = parser.range
+ token_list ["DAMAGE_SHIELD"] = parser.spell_dmg
+ token_list ["DAMAGE_SPLIT"] = parser.spell_dmg
+ token_list ["RANGE_MISSED"] = parser.rangemissed
+ token_list ["SWING_MISSED"] = parser.swingmissed
+ token_list ["SPELL_MISSED"] = parser.missed
+
+ elseif (capture_type == "heal") then
+ token_list ["SPELL_HEAL"] = parser.heal
+ token_list ["SPELL_PERIODIC_HEAL"] = parser.heal
+
+ elseif (capture_type == "aura") then
+ token_list ["SPELL_AURA_APPLIED"] = parser.buff
+ token_list ["SPELL_AURA_REMOVED"] = parser.unbuff
+ token_list ["SPELL_AURA_REFRESH"] = parser.buff_refresh
+
+ elseif (capture_type == "energy") then
+ token_list ["SPELL_ENERGIZE"] = parser.energize
+ token_list ["SPELL_PERIODIC_ENERGIZE"] = parser.energize
+
+ elseif (capture_type == "miscdata") then
+ -- dispell
+ token_list ["SPELL_DISPEL"] = parser.dispell
+ token_list ["SPELL_STOLEN"] = parser.dispell
+ -- cc broke
+ token_list ["SPELL_AURA_BROKEN"] = parser.break_cc
+ token_list ["SPELL_AURA_BROKEN_SPELL"] = parser.break_cc
+ -- ress
+ token_list ["SPELL_RESURRECT"] = parser.ress
+ -- interrupt
+ token_list ["SPELL_INTERRUPT"] = parser.interrupt
+ -- dead
+ token_list ["UNIT_DIED"] = parser.dead
+
+ end
+ end
+
+
+ -- PARSER
+ --serach key: ~parser
+ function parser:do_parser (time, token, hidding, who_serial, who_name, who_flags, who_flags2, alvo_serial, alvo_name, alvo_flags, alvo_flags2, ...)
+
+ --print (token)
+
+ -- DEBUG
+
+ --[[
+ if (who_name == "Ditador") then
+ if (token:find ("CAST")) then
+
+ if (token == "SPELL_CAST_START") then
+ _detalhes.castStart = time
+ end
+
+ if (token == "SPELL_CAST_SUCCESS") then
+ local tempoGasto = time - _detalhes.castStart
+ local default_cast_time = 2500 -- 2.5 sec
+ print (tempoGasto)
+
+ local arg1, arg2, arg3, arg4, arg5 = select (1, ...)
+ local cd = GetSpellCooldown (arg1)
+ print (cd)
+ end
+ --local arg1, arg2, arg3, arg4, arg5 = select (1, ...)
+ --print (token, arg1, arg2, arg3, arg4, arg5)
+ --local name, rank, icon, cost, isFunnel, powerType, castTime, minRange, maxRange = GetSpellInfo (arg1)
+ --print (castTime)
+ end
+ end
+ --]]
+
+ local funcao = token_list [token]
+ if (funcao) then
+ return funcao (_, token, time, who_serial, who_name, who_flags, alvo_serial, alvo_name, alvo_flags, ... )
+ else
+ return
+ end
+ end
+
+ --serach key: ~event
+ function _detalhes:OnEvent (evento, ...)
+
+ if (evento == "COMBAT_LOG_EVENT_UNFILTERED") then
+ return parser:do_parser (...)
+
+ elseif (evento == "ZONE_CHANGED_NEW_AREA" or evento == "PLAYER_ENTERING_WORLD") then
+
+ local zoneName, zoneType, _, _, _, _, _, zoneMapID = _GetInstanceInfo()
+
+ _detalhes.zone_type = zoneType
+ _detalhes.zone_id = zoneMapID
+ _detalhes.zone_name = zoneName
+
+ if (zoneType == "pvp") then
+ if (not _current_combat.pvp) then
+ --print ("Battleground found, starting new combat table")
+ _detalhes:EntrarEmCombate()
+ --> sinaliza que esse combate é pvp
+ _current_combat.pvp = true
+ _current_combat.is_boss = {index = 0, name = zoneName, zone = ZoneName, mapid = ZoneMapID, encounter = zoneType}
+ _detalhes.listener:RegisterEvent ("CHAT_MSG_BG_SYSTEM_NEUTRAL")
+ end
+ else
+ if (_current_combat.pvp) then
+ _current_combat.pvp = false
+ end
+ end
+
+ return
+
+ elseif (evento == "CHAT_MSG_BG_SYSTEM_NEUTRAL") then
+ local frase = _select (1, ...)
+
+ --> reset combat timer
+ if ( (frase:find ("The battle") and frase:find ("has begun!") ) and _current_combat.pvp) then
+ local tempo_do_combate = _tempo - _current_combat.start_time
+ _detalhes.tabela_overall.start_time = _detalhes.tabela_overall.start_time + tempo_do_combate
+ _current_combat.start_time = _tempo
+ _detalhes.listener:UnregisterEvent ("CHAT_MSG_BG_SYSTEM_NEUTRAL")
+ end
+
+ return
+
+ elseif (evento == "PLAYER_REGEN_DISABLED") then -- Entrou em Combate
+ --> inicia um timer para pegar qual é a luta:
+
+ if (_detalhes.EncounterInformation [_detalhes.zone_id]) then
+ _detalhes:ScheduleTimer ("ReadBossFrames", 1)
+ end
+
+ --> essa parte do solo mode ainda sera usada?
+ if (_detalhes.solo and _detalhes.PluginCount.SOLO > 0) then --> solo mode
+ local esta_instancia = _detalhes.tabela_instancias[_detalhes.solo]
+ esta_instancia.atualizando = true
+ end
+
+ return
+
+ elseif (evento == "PLAYER_REGEN_ENABLED") then
+ --> essa parte do solo mode ainda sera usada?
+ if (_detalhes.solo and _detalhes.PluginCount.SOLO > 0) then --> aqui, tentativa de fazer o timer da janela do Solo funcionar corretamente:
+ if (_detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Stop) then
+ _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Stop()
+ end
+ end
+ return
+
+ elseif (evento == "RAID_ROSTER_UPDATE") then
+ _detalhes.container_pets:BuscarPets()
+ return
+
+ elseif (evento == "PARTY_MEMBERS_CHANGED") then
+ --> Nothing to do here
+ return
+
+ elseif (evento == "PARTY_CONVERTED_TO_RAID") then
+ --> Nothing to do here
+ return
+
+ elseif (evento == "INSTANCE_ENCOUNTER_ENGAGE_UNIT") then
+ --> Nothing to do here
+ return
+
+ elseif (evento == "PLAYER_LOGOUT") then
+
+ --> close info window
+ _detalhes:FechaJanelaInfo()
+
+ --> leave combat start save tables
+ if (_detalhes.in_combat) then
+ _detalhes:SairDoCombate()
+ end
+
+ return _detalhes:SaveData()
+
+ elseif (evento == "ADDON_LOADED") then
+
+ local addon_name = _select (1, ...)
+
+ if (addon_name == "Details") then
+ _detalhes:LoadData()
+ _detalhes:UpdateParserGears()
+ _detalhes:Start()
+ end
+
+ return
+
+ end
+ end
+
+ _detalhes.listener:SetScript ("OnEvent", _detalhes.OnEvent)
+
+ function _detalhes:UpdateParser()
+ _tempo = _detalhes._tempo
+ end
+
+ function _detalhes:ClearParserCache()
+ damage_cache = {}
+ healing_cache = {}
+ energy_cache = {}
+ misc_cache = {}
+ end
+
+ --serach key: ~cache
+ function _detalhes:UpdateParserGears()
+
+ --> refresh combat tables
+ _current_combat = _detalhes.tabela_vigente
+ _overall_combat = _detalhes.tabela_overall
+
+ --> refresh total containers
+ _current_total = _current_combat.totals
+ _current_gtotal = _current_combat.totals_grupo
+ _overall_total = _overall_combat.totals
+ _overall_gtotal = _overall_combat.totals_grupo
+
+ --> refresh actors containers
+ _current_damage_container = _current_combat [1]
+ _overall_damage_container = _overall_combat [1]
+ _current_heal_container = _current_combat [2]
+ _overall_heal_container = _overall_combat [2]
+ _current_energy_container = _current_combat [3]
+ _overall_energy_container = _overall_combat [3]
+ _current_misc_container = _current_combat [4]
+ _overall_misc_container = _overall_combat [4]
+
+ --> refresh data capture options
+ _recording_self_buffs = _detalhes.RecordPlayerSelfBuffs
+ _recording_took_damage = _detalhes.RecordRealTimeTookDamage
+ _recording_ability_with_buffs = _detalhes.RecordPlayerAbilityWithBuffs
+ _in_combat = _detalhes.in_combat
+
+ --> clear cache
+ damage_cache = {}
+ healing_cache = {}
+ energy_cache = {}
+ misc_cache = {}
+
+ end
+
+
+
+--serach key: ~api
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ --> number of combat
+ function _detalhes:GetCombatId()
+ return _detalhes.combat_id
+ end
+
+ --> if in combat
+ function _detalhes:IsInCombat()
+ return _in_combat
+ end
+
+ --> get combat
+ function _detalhes:GetCombat (_combat)
+ if (not _combat) then
+ return _current_combat
+ elseif (_type (_combat) == "number") then
+ if (_combat == -1) then --> overall
+ return _overall_combat
+ elseif (_combat == 0) then --> current
+ return _current_combat
+ else
+ return _detalhes.tabela_historico.tabelas [_combat]
+ end
+ elseif (_type (_combat) == "string") then
+ if (_combat == "overall") then
+ return _overall_combat
+ elseif (_combat == "current") then
+ return _current_combat
+ end
+ end
+
+ return nil
+ end
+
+ --> get an actor
+ function _detalhes:GetActor (_combat, _attribute, _actorname)
+
+ if (not _combat) then
+ _combat = "current" --> current combat
+ end
+
+ if (not _attribute) then
+ _attribute = 1 --> damage
+ end
+
+ if (not _actorname) then
+ _actorname = UnitName ("player")
+ end
+
+ if (_combat == 0 or _combat == "current") then
+ local actor = _current_combat (_attribute, _actorname)
+ if (actor) then
+ return actor
+ else
+ return nil --_detalhes:NewError ("Current combat doesn't have an actor called ".. _actorname)
+ end
+ elseif (_combat == -1 or _combat == "overall") then
+ local actor = _overall_combat (_attribute, _actorname)
+ if (actor) then
+ return actor
+ else
+ return nil --_detalhes:NewError ("Combat overall doesn't have an actor called ".. _actorname)
+ end
+ elseif (type (_combat) == "number") then
+ local _combatOnHistoryTables = _detalhes.tabela_historico.tabelas [_combat]
+ if (_combatOnHistoryTables) then
+ local actor = _combatOnHistoryTables (_attribute, _actorname)
+ if (actor) then
+ return actor
+ else
+ return nil --_detalhes:NewError ("Combat ".. _combat .." doesn't have an actor called ".. _actorname)
+ end
+ else
+ return nil --_detalhes:NewError ("Combat ".._combat.." not found.")
+ end
+ else
+ return nil --_detalhes:NewError ("Couldn't find a combat object for passed parameters")
+ end
+ end
+
+
diff --git a/core/plugins.lua b/core/plugins.lua
new file mode 100644
index 00000000..91d1ef76
--- /dev/null
+++ b/core/plugins.lua
@@ -0,0 +1,172 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+ local _detalhes = _G._detalhes
+ DETAILSPLUGIN_ALWAYSENABLED = 0x1
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ function _detalhes:InstallPlugin (PluginType, PluginName, PluginIcon, PluginObject, PluginAbsoluteName, MinVersion)
+
+ if (MinVersion and MinVersion > _detalhes.realversion) then
+ print (PluginName, Loc ["STRING_TOOOLD"])
+ return _detalhes:NewError ("Details version is out of date.")
+ end
+
+ if (not PluginType) then
+ return _detalhes:NewError ("InstallPlugin parameter 1 (plugin type) not especified")
+ elseif (not PluginName) then
+ return _detalhes:NewError ("InstallPlugin parameter 2 (plugin name) can't be nil")
+ elseif (not PluginIcon) then
+ return _detalhes:NewError ("InstallPlugin parameter 3 (plugin icon) can't be nil")
+ elseif (not PluginObject) then
+ return _detalhes:NewError ("InstallPlugin parameter 4 (plugin object) can't be nil")
+ elseif (not PluginAbsoluteName) then
+ return _detalhes:NewError ("InstallPlugin parameter 5 (plugin absolut name) can't be nil")
+ end
+
+ if (_G [PluginAbsoluteName]) then
+ print (Loc ["STRING_PLUGIN_NAMEALREADYTAKEN"] .. ": " .. PluginName .. " name: " .. PluginAbsoluteName)
+ return
+ else
+ _G [PluginAbsoluteName] = PluginObject
+ PluginObject.real_name = PluginAbsoluteName
+ end
+
+ PluginObject.real_name = PluginAbsoluteName
+
+ if (PluginType == "SOLO") then
+ if (not PluginObject.Frame) then
+ return _detalhes:NewError ("plugin doesn't have a Frame, please check case-sensitive member name: Frame")
+ end
+
+ --> Install Plugin
+ _detalhes.SoloTables.Plugins [#_detalhes.SoloTables.Plugins+1] = PluginObject
+ _detalhes.SoloTables.Menu [#_detalhes.SoloTables.Menu+1] = {PluginName, PluginIcon}
+ _detalhes.SoloTables.NameTable [PluginAbsoluteName] = PluginObject
+ _detalhes:SendEvent ("INSTALL_OKEY", PluginObject)
+
+ _detalhes.PluginCount.SOLO = _detalhes.PluginCount.SOLO + 1
+
+ return true
+
+ elseif (PluginType == "TANK") then
+
+ --> Install Plugin
+ _detalhes.RaidTables.Plugins [#_detalhes.RaidTables.Plugins+1] = PluginObject
+ _detalhes.RaidTables.Menu [#_detalhes.RaidTables.Menu+1] = {PluginName, PluginIcon}
+ _detalhes.RaidTables.NameTable [PluginAbsoluteName] = PluginObject
+ _detalhes:SendEvent ("INSTALL_OKEY", PluginObject)
+
+ _detalhes.PluginCount.RAID = _detalhes.PluginCount.RAID + 1
+
+ return true
+
+ elseif (PluginType == "TOOLBAR") then
+
+ --> Install Plugin
+ _detalhes.ToolBar.Plugins [#_detalhes.ToolBar.Plugins+1] = PluginObject
+ _detalhes.ToolBar.NameTable [PluginAbsoluteName] = PluginObject
+ _detalhes:SendEvent ("INSTALL_OKEY", PluginObject)
+
+ _detalhes.PluginCount.TOOLBAR = _detalhes.PluginCount.TOOLBAR + 1
+
+ return true
+
+ elseif (PluginType == "STATUSBAR") then
+
+ --> Install Plugin
+ _detalhes.StatusBar.Plugins [#_detalhes.StatusBar.Plugins+1] = PluginObject
+ _detalhes.StatusBar.Menu [#_detalhes.StatusBar.Menu+1] = {PluginName, PluginIcon}
+ _detalhes.StatusBar.NameTable [PluginAbsoluteName] = PluginObject
+ _detalhes:SendEvent ("INSTALL_OKEY", PluginObject)
+
+ _detalhes.PluginCount.STATUSBAR = _detalhes.PluginCount.STATUSBAR + 1
+
+ return true
+ end
+
+ end
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ _detalhes.PluginCount = {
+ ["SOLO"] = 0,
+ ["RAID"] = 0,
+ ["TOOLBAR"] = 0,
+ ["STATUSBAR"] = 0
+ }
+
+ local OnEnableFunction = function (self)
+ self.__parent.Enabled = true
+ _detalhes:SendEvent ("SHOW", self.__parent)
+ end
+
+ local OnDisableFunction = function (self)
+ _detalhes:SendEvent ("HIDE", self.__parent)
+ if (bit.band (self.__parent.__options, DETAILSPLUGIN_ALWAYSENABLED) == 0) then
+ self.__parent.Enabled = false
+ end
+ end
+
+ local BuildDefaultStatusBarMembers = function (self)
+ self.childs = {}
+ self.__index = self
+ function self:Setup()
+ _detalhes.StatusBar:OpenOptionsForChild (self)
+ end
+ end
+
+ local temp_event_function = function()
+ print ("=====================")
+ print ("Hello There plugin developer!")
+ print ("Please make sure you are declaring")
+ print ("A member called 'OnDetailsEvent' on your plugin object")
+ print ("With a function to receive the events like bellow:")
+ print ("function PluginObject:OnDetailsEvent (event, ...) end")
+ print ("Thank You Sir!===================")
+ end
+
+ function _detalhes:NewPluginObject (FrameName, PluginOptions, PluginType)
+
+ PluginOptions = PluginOptions or 0x0
+ local NewPlugin = {__options = PluginOptions}
+
+ local Frame = CreateFrame ("Frame", FrameName, UIParent)
+ Frame:RegisterEvent ("ADDON_LOADED")
+ Frame:RegisterEvent ("PLAYER_LOGOUT")
+ Frame:SetScript ("OnEvent", function(event, ...) return NewPlugin:OnEvent (event, ...) end)
+
+ Frame:Hide()
+ Frame.__parent = NewPlugin
+
+ if (bit.band (PluginOptions, DETAILSPLUGIN_ALWAYSENABLED) ~= 0) then
+ NewPlugin.Enabled = true
+ else
+ NewPlugin.Enabled = false
+ end
+
+ --> default members
+ if (PluginType == "STATUSBAR") then
+ BuildDefaultStatusBarMembers (NewPlugin)
+ end
+
+ NewPlugin.Frame = Frame
+
+ Frame:SetScript ("OnShow", OnEnableFunction)
+ Frame:SetScript ("OnHide", OnDisableFunction)
+
+ --> temporary details event function
+ NewPlugin.OnDetailsEvent = temp_event_function
+
+ setmetatable (NewPlugin, _detalhes)
+
+ return NewPlugin
+ end
diff --git a/core/plugins_raid.lua b/core/plugins_raid.lua
new file mode 100644
index 00000000..a4f5ac74
--- /dev/null
+++ b/core/plugins_raid.lua
@@ -0,0 +1,148 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _math_floor = math.floor --lua local
+
+ local gump = _detalhes.gump --details local
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> constants
+
+ local modo_raid = _detalhes._detalhes_props["MODO_RAID"]
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ function _detalhes:RaidMode (enable, instancia)
+ if (enable) then
+
+ _detalhes.RaidTables.instancia = instancia
+ _detalhes.RaidTables.Mode = _detalhes.RaidTables.Mode or 1 --> solo mode
+
+ instancia.modo = _detalhes._detalhes_props["MODO_RAID"]
+
+ gump:Fade (instancia, 1, nil, "barras")
+
+ if (instancia.rolagem) then
+ instancia:EsconderScrollBar (true) --> hida a scrollbar
+ end
+
+ _detalhes:ResetaGump (instancia)
+ instancia:DefaultIcons (true, false, true, false)
+
+ _detalhes.raid = instancia.meu_id
+ instancia:AtualizaGumpPrincipal (true)
+
+ if (not _detalhes.RaidTables.Plugins [1]) then
+ _detalhes:WaitForSoloPlugin (instancia)
+ else
+ if (not _detalhes.RaidTables.Plugins [_detalhes.RaidTables.Mode]) then
+ _detalhes.RaidTables.Mode = 1
+ end
+ _detalhes.RaidTables:switch (_, _detalhes.RaidTables.Mode)
+ end
+
+ else
+
+ _detalhes.RaidTables:switch()
+ _detalhes.raid = nil
+
+ if (_G.DetailsWaitForPluginFrame:IsShown()) then
+ _detalhes:CancelWaitForPlugin()
+ end
+
+ gump:Fade (instancia, 1, nil, "barras")
+ gump:Fade (instancia.scroll, 0)
+
+ if (instancia.need_rolagem) then
+ instancia:MostrarScrollBar (true)
+ else
+ --> precisa verificar se ele precisa a rolagem certo?
+ instancia:ReajustaGump()
+ end
+
+ instancia:DefaultIcons (true, true, true, true)
+
+ --> calcula se existem barras, etc...
+ if (not instancia.barrasInfo.cabem) then --> as barras não forma iniciadas ainda
+ instancia.barrasInfo.cabem = _math_floor (instancia.baseframe.BoxBarrasAltura / instancia.barrasInfo.alturaReal)
+ if (instancia.barrasInfo.criadas < instancia.barrasInfo.cabem) then
+ for i = #instancia.barras+1, instancia.barrasInfo.cabem do
+ local nova_barra = gump:CriaNovaBarra (instancia, i, 30) --> cria nova barra
+ nova_barra.texto_esquerdo:SetText (Loc ["STRING_NEWROW"])
+ nova_barra.statusbar:SetValue (100)
+ instancia.barras [i] = nova_barra
+ end
+ instancia.barrasInfo.criadas = #instancia.barras
+ end
+ end
+
+ end
+ end
+
+ function _detalhes:InstanciaCheckForDisabledRaid (instancia)
+
+ if (not instancia) then
+ instancia = self
+ end
+
+ if (instancia.modo == modo_raid) then
+ if (instancia.iniciada) then
+ _detalhes:AlteraModo (instancia, _detalhes._detalhes_props["MODO_GROUP"])
+ instancia:RaidMode (false, instancia)
+ _detalhes:ResetaGump (instancia)
+ else
+ instancia.modo = _detalhes._detalhes_props["MODO_GROUP"]
+ instancia.last_modo = _detalhes._detalhes_props["MODO_GROUP"]
+ end
+ end
+ end
+
+ function _detalhes.RaidTables:switch (_, _switchTo)
+
+ --> just hide all
+ if (not _switchTo) then
+ if (#_detalhes.RaidTables.Plugins > 0) then --> have at least one plugin
+ _detalhes.RaidTables.Plugins [_detalhes.RaidTables.Mode].Frame:Hide()
+ end
+ return
+ end
+
+ --> jump to the next
+ if (_switchTo == -1) then
+ _switchTo = _detalhes.RaidTables.Mode + 1
+ if (_switchTo > #_detalhes.RaidTables.Plugins) then
+ _switchTo = 1
+ end
+ end
+
+ local ThisFrame = _detalhes.RaidTables.Plugins [_detalhes.RaidTables.Mode]
+ if (not ThisFrame) then
+ --> frame not found, try in few second again
+ _detalhes.RaidTables.Mode = _switchTo
+ _detalhes:WaitForSoloPlugin (_detalhes:GetRaidMode())
+ return
+ end
+
+ --> hide current frame
+ _detalhes.RaidTables.Plugins [_detalhes.RaidTables.Mode].Frame:Hide()
+ --> switch mode
+ _detalhes.RaidTables.Mode = _switchTo
+ --> show and setpoint new frame
+
+ _detalhes.RaidTables.Plugins [_detalhes.RaidTables.Mode].Frame:Show()
+ _detalhes.RaidTables.Plugins [_detalhes.RaidTables.Mode].Frame:SetPoint ("TOPLEFT",_detalhes.RaidTables.instancia.bgframe)
+
+ _detalhes.RaidTables.instancia:ChangeIcon (_detalhes.RaidTables.Menu [_detalhes.RaidTables.Mode] [2])
+
+ end
diff --git a/core/plugins_solo.lua b/core/plugins_solo.lua
new file mode 100644
index 00000000..883be6a1
--- /dev/null
+++ b/core/plugins_solo.lua
@@ -0,0 +1,292 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _pairs = pairs --lua locals
+ local _math_floor = math.floor --lua locals
+
+ local _UnitAura = UnitAura
+
+ local gump = _detalhes.gump --details local
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> constants
+
+ local modo_alone = _detalhes._detalhes_props["MODO_ALONE"]
+ local modo_grupo = _detalhes._detalhes_props["MODO_GROUP"]
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ --> When a combat start
+ function _detalhes:UpdateSolo()
+ local SoloInstance = _detalhes.tabela_instancias[_detalhes.solo]
+ _detalhes.SoloTables.CombatIDLast = _detalhes.SoloTables.CombatID
+ _detalhes.SoloTables.CombatID = _detalhes:NumeroCombate()
+ _detalhes.SoloTables.Attribute = SoloInstance.atributo
+ end
+
+ --> details can call a refresh for an plugin window
+ function _detalhes:RefreshSolo()
+ if (_detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Refresh) then
+ _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Refresh (_, SoloInstance)
+ end
+ end
+
+ --> enable and disable Solo Mode for an Instance
+ function _detalhes:SoloMode (show)
+ if (show) then
+
+ --> salvar a janela normal
+ if (self.mostrando ~= "solo") then --> caso o addon tenha ligado ja no painel solo, não precisa rodar isso aqui
+ self:SaveMainWindowPosition()
+
+ if (self.rolagem) then
+ self:EsconderScrollBar() --> hida a scrollbar
+ end
+ self.need_rolagem = false
+
+ self.baseframe:EnableMouseWheel (false)
+ gump:Fade (self, 1, nil, "barras") --> escondendo a janela da instância [instância [force hide [velocidade [hidar o que]]]]
+ self.mostrando = "solo"
+ end
+
+ self:DefaultIcons (true, false, true, false)
+ _detalhes.SoloTables.instancia = self
+
+ --> default plugin
+ if (not _detalhes.SoloTables.built) then
+ gump:PrepareSoloMode (self)
+ end
+
+ self.modo = _detalhes._detalhes_props["MODO_ALONE"]
+ _detalhes.solo = self.meu_id
+ --self:AtualizaSliderSolo (0)
+
+ if (not self.posicao.solo.w) then --> primeira vez que o solo mode é executado nessa instância
+ self.baseframe:SetWidth (300)
+ self.baseframe:SetHeight (300)
+ self:SaveMainWindowPosition()
+ else
+ self:RestoreMainWindowPosition()
+ local w, h = self:GetSize()
+ if (w ~= 300 or h ~= 300) then
+ self.baseframe:SetWidth (300)
+ self.baseframe:SetHeight (300)
+ self:SaveMainWindowPosition()
+ end
+ end
+
+ if (not _detalhes.SoloTables.Plugins [1]) then
+ _detalhes:WaitForSoloPlugin (self)
+ else
+ if (not _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode]) then
+ _detalhes.SoloTables.Mode = 1
+ end
+ _detalhes.SoloTables:switch (_, _detalhes.SoloTables.Mode)
+ end
+
+ else
+
+ if (_detalhes.PluginCount.SOLO > 0) then
+ local solo_frame = _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Frame
+ if (solo_frame) then
+ _detalhes.SoloTables:switch()
+ end
+ end
+
+ _detalhes.solo = nil --> destranca a janela solo para ser usada em outras instâncias
+ self.mostrando = "normal"
+ self:RestoreMainWindowPosition()
+ self:DefaultIcons (true, true, true, true)
+
+ if (_G.DetailsWaitForPluginFrame:IsShown()) then
+ _detalhes:CancelWaitForPlugin()
+ end
+
+ gump:Fade (self, 1, nil, "barras")
+ gump:Fade (self.scroll, 0)
+
+ if (self.need_rolagem) then
+ self:MostrarScrollBar (true)
+ else
+ --> precisa verificar se ele precisa a rolagem certo?
+ self:ReajustaGump()
+ end
+
+ --> calcula se existem barras, etc...
+ if (not self.barrasInfo.cabem) then --> as barras não forma iniciadas ainda
+ self.barrasInfo.cabem = _math_floor (self.baseframe.BoxBarrasAltura / self.barrasInfo.alturaReal)
+ if (self.barrasInfo.criadas < self.barrasInfo.cabem) then
+ for i = #self.barras+1, self.barrasInfo.cabem do
+ local nova_barra = gump:CriaNovaBarra (self, i, 30) --> cria nova barra
+ nova_barra.texto_esquerdo:SetText (Loc ["STRING_NEWROW"])
+ nova_barra.statusbar:SetValue (100)
+ self.barras [i] = nova_barra
+ end
+ self.barrasInfo.criadas = #self.barras
+ end
+ end
+ end
+ end
+
+ --> Build Solo Mode Tables and Functions
+ function gump:PrepareSoloMode (instancia)
+
+ _detalhes.SoloTables.built = true
+
+ _detalhes.SoloTables.SpellCastTable = {} --> not used
+ _detalhes.SoloTables.TimeTable = {} --> not used
+
+
+
+ _detalhes.SoloTables.Mode = _detalhes.SoloTables.Mode or 1 --> solo mode
+
+ function _detalhes.SoloTables:GetActiveIndex()
+ return _detalhes.SoloTables.Mode
+ end
+
+ function _detalhes.SoloTables:switch (_, _switchTo)
+
+ --> just hide all
+ if (not _switchTo) then
+ if (#_detalhes.SoloTables.Plugins > 0) then --> have at least one plugin
+ _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Frame:Hide()
+ end
+ _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Frame:Hide()
+ return
+ end
+
+ --> jump to the next
+ if (_switchTo == -1) then
+ _switchTo = _detalhes.SoloTables.Mode + 1
+ if (_switchTo > #_detalhes.SoloTables.Plugins) then
+ _switchTo = 1
+ end
+ end
+
+ local ThisFrame = _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode]
+ if (not ThisFrame) then
+ --> frame not found, try in few second again
+ _detalhes.SoloTables.Mode = _switchTo
+ _detalhes:WaitForSoloPlugin (instancia)
+ return
+ end
+
+ --> hide current frame
+ _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Frame:Hide()
+ --> switch mode
+ _detalhes.SoloTables.Mode = _switchTo
+ --> show and setpoint new frame
+
+ _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Frame:Show()
+ _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].Frame:SetPoint ("TOPLEFT",_detalhes.SoloTables.instancia.bgframe)
+
+ _detalhes.SoloTables.instancia:ChangeIcon (_detalhes.SoloTables.Menu [_detalhes.SoloTables.Mode] [2])
+
+ end
+
+ return true
+ end
+
+ function _detalhes:SoloCastTime (spell, start, tempo)
+ if (start) then
+ _detalhes.CastStart = tempo
+ else
+ local tempoGasto = _detalhes.CastStart - tempo
+ _detalhes.CastStart = nil
+ end
+ end
+
+ function _detalhes:CloseSoloDebuffs()
+ local SoloDebuffUptime = _detalhes.tabela_vigente.SoloDebuffUptime
+ if (not SoloDebuffUptime) then
+ return
+ end
+
+ for SpellId, DebuffTable in _pairs (SoloDebuffUptime) do
+ if (DebuffTable.start) then
+ DebuffTable.duration = DebuffTable.duration + (_detalhes._tempo - DebuffTable.start) --> time do parser será igual ao time()?
+ DebuffTable.start = nil
+ end
+ DebuffTable.Active = false
+ end
+ end
+
+ --> Buffs terá em todos os Solo Modes
+ function _detalhes.SoloTables:CatchBuffs()
+ --> reset bufftables
+ _detalhes.SoloTables.SoloBuffUptime = _detalhes.SoloTables.SoloBuffUptime or {}
+
+ for spellname, BuffTable in _pairs (_detalhes.SoloTables.SoloBuffUptime) do
+ --local BuffEntryTable = _detalhes.SoloTables.BuffTextEntry [BuffTable.tableIndex]
+
+ if (BuffTable.Active) then
+ BuffTable.start = _detalhes._tempo
+ BuffTable.castedAmt = 1
+ BuffTable.appliedAt = {}
+ --BuffEntryTable.backgroundFrame:Active()
+ else
+ BuffTable.start = nil
+ BuffTable.castedAmt = 0
+ BuffTable.appliedAt = {}
+ --BuffEntryTable.backgroundFrame:Desactive()
+ end
+
+ BuffTable.duration = 0
+ BuffTable.refreshAmt = 0
+ BuffTable.droppedAmt = 0
+ end
+
+ --> catch buffs untracked yet
+ for buffIndex = 1, 41 do
+ local name = _UnitAura ("player", buffIndex)
+ if (name) then
+ for index, BuffName in _pairs (_detalhes.SoloTables.BuffsTableNameCache) do
+ if (BuffName == name) then
+ local BuffObject = _detalhes.SoloTables.SoloBuffUptime [name]
+ if (not BuffObject) then
+ _detalhes.SoloTables.SoloBuffUptime [name] = {name = name, duration = 0, start = nil, castedAmt = 1, refreshAmt = 0, droppedAmt = 0, Active = true, tableIndex = index, appliedAt = {}}
+ end
+ end
+ end
+ end
+ end
+ end
+
+ function _detalhes:InstanciaCheckForDisabledSolo (instancia)
+
+ if (not instancia) then
+ instancia = self
+ end
+
+ if (instancia.modo == modo_alone) then
+ --print ("arrumando a instancia "..instancia.meu_id)
+ if (instancia.iniciada) then
+ _detalhes:AlteraModo (instancia, modo_grupo)
+ instancia:SoloMode (false)
+ _detalhes:ResetaGump (instancia)
+ else
+ instancia.modo = modo_grupo
+ instancia.last_modo = modo_grupo
+ end
+ end
+ end
+
+ function _detalhes:AtualizaSoloMode_AfertReset (instancia)
+ if (_detalhes.SoloTables.CombatIDLast) then
+ _detalhes.SoloTables.CombatIDLast = nil
+ end
+ if (_detalhes.SoloTables.CombatID) then
+ _detalhes.SoloTables.CombatID = 0
+ end
+ end
diff --git a/core/plugins_statusbar.lua b/core/plugins_statusbar.lua
new file mode 100644
index 00000000..93c27dc4
--- /dev/null
+++ b/core/plugins_statusbar.lua
@@ -0,0 +1,965 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+ local SharedMedia = LibStub:GetLibrary ("LibSharedMedia-3.0")
+
+ local DEFAULT_CHILD_WIDTH = 60
+ local DEFAULT_CHILD_HEIGHT = 16
+ local DEFAULT_CHILD_FONTFACE = "Friz Quadrata TT"
+ local DEFAULT_CHILD_FONTCOLOR = {1, 0.7333333333333333, 0, 1}
+ local DEFAULT_CHILD_FONTSIZE = 10
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _math_floor = math.floor --> api local
+ local _ipairs = ipairs --> api local
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> status bar core functions
+--[[ This file contains Api and Internal functions, plus 4 built-in plugins
+ You can use this four plugins to learn how they works--]]
+
+ --> create a plugin child for an instance
+ function _detalhes.StatusBar:CreateStatusBarChildForInstance (instance, pluginName)
+ local PluginObject = _detalhes.StatusBar.NameTable [pluginName]
+ if (PluginObject) then
+ local new_child = PluginObject:CreateChildObject (instance)
+ if (new_child) then
+ instance.StatusBar [#instance.StatusBar+1] = new_child
+ new_child.enabled = false
+ return new_child
+ end
+ end
+ return nil
+ end
+
+ function _detalhes.StatusBar:AlignPluginText (child, default)
+ local side = child.options.textAlign
+ if (child.options.textAlign == 0) then
+ side = default
+ end
+
+ child.text:ClearAllPoints()
+ if (side == 1) then
+ child.text:SetPoint ("left", child.frame, "left", child.options.textXMod, child.options.textYMod)
+ elseif (side == 2) then
+ child.text:SetPoint ("center", child.frame, "center", child.options.textXMod, child.options.textYMod)
+ elseif (side == 3) then
+ child.text:SetPoint ("right", child.frame, "right", child.options.textXMod, child.options.textYMod)
+ end
+ end
+
+ --> functions to set the three statusbar places: left, center and right
+ function _detalhes.StatusBar:SetCenterPlugin (instance, childObject)
+ childObject.frame:Show()
+ childObject.frame:SetPoint ("center", instance.baseframe.rodape.StatusBarCenterAnchor, "center")
+ _detalhes.StatusBar:AlignPluginText (childObject, 2)
+
+ instance.StatusBar.center = childObject
+ childObject.anchor = "center"
+ childObject.enabled = true
+ if (childObject.OnEnable) then
+ childObject:OnEnable()
+ end
+ return true
+ end
+
+ function _detalhes.StatusBar:SetLeftPlugin (instance, childObject)
+
+ childObject.frame:Show()
+ childObject.frame:SetPoint ("left", instance.baseframe.rodape.StatusBarLeftAnchor, "left")
+ _detalhes.StatusBar:AlignPluginText (childObject, 1)
+
+ instance.StatusBar.left = childObject
+ childObject.anchor = "left"
+ childObject.enabled = true
+ if (childObject.OnEnable) then
+ childObject:OnEnable()
+ end
+ return true
+ end
+
+ function _detalhes.StatusBar:SetRightPlugin (instance, childObject)
+ childObject.frame:Show()
+ childObject.frame:SetPoint ("right", instance.baseframe.rodape.direita, "right", -20, 10)
+ _detalhes.StatusBar:AlignPluginText (childObject, 3)
+
+ instance.StatusBar.right = childObject
+ childObject.anchor = "right"
+ childObject.enabled = true
+ if (childObject.OnEnable) then
+ childObject:OnEnable()
+ end
+ return true
+ end
+
+ --> disable all plugin childs attached to an specified instance and reactive the childs taking the instance statusbar anchors
+ function _detalhes.StatusBar:ReloadAnchors (instance)
+ for _, child in _ipairs (instance.StatusBar) do
+ child.frame:ClearAllPoints()
+ child.frame:Hide()
+ child.anchor = nil
+ child.enabled = false
+ if (child.OnDisable) then
+ child:OnDisable()
+ end
+ end
+ --> enable only needed plugins
+ if (instance.StatusBar.right) then
+ _detalhes.StatusBar:SetRightPlugin (instance, instance.StatusBar.right)
+ end
+ if (instance.StatusBar.center) then
+ _detalhes.StatusBar:SetCenterPlugin (instance, instance.StatusBar.center)
+ end
+ if (instance.StatusBar.left) then
+ _detalhes.StatusBar:SetLeftPlugin (instance, instance.StatusBar.left)
+ end
+ end
+
+ --> select a new plugin in for an instance anchor
+ local ChoosePlugin = function (_, _, index, current_child, anchor)
+ local pluginMestre = _detalhes.StatusBar.Plugins [index]
+ local instance = current_child.instance -- instance que estamos usando agora
+
+ local chosenChild = nil
+
+ for _, child_created in _ipairs (instance.StatusBar) do
+ if (child_created.mainPlugin == pluginMestre) then
+ chosenChild = child_created
+ break
+ end
+ end
+
+ if (not chosenChild) then
+ chosenChild = _detalhes.StatusBar:CreateStatusBarChildForInstance (current_child.instance, pluginMestre.real_name)
+ end
+
+ instance.StatusBar [anchor] = chosenChild
+ if (chosenChild.anchor) then
+ instance.StatusBar [chosenChild.anchor] = current_child
+ end
+
+ _detalhes.StatusBar:ReloadAnchors (instance)
+
+ _detalhes.popup:ShowMe (false)
+ end
+
+ --> on enter
+ local onEnterCooltipTexts = {
+ {text = "|TInterface\\TUTORIALFRAME\\UI-TUTORIAL-FRAME:14:14:0:1:512:512:8:70:224:306|t " .. Loc ["STRING_PLUGIN_TOOLTIP_LEFTBUTTON"]},
+ {text = "|TInterface\\TUTORIALFRAME\\UI-TUTORIAL-FRAME:14:14:0:1:512:512:8:70:328:409|t " .. Loc ["STRING_PLUGIN_TOOLTIP_RIGHTBUTTON"]}}
+
+ local OnEnter = function (frame)
+
+ --|TTexturePath: size X: size Y: point offset Y X : texture size : coordx1 L : coordx2 R : coordy1 T : coordy2 B |t
+ -- left click: 0.0019531:0.1484375:0.4257813:0.6210938 right click: 0.0019531:0.1484375:0.6269531:0.8222656
+ local passou = 0
+ frame:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou + elapsed
+ if (passou > 0.5) then
+ if (not _detalhes.popup.mouseOver and not _detalhes.popup.buttonOver and not _detalhes.popup.active) then
+ GameCooltip:Reset()
+ GameCooltip:AddFromTable (onEnterCooltipTexts)
+ GameCooltip:SetOption ("TextSize", 9.5)
+ GameCooltip:ShowCooltip (frame, "tooltip")
+ end
+ self:SetScript ("OnUpdate", nil)
+ _detalhes.popup.active = true
+ end
+ end)
+
+ return true
+ end
+
+ --> on leave
+ local OnLeave = function (frame)
+ if (_detalhes.popup.active) then
+ local passou = 0
+ frame:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ if (not _detalhes.popup.mouseOver and not _detalhes.popup.buttonOver and _detalhes.popup.Host == frame) then
+ _detalhes.popup:ShowMe (false)
+ end
+ _detalhes.popup.active = false
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+ else
+ _detalhes.popup.active = false
+ frame:SetScript ("OnUpdate", nil)
+ end
+ return true
+ end
+
+ local OnMouseUp = function (frame, mouse)
+
+ if (mouse == "LeftButton") then
+ if (not frame.child.Setup) then
+ print (Loc ["STRING_STATUSBAR_NOOPTIONS"])
+ return
+ end
+ frame.child:Setup()
+ else
+ GameCooltip:Reset()
+ for index, _name_and_icon in _ipairs (_detalhes.StatusBar.Menu) do
+ GameCooltip:AddMenu (1, ChoosePlugin, index, frame.child, frame.child.anchor, _name_and_icon [1], _name_and_icon [2], true)
+ end
+ GameCooltip:SetOption ("NoLastSelectedBar", true)
+ GameCooltip:SetOption ("HeightAnchorMod", -12)
+ GameCooltip:ShowCooltip (frame, "menu")
+ end
+ return true
+ end
+
+ --> build-in function for create a frame for an plugin child
+ function _detalhes.StatusBar:CreateChildFrame (instance, name, w, h)
+ local frame = _detalhes.gump:NewPanel (instance.baseframe.cabecalho.fechar, nil, name..instance:GetInstanceId(), nil, w or DEFAULT_CHILD_WIDTH, h or DEFAULT_CHILD_HEIGHT, false)
+
+ --create widgets
+ local text = _detalhes.gump:NewLabel (frame, _, "$parentText", "text", "0")
+ text:SetPoint ("right", frame, "right", 0, 0)
+ text:SetJustifyH ("right")
+ _detalhes:SetFontSize (text, 9.8)
+
+ frame:SetHook ("OnEnter", OnEnter)
+ frame:SetHook ("OnLeave", OnLeave)
+ frame:SetHook ("OnMouseUp", OnMouseUp)
+ return frame
+ end
+
+ --> built-in function for create an table for the plugin child
+ function _detalhes.StatusBar:CreateChildTable (instance, mainObject, frame)
+
+ local _table = {}
+
+ --> treat as a class
+ setmetatable (_table, mainObject)
+
+ --> default members
+ _table.instance = instance
+ _table.frame = frame
+ _table.text = frame.text
+ _table.mainPlugin = mainObject
+
+ --> options table
+ _table.options = instance.StatusBar.options [mainObject.real_name]
+ if (not _table.options) then
+ _table.options = {
+ textStyle = 2,
+ textColor = {unpack (DEFAULT_CHILD_FONTCOLOR)},
+ textSize = DEFAULT_CHILD_FONTSIZE,
+ textAlign = 0,
+ textXMod = 0,
+ textYMod = 0,
+ textFace = DEFAULT_CHILD_FONTFACE}
+ instance.StatusBar.options [mainObject.real_name] = _table.options
+ end
+
+ _detalhes.StatusBar:ApplyOptions (_table, "textcolor")
+ _detalhes.StatusBar:ApplyOptions (_table, "textsize")
+ _detalhes.StatusBar:ApplyOptions (_table, "textface")
+
+ _detalhes.StatusBar:ReloadAnchors (instance)
+
+ --> table reference on frame widget
+ frame.frame.child = _table
+
+ --> adds this new child to parent child container
+ mainObject.childs [#mainObject.childs+1] = _table
+
+ return _table
+ end
+
+ function _detalhes.StatusBar:ApplyOptions (child, option, value)
+
+ option = string.lower (option)
+
+ if (option == "textxmod") then
+ if (value) then
+ child.options.textXMod = value
+ end
+ _detalhes.StatusBar:ReloadAnchors (child.instance)
+ elseif (option == "textymod") then
+ if (value) then
+ child.options.textYMod = value
+ end
+ _detalhes.StatusBar:ReloadAnchors (child.instance)
+ elseif (option == "textcolor") then
+ if (value) then
+ child.options.textColor = value
+ end
+ child.text:SetTextColor (unpack (child.options.textColor))
+ elseif (option == "textsize") then
+ if (value) then
+ child.options.textSize = value
+ end
+ child:SetFontSize (child.text, child.options.textSize)
+ elseif (option == "textface") then
+ if (value) then
+ child.options.textFace = value
+ end
+ child:SetFontFace (child.text, SharedMedia:Fetch ("font", child.options.textFace))
+ else
+ if (child [option] and type (child [option]) == "function") then
+ child [option] (_, child, value)
+ end
+ end
+ end
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> BUILT-IN DPS PLUGIN
+do
+
+ --> Create the plugin Object [1] = frame name on _G [2] options [3] plugin type
+ local PDps = _detalhes:NewPluginObject ("Details_StatusBarDps", DETAILSPLUGIN_ALWAYSENABLED, "STATUSBAR")
+
+ --[[ Note: Declare all functions using : not . if you use . make sure to ignore first parameter and move all parameters 1 position to right ]]
+
+ -- handle event "COMBAT_PLAYER_ENTER"
+ function PDps:PlayerEnterCombat()
+ for index, child in _ipairs (PDps.childs) do
+ if (child.enabled and child.instance:GetSegment() == 0) then
+ child.tick = _detalhes:ScheduleRepeatingTimer ("PluginDpsUpdate", 1, child)
+ end
+ end
+ end
+
+ -- handle event "COMBAT_PLAYER_LEAVE"
+ function PDps:PlayerLeaveCombat()
+ for index, child in _ipairs (PDps.childs) do
+ if (child.tick) then
+ _detalhes:CancelTimer (child.tick)
+ child.tick = nil
+ end
+ end
+ end
+
+ -- handle event "DETAILS_INSTANCE_CHANGESEGMENT"
+ function PDps:ChangeSegment (instance, segment)
+ for index, child in _ipairs (PDps.childs) do
+ if (child.enabled and child.instance == instance) then
+ _detalhes:PluginDpsUpdate (child)
+ end
+ end
+ end
+
+ --handle event "DETAILS_DATA_RESET"
+ function PDps:DataReset()
+ for index, child in _ipairs (PDps.childs) do
+ if (child.enabled) then
+ child.text:SetText ("0")
+ end
+ end
+ end
+
+ function PDps:Refresh (child)
+ _detalhes:PluginDpsUpdate (child)
+ end
+
+ --still a little buggy, working on
+ function _detalhes:PluginDpsUpdate (child)
+
+ --> showing is the combat table which is current shown on instance
+ if (child.instance.showing) then
+ --GetCombatTime() return the time length of combat
+ local combatTime = child.instance.showing:GetCombatTime()
+ if (combatTime == 0) then
+ return child.text:SetText ("0")
+ end
+ --GetTotal (attribute, sub attribute, onlyGroup) return the total of requested attribute
+ local total = child.instance.showing:GetTotal (child.instance.atributo, child.instance.sub_atributo, true)
+
+ local dps = _math_floor (total / combatTime)
+
+ local textStyle = child.options.textStyle
+ if (textStyle == 1) then
+ child.text:SetText (_detalhes:ToK (dps))
+ elseif (textStyle == 2) then
+ child.text:SetText (_detalhes:comma_value (dps))
+ else
+ child.text:SetText (dps)
+ end
+ end
+ end
+
+ --> Create Plugin Frames
+ function PDps:CreateChildObject (instance)
+
+ --> create main frame and widgets
+ --> a statusbar frame is made of a panel with a member called 'text' which is a label
+ local myframe = _detalhes.StatusBar:CreateChildFrame (instance, "DetailsStatusBarDps", DEFAULT_CHILD_WIDTH, DEFAULT_CHILD_HEIGHT)
+
+ --> create the table for the child
+ --> a child table are the table which will hold parameters, default members:
+ -- ["instance"] = instance where this child are,
+ -- ["frame"] = myframe,
+ -- ["text"] = myframe.text,
+ -- ["mainPlugin"] = parent plugin
+ local new_child = _detalhes.StatusBar:CreateChildTable (instance, PDps, myframe)
+
+ return new_child
+ end
+
+ --> Handle events (must have, we'll use direct call to functions)
+ function PDps:OnDetailsEvent (event)
+ return
+ end
+
+ --> standard on enable and disable functions, this is for hook model. If isn't declared, details will auto modify member .enabled state
+ --function PDps:OnEnable()
+ -- self.enabled = true
+ --end
+ --function PDps:OnDisable()
+ -- self.enabled = false
+ --end
+
+ --> setup function runs when player click with left mouse over plugin frame
+ --> this is internal, but member Setup can be overwrite
+ --> for exclude any options panel, set Setup to nil
+ --function PDps:Setup()
+ -- _detalhes.StatusBar:OpenOptionsForChild (self)
+ --end
+
+ --> Install
+ -- _detalhes:InstallPlugin ( Plugin Type | Plugin Display Name | Plugin Icon | Plugin Object | Plugin Real Name )
+ local install = _detalhes:InstallPlugin ("STATUSBAR", Loc ["STRING_PLUGIN_PDPSNAME"], "Interface\\Icons\\Achievement_brewery_3", PDps, "DETAILS_STATUSBAR_PLUGIN_PDPS")
+ if (type (install) == "table" and install.error) then
+ print (install.errortext)
+ return
+ end
+
+ --> Register needed events
+ -- here we are redirecting the event to an specified function, otherwise events need to be handle inside "PDps:OnDetailsEvent (event)"
+ _detalhes:RegisterEvent (PDps, "DETAILS_INSTANCE_CHANGESEGMENT", PDps.ChangeSegment)
+ _detalhes:RegisterEvent (PDps, "COMBAT_PLAYER_ENTER", PDps.PlayerEnterCombat)
+ _detalhes:RegisterEvent (PDps, "COMBAT_PLAYER_LEAVE", PDps.PlayerLeaveCombat)
+ _detalhes:RegisterEvent (PDps, "DETAILS_DATA_RESET", PDps.DataReset)
+
+end
+
+---------> BUILT-IN SEGMENT PLUGIN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+do
+ --> Create the plugin Object
+ local PSegment = _detalhes:NewPluginObject ("Details_Segmenter", DETAILSPLUGIN_ALWAYSENABLED, "STATUSBAR")
+ --> Handle events (must have)
+ function PSegment:OnDetailsEvent (event)
+ return
+ end
+
+ function PSegment:Change ()
+ for index, child in _ipairs (PSegment.childs) do
+ if (child.enabled and child.instance:IsEnabled()) then
+ if (child.instance.segmento == -1) then --> overall
+ child.text:SetText (Loc ["STRING_OVERALL"])
+ elseif (child.instance.segmento == 0) then --> combate atual
+ child.text:SetText (Loc ["STRING_CURRENT"])
+ else --> alguma tabela do histórico
+ child.text:SetText (Loc ["STRING_FIGHTNUMBER"]..child.instance.segmento)
+ end
+ end
+ end
+ end
+
+ --> Create Plugin Frames (must have)
+ function PSegment:CreateChildObject (instance)
+ local myframe = _detalhes.StatusBar:CreateChildFrame (instance, "DetailsPSegmentInstance" .. instance:GetInstanceId(), DEFAULT_CHILD_WIDTH, DEFAULT_CHILD_HEIGHT)
+ local new_child = _detalhes.StatusBar:CreateChildTable (instance, PSegment, myframe)
+ return new_child
+ end
+
+ --> Install
+ local install = _detalhes:InstallPlugin ("STATUSBAR", Loc ["STRING_PLUGIN_PSEGMENTNAME"], "Interface\\Icons\\inv_misc_enchantedscroll", PSegment, "DETAILS_STATUSBAR_PLUGIN_PSEGMENT")
+ if (type (install) == "table" and install.error) then
+ print (install.errortext)
+ return
+ end
+
+ --> Register needed events
+ _detalhes:RegisterEvent (PSegment, "DETAILS_INSTANCE_CHANGESEGMENT", PSegment.Change)
+
+end
+
+---------> BUILT-IN ATTRIBUTE PLUGIN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+do
+ --> Create the plugin Object
+ local PAttribute = _detalhes:NewPluginObject ("Details_Attribute", DETAILSPLUGIN_ALWAYSENABLED, "STATUSBAR")
+ --> Handle events (must have)
+ function PAttribute:OnDetailsEvent (event)
+ return
+ end
+
+ function PAttribute:Change (instance, attribute, subAttribute)
+ if (not instance) then
+ instance, attribute, subAttribute = self.instance, self.instance.atributo, self.instance.sub_atributo
+ end
+
+ for index, child in _ipairs (PAttribute.childs) do
+ if (child.instance == instance and child.enabled and child.instance:IsEnabled()) then
+ local sName = _detalhes:GetSubAttributeName (attribute, subAttribute)
+ child.text:SetText (sName)
+ end
+ end
+ end
+
+ function PAttribute:OnEnable()
+ self:Change()
+ end
+
+ --> Create Plugin Frames (must have)
+ function PAttribute:CreateChildObject (instance)
+ local myframe = _detalhes.StatusBar:CreateChildFrame (instance, "DetailsPAttributeInstance" .. instance:GetInstanceId(), DEFAULT_CHILD_WIDTH, DEFAULT_CHILD_HEIGHT)
+ local new_child = _detalhes.StatusBar:CreateChildTable (instance, PAttribute, myframe)
+ return new_child
+ end
+
+ --> Install
+ local install = _detalhes:InstallPlugin ("STATUSBAR", Loc ["STRING_PLUGIN_PATTRIBUTENAME"], "Interface\\Icons\\inv_misc_emberclothbolt", PAttribute, "DETAILS_STATUSBAR_PLUGIN_PATTRIBUTE")
+ if (type (install) == "table" and install.error) then
+ print (install.errortext)
+ return
+ end
+
+ --> Register needed events
+ _detalhes:RegisterEvent (PAttribute, "DETAILS_INSTANCE_CHANGEATTRIBUTE", PAttribute.Change)
+
+end
+
+---------> BUILT-IN CLOCK PLUGIN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+do
+
+ --> Create the plugin Object
+ local Clock = _detalhes:NewPluginObject ("Details_Clock", DETAILSPLUGIN_ALWAYSENABLED, "STATUSBAR")
+ --> Handle events --must have this function
+ function Clock:OnDetailsEvent (event)
+ return
+ end
+
+ --enter combat
+ function Clock:PlayerEnterCombat()
+ Clock.tick = _detalhes:ScheduleRepeatingTimer ("ClockPluginTick", 1)
+ end
+ --leave combat
+ function Clock:PlayerLeaveCombat()
+ _detalhes:CancelTimer (Clock.tick)
+ end
+
+ --1 sec tick
+ function _detalhes:ClockPluginTick()
+ for index, child in _ipairs (Clock.childs) do
+ local instance = child.instance
+ if (child.enabled and instance:IsEnabled()) then
+ if (instance.showing) then
+
+ local timeType = child.options.timeType
+ if (timeType == 1) then
+ local combatTime = instance.showing:GetCombatTime()
+ local minutos, segundos = _math_floor (combatTime/60), _math_floor (combatTime%60)
+ child.text:SetText (minutos .. "m " .. segundos .. "s")
+
+ elseif (timeType == 2) then
+ local combatTime = instance.showing:GetCombatTime()
+ child.text:SetText (combatTime .. "s")
+
+ elseif (timeType == 3) then
+
+ local getSegment = instance.segmento
+
+ if (getSegment < 1) then
+ getSegment = 1
+ elseif (getSegment > _detalhes.segments_amount) then
+ getSegment = _detalhes.segments_amount
+ else
+ getSegment = getSegment+1
+ end
+
+ local lastFight = _detalhes:GetCombat (getSegment)
+ local currentCombatTime = instance.showing:GetCombatTime()
+
+ if (lastFight) then
+ child.text:SetText (currentCombatTime - lastFight:GetCombatTime() .. "s")
+ else
+ child.text:SetText (currentCombatTime .. "s")
+ end
+ end
+
+
+ end
+ end
+ end
+ end
+
+ --on reset
+ function Clock:DataReset()
+ for index, child in _ipairs (Clock.childs) do
+ if (child.enabled and child.instance:IsEnabled()) then
+ child.text:SetText ("0m 0s")
+ end
+ end
+ end
+
+ --> this is a fixed member, put all your widgets for custom options inside this function
+ --> if ExtraOptions isn't preset, secondary options box will be hided and only default options will be show
+ function Clock:ExtraOptions()
+
+ --> all widgets need to be placed on a table
+ local widgets = {}
+ --> reference of extra window for custom options
+ local window = _G.DetailsStatusBarOptions2.MyObject
+
+ --> build all your widgets -----------------------------------------------------------------------------------------------------------------------------
+ _detalhes.gump:NewLabel (window, _, "$parentClockTypeLabel", "ClockTypeLabel", Loc ["STRING_PLUGIN_CLOCKTYPE"])
+ window.ClockTypeLabel:SetPoint (10, -15)
+
+ local onSelectClockType = function (_, child, thistype)
+ child.options.timeType = thistype
+ _detalhes:ClockPluginTick()
+ end
+
+ local clockTypes = {{value = 1, label = Loc ["STRING_PLUGIN_MINSEC"], onclick = onSelectClockType},
+ {value = 2, label = Loc ["STRING_PLUGIN_SECONLY"], onclick = onSelectClockType},
+ {value = 3, label = Loc ["STRING_PLUGIN_TIMEDIFF"], onclick = onSelectClockType}}
+
+ _detalhes.gump:NewDropDown (window, _, "$parentClockTypeDropdown", "ClockTypeDropdown", 200, 20, function() return clockTypes end, 1) -- func, default
+ window.ClockTypeDropdown:SetPoint ("left", window.ClockTypeLabel, "right", 2)
+ -----------------------------------------------------------------------------------------------------------------------------
+
+ --> now we insert all widgets created on widgets table
+ table.insert (widgets, window.ClockTypeLabel)
+ table.insert (widgets, window.ClockTypeDropdown)
+
+ --> after first call we replace this function with widgets table
+ Clock.ExtraOptions = widgets
+ end
+
+ --> ExtraOptionsOnOpen is called when options are opened and plugin have custom options
+ --> here we setup options widgets for get the values of clicked child and also for tell options window what child we are configuring
+ function Clock:ExtraOptionsOnOpen (child)
+ _G.DetailsStatusBarOptions2ClockTypeDropdown.MyObject:SetFixedParameter (child)
+ _G.DetailsStatusBarOptions2ClockTypeDropdown.MyObject:Select (child.options.timeType, true)
+ end
+
+ --> Create Plugin Frames
+ function Clock:CreateChildObject (instance)
+
+ local myframe = _detalhes.StatusBar:CreateChildFrame (instance, "DetailsClockInstance"..instance:GetInstanceId(), DEFAULT_CHILD_WIDTH, DEFAULT_CHILD_HEIGHT)
+
+ --> we place custom frame, widgets inside this function
+ local texture = myframe:CreateTexture (nil, "overlay")
+ texture:SetTexture ("Interface\\AddOns\\Details\\images\\clock")
+ texture:SetPoint ("right", myframe.text.widget, "left")
+
+ local new_child = _detalhes.StatusBar:CreateChildTable (instance, Clock, myframe)
+
+ --> default text
+ new_child.text:SetText ("0m 0s")
+
+ --> some changes from default options
+ if (new_child.options.textXMod == 0) then
+ new_child.options.textXMod = 6
+ end
+
+ --> here we are adding a new option member
+ new_child.options.timeType = new_child.options.timeType or 1
+
+ return new_child
+ end
+
+ --> Install
+ local install = _detalhes:InstallPlugin ("STATUSBAR", Loc ["STRING_PLUGIN_CLOCKNAME"], "Interface\\Icons\\Achievement_BG_grab_cap_flagunderXseconds", Clock, "DETAILS_STATUSBAR_PLUGIN_CLOCK")
+ if (type (install) == "table" and install.error) then
+ print (install.errortext)
+ return
+ end
+
+ --> Register needed events
+ _detalhes:RegisterEvent (Clock, "COMBAT_PLAYER_ENTER", Clock.PlayerEnterCombat)
+ _detalhes:RegisterEvent (Clock, "COMBAT_PLAYER_LEAVE", Clock.PlayerLeaveCombat)
+ _detalhes:RegisterEvent (Clock, "DETAILS_INSTANCE_CHANGESEGMENT", _detalhes.ClockPluginTick)
+ _detalhes:RegisterEvent (Clock, "DETAILS_DATA_SEGMENTREMOVED", _detalhes.ClockPluginTick)
+ _detalhes:RegisterEvent (Clock, "DETAILS_DATA_RESET", Clock.DataReset)
+
+end
+
+---------> BUILT-IN THREAT PLUGIN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+do
+
+ local _UnitDetailedThreatSituation = UnitDetailedThreatSituation --> wow api
+ local _cstr = string.format --> lua api
+ local _math_abs = math.abs --> lua api
+
+ --> Create the plugin Object
+ local Threat = _detalhes:NewPluginObject ("Details_TargetThreat", DETAILSPLUGIN_ALWAYSENABLED, "STATUSBAR")
+ --> Handle events
+ function Threat:OnDetailsEvent (event)
+ return
+ end
+
+ Threat.isTank = nil
+
+ function Threat:PlayerEnterCombat()
+ local role = UnitGroupRolesAssigned ("player")
+ if (role == "TANK") then
+ Threat.isTank = true
+ else
+ Threat.isTank = nil
+ end
+ Threat.tick = _detalhes:ScheduleRepeatingTimer ("ThreatPluginTick", 1)
+ end
+
+ function Threat:PlayerLeaveCombat()
+ _detalhes:CancelTimer (Threat.tick)
+ end
+
+ function _detalhes:ThreatPluginTick()
+ for index, child in _ipairs (Threat.childs) do
+ local instance = child.instance
+ if (child.enabled and instance:IsEnabled()) then
+ -- atualiza a threat
+ local isTanking, status, threatpct, rawthreatpct, threatvalue = _UnitDetailedThreatSituation ("player", "target")
+ if (threatpct) then
+ child.text:SetText (_math_floor (threatpct).."%")
+ if (Threat.isTank) then
+ child.text:SetTextColor (_math_abs (threatpct-100)*0.01, threatpct*0.01, 0, 1)
+ else
+ child.text:SetTextColor (threatpct*0.01, _math_abs (threatpct-100)*0.01, 0, 1)
+ end
+ else
+ child.text:SetText ("0%")
+ child.text:SetTextColor (1, 1, 1, 1)
+ end
+ end
+ end
+ end
+
+ --> Create Plugin Frames
+ function Threat:CreateChildObject (instance)
+
+ local myframe = _detalhes.StatusBar:CreateChildFrame (instance, "DetailsThreatInstance"..instance:GetInstanceId(), DEFAULT_CHILD_WIDTH, DEFAULT_CHILD_HEIGHT)
+
+ local new_child = _detalhes.StatusBar:CreateChildTable (instance, Threat, myframe)
+
+ myframe.widget:RegisterEvent ("PLAYER_TARGET_CHANGED")
+ myframe.widget:SetScript ("OnEvent", function()
+ _detalhes:ThreatPluginTick()
+ end)
+
+ return new_child
+ end
+
+ --> Install
+ local install = _detalhes:InstallPlugin ("STATUSBAR", Loc ["STRING_PLUGIN_THREATNAME"], "Interface\\Icons\\Ability_Hunter_ResistanceIsFutile", Threat, "DETAILS_STATUSBAR_PLUGIN_THREAT")
+ if (type (install) == "table" and install.error) then
+ print (install.errortext)
+ return
+ end
+
+ --> Register needed events
+ _detalhes:RegisterEvent (Threat, "COMBAT_PLAYER_ENTER", Threat.PlayerEnterCombat)
+ _detalhes:RegisterEvent (Threat, "COMBAT_PLAYER_LEAVE", Threat.PlayerLeaveCombat)
+
+
+end
+
+---------> default options panel ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+local window = _detalhes.gump:NewPanel (UIParent, nil, "DetailsStatusBarOptions", nil, 300, 160)
+tinsert (UISpecialFrames, "DetailsStatusBarOptions")
+window:SetPoint ("center", UIParent, "center")
+window.locked = false
+window.close_with_right = true
+window.child = nil
+window.instance = nil
+
+local extraWindow = _detalhes.gump:NewPanel (window, nil, "DetailsStatusBarOptions2", "extra", 300, 160)
+extraWindow:SetPoint ("left", window, "right")
+extraWindow.close_with_right = true
+extraWindow.locked = false
+extraWindow:SetHook ("OnHide", function()
+ window:Hide()
+end)
+
+--> text style
+ _detalhes.gump:NewLabel (window, _, "$parentTextStyleLabel", "textstyle", Loc ["STRING_PLUGINOPTIONS_TEXTSTYLE"])
+ window.textstyle:SetPoint (10, -15)
+
+ local onSelectTextStyle = function (_, child, style)
+ child.options.textStyle = style
+ if (child.Refresh and type (child.Refresh) == "function") then
+ child:Refresh (child)
+ end
+ end
+ local textStyle = {{value = 1, label = Loc ["STRING_PLUGINOPTIONS_ABBREVIATE"] .. " (105.5K)", onclick = onSelectTextStyle},
+ {value = 2, label = Loc ["STRING_PLUGINOPTIONS_COMMA"] .. " (105.500)", onclick = onSelectTextStyle},
+ {value = 3, label = Loc ["STRING_PLUGINOPTIONS_NOFORMAT"] .. " (105500)", onclick = onSelectTextStyle}}
+
+ _detalhes.gump:NewDropDown (window, _, "$parentTextStyleDropdown", "textstyleDropdown", 200, 20, function() return textStyle end, 1) -- func, default
+ window.textstyleDropdown:SetPoint ("left", window.textstyle, "right", 2)
+
+--> text color
+ _detalhes.gump:NewLabel (window, _, "$parentTextColorLabel", "textcolor", Loc ["STRING_PLUGINOPTIONS_TEXTCOLOR"])
+ window.textcolor:SetPoint (10, -35)
+ local selectedColor = function()
+ local r, g, b, a = ColorPickerFrame:GetColorRGB()
+ window.textcolortexture:SetTexture (r, g, b, a)
+ _detalhes.StatusBar:ApplyOptions (window.child, "textcolor", {r, g, b, a})
+ end
+ local canceledColor = function()
+ window.textcolortexture:SetTexture (unpack (ColorPickerFrame.previousValues))
+ _detalhes.StatusBar:ApplyOptions (window.child, "textcolor", {r, g, b, a})
+ end
+ local colorpick = function()
+ ColorPickerFrame:SetColorRGB (unpack (window.child.options.textColor))
+ ColorPickerFrame.hasOpacity = false
+ ColorPickerFrame.previousValues = window.child.options.textColor
+ ColorPickerFrame.func = selectedColor
+ ColorPickerFrame.cancelFunc = canceledColor
+ ColorPickerFrame:Show()
+ end
+
+ _detalhes.gump:NewImage (window, _, "$parentTextColorTexture", "textcolortexture", 200, 16)
+ window.textcolortexture:SetPoint ("left", window.textcolor, "right", 2)
+ window.textcolortexture:SetTexture (1, 1, 1)
+
+ _detalhes.gump:NewButton (window, _, "$parentTextColorButton", "textcolorbutton", 200, 20, colorpick)
+ window.textcolorbutton:SetPoint ("left", window.textcolor, "right", 2)
+
+
+--> text size
+ _detalhes.gump:NewLabel (window, _, "$parentFontSizeLabel", "fonsizeLabel", Loc ["STRING_PLUGINOPTIONS_TEXTSIZE"])
+ window.fonsizeLabel:SetPoint (10, -55)
+ --
+ _detalhes.gump:NewSlider (window, _, "$parentSliderFontSize", "fonsizeSlider", 170, 20, 9, 15, .5, 1)
+ window.fonsizeSlider:SetPoint ("left", window.fonsizeLabel, "right", 2)
+ window.fonsizeSlider:SetThumbSize (50)
+ window.fonsizeSlider.useDecimals = true
+ window.fonsizeSlider:SetHook ("OnValueChange", function (self, child, amount)
+ _detalhes.StatusBar:ApplyOptions (child, "textsize", amount)
+ end)
+
+--> align
+ _detalhes.gump:NewLabel (window, _, "$parentTextAlignLabel", "textalign", Loc ["STRING_PLUGINOPTIONS_TEXTALIGN"])
+ window.textalign:SetPoint (10, -95)
+ --
+ _detalhes.gump:NewSlider (window, _, "$parentSliderAlign", "alignSlider", 180, 20, 0, 3, 1)
+ window.alignSlider:SetPoint ("left", window.textalign, "right")
+ window.alignSlider:SetThumbSize (75)
+ window.alignSlider:SetHook ("OnValueChange", function (self, child, side)
+
+ child.options.textAlign = side
+
+ if (side == 0) then
+ window.alignSlider.amt:SetText (Loc ["STRING_AUTO"])
+ elseif (side == 1) then
+ window.alignSlider.amt:SetText (Loc ["STRING_LEFT"])
+ elseif (side == 2) then
+ window.alignSlider.amt:SetText (Loc ["STRING_CENTER"])
+ elseif (side == 3) then
+ window.alignSlider.amt:SetText (Loc ["STRING_RIGHT"])
+ end
+
+ _detalhes.StatusBar:ReloadAnchors (child.instance)
+
+ return true
+ end)
+
+--> text font
+ local onSelectFont = function (_, child, fontName)
+ _detalhes.StatusBar:ApplyOptions (child, "textface", fontName)
+ end
+
+ local fontObjects = SharedMedia:HashTable ("font")
+ local fontTable = {}
+ for name, fontPath in pairs (fontObjects) do
+ fontTable[#fontTable+1] = {value = name, label = name, onclick = onSelectFont, font = fontPath}
+ end
+ local buildFontMenu = function() return fontTable end
+
+ _detalhes.gump:NewLabel (window, _, "$parentFontFaceLabel", "fontfaceLabel", Loc ["STRING_PLUGINOPTIONS_FONTFACE"])
+ window.fontfaceLabel:SetPoint (10, -75)
+ --
+ _detalhes.gump:NewDropDown (window, _, "$parentFontDropdown", "fontDropdown", 170, 20, buildFontMenu, nil)
+ window.fontDropdown:SetPoint ("left", window.fontfaceLabel, "right", 2)
+
+ window:Hide()
+
+--> align mod X
+ _detalhes.gump:NewLabel (window, _, "$parentAlignXLabel", "alignXLabel", Loc ["STRING_PLUGINOPTIONS_TEXTALIGN_X"])
+ window.alignXLabel:SetPoint (10, -115)
+ --
+ _detalhes.gump:NewSlider (window, _, "$parentSliderAlignX", "alignXSlider", 160, 20, -20, 20, 1, 0)
+ window.alignXSlider:SetPoint ("left", window.alignXLabel, "right", 2)
+ window.alignXSlider:SetThumbSize (40)
+ window.alignXSlider:SetHook ("OnValueChange", function (self, child, amount)
+ _detalhes.StatusBar:ApplyOptions (child, "textxmod", amount)
+ end)
+
+--> align modY
+ _detalhes.gump:NewLabel (window, _, "$parentAlignYLabel", "alignYLabel", Loc ["STRING_PLUGINOPTIONS_TEXTALIGN_Y"])
+ window.alignYLabel:SetPoint (10, -135)
+ --
+ _detalhes.gump:NewSlider (window, _, "$parentSliderAlignY", "alignYSlider", 160, 20, -10, 10, 1, 0)
+ window.alignYSlider:SetPoint ("left", window.alignYLabel, "right", 2)
+ window.alignYSlider:SetThumbSize (40)
+ window.alignYSlider:SetHook ("OnValueChange", function (self, child, amount)
+ _detalhes.StatusBar:ApplyOptions (child, "textymod", amount)
+ end)
+
+--> open options
+ function _detalhes.StatusBar:OpenOptionsForChild (child)
+
+ window.child = child
+ window.instance = child.instance
+
+ _G.DetailsStatusBarOptionsTextStyleDropdown.MyObject:SetFixedParameter (child)
+
+ _G.DetailsStatusBarOptionsTextColorTexture:SetTexture (child.options.textColor[1], child.options.textColor[2], child.options.textColor[3], child.options.textColor[4])
+
+ _G.DetailsStatusBarOptionsSliderFontSize.MyObject:SetFixedParameter (child)
+ _G.DetailsStatusBarOptionsSliderFontSize.MyObject:SetValue (child.options.textSize)
+
+ _G.DetailsStatusBarOptionsSliderAlign.MyObject:SetFixedParameter (child)
+ _G.DetailsStatusBarOptionsSliderAlign.MyObject:SetValue (child.options.textAlign)
+
+ _G.DetailsStatusBarOptionsFontDropdown.MyObject:SetFixedParameter (child)
+ _G.DetailsStatusBarOptionsFontDropdown.MyObject:Select (child.options.textFace)
+
+ _G.DetailsStatusBarOptionsSliderAlignX.MyObject:SetFixedParameter (child)
+ _G.DetailsStatusBarOptionsSliderAlignX.MyObject:SetValue (child.options.textXMod)
+
+ _G.DetailsStatusBarOptionsSliderAlignY.MyObject:SetFixedParameter (child)
+ _G.DetailsStatusBarOptionsSliderAlignY.MyObject:SetValue (child.options.textYMod)
+
+ _G.DetailsStatusBarOptions:Show()
+
+ if (child.ExtraOptions) then
+
+ if (type (child.ExtraOptions) == "function") then
+ child.ExtraOptions()
+ end
+
+ extraWindow:HideWidgets()
+
+ for _, widget in pairs (child.ExtraOptions) do
+ widget:Show()
+ end
+
+ child:ExtraOptionsOnOpen (child)
+
+ extraWindow:Show()
+ else
+ extraWindow:Hide()
+ end
+ end
\ No newline at end of file
diff --git a/core/plugins_toolbar.lua b/core/plugins_toolbar.lua
new file mode 100644
index 00000000..12790dff
--- /dev/null
+++ b/core/plugins_toolbar.lua
@@ -0,0 +1,194 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+ -- none
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ --> create a button which will be displayed on tooltip
+ function _detalhes.ToolBar:NewPluginToolbarButton (func, icon, tooltip, w, h, name)
+
+ --> random name if nameless
+ if (not name) then
+ name = "DetailsToolbarButton" .. math.random (1, 100000)
+ end
+
+ --> create button from template
+ local button = CreateFrame ("button", name, _detalhes.listener, "DetailsToolbarButton")
+
+ --> sizes
+ if (w) then
+ button:SetWidth (w)
+ end
+ if (h) then
+ button:SetHeight (h)
+ end
+
+ --> tooltip and function on click
+ button.tooltip = tooltip
+ button:SetScript ("OnClick", func)
+
+ --> textures
+ button:SetNormalTexture (icon)
+ button:SetPushedTexture (icon)
+ button:SetDisabledTexture (icon)
+ button:SetHighlightTexture (icon, "ADD")
+
+ --> blizzard built-in animation
+ local FourCornerAnimeFrame = CreateFrame ("frame", name.."Blink", button, "IconIntroAnimTemplate")
+ FourCornerAnimeFrame:SetPoint ("center", button)
+ FourCornerAnimeFrame:SetWidth (w or 14)
+ FourCornerAnimeFrame:SetHeight (w or 14)
+ FourCornerAnimeFrame.glow:SetScript ("OnFinished", nil)
+ button.blink = FourCornerAnimeFrame
+
+ return button
+ end
+
+ --> show your plugin icon on tooltip
+ function _detalhes:ShowToolbarIcon (Button, Effect)
+
+ local LastIcon
+
+ --> get the lower number instance
+ local lower_instance = _detalhes:GetLowerInstanceNumber()
+ if (not lower_instance) then
+ return
+ end
+
+ local instance = _detalhes:GetInstance (lower_instance)
+
+ if (#_detalhes.ToolBar.Shown > 0) then
+ --> already shown
+ if (_detalhes:tableIN (_detalhes.ToolBar.Shown, Button)) then
+ return
+ end
+ LastIcon = _detalhes.ToolBar.Shown [#_detalhes.ToolBar.Shown]
+ else
+ LastIcon = instance.baseframe.cabecalho.report
+ end
+
+ local x = 0
+ if (instance.consolidate) then
+ LastIcon = instance.consolidateButtonTexture
+ x = x - 3
+ end
+
+ _detalhes.ToolBar.Shown [#_detalhes.ToolBar.Shown+1] = Button
+ Button:SetPoint ("left", LastIcon, "right", Button.x + x, Button.y)
+ Button:Show()
+
+ if (Effect) then
+ if (type (Effect) == "string") then
+ if (Effect == "blink") then
+ Button.blink.glow:Play()
+ elseif (Effect == "star") then
+ Button.StarAnim:Play()
+ end
+ elseif (Effect) then
+ Button.blink.glow:Play()
+ end
+ end
+
+ return true
+ end
+
+ --> hide your plugin icon from toolbar
+ function _detalhes:HideToolbarIcon (Button)
+
+ local index = _detalhes:tableIN (_detalhes.ToolBar.Shown, Button)
+
+ if (not index) then
+ --> current not shown
+ return
+ end
+
+ Button:Hide()
+ table.remove (_detalhes.ToolBar.Shown, index)
+
+ --> reorganize icons
+ _detalhes.ToolBar:ReorganizeIcons()
+
+ end
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ function DetailsToolbarButtonOnEnter (button)
+ if (button.tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:AddLine (button.tooltip)
+ GameCooltip:ShowCooltip (button, "tooltip")
+ end
+ end
+ function DetailsToolbarButtonOnLeave (button)
+ if (button.tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+ end
+
+ _detalhes:RegisterEvent (_detalhes.ToolBar, "DETAILS_INSTANCE_OPEN", "OnInstanceOpen")
+ _detalhes:RegisterEvent (_detalhes.ToolBar, "DETAILS_INSTANCE_CLOSE", "OnInstanceClose")
+ _detalhes.ToolBar.Enabled = true --> must have this member or will not receive the event
+
+ function _detalhes.ToolBar:OnInstanceOpen()
+ _detalhes.ToolBar:ReorganizeIcons()
+ end
+ function _detalhes.ToolBar:OnInstanceClose()
+ _detalhes.ToolBar:ReorganizeIcons()
+ end
+
+ function _detalhes.ToolBar:ReorganizeIcons (lastIcon)
+
+ --> get the lower number instance
+ local lower_instance = _detalhes:GetLowerInstanceNumber()
+
+ if (not lower_instance) then
+ for _, ThisButton in ipairs (_detalhes.ToolBar.Shown) do
+ ThisButton:Hide()
+ end
+ return
+ end
+
+ local instance = _detalhes:GetInstance (lower_instance)
+
+ _detalhes:ResetButtonSnapTo (instance)
+ _detalhes.ResetButtonInstance = lower_instance
+
+ if (#_detalhes.ToolBar.Shown > 0) then
+
+ local LastIcon
+
+ local x = 0
+ if (instance.consolidate) then
+ LastIcon = instance.consolidateButtonTexture
+ x = -3
+ else
+ LastIcon = instance.lastIcon or instance.baseframe.cabecalho.report
+ end
+
+ for _, ThisButton in ipairs (_detalhes.ToolBar.Shown) do
+ ThisButton:SetPoint ("left", LastIcon, "right", ThisButton.x + x, ThisButton.y)
+ ThisButton:Show()
+ LastIcon = ThisButton
+ end
+ end
+
+ for _, instancia in pairs (_detalhes.tabela_instancias) do
+ if (instancia.baseframe and instancia:IsAtiva()) then
+ instancia:ReajustaGump()
+ end
+ end
+
+ return true
+ end
diff --git a/core/timemachine.lua b/core/timemachine.lua
new file mode 100644
index 00000000..3af00aa9
--- /dev/null
+++ b/core/timemachine.lua
@@ -0,0 +1,205 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+ local _tempo = time()
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _table_insert = table.insert --lua local
+ local _ipairs = ipairs --lua local
+ local _pairs = pairs --lua local
+ local _time = time --lua local
+ local timeMachine = _detalhes.timeMachine --details local
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> constants
+ local _tempo = _time()
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> core
+
+ timeMachine.ligada = false
+
+ function timeMachine:Core()
+
+ _tempo = _time()
+ _detalhes._tempo = _tempo
+ _detalhes:UpdateGears()
+
+ for tipo, tabela in _pairs (self.tabelas) do
+ for nome, jogador in _ipairs (tabela) do
+ if (jogador) then
+ --print (jogador) --> jogador é a referência da tabela classe_damage
+
+ local ultima_acao = jogador:UltimaAcao()+3
+ if (ultima_acao > _tempo) then --> okey o jogador esta dando dps
+ if (jogador.on_hold) then --> o dps estava pausado, retornar a ativa
+ jogador:HoldOn (false)
+ end
+ else
+ if (not jogador.on_hold) then --> não ta pausado, precisa por em pausa
+ --> verifica se esta castando alguma coisa que leve + que 3 segundos
+ jogador:HoldOn (true)
+ end
+ end
+ end
+ end
+ end
+ end
+
+ function timeMachine:Ligar()
+ self.atualizador = self:ScheduleRepeatingTimer ("Core", 1)
+ self.ligada = true
+ self.tabelas = {{}, {}} --> 1 dano 2 cura
+
+ local danos = _detalhes.tabela_vigente[1]._ActorTable
+ for _, jogador in _ipairs (danos) do
+ if (jogador.dps_started) then
+ jogador:RegistrarNaTimeMachine()
+ end
+ end
+
+ end
+
+ function timeMachine:Desligar()
+ self.ligada = false
+ self.tabelas = nil
+ if (self.atualizador) then
+ self:CancelTimer (self.atualizador)
+ self.atualizador = nil
+ end
+ end
+
+ function timeMachine:Reiniciar()
+ self.tabelas = {{}, {}} --> 1 dano 2 cura
+ end
+
+ function _detalhes:DesregistrarNaTimeMachine()
+ if (not timeMachine.ligada) then
+ return
+ end
+ local esta_tabela = timeMachine.tabelas [self.tipo]
+ esta_tabela [self.timeMachine] = nil
+ self.timeMachine = nil
+ end
+
+ function _detalhes:RegistrarNaTimeMachine()
+ if (not timeMachine.ligada) then
+ return
+ end
+
+ --if (self.tipo == 3) then
+ -- print (debugstack())
+ -- return
+ --end
+
+ local esta_tabela = timeMachine.tabelas [self.tipo]
+ _table_insert (esta_tabela, self)
+ self.timeMachine = #esta_tabela
+ end
+
+ function _detalhes:ManutencaoTimeMachine()
+ for tipo, tabela in _ipairs (timeMachine.tabelas) do
+ local t = {}
+ for index, jogador in _ipairs (tabela) do
+ if (jogador) then
+ t [#t+1] = jogador
+ jogador.timeMachine = #t
+ end
+ end
+ timeMachine.tabelas [tipo] = t
+ end
+ end
+
+ function _detalhes:Tempo()
+ if (self.end_time) then --> o tempo do jogador esta trancado
+ return self.end_time - self.start_time
+ elseif (self.on_hold) then --> o tempo esta em pausa
+ return self.delay - self.start_time
+ else
+ return _tempo - self.start_time
+ end
+ end
+
+ function _detalhes:IniciarTempo (tempo, shadow)
+
+ -- inicia o tempo no objeto atual
+ --------------------------------------------------------------------------------
+
+ if (self.start_time > 0) then
+ print ("DEBUG: "..self.name.." ja tinha start_time...")
+ else
+ self.start_time = tempo
+ end
+
+ -- inicia o tempo no shadow do objeto
+ --------------------------------------------------------------------------------
+ -- eu nao sei se a shadow esta iniciando agora sou esta apenas reabrindo
+ -- tbm nao sei se a shadow esta reabrindo normalmente ou se esta reabrindo devido a combate menor de 4 segundos
+
+ -- verificar se a shadow esta com TEMPO FINALIZADO
+ -- SE ESTIVER significa que a shadow esta sendo reaberta
+
+ if (shadow.end_time) then
+ -- reabrir o tempo da shadow
+ -- eu tenho o tempo da abertura do combate atual, e o inicio e fim do tempo da shadow
+
+ -- tempo do inicio da shadow = tempo de abertura ATUAL menos tempo de combate da shadow
+ local subs = shadow.end_time - shadow.start_time
+ shadow.start_time = tempo - subs
+ shadow.end_time = nil -- o tempo foi aberto retirando o end_time
+
+ else -- pela minha logica se nao tiver end_time significa que precisa apenas gravar o tempo de inicio
+ -- a shadow foi recém criada e esta abrindo o tempo pela primeira vez
+ if (shadow.start_time == 0) then --> ja esta em um combate
+ shadow.start_time = tempo
+ end
+ end
+ end
+
+ function _detalhes:TerminarTempo (subs)
+ if (self.end_time) then
+ return
+ end
+ subs = subs or 0
+ if (self.on_hold) then
+ self.end_time = self.delay - subs -- isso ta certo? por que self.delay carrega o tempo quando o jogador parou o dps
+ self.on_hold = false
+ self.delay = nil
+ else
+ self.end_time = _tempo - subs
+ end
+ if (self.shadow) then
+ return self.shadow:TerminarTempo (subs)
+ end
+ end
+
+ --> diz se o dps deste jogador esta em pausa
+ function _detalhes:HoldOn (pausa)
+ if (pausa == nil) then
+ return self.on_hold --retorna se o dps esta aberto ou fechado para este jogador
+ elseif (pausa) then --> true
+ self.delay = _tempo
+ self.on_hold = true
+ else --> false
+ self.start_time = self.start_time + (_tempo-self.delay)
+ self.on_hold = false
+ end
+ end
+
+ --controla quando foi a ultima vez que este jogador deu dano
+ function _detalhes:UltimaAcao (tempo)
+ if (not tempo) then
+ return self.last_event
+ else
+ self.last_event = tempo
+ end
+ end
diff --git a/core/util.lua b/core/util.lua
new file mode 100644
index 00000000..d9ec2168
--- /dev/null
+++ b/core/util.lua
@@ -0,0 +1,564 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _table_insert = table.insert --lua local
+ local _upper = string.upper --lua local
+ local _ipairs = ipairs --lua local
+ local _pairs = pairs --lua local
+ local _string_format = string.format --lua local
+ local _math_floor = math.floor --lua local
+ local _math_max = math.max --lua local
+ local _type = type --lua local
+ local _string_match = string.match --lua local
+
+ local _UnitClass = UnitClass --wow api local
+ local _IsInRaid = IsInRaid --wow api local
+ local _IsInGroup = IsInGroup --wow api local
+ local _GetNumGroupMembers = GetNumGroupMembers --wow api local
+ local _UnitAffectingCombat = UnitAffectingCombat --wow api local
+ local _GameTooltip = GameTooltip --wow api local
+ local _UIFrameFadeIn = UIFrameFadeIn --wow api local
+ local _UIFrameFadeOut = UIFrameFadeOut --wow api local
+ local _InCombatLockdown = InCombatLockdown --wow api local
+
+ local gump = _detalhes.gump --details local
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ --> set all table keys to lower
+ local temptable = {}
+ function _detalhes:LowerizeKeys (_table)
+ for key, value in _pairs (_table) do
+ temptable [string.lower (key)] = value
+ end
+ temptable, _table = table.wipe (_table), temptable
+ return _table
+ end
+
+ --> short numbers
+ function _detalhes:ToK (numero)
+ if (numero > 1000000) then
+ return _string_format ("%.2f", numero/1000000) .."M"
+ elseif (numero > 1000) then
+ return _string_format ("%.1f", numero/1000) .."K"
+ end
+ return _string_format ("%.1f", numero)
+ end
+ --> short numbers no numbers after comma
+ function _detalhes:ToK0 (numero)
+ if (numero > 1000000) then
+ return _string_format ("%.0f", numero/1000000) .."M"
+ elseif (numero > 1000) then
+ return _string_format ("%.0f", numero/1000) .."K"
+ end
+ return _string_format ("%.0f", numero)
+ end
+
+ --> remove a index from a hash table
+ function _detalhes:tableRemove (tabela, indexName)
+ local newtable = {}
+ for hash, value in _pairs (tabela) do
+ if (hash ~= indexName) then
+ newtable [hash] = value
+ end
+ end
+ return newtable
+ end
+
+ --> return if the numeric table have an object
+ function _detalhes:tableIN (tabela, objeto)
+ for index, valor in _ipairs (tabela) do
+ if (valor == objeto) then
+ return index
+ end
+ end
+ return false
+ end
+
+ --> unpack more than 1 table
+ -- thanks http://www.dzone.com/snippets/lua-unpack-multiple-tables
+ function _detalhes:unpacks (...)
+ local values = {}
+ for i = 1, select ('#', ...) do
+ for _, value in _ipairs (select (i, ...)) do
+ values[ #values + 1] = value
+ end
+ end
+ return unpack (values)
+ end
+
+ --> put points in numbers
+ -- thanks http://richard.warburton.it
+ function _detalhes:comma_value(n)
+ local left,num,right = _string_match (n,'^([^%d]*%d)(%d*)(.-)$')
+ return left..(num:reverse():gsub('(%d%d%d)','%1,'):reverse())..right
+ end
+
+ --> trim thanks from http://lua-users.org/wiki/StringTrim
+ function _detalhes:trim (s)
+ local from = s:match"^%s*()"
+ return from > #s and "" or s:match(".*%S", from)
+ end
+
+ --> scale
+ function _detalhes:Scale (rangeMin, rangeMax, scaleMin, scaleMax, x)
+ return 1 + (x-rangeMin)*(scaleMax-scaleMin)/(rangeMax-rangeMin)
+ end
+
+ --> font size
+ function _detalhes:SetFontSize (fontString, ...)
+ local fonte, _, flags = fontString:GetFont()
+ fontString:SetFont (fonte, _math_max (...), flags)
+ end
+ function _detalhes:GetFontSize (fontString)
+ local _, size = fontString:GetFont()
+ return size
+ end
+
+ --> font face
+ function _detalhes:SetFontFace (fontString, fontface)
+ local _, size, flags = fontString:GetFont()
+ fontString:SetFont (fontface, size, flags)
+ end
+ function _detalhes:GetFontFace (fontString)
+ local fontface = fontString:GetFont()
+ return fontface
+ end
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ local LastDamage = 0
+ local LastDamageRecord = 0
+
+ --> record raid/party/player damage every second
+ function _detalhes:LogDps()
+
+ LastDamageRecord = LastDamageRecord + 1
+
+ if (LastDamageRecord > 1) then
+ LastDamageRecord = 0
+
+ local NowDamage = (_detalhes.tabela_vigente.totals_grupo[1] - LastDamage) /2
+
+ _table_insert (_detalhes.tabela_vigente.DpsGraphic, NowDamage)
+ if (NowDamage > _detalhes.tabela_vigente.DpsGraphic.max) then
+ _detalhes.tabela_vigente.DpsGraphic.max = NowDamage
+ end
+
+ LastDamage = _detalhes.tabela_vigente.totals_grupo[1]
+ end
+ end
+
+ --> is in combat yet?
+ function _detalhes:EstaEmCombate()
+
+ _detalhes.tabela_vigente.TimeData:Record()
+
+ if (_detalhes.zone_type == "pvp" or _InCombatLockdown()) then
+ return true
+ elseif (_UnitAffectingCombat("player")) then
+ return true
+ elseif (_IsInRaid()) then
+ for i = 1, _GetNumGroupMembers(), 1 do
+ if (_UnitAffectingCombat ("raid"..i)) then
+ return true
+ end
+ end
+ elseif (_IsInGroup()) then
+ for i = 1, _GetNumGroupMembers()-1, 1 do
+ if (_UnitAffectingCombat ("party"..i)) then
+ return true
+ end
+ end
+ end
+
+ LastDps = 0
+ _detalhes:SairDoCombate()
+ end
+
+ --> Armazena uma label recém criada - Store a new label on the pool
+ function _detalhes.font_pool:add (_fontstring)
+ self [#self+1] = _fontstring
+ end
+
+ function gump:UpdateTooltip (qual_barra, esta_barra, instancia)
+ _GameTooltip:Hide()
+ _GameTooltip:SetOwner (esta_barra, "ANCHOR_TOPRIGHT")
+ instancia:MontaTooltip (qual_barra)
+ _GameTooltip:Show()
+ end
+
+ local function frame_task (self, elapsed)
+
+ self.FrameTime = self.FrameTime + elapsed
+
+ if (self.HaveGradientEffect) then
+
+ local done = false
+
+ for index, ThisGradient in _ipairs (self.gradientes) do
+
+ if (self.FrameTime >= ThisGradient.NextStepAt and not ThisGradient.done) then
+
+ --> effects
+ if (ThisGradient.ObjectType == "frame") then
+ local r, g, b, a = ThisGradient.Object:GetBackdropColor()
+ ThisGradient.Object:SetBackdropColor (r + ThisGradient.Colors.Red, g + ThisGradient.Colors.Green, b + ThisGradient.Colors.Blue, a + ThisGradient.Colors.Alpha)
+ elseif (ThisGradient.ObjectType == "texture") then
+ local r, g, b, a = ThisGradient.Object:GetVertexColor()
+ ThisGradient.Object:SetVertexColor (r + ThisGradient.Colors.Red, g + ThisGradient.Colors.Green, b + ThisGradient.Colors.Blue, a + ThisGradient.Colors.Alpha)
+ end
+
+ ThisGradient.OnStep = ThisGradient.OnStep + 1
+ if (ThisGradient.FinishStep == ThisGradient.OnStep) then
+ if (ThisGradient.Func) then
+ if (type (ThisGradient.Func) == "string") then
+ local f = loadstring (ThisGradient.Func)
+ f()
+ else
+ ThisGradient.Func()
+ end
+ end
+ ThisGradient.done = true
+ done = true
+ else
+ ThisGradient.NextStepAt = self.FrameTime + ThisGradient.SleepTime
+ end
+ end
+ end
+
+ if (done) then
+ local _iter = {index = 1, data = self.gradientes [1]}
+ while (_iter.data) do
+ if (_iter.data.done) then
+ _iter.data.Object.HaveGradientEffect = false
+ table.remove (self.gradientes, _iter.index)
+ _iter.data = self.gradientes [_iter.index]
+ else
+ _iter.index = _iter.index + 1
+ _iter.data = self.gradientes [_iter.index]
+ end
+ end
+
+ if (#self.gradientes < 1) then
+ self.HaveGradientEffect = false
+ end
+ end
+ end
+
+ if (not self.HaveGradientEffect) then
+ self:SetScript ("OnUpdate", nil)
+ end
+
+ end
+
+ --[[ test grayscale ]]
+ function _detalhes:teste_grayscale()
+ local instancia = _detalhes.tabela_instancias[1]
+ for i = 1, instancia.barrasInfo.criadas, 1 do
+ local barra = instancia.barras[i]
+ local red, green, blue, alpha = barra.textura:GetVertexColor()
+ local grayscale = (red*0.03+green+blue) / 3 --> grayscale lightness method
+ gump:GradientEffect ( barra.textura, "texture", red, green, blue, alpha, grayscale, grayscale, grayscale, alpha, 1)
+ end
+ end
+
+ function gump:GradientEffect ( Object, ObjectType, StartRed, StartGreen, StartBlue, StartAlpha, EndRed, EndGreen, EndBlue, EndAlpha, Duration, EndFunction)
+
+ if (type (StartRed) == "table" and type (StartGreen) == "table") then
+ Duration, EndFunction = StartBlue, StartAlpha
+ EndRed, EndGreen, EndBlue, EndAlpha = unpack (StartGreen)
+ StartRed, StartGreen, StartBlue, StartAlpha = unpack (StartRed)
+
+ elseif (type (StartRed) == "table") then
+ EndRed, EndGreen, EndBlue, EndAlpha, Duration, EndFunction = StartGreen, StartBlue, StartAlpha, EndRed, EndGreen, EndBlue
+ StartRed, StartGreen, StartBlue, StartAlpha = unpack (StartRed)
+
+ elseif (type (EndRed) == "table") then
+ Duration, EndFunction = EndGreen, EndBlue
+ EndRed, EndGreen, EndBlue, EndAlpha = unpack (EndRed)
+ end
+
+ if (not EndAlpha) then
+ EndAlpha = 1.0
+ end
+ if (not StartAlpha) then
+ StartAlpha = 1.0
+ end
+
+ if (EndRed > 1.0) then
+ EndRed = 1.0
+ end
+ if (EndGreen > 1.0) then
+ EndGreen = 1.0
+ end
+ if (EndBlue > 1.0) then
+ EndBlue = 1.0
+ end
+
+ local GradientFrameControl = _detalhes.listener
+ GradientFrameControl.gradientes = GradientFrameControl.gradientes or {}
+
+ for index = 1, #GradientFrameControl.gradientes do
+ if (GradientFrameControl.gradientes[index].Object == Object) then
+ GradientFrameControl.gradientes[index].done = true
+ end
+ end
+
+ local MinFramesPerSecond = 10 --> at least 10 frames will be necessary
+ local ExecTime = Duration * 1000 --> value in miliseconds
+ local SleepTime = 100 --> 100 miliseconds
+
+ local FrameAmount = _math_floor (ExecTime/100) --> amount of frames
+
+ if (FrameAmount < MinFramesPerSecond) then
+ FrameAmount = MinFramesPerSecond
+ SleepTime = ExecTime/FrameAmount
+ end
+
+ local ColorStep = {}
+ ColorStep.Red = (EndRed - StartRed) / FrameAmount
+ ColorStep.Green = (EndGreen - StartGreen) / FrameAmount
+ ColorStep.Blue = (EndBlue - StartBlue) / FrameAmount
+ ColorStep.Alpha = (EndAlpha - StartAlpha) / FrameAmount
+
+ GradientFrameControl.gradientes [#GradientFrameControl.gradientes+1] = {
+ OnStep = 1,
+ FinishStep = FrameAmount,
+ SleepTime = SleepTime/1000,
+ NextStepAt = GradientFrameControl.FrameTime + (SleepTime/1000),
+ Object = Object,
+ ObjectType = string.lower (ObjectType),
+ Colors = ColorStep,
+ Func = EndFunction}
+
+ Object.HaveGradientEffect = true
+ GradientFrameControl.HaveGradientEffect = true
+
+ if (not GradientFrameControl:GetScript ("OnUpdate")) then
+ GradientFrameControl:SetScript ("OnUpdate", frame_task)
+ end
+
+ end
+
+ function gump:Fade (frame, tipo, velocidade, parametros)
+
+ if (_type (frame) == "table" and frame.meu_id) then --> ups, é uma instância
+ if (parametros == "barras") then --> hida todas as barras da instância
+ if (velocidade) then
+ for i = 1, frame.barrasInfo.criadas, 1 do
+ gump:Fade (frame.barras[i], tipo, velocidade)
+ end
+ return
+ else
+ velocidade = velocidade or 0.3
+ for i = 1, frame.barrasInfo.criadas, 1 do
+ gump:Fade (frame.barras[i], tipo, 0.3+(i/10))
+ end
+ return
+ end
+ elseif (parametros == "hide_barras") then --> hida todas as barras da instância
+ for i = 1, frame.barrasInfo.criadas, 1 do
+ local esta_barra = frame.barras[i]
+ if (esta_barra.fading_in or esta_barra.fading_out) then
+ esta_barra.fadeInfo.finishedFunc = nil
+ _UIFrameFadeIn (esta_barra, 0.01, esta_barra:GetAlpha(), esta_barra:GetAlpha())
+ end
+ esta_barra.hidden = true
+ esta_barra.faded = true
+ esta_barra.fading_in = false
+ esta_barra.fading_out = false
+ esta_barra:Hide()
+ esta_barra:SetAlpha(0)
+ end
+ return
+ end
+ end
+
+ velocidade = velocidade or 0.3
+
+ --> esse ALL aqui pode dar merda com as instâncias não ativadas
+ if (frame == "all") then --> todas as instâncias
+ for _, instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (parametros == "barras") then --> hida todas as barras da instância
+ for i = 1, instancia.barrasInfo.criadas, 1 do
+ gump:Fade (instancia.barras[i], tipo, velocidade+(i/10))
+ end
+ end
+ end
+
+ elseif (_upper (tipo) == "IN") then
+
+ if (frame:GetAlpha() == 0 and frame.hidden and not frame.fading_out) then --> ja esta escondida
+ return
+ elseif (frame.fading_in) then --> ja esta com uma animação, se for true
+ return
+ end
+
+ if (frame.fading_out) then --> se tiver uma animação de aparecer em andamento se for true
+ frame.fading_out = false
+ end
+
+ _UIFrameFadeIn (frame, velocidade, frame:GetAlpha(), 0)
+ frame.fading_in = true
+ frame.fadeInfo.finishedFunc =
+ function()
+ frame.hidden = true
+ frame.faded = true
+ frame.fading_in = false
+ frame:Hide()
+ end
+
+ elseif (_upper (tipo) == "OUT") then --> aparecer
+ if (frame:GetAlpha() == 1 and not frame.hidden and not frame.fading_in) then --> ja esta na tela
+ return
+ elseif (frame.fading_out) then --> já ta com fading out
+ return
+ end
+
+ if (frame.fading_in) then --> se tiver uma animação de hidar em andamento se for true
+ frame.fading_in = false
+ end
+
+ frame:Show()
+ _UIFrameFadeOut (frame, velocidade, frame:GetAlpha(), 1.0)
+ frame.fading_out = true
+ frame.fadeInfo.finishedFunc =
+ function()
+ frame.hidden = false
+ frame.faded = false
+ frame.fading_out = false
+ end
+
+ elseif (tipo == 0) then --> força o frame a ser mostrado
+ frame.hidden = false
+ frame.faded = false
+ frame.fading_out = false
+ frame.fading_in = false
+ frame:Show()
+ frame:SetAlpha(1)
+ if (frame.fadeInfo) then --> limpa a função de fade se tiver alguma
+ frame.fadeInfo.finishedFunc = nil
+ end
+
+ elseif (tipo == 1) then --> força o frame a ser hidado
+
+ frame.hidden = true
+ frame.faded = true
+ frame.fading_out = false
+ frame.fading_in = false
+ frame:Hide()
+ frame:SetAlpha(0)
+ if (frame.fadeInfo) then --> limpa a função de fade se tiver alguma
+ frame.fadeInfo.finishedFunc = nil
+ end
+
+ elseif (tipo == -1) then --> apenas da fade sem hidar
+ if (frame:GetAlpha() == 0 and frame.hidden and not frame.fading_out) then --> ja esta escondida
+ return
+ elseif (frame.fading_in) then --> ja esta com uma animação, se for true
+ return
+ end
+
+ if (frame.fading_out) then --> se tiver uma animação de aparecer em andamento se for true
+ frame.fading_out = false
+ end
+
+ _UIFrameFadeIn (frame, velocidade, frame:GetAlpha(), 0)
+ frame.fading_in = true
+ frame.fadeInfo.finishedFunc =
+ function()
+ frame.hidden = false
+ frame.faded = true
+ frame.fading_in = false
+ end
+
+ elseif (_upper (tipo) == "ALPHAANIM") then
+
+ local value = velocidade
+ local currentApha = frame:GetAlpha()
+ frame:Show()
+
+ if (currentApha < value) then
+ if (frame.fading_in) then --> se tiver uma animação de hidar em andamento se for true
+ frame.fading_in = false
+ frame.fadeInfo.finishedFunc = nil
+ end
+ UIFrameFadeOut (frame, 0.3, currentApha, value)
+ frame.fading_out = true
+ frame.fadeInfo.finishedFunc =
+ function()
+ frame.fading_out = false
+ end
+ else
+ if (frame.fading_out) then --> se tiver uma animação de hidar em andamento se for true
+ frame.fading_out = false
+ frame.fadeInfo.finishedFunc = nil
+ end
+ UIFrameFadeIn (frame, 0.3, currentApha, value)
+ frame.fading_in = true
+ frame.fadeInfo.finishedFunc =
+ function()
+ frame.fading_in = false
+ end
+ end
+
+ elseif (_upper (tipo) == "ALPHA") then --> setando um alpha determinado
+ if (frame.fading_in or frame.fading_out) then
+ frame.fadeInfo.finishedFunc = nil
+ _UIFrameFadeIn (frame, velocidade, frame:GetAlpha(), frame:GetAlpha())
+ end
+ frame.hidden = false
+ frame.faded = false
+ frame.fading_in = false
+ frame.fading_out = false
+ frame:Show()
+ frame:SetAlpha (velocidade)
+ end
+ end
+
+ function _detalhes:name_space (barra)
+ --if (barra.icone_secundario_ativo) then
+ -- local tamanho = barra:GetWidth()-barra.texto_direita:GetStringWidth()-16-barra:GetHeight()
+ -- barra.texto_esquerdo:SetSize (tamanho-2, 15)
+ --else
+ barra.texto_esquerdo:SetSize (barra:GetWidth()-barra.texto_direita:GetStringWidth()-18, 15)
+ --end
+ end
+
+ function _detalhes:name_space_info (barra)
+ if (barra.icone_secundario_ativo) then
+ local tamanho = barra:GetWidth()-barra.texto_direita:GetStringWidth()-16-barra:GetHeight()
+ barra.texto_esquerdo:SetSize (tamanho-10, 15)
+ else
+ local tamanho = barra:GetWidth()-barra.texto_direita:GetStringWidth()-16
+ barra.texto_esquerdo:SetSize (tamanho-10, 15)
+ end
+ end
+
+ function _detalhes:name_space_generic (barra, separador)
+ local texto_direita_tamanho = barra.texto_direita:GetStringWidth()
+ local tamanho = barra:GetWidth()-texto_direita_tamanho-16
+ if (separador) then
+ barra.texto_esquerdo:SetSize (tamanho+separador, 10)
+ barra.texto_direita:SetSize (texto_direita_tamanho+15, 10)
+ else
+ barra.texto_esquerdo:SetSize (tamanho-10, 15)
+ barra.texto_direita:SetSize (texto_direita_tamanho+5, 15)
+ end
+ end
+
diff --git a/core/windows.lua b/core/windows.lua
new file mode 100644
index 00000000..82e896de
--- /dev/null
+++ b/core/windows.lua
@@ -0,0 +1,570 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _math_floor = math.floor --lua local
+ local _type = type --lua local
+ local _math_abs = math.abs --lua local
+ local _ipairs = ipairs --lua local
+
+ local _GetScreenWidth = GetScreenWidth --wow api local
+ local _GetScreenHeight = GetScreenHeight --wow api local
+ local _UIParent = UIParent --wow api local
+
+ local gump = _detalhes.gump --details local
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> core
+
+
+ function _detalhes:AnimarSplit (barra, goal)
+ barra.inicio = barra.split.barra:GetValue()
+ barra.fim = goal
+ barra.proximo_update = 0
+ barra.tem_animacao = 1
+ barra:SetScript ("OnUpdate", self.FazerAnimacaoSplit)
+ end
+
+ function _detalhes:FazerAnimacaoSplit (elapsed)
+
+ --[[
+ local velocidade = 0.1
+ local distancia = self.inicio - self.fim
+ if (distancia > 40 or distancia < -40) then
+ velocidade = 0.8
+ elseif (distancia > 20 or distancia < -20) then
+ velocidade = 0.4
+ end
+ --]]
+ local velocidade = 0.8
+
+ if (self.fim > self.inicio) then
+ self.inicio = self.inicio+velocidade
+ self.split.barra:SetValue (self.inicio)
+
+ self.split.div:SetPoint ("left", self.split.barra, "left", self.split.barra:GetValue()* (self.split.barra:GetWidth()/100) - 4, 0)
+
+ if (self.inicio+1 >= self.fim) then
+ self.tem_animacao = 0
+ self:SetScript ("OnUpdate", nil)
+ end
+ else
+ self.inicio = self.inicio-velocidade
+ self.split.barra:SetValue (self.inicio)
+
+ self.split.div:SetPoint ("left", self.split.barra, "left", self.split.barra:GetValue()* (self.split.barra:GetWidth()/100) - 4, 0)
+
+ if (self.inicio-1 <= self.fim) then
+ self.tem_animacao = 0
+ self:SetScript ("OnUpdate", nil)
+ end
+ end
+ self.proximo_update = 0
+ end
+
+ function _detalhes:AnimarBarra (esta_barra, fim)
+ esta_barra.inicio = esta_barra.statusbar:GetValue()
+ esta_barra.fim = fim
+ esta_barra.proximo_update = 0
+ esta_barra.tem_animacao = 1
+ esta_barra:SetScript ("OnUpdate", self.FazerAnimacao)
+ end
+
+ function _detalhes:FazerAnimacao (elapsed)
+
+ local velocidade = 0.8
+ --[[
+ local velocidade = 0.1
+ local distancia = self.inicio - self.fim
+ if (distancia > 40 or distancia < -40) then
+ velocidade = 0.8
+ elseif (distancia > 20 or distancia < -20) then
+ velocidade = 0.4
+ end
+ --]]
+ if (self.fim > self.inicio) then
+ self.inicio = self.inicio+velocidade
+ self.statusbar:SetValue (self.inicio)
+ if (self.inicio+1 >= self.fim) then
+ self.tem_animacao = 0
+ self:SetScript ("OnUpdate", nil)
+ end
+ else
+ self.inicio = self.inicio-velocidade
+ self.statusbar:SetValue (self.inicio)
+ if (self.inicio-1 <= self.fim) then
+ self.tem_animacao = 0
+ self:SetScript ("OnUpdate", nil)
+ end
+ end
+ self.proximo_update = 0
+ end
+
+ function _detalhes:AtualizaPontos()
+ local xOfs, yOfs = self.baseframe:GetCenter()
+
+ if (not xOfs) then
+ return
+ end
+
+ -- credits to ckknight (http://www.curseforge.com/profiles/ckknight/)
+ local _scale = self.baseframe:GetEffectiveScale()
+ local _UIscale = _UIParent:GetScale()
+ xOfs = xOfs*_scale - _GetScreenWidth()*_UIscale/2
+ yOfs = yOfs*_scale - _GetScreenHeight()*_UIscale/2
+ local _x = xOfs/_UIscale
+ local _y = yOfs/_UIscale
+ local _w = self.baseframe:GetWidth()
+ local _h = self.baseframe:GetHeight()
+
+ local metade_largura = _w/2
+ local metade_altura = _h/2
+
+ self.ponto1 = {x = _x - metade_largura, y = _y + metade_altura}
+ self.ponto2 = {x = _x - metade_largura, y = _y - metade_altura}
+ self.ponto3 = {x = _x + metade_largura, y = _y - metade_altura}
+ self.ponto4 = {x = _x + metade_largura, y = _y + metade_altura}
+ end
+
+ function _detalhes:SaveMainWindowPosition (instance)
+
+ if (instance) then
+ self = instance
+ end
+
+ local xOfs, yOfs = self.baseframe:GetCenter()
+
+ if (not xOfs) then
+ --> this is a small and unknow bug when resizing all windows throgh crtl key (all) the last window of a horizontal row can't 'GetCenter'.
+ --> so, the trick is we start a timer to save pos later.
+ return _detalhes:ScheduleTimer ("SaveMainWindowPosition", 1, self)
+ end
+
+ -- credits to ckknight (http://www.curseforge.com/profiles/ckknight/)
+ local _scale = self.baseframe:GetEffectiveScale()
+ local _UIscale = _UIParent:GetScale()
+ local mostrando = self.mostrando
+
+ xOfs = xOfs*_scale - _GetScreenWidth()*_UIscale/2
+ yOfs = yOfs*_scale - _GetScreenHeight()*_UIscale/2
+
+ local _w = self.baseframe:GetWidth()
+ local _h = self.baseframe:GetHeight()
+ local _x = xOfs/_UIscale
+ local _y = yOfs/_UIscale
+
+ self.posicao[mostrando].x = _x
+ self.posicao[mostrando].y = _y
+ self.posicao[mostrando].w = _w
+ self.posicao[mostrando].h = _h
+
+ local metade_largura = _w/2
+ local metade_altura = _h/2
+
+ self.ponto1 = {x = _x - metade_largura, y = _y + metade_altura}
+ self.ponto2 = {x = _x - metade_largura, y = _y - metade_altura}
+ self.ponto3 = {x = _x + metade_largura, y = _y - metade_altura}
+ self.ponto4 = {x = _x + metade_largura, y = _y + metade_altura}
+
+ self.baseframe.BoxBarrasAltura = self.baseframe:GetHeight()-4 --> isso aqui não sei o que esta fazendo aqui
+
+ return {altura = self.baseframe:GetHeight(), largura = self.baseframe:GetWidth(), x = xOfs/_UIscale, y = yOfs/_UIscale}
+ end
+
+ function _detalhes:RestoreMainWindowPosition (pre_defined)
+
+ -- credits to ckknight (http://www.curseforge.com/profiles/ckknight/)
+ local _scale = self.baseframe:GetEffectiveScale()
+ local _UIscale = _UIParent:GetScale()
+
+ local novo_x = self.posicao[self.mostrando].x*_UIscale/_scale
+ local novo_y = self.posicao[self.mostrando].y*_UIscale/_scale
+
+ if (pre_defined) then --> overwrite
+ novo_x = pre_defined.x*_UIscale/_scale
+ novo_y = pre_defined.y*_UIscale/_scale
+ self.posicao[self.mostrando].w = pre_defined.largura
+ self.posicao[self.mostrando].h = pre_defined.altura
+ end
+
+ self.baseframe:ClearAllPoints()
+ self.baseframe:SetPoint ("CENTER", _UIParent, "CENTER", novo_x, novo_y)
+
+ self.baseframe:SetWidth (self.posicao[self.mostrando].w) --slider frame
+ self.baseframe:SetHeight (self.posicao[self.mostrando].h)
+
+ self.baseframe.BoxBarrasAltura = self.baseframe:GetHeight()-4 --> ?????
+ end
+
+ function _detalhes:RestoreMainWindowPositionNoResize (pre_defined, x, y)
+
+ x = x or 0
+ y = y or 0
+
+ -- credits to ckknight (http://www.curseforge.com/profiles/ckknight/)
+ local _scale = self.baseframe:GetEffectiveScale()
+ local _UIscale = _UIParent:GetScale()
+
+ local novo_x = self.posicao[self.mostrando].x*_UIscale/_scale
+ local novo_y = self.posicao[self.mostrando].y*_UIscale/_scale
+
+ if (pre_defined) then --> overwrite
+ novo_x = pre_defined.x*_UIscale/_scale
+ novo_y = pre_defined.y*_UIscale/_scale
+ self.posicao[self.mostrando].w = pre_defined.largura
+ self.posicao[self.mostrando].h = pre_defined.altura
+ end
+
+ self.baseframe:ClearAllPoints()
+ self.baseframe:SetPoint ("CENTER", _UIParent, "CENTER", novo_x + x, novo_y + y)
+ self.baseframe.BoxBarrasAltura = self.baseframe:GetHeight()-4 --> ?????
+ end
+
+ function _detalhes:ResetaGump (instancia, tipo, segmento)
+ if (not instancia or _type (instancia) == "boolean") then
+ segmento = tipo
+ tipo = instancia
+ instancia = self
+ end
+
+ if (tipo and tipo == 0x1) then --> entrando em combate
+ if (instancia.segmento == -1) then --> esta mostrando a tabela overall
+ return
+ end
+ end
+
+ if (segmento and instancia.segmento ~= segmento) then
+ return
+ end
+
+ instancia.barraS = {nil, nil} --> zera o iterator
+ instancia.barrasInfo.mostrando = 0 --> resetou, então não esta mostranho nenhuma barra
+
+ for i = 1, instancia.barrasInfo.criadas, 1 do --> limpa a referência do que estava sendo mostrado na barra
+ local esta_barra= instancia.barras[i]
+ esta_barra.minha_tabela = nil
+ end
+
+ if (instancia.rolagem) then
+ instancia:EsconderScrollBar() --> hida a scrollbar
+ end
+ instancia.need_rolagem = false
+ instancia.bar_mod = nil
+
+ end
+
+ function _detalhes:ReajustaGump()
+
+ if (self.mostrando == "normal") then --> somente alterar o tamanho das barras se tiver mostrando o gump normal
+
+ if (self.meu_id == _detalhes.ResetButtonInstance) then
+ if (self.baseframe:GetWidth() < 215) then
+ gump:Fade (_detalhes.ResetButton, 1)
+ gump:Fade (_detalhes.ResetButton2, 0)
+ _detalhes.ResetButtonMode = 2
+ else
+ gump:Fade (_detalhes.ResetButton, 0)
+ gump:Fade (_detalhes.ResetButton2, 1)
+ _detalhes.ResetButtonMode = 1
+ end
+ end
+
+ if (not self.baseframe.isStretching and self.stretchToo and #self.stretchToo > 0) then
+ if (self.eh_horizontal or self.eh_tudo or (self.verticalSnap and not self.eh_vertical)) then
+ for _, instancia in _ipairs (self.stretchToo) do
+ instancia.baseframe:SetWidth (self.baseframe:GetWidth())
+ local mod = (self.baseframe:GetWidth() - instancia.baseframe._place.largura) / 2
+ instancia:RestoreMainWindowPositionNoResize (instancia.baseframe._place, mod, nil)
+ instancia:BaseFrameSnap()
+ end
+ end
+ if ( (self.eh_vertical or self.eh_tudo or not self.eh_horizontal) and (not self.verticalSnap or self.eh_vertical)) then
+ for _, instancia in _ipairs (self.stretchToo) do
+ if (instancia.baseframe) then --> esta criada
+ instancia.baseframe:SetHeight (self.baseframe:GetHeight())
+ local mod
+ if (self.eh_vertical) then
+ mod = (self.baseframe:GetHeight() - instancia.baseframe._place.altura) / 2
+ else
+ mod = - (self.baseframe:GetHeight() - instancia.baseframe._place.altura) / 2
+ end
+ instancia:RestoreMainWindowPositionNoResize (instancia.baseframe._place, nil, mod)
+ instancia:BaseFrameSnap()
+ end
+ end
+ end
+ elseif (self.baseframe.isStretching and self.stretchToo and #self.stretchToo > 0) then
+ for _, instancia in _ipairs (self.stretchToo) do
+ instancia.baseframe:SetHeight (self.baseframe:GetHeight())
+ local mod = (self.baseframe:GetHeight() - instancia.baseframe._place.altura) / 2
+ instancia:RestoreMainWindowPositionNoResize (instancia.baseframe._place, nil, mod)
+ end
+ end
+
+ if (_detalhes.lower_instance == self.meu_id or self.consolidate) then
+ if (not self.consolidate) then
+ if (self.baseframe:GetWidth() < 180) then
+ --> consolidate menus
+ self:ConsolidateIcons()
+ end
+ else
+ if (self.baseframe:GetWidth() > 180 or _detalhes.lower_instance ~= self.meu_id) then
+ --> un consolidade menus
+ self:UnConsolidateIcons()
+ end
+ end
+ end
+
+ if (self.freezed) then
+ --> reajusta o freeze
+ _detalhes:Freeze (self)
+ end
+
+ -- -4 difere a precisão de quando a barra será adicionada ou apagada da barra
+ self.baseframe.BoxBarrasAltura = self.baseframe:GetHeight()-4
+
+ local T = self.barrasInfo.cabem
+ if (not T) then --> primeira vez que o gump esta sendo reajustado
+ T = _math_floor (self.baseframe.BoxBarrasAltura / self.barrasInfo.alturaReal)
+ -- o que mais precisa por aqui?
+ end
+
+ --> reajustar o local do relógio
+ local meio = self.baseframe:GetWidth() / 2
+ local novo_local = meio - 25
+ self.barrasInfo.cabem = _math_floor ( self.baseframe.BoxBarrasAltura / self.barrasInfo.alturaReal)
+
+ if (self.barrasInfo.cabem > #self.barras) then--> verifica se precisa criar mais barras
+ for i = #self.barras+1, self.barrasInfo.cabem, 1 do
+ local nova_barra = gump:CriaNovaBarra (self, i, 30) --> cria nova barra
+ nova_barra.texto_esquerdo:SetText (Loc ["STRING_NEWROW"]) --seta o texto da esqueda
+ nova_barra.statusbar:SetValue (100)
+ self.barras [i] = nova_barra
+ end
+ self.barrasInfo.criadas = #self.barras
+ end
+
+ --> seta a largura das barras
+ if (self.bar_mod and self.bar_mod ~= 0) then
+ for index = 1, self.barrasInfo.cabem do
+ self.barras [index]:SetWidth (self.baseframe:GetWidth()+self.bar_mod)
+ end
+ else
+ for index = 1, self.barrasInfo.cabem do
+ self.barras [index]:SetWidth (self.baseframe:GetWidth()+self.barrasInfo.espaco.direita)
+ end
+ end
+
+ local A = self.barraS[1]
+ if (not A) then --> primeira vez que o resize esta sendo usado, no caso no startup do addon ou ao criar uma nova instância
+ --> hida as barras não usadas
+ for i = 1, self.barrasInfo.criadas, 1 do
+ gump:Fade (self.barras [i], 1)
+ self.barras [i].on = false
+ end
+ return
+ end
+
+ local X = self.barrasInfo.mostrando
+ local C = self.barrasInfo.cabem
+
+ --> novo iterator
+ local barras_diff = C - T --> aqui pega a quantidade de barras, se aumentou ou diminuiu
+ if (barras_diff > 0) then --> ganhou barras_diff novas barras
+ local fim_iterator = self.barraS[2] --> posição atual
+ fim_iterator = fim_iterator+barras_diff --> nova posição
+ local excedeu_iterator = fim_iterator - X --> total que ta sendo mostrado - fim do iterator
+ if (excedeu_iterator > 0) then --> extrapolou
+ fim_iterator = X --> seta o fim do iterator pra ser na ultima barra
+ self.barraS[2] = fim_iterator --> fim do iterator setado
+
+ local inicio_iterator = self.barraS[1]
+ if (inicio_iterator-excedeu_iterator > 0) then --> se as barras que sobraram preenchem o inicio do iterator
+ inicio_iterator = inicio_iterator-excedeu_iterator --> pega o novo valor do iterator
+ self.barraS[1] = inicio_iterator
+ else
+ self.barraS[1] = 1 --> se ganhou mais barras pra cima, ignorar elas e mover o iterator para a pocição inicial
+ end
+ else
+ --> se não extrapolou esta okey e esta mostrando a quantidade de barras correta
+ self.barraS[2] = fim_iterator
+ end
+
+ for index = T+1, C do
+ if (index <= X) then
+ gump:Fade (self.barras[index], "out")
+ else
+ --gump:Fade (self.barras[index], "in")
+ if (self.baseframe.isStretching or self.auto_resize) then
+ gump:Fade (self.barras[index], 1)
+ else
+ gump:Fade (self.barras[index], "in", 0.1)
+ end
+ end
+ end
+
+ elseif (barras_diff < 0) then --> perdeu barras_diff barras
+ local fim_iterator = self.barraS[2] --> posição atual
+ if (not (fim_iterator == X and fim_iterator < C)) then --> calcula primeiro as barras que foram perdidas são barras que não estavam sendo usadas
+ --> perdi X barras, diminui X posições no iterator
+ local perdeu = _math_abs (barras_diff)
+
+ if (fim_iterator == X) then --> se o iterator tiver na ultima posição
+ perdeu = perdeu - (C - X)
+ end
+
+ fim_iterator = fim_iterator - perdeu
+
+ if (fim_iterator < C) then
+ fim_iterator = C
+ end
+
+ self.barraS[2] = fim_iterator
+
+ for index = T, C+1, -1 do
+ --gump:Fade (self.barras[index], "in")
+ if (self.baseframe.isStretching or self.auto_resize) then
+ gump:Fade (self.barras[index], 1)
+ else
+ gump:Fade (self.barras[index], "in", 0.1)
+ end
+ end
+ end
+ end
+
+ if (X <= C) then --> desligar a rolagem
+ if (self.rolagem and not self.baseframe.isStretching) then
+ self:EsconderScrollBar()
+ end
+ self.need_rolagem = false
+ else --> ligar ou atualizar a rolagem
+ if (not self.rolagem and not self.baseframe.isStretching) then
+ self:MostrarScrollBar()
+ end
+ self.need_rolagem = true
+ end
+
+ --> verificar o tamanho dos nomes
+ local qual_barra = 1
+ for i = self.barraS[1], self.barraS[2], 1 do
+ local esta_barra = self.barras [qual_barra]
+ local tabela = esta_barra.minha_tabela
+
+ if (tabela) then --> a barra esta mostrando alguma coisa
+
+ if (tabela._custom) then
+ tabela (esta_barra, self)
+ else
+ tabela:RefreshBarra (esta_barra, self)
+ end
+
+ if (esta_barra.minha_tabela.enemy) then
+ --if (i == 1) then
+ --print (esta_barra.texto_esquerdo:GetWrappedWidth())
+ --end
+
+ --esta_barra.texto_esquerdo:SetText (esta_barra.colocacao.."."..esta_barra.minha_tabela.nome.." |TInterface\\PVPFrame\\PVP-Currency-Horde:14:14|t") --seta o texto da esqueda
+
+ --local texto_len = esta_barra.texto_esquerdo:GetStringWidth()
+ --if (esta_barra.texto_esquerdo:IsTruncated()) then
+ --local tamanho = esta_barra:GetWidth()-esta_barra.texto_direita:GetStringWidth()-16-esta_barra:GetHeight()
+ --esta_barra.icone_secundario:SetPoint ("left", esta_barra.texto_esquerdo, "left", tamanho-2, 0)
+ --print ("aqui")
+ --else
+ --print ("aqui")
+ --if (i == 1) then
+ --print (esta_barra.texto_esquerdo:GetStringWidth()) --debug
+ --print (esta_barra.texto_esquerdo:GetText())
+ --end
+ --local fonte, size, flags = esta_barra.texto_esquerdo:GetFont()
+ --print (fonte, size, flags)
+ --esta_barra.icone_secundario:SetPoint ("left", esta_barra.texto_esquerdo, "left", esta_barra.texto_esquerdo:GetStringWidth()+3, 0)
+ --esta_barra.texto_esquerdo:SetText (esta_barra.colocacao.."."..esta_barra.minha_tabela.nome.." |TInterface\\PVPFrame\\PVP-Currency-Horde:14:14|t") --seta o texto da esqueda
+ --end
+ end
+ end
+
+ qual_barra = qual_barra+1
+ end
+
+ --> força o próximo refresh
+ self.showing[self.atributo].need_refresh = true
+
+ end
+ end
+
+ --> cria o frame de wait for plugin
+ do
+ local WaitForPluginFrame = CreateFrame ("frame", "DetailsWaitForPluginFrame", UIParent)
+ local WaitTexture = WaitForPluginFrame:CreateTexture (nil, "overlay")
+ WaitTexture:SetTexture ("Interface\\UNITPOWERBARALT\\Mechanical_Circular_Frame")
+ WaitTexture:SetPoint ("center", WaitForPluginFrame)
+ WaitTexture:SetWidth (180)
+ WaitTexture:SetHeight (180)
+ WaitForPluginFrame.wheel = WaitTexture
+ local RotateAnimGroup = WaitForPluginFrame:CreateAnimationGroup()
+ local rotate = RotateAnimGroup:CreateAnimation ("Rotation")
+ rotate:SetDegrees (360)
+ rotate:SetDuration (60)
+ RotateAnimGroup:SetLooping ("repeat")
+
+ local bgpanel = gump:NewPanel (UIParent, UIParent, "DetailsWaitFrameBG", nil, 120, 30, false, false, false)
+ bgpanel:SetPoint ("center", WaitForPluginFrame, "center")
+ bgpanel:SetBackdrop ({bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
+ bgpanel:SetBackdropColor (.2, .2, .2, 1)
+
+ local label = gump:NewLabel (UIParent, UIParent, nil, nil, Loc ["STRING_WAITPLUGIN"]) --> localize-me
+ label.color = "silver"
+ label:SetPoint ("center", WaitForPluginFrame, "center")
+ label:SetJustifyH ("center")
+ label:Hide()
+
+ WaitForPluginFrame:Hide()
+
+ function _detalhes:WaitForSoloPlugin (instancia)
+
+ if (WaitForPluginFrame:IsShown() and WaitForPluginFrame:GetParent() == instancia.baseframe) then
+ return _detalhes:ScheduleTimer ("ExecDelayedPlugin", 5, instancia)
+ end
+
+ WaitForPluginFrame:SetParent (instancia.baseframe)
+ WaitForPluginFrame:SetAllPoints (instancia.baseframe)
+ local size = math.max (instancia.baseframe:GetHeight()* 0.35, 100)
+ WaitForPluginFrame.wheel:SetWidth (size)
+ WaitForPluginFrame.wheel:SetHeight (size)
+ WaitForPluginFrame:Show()
+ label:Show()
+ bgpanel:Show()
+ RotateAnimGroup:Play()
+
+ return _detalhes:ScheduleTimer ("ExecDelayedPlugin", 5, instancia)
+ end
+
+ function _detalhes:CancelWaitForPlugin()
+ RotateAnimGroup:Stop()
+ WaitForPluginFrame:Hide()
+ label:Hide()
+ bgpanel:Hide()
+ end
+
+ function _detalhes:ExecDelayedPlugin (instancia)
+ RotateAnimGroup:Stop()
+ WaitForPluginFrame:Hide()
+ label:Hide()
+ bgpanel:Hide()
+ if (instancia.meu_id == _detalhes.solo) then
+ _detalhes.SoloTables:switch (_, _detalhes.SoloTables.Mode)
+ elseif (instancia.meu_id == _detalhes.raid) then
+ _detalhes.RaidTables:switch (_, _detalhes.RaidTables.Mode)
+ end
+ end
+ end
diff --git a/embeds.xml b/embeds.xml
new file mode 100644
index 00000000..d68c3f3e
--- /dev/null
+++ b/embeds.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/button.lua b/framework/button.lua
new file mode 100644
index 00000000..b1161088
--- /dev/null
+++ b/framework/button.lua
@@ -0,0 +1,665 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local _setmetatable = setmetatable --> lua local
+local _unpack = unpack --> lua local
+local _type = type --> lua local
+local _math_floor = math.floor --> lua local
+local loadstring = loadstring --> lua local
+
+local cleanfunction = function() end
+local APIButtonFunctions = false
+local ButtonMetaFunctions = {}
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ ButtonMetaFunctions.__call = function (_table, value, ...)
+ return self.func (_table.param1, _table.param2, value, ...)
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> tooltip
+ local gmember_tooltip = function (_object)
+ return _object:GetTooltip()
+ end
+ --> shown
+ local gmember_shown = function (_object)
+ return _object:IsShown()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.button:GetWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.button:GetHeight()
+ end
+ --> text
+ local gmember_text = function (_object)
+ return _object.button.text:GetText()
+ end
+ --> function
+ local gmember_function = function (_object)
+ return _rawget (_object, "func")
+ end
+ --> text color
+ local gmember_textcolor = function (_object)
+ return _object.button.text:GetTextColor()
+ end
+ --> text font
+ local gmember_textfont = function (_object)
+ local fontface = _object.button.text:GetFont()
+ return fontface
+ end
+ --> text size
+ local gmember_textsize = function (_object)
+ local _, fontsize = _object.button.text:GetFont()
+ return fontsize
+ end
+ --> texture
+ local gmember_texture = function (_object)
+ return {_object.button:GetNormalTexture(), _object.button:GetHighlightTexture(), _object.button:GetPushedTexture(), _object.button:GetDisabledTexture()}
+ end
+ --> locked
+ local gmember_locked = function (_object)
+ return _rawget (_object, "is_locked")
+ end
+
+ local get_members_function_index = {
+ ["tooltip"] = gmember_tooltip,
+ ["shown"] = gmember_shown,
+ ["width"] = gmember_width,
+ ["height"] = gmember_height,
+ ["text"] = gmember_text,
+ ["clickfunction"] = gmember_function,
+ ["texture"] = gmember_texture,
+ ["locked"] = gmember_locked,
+ ["fontcolor"] = gmember_textcolor,
+ ["fontface"] = gmember_textfont,
+ ["fontsize"] = gmember_textsize,
+ ["textcolor"] = gmember_textcolor, --alias
+ ["textfont"] = gmember_textfont, --alias
+ ["textsize"] = gmember_textsize --alias
+ }
+
+ ButtonMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return ButtonMetaFunctions [_member_requested]
+ end
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> tooltip
+ local smember_tooltip = function (_object, _value)
+ return _object:SetTooltip (_value)
+ end
+ --> show
+ local smember_show = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (not _value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> frame width
+ local smember_width = function (_object, _value)
+ return _object.button:SetWidth (_value)
+ end
+ --> frame height
+ local smember_height = function (_object, _value)
+ return _object.button:SetHeight (_value)
+ end
+ --> text
+ local smember_text = function (_object, _value)
+ return _object.button.text:SetText (_value)
+ end
+ --> function
+ local smember_function = function (_object, _value)
+ return _rawset (_object, "func", _value)
+ end
+ --> text color
+ local smember_textcolor = function (_object, _value)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_value)
+ return _object.button.text:SetTextColor (_value1, _value2, _value3, _value4)
+ end
+ --> text font
+ local smember_textfont = function (_object, _value)
+ return _detalhes:SetFontFace (_object.button.text, _value)
+ end
+ --> text size
+ local smember_textsize = function (_object, _value)
+ return _detalhes:SetFontSize (_object.button.text, _value)
+ end
+ --> texture
+ local smember_texture = function (_object, _value)
+ if (_type (_value) == "table") then
+ local _value1, _value2, _value3, _value4 = unpack (_value)
+ if (_value1) then
+ _object.button:SetNormalTexture (_value1)
+ end
+ if (_value2) then
+ _object.button:SetHighlightTexture (_value2, "ADD")
+ end
+ if (_value3) then
+ _object.button:SetPushedTexture (_value3)
+ end
+ if (_value4) then
+ _object.button:SetDisabledTexture (_value4)
+ end
+ else
+ _object.button:SetNormalTexture (_value)
+ _object.button:SetHighlightTexture (_value, "ADD")
+ _object.button:SetPushedTexture (_value)
+ _object.button:SetDisabledTexture (_value)
+ end
+ return
+ end
+ --> locked
+ local smember_locked = function (_object, _value)
+ if (_value) then
+ _object.button:SetMovable (false)
+ return _rawset (_object, "is_locked", true)
+ else
+ _object.button:SetMovable (true)
+ _rawset (_object, "is_locked", false)
+ return
+ end
+ end
+
+ local set_members_function_index = {
+ ["tooltip"] = smember_tooltip,
+ ["show"] = smember_show,
+ ["hide"] = smember_hide,
+ ["width"] = smember_width,
+ ["height"] = smember_height,
+ ["text"] = smember_text,
+ ["clickfunction"] = smember_function,
+ ["textcolor"] = smember_textcolor,
+ ["textfont"] = smember_textfont,
+ ["textsize"] = smember_textsize,
+ ["texture"] = smember_texture,
+ ["locked"] = smember_locked,
+ }
+
+ ButtonMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+
+--> show & hide
+ function ButtonMetaFunctions:IsShown()
+ return self.button:IsShown()
+ end
+ function ButtonMetaFunctions:Show()
+ return self.button:Show()
+ end
+ function ButtonMetaFunctions:Hide()
+ return self.button:Hide()
+ end
+
+-- setpoint
+ function ButtonMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+ end
+
+-- sizes
+ function ButtonMetaFunctions:SetSize (w, h)
+ if (w) then
+ self.button:SetWidth (w)
+ end
+ if (h) then
+ return self.button:SetHeight (h)
+ end
+ end
+
+-- tooltip
+ function ButtonMetaFunctions:SetTooltip (tooltip)
+ if (tooltip) then
+ return _rawset (self, "have_tooltip", tooltip)
+ else
+ return _rawset (self, "have_tooltip", nil)
+ end
+ end
+ function ButtonMetaFunctions:GetTooltip()
+ return _rawget (self, "have_tooltip")
+ end
+
+-- functions
+ function ButtonMetaFunctions:SetClickFunction (func, param1, param2, clicktype)
+ if (not clicktype or string.find (string.lower (clicktype), "left")) then
+ if (func) then
+ _rawset (self, "func", func)
+ else
+ _rawset (self, "func", cleanfunction)
+ end
+
+ if (param1) then
+ _rawset (self, "param1", param1)
+ end
+ if (param2) then
+ _rawset (self, "param2", param2)
+ end
+
+ elseif (clicktype or string.find (string.lower (clicktype), "right")) then
+ if (func) then
+ _rawset (self, "funcright", func)
+ else
+ _rawset (self, "funcright", cleanfunction)
+ end
+ end
+ end
+
+-- text
+ function ButtonMetaFunctions:SetText (text)
+ if (text) then
+ self.button.text:SetText (text)
+ else
+ self.button.text:SetText (nil)
+ end
+ end
+
+-- textcolor
+ function ButtonMetaFunctions:SetTextColor (color)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (color)
+ return self.button.text:SetTextColor (_value1, _value2, _value3, _value4)
+ end
+
+-- textsize
+ function ButtonMetaFunctions:SetTextSize (size)
+ return _detalhes:SetFontSize (self.button.text, _value)
+ end
+
+-- textfont
+ function ButtonMetaFunctions:SetTextFont (font)
+ return _detalhes:SetFontFace (_object.button.text, _value)
+ end
+
+-- textures
+ function ButtonMetaFunctions:SetTexture (normal, highlight, pressed, disabled)
+ if (normal) then
+ self.button:SetNormalTexture (normal)
+ elseif (_type (normal) ~= "boolean") then
+ self.button:SetNormalTexture (nil)
+ end
+
+ if (_type (highlight) == "boolean") then
+ if (highlight and normal and _type (normal) ~= "boolean") then
+ self.button:SetHighlightTexture (normal, "ADD")
+ end
+ elseif (highlight == nil) then
+ self.button:SetHighlightTexture (nil)
+ else
+ self.button:SetHighlightTexture (highlight, "ADD")
+ end
+
+ if (_type (pressed) == "boolean") then
+ if (pressed and normal and _type (normal) ~= "boolean") then
+ self.button:SetPushedTexture (normal)
+ end
+ elseif (pressed == nil) then
+ self.button:SetPushedTexture (nil)
+ else
+ self.button:SetPushedTexture (pressed, "ADD")
+ end
+
+ if (_type (disabled) == "boolean") then
+ if (disabled and normal and _type (normal) ~= "boolean") then
+ self.button:SetDisabledTexture (normal)
+ end
+ elseif (disabled == nil) then
+ self.button:SetDisabledTexture (nil)
+ else
+ self.button:SetDisabledTexture (disabled, "ADD")
+ end
+
+ end
+
+-- frame levels
+ function ButtonMetaFunctions:GetFrameLevel()
+ return self.button:GetFrameLevel()
+ end
+ function ButtonMetaFunctions:SetFrameLevel (level, frame)
+ if (not frame) then
+ return self.button:SetFrameLevel (level)
+ else
+ local framelevel = frame:GetFrameLevel (frame) + level
+ return self.button:SetFrameLevel (framelevel)
+ end
+ end
+
+-- frame stratas
+ function ButtonMetaFunctions:SetFrameStrata()
+ return self.button:GetFrameStrata()
+ end
+ function ButtonMetaFunctions:SetFrameStrata (strata)
+ if (_type (strata) == "table") then
+ self.button:SetFrameStrata (strata:GetFrameStrata())
+ else
+ self.button:SetFrameStrata (strata)
+ end
+ end
+
+-- enabled
+ function ButtonMetaFunctions:IsEnabled()
+ return self.button:IsEnabled()
+ end
+ function ButtonMetaFunctions:Enable()
+ return self.button:Enable()
+ end
+ function ButtonMetaFunctions:Disable()
+ return self.button:Disable()
+ end
+
+-- exec
+ function ButtonMetaFunctions:Exec()
+ return self.func (self.param1, self.param2)
+ end
+ function ButtonMetaFunctions:Click()
+ return self.func (self.param1, self.param2)
+ end
+ function ButtonMetaFunctions:RightClick()
+ return self.funcright()
+ end
+
+--> hooks
+ function ButtonMetaFunctions:SetHook (hookType, func)
+ if (func) then
+ _rawset (self, hookType.."Hook", func)
+ else
+ _rawset (self, hookType.."Hook", nil)
+ end
+ end
+
+--> custom textures
+ function ButtonMetaFunctions:InstallCustomTexture (texture, rect)
+
+ self.button:SetNormalTexture (nil)
+ self.button:SetPushedTexture (nil)
+ self.button:SetDisabledTexture (nil)
+ self.button:SetHighlightTexture (nil)
+
+ texture = texture or "Interface\\AddOns\\Details\\images\\default_button"
+ self.button.texture = self.button:CreateTexture (nil, "background")
+
+ if (not rect) then
+ self.button.texture:SetAllPoints (self.button)
+ else
+ self.button.texture:SetPoint ("topleft", self.button, "topleft", rect.x1, rect.y1)
+ self.button.texture:SetPoint ("bottomright", self.button, "bottomright", rect.x2, rect.y2)
+ end
+
+ self.button.texture:SetTexCoord (0, 1, 0, 0.24609375)
+ self.button.texture:SetTexture (texture)
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> scripts
+
+ local OnEnter = function (button)
+
+ if (button.MyObject.OnEnterHook) then
+ local interrupt = button.MyObject.OnEnterHook (button)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (button.texture) then
+ button.texture:SetTexCoord (0, 1, 0.25+(0.0078125/2), 0.5+(0.0078125/2))
+ end
+
+ if (button.MyObject.have_tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:AddLine (button.MyObject.have_tooltip)
+ GameCooltip:ShowCooltip (button, "tooltip")
+ end
+
+ local parent = button:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient()
+ end
+ end
+ end
+
+ local OnLeave = function (button)
+ if (button.MyObject.OnLeaveHook) then
+ local interrupt = button.MyObject.OnLeaveHook (button)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (button.texture) then
+ button.texture:SetTexCoord (0, 1, 0, 0.24609375)
+ end
+
+ if (button.MyObject.have_tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+
+ local parent = button:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient (false)
+ end
+ end
+ end
+
+ local OnHide = function (button)
+ if (button.MyObject.OnHideHook) then
+ local interrupt = button.MyObject.OnHideHook (button)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnShow = function (button)
+ if (button.MyObject.OnShowHook) then
+ local interrupt = button.MyObject.OnShowHook (button)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnMouseDown = function (button, buttontype)
+ if (not button:IsEnabled()) then
+ return
+ end
+
+ if (button.MyObject.OnMouseDownHook) then
+ local interrupt = button.MyObject.OnMouseDownHook (button, buttontype)
+ if (interrupt) then
+ return
+ end
+ end
+
+ button.text:SetPoint ("center", button,"center", 1, -1)
+
+ button.mouse_down = GetTime()
+ local x, y = GetCursorPosition()
+ button.x = _math_floor (x)
+ button.y = _math_floor (y)
+
+ if (not button.MyObject.container.isLocked and button.MyObject.container:IsMovable()) then
+ if (not button.isLocked and button:IsMovable()) then
+ button.MyObject.container.isMoving = true
+ button.MyObject.container:StartMoving()
+ end
+ end
+
+ if (button.MyObject.options.OnGrab) then
+ if (_type (button.MyObject.options.OnGrab) == "string" and button.MyObject.options.OnGrab == "PassClick") then
+ if (buttontype == "LeftButton") then
+ button.MyObject.func (button.MyObject.param1, button.MyObject.param2)
+ else
+ button.MyObject.funcright (button.MyObject.param1, button.MyObject.param2)
+ end
+ end
+ end
+ end
+
+ local OnMouseUp = function (button, buttontype)
+ if (not button:IsEnabled()) then
+ return
+ end
+
+ if (button.MyObject.OnMouseUpHook) then
+ local interrupt = button.MyObject.OnMouseUpHook (button, buttontype)
+ if (interrupt) then
+ return
+ end
+ end
+
+ button.text:SetPoint ("center", button,"center", 0, 0)
+
+ if (button.MyObject.container.isMoving) then
+ button.MyObject.container:StopMovingOrSizing()
+ button.MyObject.container.isMoving = false
+ end
+
+ local x, y = GetCursorPosition()
+ x = _math_floor (x)
+ y = _math_floor (y)
+ if ((button.mouse_down+0.4 > GetTime() and (x == button.x and y == button.y)) or (x == button.x and y == button.y)) then
+ if (buttontype == "LeftButton") then
+ button.MyObject.func (button.MyObject.param1, button.MyObject.param2, button)
+ else
+ button.MyObject.funcright (button.MyObject.param1, button.MyObject.param2, button)
+ end
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+
+function gump:NewButton (parent, container, name, member, w, h, func, param1, param2, texture, text)
+
+ if (not name) then
+ return nil
+ elseif (not parent) then
+ return nil
+ end
+ if (not container) then
+ container = parent
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+
+ local ButtonObject = {type = "button", dframework = true}
+
+ if (member) then
+ parent [member] = ButtonObject
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+ --> default members:
+ --> hooks
+ ButtonObject.OnEnterHook = nil
+ ButtonObject.OnLeaveHook = nil
+ ButtonObject.OnHideHook = nil
+ ButtonObject.OnShowHook = nil
+ ButtonObject.OnMouseDownHook = nil
+ ButtonObject.OnMouseUpHook = nil
+ --> misc
+ ButtonObject.is_locked = true
+ ButtonObject.container = container
+ ButtonObject.have_tooltip = nil
+ ButtonObject.options = {OnGrab = false}
+
+
+ ButtonObject.button = CreateFrame ("button", name, parent, "DetailsButtonTemplate")
+ ButtonObject.widget = ButtonObject.button
+
+ if (not APIButtonFunctions) then
+ APIButtonFunctions = true
+ local idx = getmetatable (ButtonObject.button).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not ButtonMetaFunctions [funcName]) then
+ ButtonMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.button:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ ButtonObject.button:SetWidth (w or 100)
+ ButtonObject.button:SetHeight (h or 20)
+ ButtonObject.button.MyObject = ButtonObject
+
+ ButtonObject.text_overlay = _G [name .. "_Text"]
+ ButtonObject.disabled_overlay = _G [name .. "_TextureDisabled"]
+
+ ButtonObject.button:SetNormalTexture (texture)
+ ButtonObject.button:SetPushedTexture (texture)
+ ButtonObject.button:SetDisabledTexture (texture)
+ ButtonObject.button:SetHighlightTexture (texture, "ADD")
+
+ ButtonObject.button.text:SetText (text)
+
+ ButtonObject.func = func or cleanfunction
+ ButtonObject.funcright = cleanfunction
+ ButtonObject.param1 = param1
+ ButtonObject.param2 = param2
+
+ --> hooks
+ ButtonObject.button:SetScript ("OnEnter", OnEnter)
+ ButtonObject.button:SetScript ("OnLeave", OnLeave)
+ ButtonObject.button:SetScript ("OnHide", OnHide)
+ ButtonObject.button:SetScript ("OnShow", OnShow)
+ ButtonObject.button:SetScript ("OnMouseDown", OnMouseDown)
+ ButtonObject.button:SetScript ("OnMouseUp", OnMouseUp)
+
+ _setmetatable (ButtonObject, ButtonMetaFunctions)
+
+ return ButtonObject
+
+end
\ No newline at end of file
diff --git a/framework/button.xml b/framework/button.xml
new file mode 100644
index 00000000..877aae3c
--- /dev/null
+++ b/framework/button.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/colors.lua b/framework/colors.lua
new file mode 100644
index 00000000..b3d05562
--- /dev/null
+++ b/framework/colors.lua
@@ -0,0 +1,150 @@
+do
+ local _detalhes = _G._detalhes
+ local gump = _detalhes.gump
+
+ gump.alias_text_colors = {
+ ["aliceblue"] = {0.941176, 0.972549, 1, 1},
+ ["antiquewhite"] = {0.980392, 0.921569, 0.843137, 1},
+ ["aqua"] = {0, 1, 1, 1},
+ ["aquamarine"] = {0.498039, 1, 0.831373, 1},
+ ["azure"] = {0.941176, 1, 1, 1},
+ ["beige"] = {0.960784, 0.960784, 0.862745, 1},
+ ["bisque"] = {1, 0.894118, 0.768627, 1},
+ ["black"] = {0, 0, 0, 1},
+ ["blanchedalmond"] = {1, 0.921569, 0.803922, 1},
+ ["blue"] = {0, 0, 1, 1},
+ ["blueviolet"] = {0.541176, 0.168627, 0.886275, 1},
+ ["brown"] = {0.647059, 0.164706, 0.164706, 1},
+ ["burlywood"] = {0.870588, 0.721569, 0.529412, 1},
+ ["cadetblue"] = {0.372549, 0.619608, 0.627451, 1},
+ ["chartreuse"] = {0.498039, 1, 0, 1},
+ ["chocolate"] = {0.823529, 0.411765, 0.117647, 1},
+ ["coral"] = {1, 0.498039, 0.313725, 1},
+ ["cornflowerblue"] = {0.392157, 0.584314, 0.929412, 1},
+ ["cornsilk"] = {1, 0.972549, 0.862745, 1},
+ ["crimson"] = {0.862745, 0.0784314, 0.235294, 1},
+ ["cyan"] = {0, 1, 1, 1},
+ ["darkblue"] = {0, 0, 0.545098, 1},
+ ["darkcyan"] = {0, 0.545098, 0.545098, 1},
+ ["darkgoldenrod"] = {0.721569, 0.52549, 0.0431373, 1},
+ ["darkgray"] = {0.662745, 0.662745, 0.662745, 1},
+ ["darkgreen"] = {0, 0.392157, 0, 1},
+ ["darkkhaki"] = {0.741176, 0.717647, 0.419608, 1},
+ ["darkmagenta"] = {0.545098, 0, 0.545098, 1},
+ ["darkolivegreen"] = {0.333333, 0.419608, 0.184314, 1},
+ ["darkorange"] = {1, 0.54902, 0, 1},
+ ["darkorchid"] = {0.6, 0.196078, 0.8, 1},
+ ["darkred"] = {0.545098, 0, 0, 1},
+ ["darksalmon"] = {0.913725, 0.588235, 0.478431, 1},
+ ["darkseagreen"] = {0.560784, 0.737255, 0.560784, 1},
+ ["darkslateblue"] = {0.282353, 0.239216, 0.545098, 1},
+ ["darkslategray"] = {0.184314, 0.309804, 0.309804, 1},
+ ["darkturquoise"] = {0, 0.807843, 0.819608, 1},
+ ["darkviolet"] = {0.580392, 0, 0.827451, 1},
+ ["deeppink"] = {1, 0.0784314, 0.576471, 1},
+ ["deepskyblue"] = {0, 0.74902, 1, 1},
+ ["dimgray"] = {0.411765, 0.411765, 0.411765, 1},
+ ["dimgrey"] = {0.411765, 0.411765, 0.411765, 1},
+ ["dodgerblue"] = {0.117647, 0.564706, 1, 1},
+ ["firebrick"] = {0.698039, 0.133333, 0.133333, 1},
+ ["floralwhite"] = {1, 0.980392, 0.941176, 1},
+ ["forestgreen"] = {0.133333, 0.545098, 0.133333, 1},
+ ["fuchsia"] = {1, 0, 1, 1},
+ ["gainsboro"] = {0.862745, 0.862745, 0.862745, 1},
+ ["ghostwhite"] = {0.972549, 0.972549, 1, 1},
+ ["gold"] = {1, 0.843137, 0, 1},
+ ["goldenrod"] = {0.854902, 0.647059, 0.12549, 1},
+ ["gray"] = {0.501961, 0.501961, 0.501961, 1},
+ ["green"] = {0, 0.501961, 0, 1},
+ ["greenyellow"] = {0.678431, 1, 0.184314, 1},
+ ["honeydew"] = {0.941176, 1, 0.941176, 1},
+ ["hotpink"] = {1, 0.411765, 0.705882, 1},
+ ["indianred"] = {0.803922, 0.360784, 0.360784, 1},
+ ["indigo"] = {0.294118, 0, 0.509804, 1},
+ ["ivory"] = {1, 1, 0.941176, 1},
+ ["khaki"] = {0.941176, 0.901961, 0.54902, 1},
+ ["lavender"] = {0.901961, 0.901961, 0.980392, 1},
+ ["lavenderblush"] = {1, 0.941176, 0.960784, 1},
+ ["lawngreen"] = {0.486275, 0.988235, 0, 1},
+ ["lemonchiffon"] = {1, 0.980392, 0.803922, 1},
+ ["lightblue"] = {0.678431, 0.847059, 0.901961, 1},
+ ["lightcoral"] = {0.941176, 0.501961, 0.501961, 1},
+ ["lightcyan"] = {0.878431, 1, 1, 1},
+ ["lightgoldenrodyellow"] = {0.980392, 0.980392, 0.823529, 1},
+ ["lightgray"] = {0.827451, 0.827451, 0.827451, 1},
+ ["lightgreen"] = {0.564706, 0.933333, 0.564706, 1},
+ ["lightpink"] = {1, 0.713725, 0.756863, 1},
+ ["lightsalmon"] = {1, 0.627451, 0.478431, 1},
+ ["lightseagreen"] = {0.12549, 0.698039, 0.666667, 1},
+ ["lightskyblue"] = {0.529412, 0.807843, 0.980392, 1},
+ ["lightslategray"] = {0.466667, 0.533333, 0.6, 1},
+ ["lightsteelblue"] = {0.690196, 0.768627, 0.870588, 1},
+ ["lightyellow"] = {1, 1, 0.878431, 1},
+ ["lime"] = {0, 1, 0, 1},
+ ["limegreen"] = {0.196078, 0.803922, 0.196078, 1},
+ ["linen"] = {0.980392, 0.941176, 0.901961, 1},
+ ["magenta"] = {1, 0, 1, 1},
+ ["maroon"] = {0.501961, 0, 0, 1},
+ ["mediumaquamarine"] = {0.4, 0.803922, 0.666667, 1},
+ ["mediumblue"] = {0, 0, 0.803922, 1},
+ ["mediumorchid"] = {0.729412, 0.333333, 0.827451, 1},
+ ["mediumpurple"] = {0.576471, 0.439216, 0.858824, 1},
+ ["mediumseagreen"] = {0.235294, 0.701961, 0.443137, 1},
+ ["mediumslateblue"] = {0.482353, 0.407843, 0.933333, 1},
+ ["mediumspringgreen"] = {0, 0.980392, 0.603922, 1},
+ ["mediumturquoise"] = {0.282353, 0.819608, 0.8, 1},
+ ["mediumvioletred"] = {0.780392, 0.0823529, 0.521569, 1},
+ ["midnightblue"] = {0.0980392, 0.0980392, 0.439216, 1},
+ ["mintcream"] = {0.960784, 1, 0.980392, 1},
+ ["mistyrose"] = {1, 0.894118, 0.882353, 1},
+ ["moccasin"] = {1, 0.894118, 0.709804, 1},
+ ["navajowhite"] = {1, 0.870588, 0.678431, 1},
+ ["navy"] = {0, 0, 0.501961, 1},
+ ["none"] ={0, 0, 0, 0},
+ ["oldlace"] = {0.992157, 0.960784, 0.901961, 1},
+ ["olive"] = {0.501961, 0.501961, 0, 1},
+ ["olivedrab"] = {0.419608, 0.556863, 0.137255, 1},
+ ["orange"] = {1, 0.647059, 0, 1},
+ ["orangered"] = {1, 0.270588, 0, 1},
+ ["orchid"] = {0.854902, 0.439216, 0.839216, 1},
+ ["palegoldenrod"] = {0.933333, 0.909804, 0.666667, 1},
+ ["palegreen"] = {0.596078, 0.984314, 0.596078, 1},
+ ["paleturquoise"] = {0.686275, 0.933333, 0.933333, 1},
+ ["palevioletred"] = {0.858824, 0.439216, 0.576471, 1},
+ ["papayawhip"] = {1, 0.937255, 0.835294, 1},
+ ["peachpuff"] = {1, 0.854902, 0.72549, 1},
+ ["peru"] = {0.803922, 0.521569, 0.247059, 1},
+ ["pink"] = {1, 0.752941, 0.796078, 1},
+ ["plum"] = {0.866667, 0.627451, 0.866667, 1},
+ ["powderblue"] = {0.690196, 0.878431, 0.901961, 1},
+ ["purple"] = {0.501961, 0, 0.501961, 1},
+ ["red"] = {1, 0, 0, 1},
+ ["rosybrown"] = {0.737255, 0.560784, 0.560784, 1},
+ ["royalblue"] = {0.254902, 0.411765, 0.882353, 1},
+ ["saddlebrown"] = {0.545098, 0.270588, 0.0745098, 1},
+ ["salmon"] = {0.980392, 0.501961, 0.447059, 1},
+ ["sandybrown"] = {0.956863, 0.643137, 0.376471, 1},
+ ["seagreen"] = {0.180392, 0.545098, 0.341176, 1},
+ ["seashell"] = {1, 0.960784, 0.933333, 1},
+ ["sienna"] = {0.627451, 0.321569, 0.176471, 1},
+ ["silver"] = {0.752941, 0.752941, 0.752941, 1},
+ ["skyblue"] = {0.529412, 0.807843, 0.921569, 1},
+ ["slateblue"] = {0.415686, 0.352941, 0.803922, 1},
+ ["slategray"] = {0.439216, 0.501961, 0.564706, 1},
+ ["snow"] = {1, 0.980392, 0.980392, 1},
+ ["springgreen"] = {0, 1, 0.498039, 1},
+ ["steelblue"] = {0.27451, 0.509804, 0.705882, 1},
+ ["tan"] = {0.823529, 0.705882, 0.54902, 1},
+ ["teal"] = {0, 0.501961, 0.501961, 1},
+ ["thistle"] = {0.847059, 0.74902, 0.847059, 1},
+ ["tomato"] = {1, 0.388235, 0.278431, 1},
+ ["transparent"] ={0, 0, 0, 0},
+ ["turquoise"] = {0.25098, 0.878431, 0.815686, 1},
+ ["violet"] = {0.933333, 0.509804, 0.933333, 1},
+ ["wheat"] = {0.960784, 0.870588, 0.701961, 1},
+ ["white"] = {1, 1, 1, 1},
+ ["whitesmoke"] = {0.960784, 0.960784, 0.960784, 1},
+ ["yellow"] = {1, 1, 0, 1},
+ ["yellowgreen"] = {0.603922, 0.803922, 0.196078, 1}
+ }
+end
\ No newline at end of file
diff --git a/framework/cooltip.lua b/framework/cooltip.lua
new file mode 100644
index 00000000..d8ca8f8f
--- /dev/null
+++ b/framework/cooltip.lua
@@ -0,0 +1,2018 @@
+
+local _detalhes = _G._detalhes
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+--lua locals
+local _math_floor= math.floor
+local _type = type
+local _math_abs = math.abs
+local _tinsert = tinsert
+local _unpack = unpack
+local _ipairs = ipairs
+local _table_wipe = table.wipe
+local _table_insert = table.insert
+local _math_max = math.max
+--api locals
+local _GetScreenWidth = GetScreenWidth
+local _GetScreenHeight = GetScreenHeight
+local _UIParent = UIParent
+local _CreateFrame = CreateFrame
+local _UISpecialFrames = UISpecialFrames
+
+function DetailsCreateCoolTip()
+
+ if (_G.GameCooltip) then
+ return _G.GameCooltip
+ end
+
+----------------------------------------------------------------------
+ --> Cooltip Startup
+----------------------------------------------------------------------
+
+ --> Start Cooltip Table
+ local CoolTip = {}
+ _G.GameCooltip = CoolTip
+
+ --> Containers
+ CoolTip.LeftTextTable = {}
+ CoolTip.LeftTextTableSub = {}
+ CoolTip.RightTextTable = {}
+ CoolTip.RightTextTableSub = {}
+ CoolTip.LeftIconTable = {}
+ CoolTip.LeftIconTableSub = {}
+ CoolTip.RightIconTable = {}
+ CoolTip.RightIconTableSub = {}
+ CoolTip.StatusBarTable = {}
+ CoolTip.StatusBarTableSub = {}
+
+ CoolTip.FunctionsTableMain = {} --> menus
+ CoolTip.FunctionsTableSub = {} --> menus
+ CoolTip.ParametersTableMain = {} --> menus
+ CoolTip.ParametersTableSub = {} --> menus
+
+ CoolTip.FixedValue = nil --> menus
+ CoolTip.SelectedIndexMain = nil --> menus
+ CoolTip.SelectedIndexSec = {} --> menus
+
+
+ --options table
+ CoolTip.OptionsList = {
+ ["IconSize"] = true,
+ ["HeightAnchorMod"] = true,
+ ["WidthAnchorMod"] = true,
+ ["FixedWidth"] = true,
+ ["FixedHeight"] = true,
+ ["FixedWidthSub"] = true,
+ ["FixedHeightSub"] = true,
+ ["IgnoreSubMenu"] = true,
+ ["TextHeightMod"] = true,
+ ["ButtonHeightMod"] = true,
+ ["ButtonHeightModSub"] = true,
+ ["YSpacingMod"] = true,
+ ["YSpacingModSub"] = true,
+ ["ButtonsYMod"] = true,
+ ["ButtonsYModSub"] = true,
+ ["IconHeightMod"] = true,
+ ["StatusBarHeightMod"] = true,
+ ["StatusBarTexture"] = true,
+ ["TextSize"] = true,
+ ["TextFont"] = true,
+ ["NoFade"] = true,
+ ["MyAnchor"] = true,
+ ["Anchor"] = true,
+ ["RelativeAnchor"] = true,
+ ["NoLastSelectedBar"] = true,
+ ["SubMenuIsTooltip"] = true
+
+ }
+ CoolTip.OptionsTable = {
+ ["IconSize"] = nil,
+ ["HeightAnchorMod"] = nil,
+ ["WidthAnchorMod"] = nil,
+ ["FixedWidth"] = nil,
+ ["FixedHeight"] = nil,
+ ["FixedWidthSub"] = nil,
+ ["FixedHeightSub"] = nil,
+ ["IgnoreSubMenu"] = nil,
+ ["TextHeightMod"] = nil,
+ ["ButtonHeightMod"] = nil,
+ ["ButtonHeightModSub"] = nil,
+ ["YSpacingMod"] = nil,
+ ["YSpacingModSub"] = nil,
+ ["ButtonsYMod"] = nil,
+ ["ButtonsYModSub"] = nil,
+ ["IconHeightMod"] = nil,
+ ["StatusBarHeightMod"] = nil,
+ ["StatusBarTexture"] = nil,
+ ["TextSize"] = nil,
+ ["TextFont"] = nil,
+ ["NoFade"] = nil,
+ ["MyAnchor"] = nil,
+ ["Anchor"] = nil,
+ ["RelativeAnchor"] = nil,
+ ["NoLastSelectedBar"] = nil,
+ ["SubMenuIsTooltip"] = nil
+ }
+
+ --cprops
+ CoolTip.Indexes = 0 --> amount of lines current on shown
+ CoolTip.IndexesSub = {} --> amount of lines current on shown
+ CoolTip.HaveSubMenu = false --> amount of lines current on shown
+ CoolTip.SubIndexes = 0 --> amount of lines current on shown on sub menu
+ CoolTip.Type = 1 --> 1 tooltip 2 tooltip with bars 3 menu 4 menu + submenus
+ CoolTip.Host = nil --> frame to anchor
+
+ --defaults
+ CoolTip.default_height = 20
+ CoolTip.default_text_size = 10.5
+ CoolTip.default_text_font = "GameFontHighlight"
+
+ --> Create Frames
+
+ --> main frame
+ local frame1 = CreateFrame ("Frame", "CoolTipFrame1", UIParent, "CooltipMainFrameTemplate")
+ tinsert (UISpecialFrames, "CoolTipFrame1")
+ --> secondary frame
+ local frame2 = CreateFrame ("Frame", "CoolTipFrame2", UIParent, "CooltipMainFrameTemplate")
+ tinsert (UISpecialFrames, "CoolTipFrame2")
+ frame2:SetPoint ("bottomleft", frame1, "bottomright")
+
+ CoolTip.frame1 = frame1
+ CoolTip.frame2 = frame2
+ gump:Fade (frame1, 0)
+ gump:Fade (frame2, 0)
+
+ --> button containers
+ frame1.Lines = {}
+ frame2.Lines = {}
+
+----------------------------------------------------------------------
+ --> Title Function
+----------------------------------------------------------------------
+
+ function CoolTip:SetTitleAnchor (_f, _anchor, ...)
+ _anchor = string.lower (_anchor)
+ if (_f == 1) then
+ self.frame1.titleIcon:ClearAllPoints()
+ self.frame1.titleText:ClearAllPoints()
+ if (_anchor == "left") then
+ self.frame1.titleIcon:SetPoint ("left", frame1, "left", ...)
+ self.frame1.titleText:SetPoint ("left", frame1.titleIcon, "right")
+ elseif (_anchor == "center") then
+ self.frame1.titleIcon:SetPoint ("center", frame1, "center", ...)
+ self.frame1.titleText:SetPoint ("left", frame1.titleIcon, "right")
+ elseif (_anchor == "right") then
+ self.frame1.titleIcon:SetPoint ("right", frame1, "right", ...)
+ self.frame1.titleText:SetPoint ("right", frame1.titleIcon, "left")
+ end
+ elseif (_f == 2) then
+ self.frame2.titleIcon:ClearAllPoints()
+ self.frame2.titleText:ClearAllPoints()
+ if (_anchor == "left") then
+ self.frame2.titleIcon:SetPoint ("left", frame2, "left", ...)
+ self.frame2.titleText:SetPoint ("left", frame2.titleIcon, "right")
+ elseif (_anchor == "center") then
+ self.frame2.titleIcon:SetPoint ("center", frame2, "center", ...)
+ self.frame2.titleText:SetPoint ("left", frame2.titleIcon, "right")
+ elseif (_anchor == "right") then
+ self.frame2.titleIcon:SetPoint ("right", frame2, "right", ...)
+ self.frame2.titleText:SetPoint ("right", frame2.titleIcon, "left")
+ end
+ end
+ end
+
+----------------------------------------------------------------------
+ --> Button Hide and Show Functions
+----------------------------------------------------------------------
+
+ local elapsedTime = 0
+
+ CoolTip.mouseOver = false
+ CoolTip.buttonClicked = false
+
+ frame1:SetScript ("OnEnter", function (self)
+ if (CoolTip.Type ~= 1 and CoolTip.Type ~= 2) then
+ CoolTip.active = true
+ CoolTip.mouseOver = true
+ self:SetScript ("OnUpdate", nil)
+ gump:Fade (self, 0)
+ --rever
+ if (CoolTip.sub_menus) then
+ gump:Fade (frame2, 0)
+ end
+ end
+ end)
+
+ frame2:SetScript ("OnEnter", function (self)
+ if (CoolTip.OptionsTable.SubMenuIsTooltip) then
+ return CoolTip:Close()
+ end
+ if (CoolTip.Type ~= 1 and CoolTip.Type ~= 2) then
+ CoolTip.active = true
+ CoolTip.mouseOver = true
+ self:SetScript ("OnUpdate", nil)
+ gump:Fade (self, 0)
+ gump:Fade (frame1, 0)
+ end
+ end)
+
+ local OnLeaveUpdateFrame1 = function (self, elapsed)
+ elapsedTime = elapsedTime+elapsed
+ if (elapsedTime > 0.7) then
+ if (not CoolTip.active and not CoolTip.buttonClicked and self == CoolTip.Host) then
+ gump:Fade (self, 1)
+ gump:Fade (frame2, 1)
+ elseif (not CoolTip.active) then
+ gump:Fade (self, 1)
+ gump:Fade (frame2, 1)
+ end
+ self:SetScript ("OnUpdate", nil)
+ frame2:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ frame1:SetScript ("OnLeave", function (self)
+
+ if (CoolTip.Type ~= 1 and CoolTip.Type ~= 2) then
+ CoolTip.active = false
+ CoolTip.mouseOver = false
+ elapsedTime = 0
+ self:SetScript ("OnUpdate", OnLeaveUpdateFrame1)
+ else
+ CoolTip.active = false
+ CoolTip.mouseOver = false
+ elapsedTime = 0
+ self:SetScript ("OnUpdate", OnLeaveUpdateFrame1)
+ end
+ end)
+
+ local OnLeaveUpdateFrame2 = function (self, elapsed)
+ elapsedTime = elapsedTime+elapsed
+ if (elapsedTime > 0.7) then
+ if (not CoolTip.active and not CoolTip.buttonClicked and self == CoolTip.Host) then
+ gump:Fade (self, 1)
+ gump:Fade (frame2, 1)
+ elseif (not CoolTip.active) then
+ gump:Fade (self, 1)
+ gump:Fade (frame2, 1)
+ end
+ self:SetScript ("OnUpdate", nil)
+ frame1:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ frame2:SetScript ("OnLeave", function (self)
+ if (CoolTip.Type ~= 1 and CoolTip.Type ~= 2) then
+ CoolTip.active = false
+ CoolTip.mouseOver = false
+ elapsedTime = 0
+ self:SetScript ("OnUpdate", OnLeaveUpdateFrame2)
+ else
+ CoolTip.active = false
+ CoolTip.mouseOver = false
+ elapsedTime = 0
+ self:SetScript ("OnUpdate", OnLeaveUpdateFrame2)
+
+ end
+ end)
+
+ frame1:SetScript ("OnHide", function (self)
+ if (not frame1.hidden) then --> significa que foi fechado com ESC
+ frame1:Show()
+ gump:Fade (frame1, 1)
+ end
+ if (not frame2.hidden) then --> significa que foi fechado com ESC
+ frame2:Show()
+ gump:Fade (frame2, 1)
+ end
+ CoolTip.active = false
+ CoolTip.buttonClicked = false
+ CoolTip.mouseOver = false
+ end)
+
+
+----------------------------------------------------------------------
+ --> Button Creation Functions
+----------------------------------------------------------------------
+
+ function GameCooltipButtonMouseDown (button)
+ button.leftText:SetPoint ("center", button.leftIcon, "center", 0, 0)
+ button.leftText:SetPoint ("left", button.leftIcon, "right", 4, -1)
+ end
+
+ function GameCooltipButtonMouseUp (button)
+ button.leftText:SetPoint ("center", button.leftIcon, "center", 0, 0)
+ button.leftText:SetPoint ("left", button.leftIcon, "right", 3, 0)
+ end
+
+ function CoolTip:CreateButton (index, frame, name)
+ local new_button = CreateFrame ("Button", name, frame, "CooltipButtonTemplate")
+ frame.Lines [index] = new_button
+ return new_button
+ end
+
+ local OnEnterUpdateButton = function (self, elapsed)
+ elapsedTime = elapsedTime+elapsed
+ if (elapsedTime > 0.3) then
+ --> search key: ~onenterupdatemain
+ CoolTip:ShowSub (self.index)
+ CoolTip.last_button = self.index
+ self:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ local OnLeaveUpdateButton = function (self, elapsed)
+ elapsedTime = elapsedTime+elapsed
+ if (elapsedTime > 0.7) then
+ if (not CoolTip.active and not CoolTip.buttonClicked) then
+ gump:Fade (frame1, 1)
+ gump:Fade (frame2, 1)
+
+ elseif (not CoolTip.active) then
+ gump:Fade (frame1, 1)
+ gump:Fade (frame2, 1)
+ end
+ frame1:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ function CoolTip:NewMainButton (i)
+ local botao = CoolTip:CreateButton (i, frame1, "CooltipMainButton"..i)
+
+ --> serach key: ~onenter
+ botao:SetScript ("OnEnter", function()
+ if (CoolTip.Type ~= 1 and CoolTip.Type ~= 2) then
+ CoolTip.active = true
+ CoolTip.mouseOver = true
+
+ frame1:SetScript ("OnUpdate", nil)
+ frame2:SetScript ("OnUpdate", nil)
+
+ botao.background:Show()
+
+ if (CoolTip.IndexesSub [botao.index] and CoolTip.IndexesSub [botao.index] > 0) then
+ if (CoolTip.OptionsTable.SubMenuIsTooltip) then
+ CoolTip:ShowSub (botao.index)
+ botao.index = i
+ else
+ if (CoolTip.last_button) then
+ CoolTip:ShowSub (CoolTip.last_button)
+ else
+ CoolTip:ShowSub (botao.index)
+ end
+ elapsedTime = 0
+ botao.index = i
+ botao:SetScript ("OnUpdate", OnEnterUpdateButton)
+ end
+
+ else
+ --hide second frame
+ gump:Fade (frame2, 1)
+ CoolTip.last_button = nil
+ end
+ else
+ CoolTip.mouseOver = true
+ end
+ end)
+
+ botao:SetScript ("OnLeave", function()
+ if (CoolTip.Type ~= 1 and CoolTip.Type ~= 2) then
+ CoolTip.active = false
+ CoolTip.mouseOver = false
+ botao:SetScript ("OnUpdate", nil)
+
+ botao.background:Hide()
+
+ elapsedTime = 0
+ frame1:SetScript ("OnUpdate", OnLeaveUpdateButton)
+ CoolTip:HideSub (i)
+ else
+ CoolTip.active = false
+ elapsedTime = 0
+ frame1:SetScript ("OnUpdate", OnLeaveUpdateButton)
+ CoolTip.mouseOver = false
+ end
+ end)
+
+ return botao
+ end
+
+ local OnLeaveUpdateButtonSec = function (self, elapsed)
+ elapsedTime = elapsedTime+elapsed
+ if (elapsedTime > 0.7) then
+ if (not CoolTip.active and not CoolTip.buttonClicked) then
+ gump:Fade (frame1, 1)
+ gump:Fade (frame2, 1)
+ elseif (not CoolTip.active) then
+ gump:Fade (frame1, 1)
+ gump:Fade (frame2, 1)
+ end
+ frame2:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ function CoolTip:NewSecondaryButton (i)
+ local botao = CoolTip:CreateButton (i, frame2, "CooltipSecButton"..i)
+
+ botao:SetScript ("OnEnter", function()
+ if (CoolTip.OptionsTable.SubMenuIsTooltip) then
+ return CoolTip:Close()
+ end
+ if (CoolTip.Type ~= 1 and CoolTip.Type ~= 2) then
+ CoolTip.active = true
+ CoolTip.mouseOver = true
+
+ botao.background:Show()
+
+ frame1:SetScript ("OnUpdate", nil)
+ frame2:SetScript ("OnUpdate", nil)
+
+ gump:Fade (frame1, 0)
+ gump:Fade (frame2, 0)
+ else
+ CoolTip.mouseOver = true
+ end
+ end)
+
+ botao:SetScript ("OnLeave", function()
+ if (CoolTip.Type ~= 1 and CoolTip.Type ~= 2) then
+ CoolTip.active = false
+ CoolTip.mouseOver = false
+
+ botao.background:Hide()
+
+ elapsedTime = 0
+ frame2:SetScript ("OnUpdate", OnLeaveUpdateButtonSec)
+ else
+ CoolTip.active = false
+ CoolTip.mouseOver = false
+ elapsedTime = 0
+ frame2:SetScript ("OnUpdate", OnLeaveUpdateButtonSec)
+ end
+ end)
+
+ return botao
+ end
+
+----------------------------------------------------------------------
+ --> Button Click Functions
+----------------------------------------------------------------------
+
+ local OnClickFunctionButtonPrincipal = function (self)
+ if (CoolTip.IndexesSub [self.index] and CoolTip.IndexesSub [self.index] > 0) then
+ CoolTip:ShowSub (self.index)
+ CoolTip.last_button = self.index
+ end
+
+ CoolTip.buttonClicked = true
+ frame1.selected:SetPoint ("top", self, "top", 0, -1)
+ frame1.selected:SetPoint ("bottom", self, "bottom")
+ if (not CoolTip.OptionsTable.NoLastSelectedBar) then
+ frame1.selected:Show()
+ end
+ CoolTip.SelectedIndexMain = self.index
+
+ if (CoolTip.FunctionsTableMain [self.index]) then
+ local parameterTable = CoolTip.ParametersTableMain [self.index]
+ CoolTip.FunctionsTableMain [self.index] (_, CoolTip.FixedValue, parameterTable [1], parameterTable [2], parameterTable [3])
+ end
+ end
+
+ local OnClickFunctionButtonSecundario = function (self)
+ CoolTip.buttonClicked = true
+ frame2.selected:SetPoint ("top", self, "top", 0, -1)
+ frame2.selected:SetPoint ("bottom", self, "bottom")
+
+ UIFrameFlash (frame2.selected, 0.05, 0.05, 0.2, true, 0, 0)
+
+ if (CoolTip.FunctionsTableSub [self.mainIndex] and CoolTip.FunctionsTableSub [self.mainIndex] [self.index]) then
+ local parameterTable = CoolTip.ParametersTableSub [self.mainIndex] [self.index]
+ CoolTip.FunctionsTableSub [self.mainIndex] [self.index] (_, CoolTip.FixedValue, parameterTable [1], parameterTable [2], parameterTable [3])
+ end
+
+ local botao_p = frame1.Lines [self.mainIndex]
+ frame1.selected:SetPoint ("top", botao_p, "top", 0, -1)
+ frame1.selected:SetPoint ("bottom", botao_p, "bottom")
+ if (not CoolTip.OptionsTable.NoLastSelectedBar) then
+ frame1.selected:Show()
+ end
+
+ CoolTip.SelectedIndexMain = self.mainIndex
+ CoolTip.SelectedIndexSec [self.mainIndex] = self.index
+
+ end
+
+ function CoolTip:TextAndIcon (frame, menuButton, leftTextTable, rightTextTable, leftIconTable, rightIconTable, isSub)
+
+ --> reset width
+ menuButton.leftText:SetWidth (0)
+ menuButton.leftText:SetHeight (0)
+ menuButton.rightText:SetWidth (0)
+ menuButton.rightText:SetHeight (0)
+
+ --> set text
+ if (leftTextTable) then
+ menuButton.leftText:SetText (leftTextTable [1])
+ menuButton.leftText:SetTextColor (leftTextTable [2], leftTextTable [3], leftTextTable [4], leftTextTable [5])
+ else
+ menuButton.leftText:SetText ("")
+ end
+
+ if (rightTextTable) then
+ menuButton.rightText:SetText (rightTextTable [1])
+ menuButton.rightText:SetTextColor (rightTextTable [2], rightTextTable [3], rightTextTable [4], rightTextTable [5])
+ else
+ menuButton.rightText:SetText ("")
+ end
+
+ --> overwrite text size
+ _detalhes:SetFontSize (menuButton.leftText, CoolTip.OptionsTable.TextSize or self.default_text_size)
+ _detalhes:SetFontSize (menuButton.rightText, CoolTip.OptionsTable.TextSize or self.default_text_size)
+
+ --> overwrite text font object
+ menuButton.leftText:SetFontObject (CoolTip.OptionsTable.TextFont or self.default_text_font)
+ menuButton.rightText:SetFontObject (CoolTip.OptionsTable.TextFont or self.default_text_font)
+
+ --> left icon
+ if (leftIconTable and leftIconTable [1]) then
+ menuButton.leftIcon:SetTexture (leftIconTable [1])
+ menuButton.leftIcon:SetWidth (leftIconTable [2])
+ menuButton.leftIcon:SetHeight (leftIconTable [3])
+ menuButton.leftIcon:SetTexCoord (leftIconTable [4], leftIconTable [5], leftIconTable [6], leftIconTable [7])
+ --[[
+ if (CoolTip.OptionsTable.IconHeightMod) then
+ menuButton.leftIcon:SetPoint ("left", menuButton.leftIcon:GetParent(), "left", 0, CoolTip.OptionsTable.IconHeightMod)
+ else
+ menuButton.leftIcon:SetPoint ("left", menuButton.leftIcon:GetParent(), "left", 0, 0)
+ end
+ --]]
+ else
+ menuButton.leftIcon:SetTexture (nil)
+ menuButton.leftIcon:SetWidth (3)
+ menuButton.leftIcon:SetHeight (3)
+ end
+
+ --> right icon
+ if (rightIconTable and rightIconTable [1]) then
+ menuButton.rightIcon:SetTexture (rightIconTable [1])
+ menuButton.rightIcon:SetWidth (rightIconTable [2])
+ menuButton.rightIcon:SetHeight (rightIconTable [3])
+ menuButton.rightIcon:SetTexCoord (rightIconTable [4], rightIconTable [5], rightIconTable [6], rightIconTable [7])
+ else
+ menuButton.rightIcon:SetTexture (nil)
+ menuButton.rightIcon:SetWidth (3)
+ menuButton.rightIcon:SetHeight (3)
+ end
+
+ --> overwrite icon size
+ if (CoolTip.OptionsTable.IconSize) then
+ menuButton.leftIcon:SetWidth (CoolTip.OptionsTable.IconSize)
+ menuButton.leftIcon:SetHeight (CoolTip.OptionsTable.IconSize)
+ menuButton.rightIcon:SetWidth (CoolTip.OptionsTable.IconSize)
+ menuButton.rightIcon:SetHeight (CoolTip.OptionsTable.IconSize)
+ end
+
+ if (CoolTip.Type == 2) then
+ CoolTip:LeftTextSpace (menuButton)
+ end
+
+ --> string length
+ if (not CoolTip.OptionsTable.FixedWidth) then
+ if (CoolTip.Type == 1 or CoolTip.Type == 2) then
+ local stringWidth = menuButton.leftText:GetStringWidth() + menuButton.rightText:GetStringWidth() + menuButton.leftIcon:GetWidth() + menuButton.rightIcon:GetWidth()
+ if (stringWidth > frame.w) then
+ frame.w = stringWidth
+ end
+ end
+ else
+ if (isSub and CoolTip.OptionsTable.FixedWidthSub) then
+ menuButton.leftText:SetWidth (CoolTip.OptionsTable.FixedWidthSub - menuButton.leftIcon:GetWidth() - 20)
+ end
+ end
+
+ local height = _math_max ( menuButton.leftIcon:GetHeight(), menuButton.rightIcon:GetHeight(), menuButton.leftText:GetStringHeight(), menuButton.rightText:GetStringHeight() )
+ if (height > frame.hHeight) then
+ frame.hHeight = height
+ end
+
+ end
+
+ function CoolTip:StatusBar (menuButton, StatusBar)
+
+ if (StatusBar) then
+
+ menuButton.statusbar:SetValue (StatusBar [1])
+ menuButton.statusbar:SetStatusBarColor (StatusBar [2], StatusBar [3], StatusBar [4], StatusBar [5])
+ menuButton.statusbar:SetHeight (20 + (CoolTip.OptionsTable.StatusBarHeightMod or 0))
+
+ if (StatusBar [6]) then
+ menuButton.spark:Show()
+ menuButton.spark:ClearAllPoints()
+ menuButton.spark:SetPoint ("LEFT", menuButton.statusbar, "LEFT", (StatusBar [1] * (menuButton.statusbar:GetWidth() / 100)) - 3, 0)
+ else
+ menuButton.spark:Hide()
+ end
+
+ if (CoolTip.OptionsTable.StatusBarTexture) then
+ menuButton.statusbar.texture:SetTexture (CoolTip.OptionsTable.StatusBarTexture)
+ else
+ menuButton.statusbar.texture:SetTexture ("Interface\\PaperDollInfoFrame\\UI-Character-Skills-Bar")
+ end
+
+ else
+ menuButton.statusbar:SetValue (0)
+ menuButton.spark:Hide()
+ end
+ end
+
+ function CoolTip:SetupMainButton (menuButton, index)
+ menuButton.index = index
+
+ --> setup texts and icons
+ CoolTip:TextAndIcon (frame1, menuButton, CoolTip.LeftTextTable [index], CoolTip.RightTextTable [index], CoolTip.LeftIconTable [index], CoolTip.RightIconTable [index])
+ --> setup statusbar
+ CoolTip:StatusBar (menuButton, CoolTip.StatusBarTable [index])
+
+ --> click
+ menuButton:RegisterForClicks ("LeftButtonDown")
+
+ --> string length
+ if (not CoolTip.OptionsTable.FixedWidth) then
+ local stringWidth = menuButton.leftText:GetStringWidth() + menuButton.rightText:GetStringWidth() + menuButton.leftIcon:GetWidth() + menuButton.rightIcon:GetWidth()
+ if (stringWidth > frame1.w) then
+ frame1.w = stringWidth
+ end
+ end
+
+ --> register click function
+ menuButton:SetScript ("OnClick", OnClickFunctionButtonPrincipal)
+ menuButton:Show()
+ end
+
+ function CoolTip:SetupSecondaryButton (menuButton, index, mainMenuIndex)
+
+ menuButton.index = index
+ menuButton.mainIndex = mainMenuIndex
+
+ --> setup texts and icons
+ CoolTip:TextAndIcon (frame2, menuButton, CoolTip.LeftTextTableSub [mainMenuIndex] and CoolTip.LeftTextTableSub [mainMenuIndex] [index],
+ CoolTip.RightTextTableSub [mainMenuIndex] and CoolTip.RightTextTableSub [mainMenuIndex] [index],
+ CoolTip.LeftIconTableSub [mainMenuIndex] and CoolTip.LeftIconTableSub [mainMenuIndex] [index],
+ CoolTip.RightIconTableSub [mainMenuIndex] and CoolTip.RightIconTableSub [mainMenuIndex] [index], true)
+ --> setup statusbar
+ CoolTip:StatusBar (menuButton, CoolTip.StatusBarTable [mainMenuIndex] and CoolTip.StatusBarTable [mainMenuIndex] [index])
+
+ --> click
+ menuButton:RegisterForClicks ("LeftButtonDown")
+
+ menuButton:ClearAllPoints()
+ menuButton:SetPoint ("center", frame2, "center")
+ menuButton:SetPoint ("top", frame2, "top", 0, (((index-1)*20)*-1)-3)
+ menuButton:SetPoint ("left", frame2, "left")
+ menuButton:SetPoint ("right", frame2, "right")
+
+ gump:Fade (menuButton, 0)
+
+ --> string length
+ local stringWidth = menuButton.leftText:GetStringWidth() + menuButton.rightText:GetStringWidth() + menuButton.leftIcon:GetWidth() + menuButton.rightIcon:GetWidth()
+ if (stringWidth > frame2.w) then
+ frame2.w = stringWidth
+ end
+
+ menuButton:SetScript ("OnClick", OnClickFunctionButtonSecundario)
+ menuButton:Show()
+
+ return true
+ end
+
+ -- -- --------------------------------------------------------------------------------------------------------------
+
+ function CoolTip:ShowSub (index)
+
+ if (CoolTip.OptionsTable.IgnoreSubMenu) then
+ gump:Fade (frame2, 1)
+ return
+ end
+
+ frame2:SetHeight (6)
+
+ local amtIndexes = CoolTip.IndexesSub [index]
+ if (not amtIndexes) then
+ --print ("Sub menu called but sub menu indexes is nil")
+ return
+ end
+
+ if (CoolTip.OptionsTable.FixedWidthSub) then
+ frame2:SetWidth (CoolTip.OptionsTable.FixedWidthSub)
+ end
+
+ frame2.h = CoolTip.IndexesSub [index] * 20
+ frame2.hHeight = 0
+ frame2.w = 0
+
+ --> pegar a fontsize da label principal
+ local mainButton = frame1.Lines [index]
+ local fontSize = _detalhes:GetFontSize (mainButton.leftText)
+
+ local GotChecked = false
+
+ for i = 1, CoolTip.IndexesSub [index] do
+
+ local button = frame2.Lines [i]
+
+ if (not button) then
+ button = CoolTip:NewSecondaryButton (i)
+ end
+
+ local checked = CoolTip:SetupSecondaryButton (button, i, index)
+ if (checked) then
+ GotChecked = true
+ end
+ end
+
+ local selected = CoolTip.SelectedIndexSec [index]
+ if (selected) then
+ frame2.selected:SetPoint ("top", frame2.Lines [selected], "top", 0, -1)
+ frame2.selected:SetPoint ("bottom", frame2.Lines [selected], "bottom")
+ if (not CoolTip.OptionsTable.NoLastSelectedBar) then
+ frame2.selected:Show()
+ end
+ else
+ frame2.selected:Hide()
+ end
+
+ for i = CoolTip.IndexesSub [index] + 1, #frame2.Lines do
+ gump:Fade (frame2.Lines[i], 1)
+ end
+
+ --[
+ local spacing = 0
+ if (CoolTip.OptionsTable.YSpacingModSub) then
+ spacing = CoolTip.OptionsTable.YSpacingModSub
+ end
+
+ --> normalize height of all rows
+ for i = 1, CoolTip.IndexesSub [index] do
+ local menuButton = frame2.Lines [i]
+ --> height
+ menuButton:SetHeight (frame2.hHeight + (CoolTip.OptionsTable.ButtonHeightModSub or 0))
+ --> points
+ menuButton:ClearAllPoints()
+ menuButton:SetPoint ("center", frame2, "center")
+ menuButton:SetPoint ("top", frame2, "top", 0, ( ( (i-1) * frame2.hHeight) * -1) - 4 + (CoolTip.OptionsTable.ButtonsYModSub or 0) + spacing)
+ if (CoolTip.OptionsTable.YSpacingModSub) then
+ spacing = spacing + CoolTip.OptionsTable.YSpacingModSub
+ end
+ menuButton:SetPoint ("left", frame2, "left")
+ menuButton:SetPoint ("right", frame2, "right")
+ end
+ --]]
+
+ frame2:SetHeight ( (frame2.hHeight * CoolTip.IndexesSub [index]) + 12 + (-spacing))
+
+ if (not CoolTip.OptionsTable.FixedWidthSub) then
+ frame2:SetWidth (frame2.w + 44)
+ end
+
+ gump:Fade (frame2, 0)
+
+ end
+
+ function CoolTip:HideSub()
+ gump:Fade (frame2, 1)
+ end
+
+
+ function CoolTip:LeftTextSpace (row)
+ row.leftText:SetWidth (row:GetWidth() - 30 - row.leftIcon:GetWidth() - row.rightIcon:GetWidth() - row.rightText:GetStringWidth())
+ row.leftText:SetHeight (10)
+ end
+
+ function CoolTip:monta_tooltip()
+
+ --> hide sub frame
+ gump:Fade (frame2, 1)
+ --> hide select bar
+ gump:Fade (frame1.selected, 1)
+
+ frame1:EnableMouse (false)
+
+ --> elevator
+ local yDown = 5
+ --> width
+ if (CoolTip.OptionsTable.FixedWidth) then
+ frame1:SetWidth (CoolTip.OptionsTable.FixedWidth)
+ end
+
+ frame1.w = CoolTip.OptionsTable.FixedWidth or 0
+ frame1.hHeight = 0
+ frame2.hHeight = 0
+
+ CoolTip.active = true
+
+ for i = 1, CoolTip.Indexes do
+
+ local button = frame1.Lines [i]
+ if (not button) then
+ button = CoolTip:NewMainButton (i)
+ end
+
+ button.index = i
+
+ --> basic stuff
+ button:Show()
+ button.background:Hide()
+ button:SetHeight (CoolTip.OptionsTable.ButtonHeightMod or CoolTip.default_height)
+ button:RegisterForClicks()
+
+ --> setup texts and icons
+ CoolTip:TextAndIcon (frame1, button, CoolTip.LeftTextTable [i], CoolTip.RightTextTable [i], CoolTip.LeftIconTable [i], CoolTip.RightIconTable [i])
+ --> setup statusbar
+ CoolTip:StatusBar (button, CoolTip.StatusBarTable [i])
+ end
+
+ --> hide unused lines
+ for i = CoolTip.Indexes+1, #frame1.Lines do
+ frame1.Lines[i]:Hide()
+ end
+ CoolTip.NumLines = CoolTip.Indexes
+
+ local spacing = 0
+ if (CoolTip.OptionsTable.YSpacingMod) then
+ spacing = CoolTip.OptionsTable.YSpacingMod
+ end
+
+ --> normalize height of all rows
+ for i = 1, CoolTip.Indexes do
+ local menuButton = frame1.Lines [i]
+ --> height
+ menuButton:SetHeight (frame1.hHeight + (CoolTip.OptionsTable.ButtonHeightMod or 0))
+ --> points
+ menuButton:ClearAllPoints()
+ menuButton:SetPoint ("center", frame1, "center")
+ menuButton:SetPoint ("left", frame1, "left")
+ menuButton:SetPoint ("right", frame1, "right")
+ menuButton:SetPoint ("top", frame1, "top", 0, ( ( (i-1) * frame1.hHeight) * -1) - 6 + (CoolTip.OptionsTable.ButtonsYMod or 0) + spacing)
+ if (CoolTip.OptionsTable.YSpacingMod) then
+ spacing = spacing + CoolTip.OptionsTable.YSpacingMod
+ end
+
+ menuButton:EnableMouse (false)
+ end
+
+ --> set frame sizes
+ if (not CoolTip.OptionsTable.FixedWidth) then
+ if (CoolTip.Type == 2) then
+ frame1:SetWidth (frame1.w + 34)
+ else
+ frame1:SetWidth (frame1.w + 24)
+ end
+ end
+
+ if (not CoolTip.OptionsTable.FixedHeight) then
+ frame1:SetHeight ( _math_max ( (frame1.hHeight * CoolTip.Indexes) + 12, 22 ))
+ else
+ frame1:SetHeight (CoolTip.OptionsTable.FixedHeight)
+ end
+
+ --> unhide frame
+ gump:Fade (frame1, 0)
+ CoolTip:SetMyPoint (host)
+ end
+
+ function CoolTip:monta_cooltip (host, instancia, options, sub_menus, icones, tamanho1, tamanho2, font, fontsize)
+
+ if (CoolTip.Indexes == 0) then
+ CoolTip:Reset()
+ CoolTip:SetType ("tooltip")
+ CoolTip:AddLine (Loc ["STRING_COOLTIP_NOOPTIONS"])
+ CoolTip:ShowCooltip()
+ return
+ end
+
+ if (CoolTip.OptionsTable.FixedWidth) then
+ frame1:SetWidth (CoolTip.OptionsTable.FixedWidth)
+ end
+
+ frame1.w = CoolTip.OptionsTable.FixedWidth or 0
+ frame1.hHeight = 0
+ frame2.hHeight = 0
+
+ frame1:EnableMouse (true)
+
+ --CoolTip.IndexesSub [CoolTip.Indexes]
+
+ if (CoolTip.HaveSubMenu) then --> zera o segundo frame
+ frame2.w = 0
+ frame2:SetHeight (6)
+ if (CoolTip.SelectedIndexMain) then
+ gump:Fade (frame2, 0)
+ else
+ gump:Fade (frame2, 1)
+ end
+ else
+ gump:Fade (frame2, 1)
+ end
+
+ CoolTip.active = true
+
+ for i = 1, CoolTip.Indexes do
+
+ local menuButton = frame1.Lines [i]
+ if (not menuButton) then
+ menuButton = CoolTip:NewMainButton (i)
+ end
+
+ CoolTip:SetupMainButton (menuButton, i)
+
+ if (CoolTip.SelectedIndexMain and CoolTip.SelectedIndexMain == i) then
+ if (CoolTip.HaveSubMenu) then
+ CoolTip:ShowSub (i)
+ end
+ end
+
+ menuButton.background:Hide()
+
+ --menuButton:SetHeight (CoolTip.OptionsTable.ButtonHeightMod or CoolTip.default_height)
+ end
+
+ --> selected texture
+ if (CoolTip.SelectedIndexMain) then
+ frame1.selected:SetPoint ("top", frame1.Lines [CoolTip.SelectedIndexMain], "top", 0, -1)
+ frame1.selected:SetPoint ("bottom", frame1.Lines [CoolTip.SelectedIndexMain], "bottom")
+ if (CoolTip.OptionsTable.NoLastSelectedBar) then
+ gump:Fade (frame1.selected, 1)
+ else
+ gump:Fade (frame1.selected, 0)
+ end
+ else
+ gump:Fade (frame1.selected, 1)
+ end
+
+ if (CoolTip.Indexes < #frame1.Lines) then
+ for i = CoolTip.Indexes+1, #frame1.Lines do
+ frame1.Lines[i]:Hide()
+ end
+ end
+
+ CoolTip.NumLines = CoolTip.Indexes
+
+ local spacing = 0
+ if (CoolTip.OptionsTable.YSpacingMod) then
+ spacing = CoolTip.OptionsTable.YSpacingMod
+ end
+
+ --> normalize height of all rows
+ for i = 1, CoolTip.Indexes do
+ local menuButton = frame1.Lines [i]
+ --> height
+ menuButton:SetHeight (frame1.hHeight + (CoolTip.OptionsTable.ButtonHeightMod or 0))
+ --> points
+ menuButton:ClearAllPoints()
+ menuButton:SetPoint ("center", frame1, "center")
+ menuButton:SetPoint ("top", frame1, "top", 0, ( ( (i-1) * frame1.hHeight) * -1) - 4 + (CoolTip.OptionsTable.ButtonsYMod or 0) + spacing)
+ if (CoolTip.OptionsTable.YSpacingMod) then
+ spacing = spacing + CoolTip.OptionsTable.YSpacingMod
+ end
+ menuButton:SetPoint ("left", frame1, "left")
+ menuButton:SetPoint ("right", frame1, "right")
+
+ menuButton:EnableMouse (true)
+ end
+
+ if (not CoolTip.OptionsTable.FixedWidth) then
+ frame1:SetWidth (frame1.w + 24)
+ end
+
+ if (CoolTip.OptionsTable.FixedHeight) then
+ frame1:SetHeight (CoolTip.OptionsTable.FixedHeight)
+ else
+ frame1:SetHeight (_math_max ( (frame1.hHeight * CoolTip.Indexes) + 12 + (-spacing), 22 ))
+ end
+
+ frame1:ClearAllPoints()
+ CoolTip:SetMyPoint (host)
+
+ gump:Fade (frame1, 0)
+
+ return true
+ end
+
+ function CoolTip:SetMyPoint (host, x_mod, y_mod)
+
+ local moveX = x_mod or 0
+ local moveY = y_mod or 0
+
+ --> clear all points
+ frame1:ClearAllPoints()
+
+ local anchor = CoolTip.OptionsTable.Anchor or CoolTip.Host
+ frame1:SetPoint (CoolTip.OptionsTable.MyAnchor, anchor, CoolTip.OptionsTable.RelativeAnchor, 0 + moveX + CoolTip.OptionsTable.WidthAnchorMod, 10 + CoolTip.OptionsTable.HeightAnchorMod + moveY)
+
+ if (not x_mod) then
+ --> check if cooltip is out of screen bounds
+ local center_x = frame1:GetCenter()
+
+ if (center_x) then
+ local screen_x_res = GetScreenWidth()
+ local half_x = frame1:GetWidth() / 2
+
+ if (center_x+half_x > screen_x_res) then
+ --> out of right side
+ local move_to_left = (center_x + half_x) - screen_x_res
+ return CoolTip:SetMyPoint (host, -move_to_left, 0)
+
+ elseif (center_x-half_x < 0) then
+ --> out of left side
+ local move_to_right = center_x - half_x
+ return CoolTip:SetMyPoint (host, move_to_right*-1, 0)
+ end
+ end
+ end
+
+ if (not y_mod) then
+ --> check if cooltip is out of screen bounds
+ local _, center_y = frame1:GetCenter()
+ local screen_y_res = GetScreenHeight()
+ local half_y = frame1:GetHeight() / 2
+
+ if (center_y) then
+ if (center_y+half_y > screen_y_res) then
+ --> out of top side
+ local move_to_down = (center_y + half_y) - screen_y_res
+ return CoolTip:SetMyPoint (host, 0, -move_to_down)
+
+ elseif (center_y-half_y < 0) then
+ --> out of bottom side
+ local move_to_up = center_y - half_y
+ return CoolTip:SetMyPoint (host, 0, move_to_up*-1)
+
+ end
+ end
+ end
+ end
+
+ function CoolTip:GetText (buttonIndex)
+ local button1 = frame1.Lines [buttonIndex]
+ if (not button1) then
+ return ""
+ else
+ return button1.leftText:GetText()
+ end
+ end
+
+----------------------------------------------------------------------
+ --> Get the number of lines current shown on cooltip
+
+ function CoolTip:GetNumLines()
+ return CoolTip.NumLines or 0
+ end
+
+----------------------------------------------------------------------
+ --> Remove all options actived
+ --> Set a option on current cooltip
+
+ function CoolTip:ClearAllOptions()
+ for option, _ in pairs (CoolTip.OptionsTable) do
+ CoolTip.OptionsTable [option] = nil
+ end
+
+ CoolTip:SetOption ("MyAnchor", "bottom")
+ CoolTip:SetOption ("RelativeAnchor", "top")
+ CoolTip:SetOption ("WidthAnchorMod", 0)
+ CoolTip:SetOption ("HeightAnchorMod", 0)
+ end
+
+ function CoolTip:SetOption (option, value)
+ --> check if this options exists
+ if (not CoolTip.OptionsList [option]) then
+ return --> error
+ end
+
+ --> set options
+ CoolTip.OptionsTable [option] = value
+ end
+
+----------------------------------------------------------------------
+ --> set the anchor of cooltip
+ --> parameters: frame [, cooltip anchor point, frame anchor point [, x mod, y mod]]
+ --> frame [, x mod, y mod]
+
+ --> alias
+ function CoolTip:SetOwner (frame, myPoint, hisPoint, x, y)
+ return CoolTip:SetHost (frame, myPoint, hisPoint, x, y)
+ end
+
+ function CoolTip:SetHost (frame, myPoint, hisPoint, x, y)
+ --> check data integrity
+ if (type (frame) ~= "table" or not frame.GetObjectType) then
+ print ("host need to be a frame")
+ return --> error
+ end
+
+ CoolTip.Host = frame
+
+ --> defaults
+ myPoint = myPoint or CoolTip.OptionsTable.MyAnchor or "bottom"
+ hisPoint = hisPoint or CoolTip.OptionsTable.hisPoint or "top"
+
+ x = x or CoolTip.OptionsTable.WidthAnchorMod or 0
+ y = y or CoolTip.OptionsTable.HeightAnchorMod or 0
+
+ --> check options
+ if (type (myPoint) == "string") then
+ CoolTip:SetOption ("MyAnchor", myPoint)
+ CoolTip:SetOption ("WidthAnchorMod", x)
+ elseif (type (myPoint) == "number") then
+ CoolTip:SetOption ("HeightAnchorMod", myPoint)
+ end
+
+ if (type (hisPoint) == "string") then
+ CoolTip:SetOption ("RelativeAnchor", hisPoint)
+ CoolTip:SetOption ("HeightAnchorMod", y)
+ elseif (type (hisPoint) == "number") then
+ CoolTip:SetOption ("WidthAnchorMod", hisPoint)
+ end
+ end
+
+----------------------------------------------------------------------
+ --> set cooltip type
+ --> parameters: type (1 = tooltip | 2 = tooltip with bars | 3 = menu)
+
+ function CoolTip:SetType (newType)
+ if (type (newType) == "string") then
+ if (newType == "tooltip") then
+ CoolTip.Type = 1
+ elseif (newType == "tooltipbar") then
+ CoolTip.Type = 2
+ elseif (newType == "menu") then
+ CoolTip.Type = 3
+ else
+ --> error
+ end
+ elseif (type (newType) == "number") then
+ if (newType == 1) then
+ CoolTip.Type = 1
+ elseif (newType == 2) then
+ CoolTip.Type = 2
+ elseif (newType == 3) then
+ CoolTip.Type = 3
+ else
+ --> error
+ end
+ else
+ --> error
+ end
+ end
+
+ --> Set a fixed value for menu
+ function CoolTip:SetFixedParameter (value, injected)
+ if (injected ~= nil) then
+ local frame = value
+ if (frame.dframework) then
+ frame = frame.widget
+ end
+ if (frame.CoolTip) then
+ frame.CoolTip.FixedValue = injected
+ else
+ --debug
+ end
+ end
+ CoolTip.FixedValue = value
+ end
+
+ function CoolTip:SetColor (menuType, ...)
+ local ColorR, ColorG, ColorB, ColorA = gump:ParseColors (...)
+ if ((type (menuType) == "string" and menuType == "main") or (type (menuType) == "number" and menuType == 1)) then
+ frame1.framebackground:SetVertexColor (ColorR, ColorG, ColorB, ColorA)
+ elseif ((type (menuType) == "string" and menuType == "sec") or (type (menuType) == "number" and menuType == 2)) then
+ frame2.framebackground:SetVertexColor (ColorR, ColorG, ColorB, ColorA)
+ else
+ return --> error
+ end
+ end
+
+ --> Set last selected option
+ function CoolTip:SetLastSelected (menuType, index, index2)
+
+ if (CoolTip.Type == 3) then
+ if ((type (menuType) == "string" and menuType == "main") or (type (menuType) == "number" and menuType == 1)) then
+ CoolTip.SelectedIndexMain = index
+ elseif ((type (menuType) == "string" and menuType == "sec") or (type (menuType) == "number" and menuType == 2)) then
+ CoolTip.SelectedIndexSec [index] = index2
+ else
+ return --> error
+ end
+ else
+ return --> error
+ end
+ end
+
+ --> serack key: ~select
+ function CoolTip:Select (menuType, option, mainIndex)
+ if (menuType == 1) then --main menu
+ local botao = frame1.Lines [option]
+ CoolTip.buttonClicked = true
+ frame1.selected:SetPoint ("top", botao, "top", 0, -1)
+ frame1.selected:SetPoint ("bottom", botao, "bottom")
+ UIFrameFlash (frame1.selected, 0.05, 0.05, 0.2, true, 0, 0)
+
+ elseif (menuType == 2) then --sub menu
+ CoolTip:ShowSub (mainIndex)
+ local botao = frame2.Lines [option]
+ CoolTip.buttonClicked = true
+ frame2.selected:SetPoint ("top", botao, "top", 0, -1)
+ frame2.selected:SetPoint ("bottom", botao, "bottom")
+ UIFrameFlash (frame2.selected, 0.05, 0.05, 0.2, true, 0, 0)
+ end
+ end
+
+----------------------------------------------------------------------
+ --> Reset cooltip
+
+ --> wipe all data
+ function CoolTip:Reset()
+
+ CoolTip.FixedValue = nil
+ CoolTip.HaveSubMenu = false
+
+ CoolTip.SelectedIndexMain = nil
+ _table_wipe (CoolTip.SelectedIndexSec)
+
+ CoolTip.Indexes = 0
+ CoolTip.SubIndexes = 0
+ _table_wipe (CoolTip.IndexesSub)
+
+ _table_wipe (CoolTip.LeftTextTable)
+ _table_wipe (CoolTip.LeftTextTableSub)
+ _table_wipe (CoolTip.RightTextTable)
+ _table_wipe (CoolTip.RightTextTableSub)
+
+ _table_wipe (CoolTip.LeftIconTable)
+ _table_wipe (CoolTip.LeftIconTableSub)
+ _table_wipe (CoolTip.RightIconTable)
+ _table_wipe (CoolTip.RightIconTableSub)
+
+ _table_wipe (CoolTip.StatusBarTable)
+ _table_wipe (CoolTip.StatusBarTableSub)
+
+ _table_wipe (CoolTip.FunctionsTableMain)
+ _table_wipe (CoolTip.FunctionsTableSub)
+
+ _table_wipe (CoolTip.ParametersTableMain)
+ _table_wipe (CoolTip.ParametersTableSub)
+
+ CoolTip:ClearAllOptions()
+ CoolTip:SetColor (1, "transparent")
+ CoolTip:SetColor (2, "transparent")
+ end
+
+----------------------------------------------------------------------
+ --> Menu functions
+
+
+ function CoolTip:AddMenu (menuType, func, param1, param2, param3, leftText, leftIcon, indexUp)
+
+ if (leftText and indexUp and ((type (menuType) == "string" and menuType == "main") or (type (menuType) == "number" and menuType == 1))) then
+ CoolTip.Indexes = CoolTip.Indexes + 1
+
+ if (not CoolTip.IndexesSub [CoolTip.Indexes]) then
+ CoolTip.IndexesSub [CoolTip.Indexes] = 0
+ end
+
+ CoolTip.SubIndexes = 0
+ end
+
+ --> need a previous line
+ if (CoolTip.Indexes == 0) then
+ print ("Indexes are 0")
+ return --> return error
+ end
+
+ --> check data integrity
+ if (type (func) ~= "function") then
+ print ("No function")
+ return --> erroe
+ end
+
+ --> add
+
+ if ((type (menuType) == "string" and menuType == "main") or (type (menuType) == "number" and menuType == 1)) then
+
+ local parameterTable
+ if (CoolTip.isSpecial) then
+ parameterTable = {}
+ _table_insert (CoolTip.FunctionsTableMain, CoolTip.Indexes, func)
+ _table_insert (CoolTip.ParametersTableMain, CoolTip.Indexes, parameterTable)
+ else
+
+ CoolTip.FunctionsTableMain [CoolTip.Indexes] = func
+
+ parameterTable = CoolTip.ParametersTableMain [CoolTip.Indexes]
+ if (not parameterTable) then
+ parameterTable = {}
+ CoolTip.ParametersTableMain [CoolTip.Indexes] = parameterTable
+ end
+ end
+
+ parameterTable [1] = param1
+ parameterTable [2] = param2
+ parameterTable [3] = param3
+
+ if (leftIcon) then
+ local iconTable = CoolTip.LeftIconTable [CoolTip.Indexes]
+
+ if (not iconTable or CoolTip.isSpecial) then
+ iconTable = {}
+ CoolTip.LeftIconTable [CoolTip.Indexes] = iconTable
+ end
+
+ iconTable [1] = leftIcon
+ iconTable [2] = 16 --> default 16
+ iconTable [3] = 16 --> default 16
+ iconTable [4] = 0 --> default 0
+ iconTable [5] = 1 --> default 1
+ iconTable [6] = 0 --> default 0
+ iconTable [7] = 1 --> default 1
+ end
+
+ if (leftText) then
+ local lineTable_left = CoolTip.LeftTextTable [CoolTip.Indexes]
+
+ if (not lineTable_left or CoolTip.isSpecial) then
+ lineTable_left = {}
+ CoolTip.LeftTextTable [CoolTip.Indexes] = lineTable_left
+ end
+
+ lineTable_left [1] = leftText --> line text
+ lineTable_left [2] = 1
+ lineTable_left [3] = 1
+ lineTable_left [4] = 1
+ lineTable_left [5] = 1
+ lineTable_left [6] = true
+
+ end
+
+ elseif ((type (menuType) == "string" and menuType == "sec") or (type (menuType) == "number" and menuType == 2)) then
+
+ if (CoolTip.SubIndexes == 0) then
+ if (not indexUp or not leftText) then
+ print ("not indexUp or not leftText")
+ return --> error
+ end
+ end
+
+ if (indexUp and leftText) then
+ CoolTip.SubIndexes = CoolTip.SubIndexes + 1
+ CoolTip.IndexesSub [CoolTip.Indexes] = CoolTip.IndexesSub [CoolTip.Indexes] + 1
+ elseif (indexUp and not leftText) then
+ print ("indexUp and not leftText")
+ return --> error [leftText can't be nil if indexUp are true]
+ end
+
+ --> menu container
+ local subMenuContainerParameters = CoolTip.ParametersTableSub [CoolTip.Indexes]
+ if (not subMenuContainerParameters) then
+ subMenuContainerParameters = {}
+ CoolTip.ParametersTableSub [CoolTip.Indexes] = subMenuContainerParameters
+ end
+
+ local subMenuContainerFunctions = CoolTip.FunctionsTableSub [CoolTip.Indexes]
+ if (not subMenuContainerFunctions or CoolTip.isSpecial) then
+ subMenuContainerFunctions = {}
+ CoolTip.FunctionsTableSub [CoolTip.Indexes] = subMenuContainerFunctions
+ end
+
+ --> menu table
+ local subMenuTablesParameters = subMenuContainerParameters [CoolTip.SubIndexes]
+ if (not subMenuTablesParameters or CoolTip.isSpecial) then
+ subMenuTablesParameters = {}
+ subMenuContainerParameters [CoolTip.SubIndexes] = subMenuTablesParameters
+ end
+
+ --> add
+ subMenuContainerFunctions [CoolTip.SubIndexes] = func
+
+ subMenuTablesParameters [1] = param1
+ subMenuTablesParameters [2] = param2
+ subMenuTablesParameters [3] = param3
+
+ --> text and icon
+ if (leftIcon) then
+
+ local subMenuContainerIcons = CoolTip.LeftIconTableSub [CoolTip.Indexes]
+ if (not subMenuContainerIcons) then
+ subMenuContainerIcons = {}
+ CoolTip.LeftIconTableSub [CoolTip.Indexes] = subMenuContainerIcons
+ end
+ local subMenuTablesIcons = subMenuContainerIcons [CoolTip.SubIndexes]
+ if (not subMenuTablesIcons or CoolTip.isSpecial) then
+ subMenuTablesIcons = {}
+ subMenuContainerIcons [CoolTip.SubIndexes] = subMenuTablesIcons
+ end
+
+ subMenuTablesIcons [1] = leftIcon
+ subMenuTablesIcons [2] = 16 --> default 16
+ subMenuTablesIcons [3] = 16 --> default 16
+ subMenuTablesIcons [4] = 0 --> default 0
+ subMenuTablesIcons [5] = 1 --> default 1
+ subMenuTablesIcons [6] = 0 --> default 0
+ subMenuTablesIcons [7] = 1 --> default 1
+ end
+
+ if (leftText) then
+
+ local subMenuContainerTexts = CoolTip.LeftTextTableSub [CoolTip.Indexes]
+ if (not subMenuContainerTexts) then
+ subMenuContainerTexts = {}
+ CoolTip.LeftTextTableSub [CoolTip.Indexes] = subMenuContainerTexts
+ end
+ local subMenuTablesTexts = subMenuContainerTexts [CoolTip.SubIndexes]
+ if (not subMenuTablesTexts or CoolTip.isSpecial) then
+ subMenuTablesTexts = {}
+ subMenuContainerTexts [CoolTip.SubIndexes] = subMenuTablesTexts
+ end
+
+ subMenuTablesTexts [1] = leftText --> line text
+ subMenuTablesTexts [2] = 1
+ subMenuTablesTexts [3] = 1
+ subMenuTablesTexts [4] = 1
+ subMenuTablesTexts [5] = 1
+ subMenuTablesTexts [6] = true
+
+ end
+
+ CoolTip.HaveSubMenu = true
+
+ else
+ return --> error
+ end
+ end
+
+----------------------------------------------------------------------
+ --> adds a statusbar to the last line added.
+ --> only works with cooltip type 2 (tooltip with bars)
+ --> parameters: value [, color red, color green, color blue, color alpha [, glow]]
+ --> can also use a table or html color name in color red and send glow in color green
+
+ function CoolTip:AddStatusBar (statusbarValue, frame, ColorR, ColorG, ColorB, ColorA, statusbarGlow)
+
+ --> need a previous line
+ if (CoolTip.Indexes == 0) then
+ return --> return error
+ end
+
+ --> check data integrity
+ if (type (statusbarValue) ~= "number") then
+ return --> error
+ end
+
+ if (type (ColorR) == "table" or type (ColorR) == "string") then
+ statusbarGlow, ColorR, ColorG, ColorB, ColorA = ColorG, gump:ParseColors (ColorR)
+ elseif (type (ColorR) == "boolean") then
+ statusbarGlow = ColorR
+ ColorR, ColorG, ColorB, ColorA = 1, 1, 1, 1
+ else
+ --> error
+ end
+
+ --> add
+ local frameTable
+ local statusbarTable
+
+ if (not frame or (type (frame) == "string" and frame == "main") or (type (frame) == "number" and frame == 1)) then
+ frameTable = CoolTip.StatusBarTable
+
+ if (CoolTip.isSpecial) then
+ statusbarTable = {}
+ _table_insert (frameTable, CoolTip.Indexes, statusbarTable)
+ else
+ statusbarTable = frameTable [CoolTip.Indexes]
+ if (not statusbarTable) then
+ statusbarTable = {}
+ _table_insert (frameTable, CoolTip.Indexes, statusbarTable)
+ --frameTable [CoolTip.Indexes] = statusbarTable
+ end
+ end
+
+ elseif ((type (frame) == "string" and frame == "sub") or (type (frame) == "number" and frame == 2)) then
+
+ frameTable = CoolTip.StatusBarTableSub
+
+ local subMenuContainerStatusBar = frameTable [CoolTip.Indexes]
+ if (not subMenuContainerStatusBar) then
+ subMenuContainerStatusBar = {}
+ frameTable [CoolTip.Indexes] = subMenuContainerStatusBar
+ end
+
+ if (CoolTip.isSpecial) then
+ statusbarTable = {}
+ _table_insert (subMenuContainerStatusBar, CoolTip.SubIndexes, statusbarTable)
+ else
+ statusbarTable = subMenuContainerStatusBar [CoolTip.SubIndexes]
+ if (not statusbarTable) then
+ statusbarTable = {}
+ _table_insert (subMenuContainerStatusBar, CoolTip.SubIndexes, statusbarTable)
+ end
+ end
+ else
+ print ("unknow frame")
+ return --> error
+ end
+
+ statusbarTable [1] = statusbarValue
+ statusbarTable [2] = ColorR
+ statusbarTable [3] = ColorG
+ statusbarTable [4] = ColorB
+ statusbarTable [5] = ColorA
+ statusbarTable [6] = statusbarGlow
+
+ end
+
+----------------------------------------------------------------------
+ --> adds a icon to the last line added.
+ --> only works with cooltip type 1 and 2 (tooltip and tooltip with bars)
+ --> parameters: icon [, width [, height [, TexCoords L R T B ]]]
+ --> texture support string path or texture object
+
+ function CoolTip:AddIcon (iconTexture, frame, side, iconWidth, iconHeight, L, R, T, B)
+
+ --> need a previous line
+ if (CoolTip.Indexes == 0) then
+ return --> return error
+ end
+
+ --> check data integrity
+ if (type (iconTexture) ~= "string" and (type (iconTexture) ~= "table" or not iconTexture.GetObjectType or iconTexture:GetObjectType() ~= "Texture") ) then
+ return --> return error
+ end
+
+ side = side or 1
+
+ local frameTable
+ local iconTable
+
+ if (not frame or (type (frame) == "string" and frame == "main") or (type (frame) == "number" and frame == 1)) then
+ if (not side or (type (side) == "string" and side == "left") or (type (side) == "number" and side == 1)) then
+ frameTable = CoolTip.LeftIconTable
+ elseif ((type (side) == "string" and side == "right") or (type (side) == "number" and side == 2)) then
+ frameTable = CoolTip.RightIconTable
+ end
+
+ if (CoolTip.isSpecial) then
+ iconTable = {}
+ _table_insert (frameTable, CoolTip.Indexes, iconTable)
+ else
+ iconTable = frameTable [CoolTip.Indexes]
+ if (not iconTable) then
+ iconTable = {}
+ _table_insert (frameTable, CoolTip.Indexes, iconTable)
+ --frameTable [CoolTip.Indexes] = iconTable
+ end
+ end
+
+ elseif ((type (frame) == "string" and frame == "sub") or (type (frame) == "number" and frame == 2)) then
+
+ if ((type (side) == "string" and side == "left") or (type (side) == "number" and side == 1)) then
+ frameTable = CoolTip.LeftIconTableSub
+ elseif ((type (side) == "string" and side == "right") or (type (side) == "number" and side == 2)) then
+ frameTable = CoolTip.RightIconTableSub
+ end
+
+ local subMenuContainerIcons = frameTable [CoolTip.Indexes]
+ if (not subMenuContainerIcons) then
+ subMenuContainerIcons = {}
+ frameTable [CoolTip.Indexes] = subMenuContainerIcons
+ end
+
+ if (CoolTip.isSpecial) then
+ iconTable = {}
+ subMenuContainerIcons [CoolTip.SubIndexes] = iconTable
+ else
+ iconTable = subMenuContainerIcons [CoolTip.SubIndexes]
+ if (not iconTable) then
+ iconTable = {}
+ subMenuContainerIcons [CoolTip.SubIndexes] = iconTable
+ end
+ end
+
+ else
+ return --> error
+ end
+
+ iconTable [1] = iconTexture
+ iconTable [2] = iconWidth or 16 --> default 16
+ iconTable [3] = iconHeight or 16 --> default 16
+ iconTable [4] = L or 0 --> default 0
+ iconTable [5] = R or 1 --> default 1
+ iconTable [6] = T or 0 --> default 0
+ iconTable [7] = B or 1 --> default 1
+
+ return true
+ end
+
+----------------------------------------------------------------------
+ --> adds a line.
+ --> only works with cooltip type 1 and 2 (tooltip and tooltip with bars)
+ --> parameters: left text, right text [, L color R, L color G, L color B, L color A [, R color R, R color G, R color B, R color A [, wrap]]]
+
+ --> adds a line for tooltips
+ function CoolTip:AddLine (leftText, rightText, frame, ColorR, ColorG, ColorB, ColorA, ColorR1, ColorG2, ColorB3, ColorA4, wrapLine)
+
+ --> check data integrity
+ if (type (leftText) ~= "string") then
+ leftText = ""
+ end
+ if (type (rightText) ~= "string") then
+ rightText = ""
+ end
+
+ if (type (ColorR) == "table" or type (ColorR) == "string") then
+ ColorR1, ColorG2, ColorB3, ColorA4, wrapLine, ColorR, ColorG, ColorB, ColorA = ColorG, ColorB, ColorA, ColorR1, ColorG2, gump:ParseColors (ColorR)
+ if (type (ColorR1) == "table" or type (ColorR1) == "string") then
+ wrapLine = ColorG2
+ ColorR1, ColorG2, ColorB3, ColorA4 = gump:ParseColors (ColorR1)
+ end
+ elseif (type (ColorR) == "boolean") then
+ wrapLine = ColorR
+ ColorR, ColorG, ColorB, ColorA = 1, 1, 1, 1
+ ColorR1, ColorG2, ColorB3, ColorA4 = 1, 1, 1, 1
+ else
+ ColorR, ColorG, ColorB, ColorA = 1, 1, 1, 1
+ ColorR1, ColorG2, ColorB3, ColorA4 = 1, 1, 1, 1
+ wrapLine = true
+ end
+
+ local frameTableLeft
+ local frameTableRight
+ local lineTable_left
+ local lineTable_right
+
+ if (not frame or (type (frame) == "string" and frame == "main") or (type (frame) == "number" and frame == 1)) then
+
+ CoolTip.Indexes = CoolTip.Indexes + 1
+
+ if (not CoolTip.IndexesSub [CoolTip.Indexes]) then
+ CoolTip.IndexesSub [CoolTip.Indexes] = 0
+ end
+
+ CoolTip.SubIndexes = 0
+
+ frameTableLeft = CoolTip.LeftTextTable
+ frameTableRight = CoolTip.RightTextTable
+
+ if (CoolTip.isSpecial) then
+ lineTable_left = {}
+ _table_insert (frameTableLeft, CoolTip.Indexes, lineTable_left)
+ lineTable_right = {}
+ _table_insert (frameTableRight, CoolTip.Indexes, lineTable_right)
+ else
+ lineTable_left = frameTableLeft [CoolTip.Indexes]
+ lineTable_right = frameTableRight [CoolTip.Indexes]
+
+ if (not lineTable_left) then
+ lineTable_left = {}
+ _table_insert (frameTableLeft, CoolTip.Indexes, lineTable_left)
+ --frameTableLeft [CoolTip.Indexes] = lineTable_left
+ end
+ if (not lineTable_right) then
+ lineTable_right = {}
+ _table_insert (frameTableRight, CoolTip.Indexes, lineTable_right)
+ --frameTableRight [CoolTip.Indexes] = lineTable_right
+ end
+ end
+
+ elseif ((type (frame) == "string" and frame == "sub") or (type (frame) == "number" and frame == 2)) then
+
+ CoolTip.SubIndexes = CoolTip.SubIndexes + 1
+ CoolTip.IndexesSub [CoolTip.Indexes] = CoolTip.IndexesSub [CoolTip.Indexes] + 1
+ CoolTip.HaveSubMenu = true
+
+ frameTableLeft = CoolTip.LeftTextTableSub
+ frameTableRight = CoolTip.RightTextTableSub
+
+ local subMenuContainerTexts = frameTableLeft [CoolTip.Indexes]
+ if (not subMenuContainerTexts) then
+ subMenuContainerTexts = {}
+ _table_insert (frameTableLeft, CoolTip.Indexes, subMenuContainerTexts)
+ end
+
+ if (CoolTip.isSpecial) then
+ lineTable_left = {}
+ _table_insert (subMenuContainerTexts, CoolTip.SubIndexes, lineTable_left)
+ else
+ lineTable_left = subMenuContainerTexts [CoolTip.SubIndexes]
+ if (not lineTable_left) then
+ lineTable_left = {}
+ --subMenuContainerTexts [CoolTip.SubIndexes] = lineTable_left
+ _table_insert (subMenuContainerTexts, CoolTip.SubIndexes, lineTable_left)
+ end
+ end
+
+ local subMenuContainerTexts = frameTableRight [CoolTip.Indexes]
+ if (not subMenuContainerTexts) then
+ subMenuContainerTexts = {}
+ _table_insert (frameTableRight, CoolTip.Indexes, subMenuContainerTexts)
+ --frameTableRight [CoolTip.Indexes] = subMenuContainerTexts
+ end
+
+ if (CoolTip.isSpecial) then
+ lineTable_right = {}
+ _table_insert (subMenuContainerTexts, CoolTip.SubIndexes, lineTable_right)
+ else
+ lineTable_right = subMenuContainerTexts [CoolTip.SubIndexes]
+ if (not lineTable_right) then
+ lineTable_right = {}
+ _table_insert (subMenuContainerTexts, CoolTip.SubIndexes, lineTable_right)
+ --subMenuContainerTexts [CoolTip.SubIndexes] = lineTable_right
+ end
+ end
+ else
+ return --> error
+ end
+
+ lineTable_left [1] = leftText --> line text
+ lineTable_left [2] = ColorR
+ lineTable_left [3] = ColorG
+ lineTable_left [4] = ColorB
+ lineTable_left [5] = ColorA
+ lineTable_left [6] = wrapLine
+
+ lineTable_right [1] = rightText --> line text
+ lineTable_right [2] = ColorR1
+ lineTable_right [3] = ColorG2
+ lineTable_right [4] = ColorB3
+ lineTable_right [5] = ColorA4
+ lineTable_right [6] = wrapLine
+ end
+
+ function CoolTip:AddSpecial (widgetType, index, subIndex, ...)
+
+ local currentIndex = CoolTip.Indexes
+ local currentSubIndex = CoolTip.SubIndexes
+ CoolTip.isSpecial = true
+
+ widgetType = string.lower (widgetType)
+
+ if (widgetType == "line") then
+
+ if (subIndex) then
+ CoolTip.Indexes = index
+ CoolTip.SubIndexes = subIndex-1
+ else
+ CoolTip.Indexes = index-1
+ end
+
+ CoolTip:AddLine (...)
+
+ if (subIndex) then
+ CoolTip.Indexes = currentIndex
+ CoolTip.SubIndexes = currentSubIndex+1
+ else
+ CoolTip.Indexes = currentIndex+1
+ end
+
+ elseif (widgetType == "icon") then
+
+ CoolTip.Indexes = index
+ if (subIndex) then
+ CoolTip.SubIndexes = subIndex
+ end
+
+ CoolTip:AddIcon (...)
+
+ CoolTip.Indexes = currentIndex
+ if (subIndex) then
+ CoolTip.SubIndexes = currentSubIndex
+ end
+
+ elseif (widgetType == "statusbar") then
+
+ CoolTip.Indexes = index
+ if (subIndex) then
+ CoolTip.SubIndexes = subIndex
+ end
+
+ CoolTip:AddStatusBar (...)
+
+ CoolTip.Indexes = currentIndex
+ if (subIndex) then
+ CoolTip.SubIndexes = currentSubIndex
+ end
+
+ elseif (widgetType == "menu") then
+
+ CoolTip.Indexes = index
+ if (subIndex) then
+ CoolTip.SubIndexes = subIndex
+ end
+
+ CoolTip:AddMenu (...)
+
+ CoolTip.Indexes = currentIndex
+ if (subIndex) then
+ CoolTip.SubIndexes = currentSubIndex
+ end
+
+ end
+
+ CoolTip.isSpecial = false
+
+ end
+
+ --> search key: ~fromline
+ function CoolTip:AddFromTable (_table)
+ for index, menu in _ipairs (_table) do
+ if (menu.func) then
+ CoolTip:AddMenu (menu.type or 1, menu.func, menu.param1, menu.param2, menu.param3, nil, menu.icon)
+ elseif (menu.statusbar) then
+ CoolTip:AddStatusBar (menu.value, menu.type or 1, menu.color, true)
+ elseif (menu.icon) then
+ CoolTip:AddIcon (menu.icon, menu.type or 1, menu.side or 1, menu.width, menu.height, menu.l, menu.r, menu.t, menu.b)
+ elseif (menu.textleft or menu.textright or menu.text) then
+ CoolTip:AddLine (menu.text, "", menu.type, menu.color, menu.color, true)
+ end
+ end
+ end
+
+----------------------------------------------------------------------
+ --> show cooltip
+
+ --> serach key: ~start
+ function CoolTip:ShowCooltip (frame, menuType, color)
+
+ if (frame) then
+ --> details framework
+ if (frame.dframework) then
+ frame = frame.widget
+ end
+ CoolTip:SetHost (frame)
+ end
+ if (menuType) then
+ CoolTip:SetType (menuType)
+ end
+ if (color) then
+ CoolTip:SetColor (1, color)
+ CoolTip:SetColor (2, color)
+ end
+
+ if (CoolTip.Type == 1 or CoolTip.Type == 2) then
+ return CoolTip:monta_tooltip()
+
+ elseif (CoolTip.Type == 3) then
+ return CoolTip:monta_cooltip()
+
+ end
+ end
+
+ local emptyOptions = {}
+
+ function CoolTip:Close()
+ CoolTip.active = false
+ gump:Fade (frame1, 1)
+ gump:Fade (frame2, 1)
+ end
+
+ --> old function call
+ function CoolTip:ShowMe (host, arg2)
+
+ --> ignore if mouse is up me
+ if (CoolTip.mouseOver) then
+ return
+ end
+
+ if (not host or not arg2) then --> hideme
+ CoolTip.active = false
+ gump:Fade (frame1, 1)
+ gump:Fade (frame2, 1)
+ end
+ end
+
+ --> search key: ~inject
+ function CoolTip:ExecFunc (host, fromClick)
+
+ if (host.dframework) then
+ if (not host.widget.CoolTip) then
+ host.widget.CoolTip = host.CoolTip
+ end
+ host = host.widget
+ end
+
+ CoolTip:Reset()
+ CoolTip:SetType (host.CoolTip.Type)
+ CoolTip:SetFixedParameter (host.CoolTip.FixedValue)
+ CoolTip:SetColor ("main", host.CoolTip.MainColor or "transparent")
+ CoolTip:SetColor ("sec", host.CoolTip.SubColor or "transparent")
+
+ CoolTip:SetOwner (host, host.CoolTip.MyAnchor, host.CoolTip.HisAnchor, host.CoolTip.X, host.CoolTip.Y)
+
+ local options = host.CoolTip.Options
+ if (type (options) == "function") then
+ options = options()
+ end
+ if (options) then
+ for optionName, optionValue in pairs (options) do
+ CoolTip:SetOption (optionName, optionValue)
+ end
+ end
+
+ host.CoolTip.BuildFunc()
+ CoolTip:ShowCooltip()
+
+ if (fromClick) then
+ UIFrameFlash (frame1, 0.05, 0.05, 0.2, true, 0, 0)
+ end
+ end
+
+ local InjectOnUpdateEnter = function (self, elapsed)
+ elapsedTime = elapsedTime+elapsed
+ if (elapsedTime > 0.3) then
+ self:SetScript ("OnUpdate", nil)
+ CoolTip:ExecFunc (self)
+ end
+ end
+
+ local InjectOnUpdateLeave = function (self, elapsed)
+ elapsedTime = elapsedTime+elapsed
+ if (elapsedTime > 0.3) then
+ if (not CoolTip.mouseOver and not CoolTip.buttonOver and self == CoolTip.Host) then
+ CoolTip:ShowMe (false)
+ end
+ self:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ local InjectOnLeave = function (self)
+ CoolTip.buttonOver = false
+
+ if (CoolTip.active) then
+ elapsedTime = 0
+ self:SetScript ("OnUpdate", InjectOnUpdateLeave)
+ else
+ self:SetScript ("OnUpdate", nil)
+ end
+
+ if (self.CoolTip.OnLeaveFunc) then
+ self.CoolTip.OnLeaveFunc()
+ end
+
+ if (self.OldOnLeaveScript) then
+ self:OldOnLeaveScript()
+ end
+ end
+
+ local InjectOnEnter = function (self)
+ CoolTip.buttonOver = true
+ if (CoolTip.active) then
+ CoolTip:ExecFunc (self)
+ else
+ elapsedTime = 0
+ self:SetScript ("OnUpdate", InjectOnUpdateEnter)
+ end
+
+ if (self.CoolTip.OnEnterFunc) then
+ self.CoolTip.OnEnterFunc()
+ end
+
+ if (self.OldOnEnterScript) then
+ self:OldOnEnterScript()
+ end
+ end
+
+ function CoolTip:CoolTipInject (host, openOnClick)
+ if (host.dframework) then
+ if (not host.widget.CoolTip) then
+ host.widget.CoolTip = host.CoolTip
+ end
+ host = host.widget
+ end
+
+ local coolTable = host.CoolTip
+ if (not coolTable) then
+ print ("Host nao tem uma CoolTable.")
+ return false
+ end
+
+ host.OldOnEnterScript = host:GetScript ("OnEnter")
+ host.OldOnLeaveScript = host:GetScript ("OnLeave")
+
+ host:SetScript ("OnEnter", InjectOnEnter)
+ host:SetScript ("OnLeave", InjectOnLeave)
+
+ if (openOnClick) then
+ if (host:GetObjectType() == "Button") then
+ host:SetScript ("OnClick", function() CoolTip:ExecFunc (host, true) end)
+ end
+ end
+
+ return ture
+ end
+
+ --> all done
+ CoolTip:ClearAllOptions()
+
+ return CoolTip
+end
\ No newline at end of file
diff --git a/framework/cooltip.xml b/framework/cooltip.xml
new file mode 100644
index 00000000..a6791c24
--- /dev/null
+++ b/framework/cooltip.xml
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetBackdropColor (0.09019, 0.09019, 0.18823, 1)
+ self:SetBackdropBorderColor (1, 1, 1, 1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/dropdown.lua b/framework/dropdown.lua
new file mode 100644
index 00000000..5d21e518
--- /dev/null
+++ b/framework/dropdown.lua
@@ -0,0 +1,771 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local _setmetatable = setmetatable --> lua local
+local _unpack = unpack --> lua local
+local _type = type --> lua local
+local _math_floor = math.floor --> lua local
+local loadstring = loadstring --> lua local
+local _string_len = string.len --> lua local
+
+local cleanfunction = function() end
+local APIDropDownFunctions = false
+local DropDownMetaFunctions = {}
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ DropDownMetaFunctions.__call = function (_table, value)
+ --> unknow
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> selected value
+ local gmember_value = function (_object)
+ return _object:GetValue()
+ end
+ --> tooltip
+ local gmember_tooltip = function (_object)
+ return _object:GetTooltip()
+ end
+ --> shown
+ local gmember_shown = function (_object)
+ return _object:IsShown()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.button:GetWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.button:GetHeight()
+ end
+ --> current text
+ local gmember_text = function (_object)
+ return _object.label:GetText()
+ end
+ --> menu creation function
+ local gmember_function = function (_object)
+ return _object:GetFunction()
+ end
+ --> menu width
+ local gmember_menuwidth = function (_object)
+ return _rawget (self, "realsizeW")
+ end
+ --> menu height
+ local gmember_menuheight = function (_object)
+ return _rawget (self, "realsizeH")
+ end
+
+ local get_members_function_index = {
+ ["value"] = gmember_value,
+ ["text"] = gmember_text,
+ ["shown"] = gmember_shown,
+ ["width"] = gmember_width,
+ ["menuwidth"] = gmember_menuwidth,
+ ["height"] = gmember_height,
+ ["menuheight"] = gmember_menuheight,
+ ["tooltip"] = gmember_tooltip,
+ ["func"] = gmember_function,
+ }
+
+ DropDownMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return DropDownMetaFunctions [_member_requested]
+ end
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> tooltip
+ local smember_tooltip = function (_object, _value)
+ return _object:SetTooltip (_value)
+ end
+ --> show
+ local smember_show = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (not _value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> frame width
+ local smember_width = function (_object, _value)
+ return _object.dropdown:SetWidth (_value)
+ end
+ --> frame height
+ local smember_height = function (_object, _value)
+ return _object.dropdown:SetHeight (_value)
+ end
+ --> menu creation function
+ local smember_function = function (_object, _value)
+ return _object:SetFunction (_value)
+ end
+ --> menu width
+ local smember_menuwidth = function (_object, _value)
+ _object:SetMenuSize (_value, nil)
+ end
+ --> menu height
+ local smember_menuheight = function (_object, _value)
+ _object:SetMenuSize (nil, _value)
+ end
+
+ local set_members_function_index = {
+ ["tooltip"] = smember_tooltip,
+ ["show"] = smember_show,
+ ["hide"] = smember_hide,
+ ["width"] = smember_width,
+ ["menuwidth"] = smember_menuwidth,
+ ["height"] = smember_height,
+ ["menuheight"] = smember_menuheight,
+ ["func"] = smember_function,
+ }
+
+ DropDownMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+ function DropDownMetaFunctions:IsShown()
+ return self.dropdown:IsShown()
+ end
+ function DropDownMetaFunctions:Show()
+ return self.dropdown:Show()
+ end
+ function DropDownMetaFunctions:Hide()
+ return self.dropdown:Hide()
+ end
+
+--> menu width and height
+ function DropDownMetaFunctions:SetMenuSize (w, h)
+ if (w) then
+ return _rawset (self, "realsizeW", w)
+ end
+ if (h) then
+ return _rawset (self, "realsizeH", h)
+ end
+ end
+ function DropDownMetaFunctions:GetMenuSize()
+ return _rawget (self, "realsizeW"), _rawget (self, "realsizeH")
+ end
+
+--> function
+ function DropDownMetaFunctions:SetFunction (func)
+ return _rawset (self, "func", func)
+ end
+ function DropDownMetaFunctions:GetFunction()
+ return _rawget (self, "func")
+ end
+
+--> value
+ function DropDownMetaFunctions:GetValue()
+ return _rawget (self, "myvalue")
+ end
+ function DropDownMetaFunctions:SetValue (value)
+ return _rawset (self, "myvalue", value)
+ end
+
+--> setpoint
+ function DropDownMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+ end
+
+--> sizes
+ function DropDownMetaFunctions:SetSize (w, h)
+ if (w) then
+ self.dropdown:SetWidth (w)
+ end
+ if (h) then
+ return self.dropdown:SetHeight (h)
+ end
+ end
+
+--> tooltip
+ function DropDownMetaFunctions:SetTooltip (tooltip)
+ if (tooltip) then
+ return _rawset (self, "have_tooltip", tooltip)
+ else
+ return _rawset (self, "have_tooltip", nil)
+ end
+ end
+ function DropDownMetaFunctions:GetTooltip()
+ return _rawget (self, "have_tooltip")
+ end
+
+--> frame levels
+ function DropDownMetaFunctions:GetFrameLevel()
+ return self.dropdown:GetFrameLevel()
+ end
+ function DropDownMetaFunctions:SetFrameLevel (level, frame)
+ if (not frame) then
+ return self.dropdown:SetFrameLevel (level)
+ else
+ local framelevel = frame:GetFrameLevel (frame) + level
+ return self.dropdown:SetFrameLevel (framelevel)
+ end
+ end
+
+--> frame stratas
+ function DropDownMetaFunctions:SetFrameStrata()
+ return self.dropdown:GetFrameStrata()
+ end
+ function DropDownMetaFunctions:SetFrameStrata (strata)
+ if (_type (strata) == "table") then
+ self.dropdown:SetFrameStrata (strata:GetFrameStrata())
+ else
+ self.dropdown:SetFrameStrata (strata)
+ end
+ end
+
+--> enabled
+ function DropDownMetaFunctions:IsEnabled()
+ return self.dropdown:IsEnabled()
+ end
+ function DropDownMetaFunctions:Enable()
+ return self.dropdown:Enable()
+ end
+ function DropDownMetaFunctions:Disable()
+ return self.dropdown:Disable()
+ end
+
+--> fixed value
+ function DropDownMetaFunctions:SetFixedParameter (value)
+ _rawset (self, "FixedValue", value)
+ end
+
+--> hooks
+ function DropDownMetaFunctions:SetHook (hookType, func)
+ if (func) then
+ _rawset (self, hookType.."Hook", func)
+ else
+ _rawset (self, hookType.."Hook", nil)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> scripts
+
+local function isOptionVisible (thisOption)
+ if (_type (thisOption.shown) == "boolean" or _type (thisOption.shown) == "function") then
+ if (not thisOption.shown) then
+ return false
+ elseif (not thisOption.shown()) then
+ return false
+ end
+ end
+ return true
+end
+
+function DropDownMetaFunctions:Select (optionName, byOptionNumber)
+ local menu = self.func()
+
+ if (byOptionNumber and type (optionName) == "number") then
+ return self:Selected (menu [optionName])
+ end
+
+ for _, thisMenu in ipairs (menu) do
+ if (thisMenu.label == optionName and isOptionVisible (thisMenu)) then
+ return self:Selected (thisMenu)
+ end
+ end
+end
+
+function DropDownMetaFunctions:Selected (_table)
+
+ self.label:SetText (_table.label)
+ self.icon:SetTexture (_table.icon)
+
+ if (_table.icon) then
+ self.label:SetPoint ("left", self.icon, "right", 2, 0)
+ if (_table.texcoord) then
+ self.icon:SetTexCoord (unpack (_table.texcoord))
+ else
+ self.icon:SetTexCoord (0, 1, 0, 1)
+ end
+ else
+ self.label:SetPoint ("left", self.label:GetParent(), "left", 4, 0)
+ end
+
+ self.statusbar:SetTexture (_table.statusbar)
+
+ if (_table.color) then
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_table.color)
+ self.label:SetTextColor (_value1, _value2, _value3, _value4)
+ else
+ self.label:SetTextColor (1, 1, 1, 1)
+ end
+
+ if (_table.font) then
+ self.label:SetFont (_table.font, 10.5)
+ else
+ self.label:SetFont ("GameFontHighlightSmall", 10.5)
+ end
+
+ self:SetValue (_table.value)
+
+end
+
+function DetailsDropDownOptionClick (button)
+
+ --> update name and icon on main frame
+ button.object:Selected (button.table)
+
+ --> close menu frame
+ button.object:Close()
+
+ --> exec function if any
+ if (button.table.onclick) then
+ button.table.onclick (button:GetParent():GetParent():GetParent().MyObject, button.object.FixedValue, button.table.value)
+ end
+
+ --> set the value of selected option in main object
+ button.object.myvalue = button.table.value
+end
+
+function DropDownMetaFunctions:Open()
+ self.dropdown.dropdownframe:Show()
+ self.dropdown.dropdownborder:Show()
+ self.dropdown.arrowTexture:SetTexture ("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Down")
+ self.opened = true
+end
+
+function DropDownMetaFunctions:Close()
+ --> when menu is being close, just hide the border and the script will call back this again
+ if (self.dropdown.dropdownborder:IsShown()) then
+ self.dropdown.dropdownborder:Hide()
+ return
+ end
+ self.dropdown.dropdownframe:Hide()
+ self.dropdown.arrowTexture:SetTexture ("Interface\\Buttons\\UI-ScrollBar-ScrollDownButton-Up")
+
+ local selectedTexture = _G [self:GetName() .. "_ScrollFrame_ScrollChild_SelectedTexture"]
+ selectedTexture:Hide()
+
+ self.opened = false
+end
+
+--> close by escape key
+function DetailsDropDownOptionsFrameOnHide (frame)
+ frame:GetParent().MyObject:Close()
+end
+
+function DetailsDropDownOptionOnEnter (frame)
+ if (frame.table.desc) then
+ GameCooltip:Reset()
+ GameCooltip:SetType ("tooltip")
+ GameCooltip:SetColor ("main", "transparent")
+ GameCooltip:AddLine (frame.table.desc)
+ GameCooltip:SetOwner (frame:GetParent():GetParent():GetParent())
+ GameCooltip:ShowCooltip()
+ frame.tooltip = true
+ end
+ frame:GetParent().mouseover:SetPoint ("left", frame)
+ frame:GetParent().mouseover:Show()
+end
+
+function DetailsDropDownOptionOnLeave (frame)
+ if (frame.table.desc) then
+ _detalhes.popup:ShowMe (false)
+ end
+ frame:GetParent().mouseover:Hide()
+end
+
+function DetailsDropDownOnMouseDown (button)
+
+ local object = button.MyObject
+
+ if (not object.opened) then --> click to open
+
+ local menu = object:func()
+ local frame_witdh = object.realsizeW
+
+ if (menu [1]) then
+ --> build menu
+
+ local scrollFrame = _G [button:GetName() .. "_ScrollFrame"]
+ local scrollChild = _G [button:GetName() .. "_ScrollFrame_ScrollChild"]
+ local scrollBorder = _G [button:GetName() .. "_Border"]
+ local selectedTexture = _G [button:GetName() .. "_ScrollFrame_ScrollChild_SelectedTexture"]
+ local mouseOverTexture = _G [button:GetName() .. "_ScrollFrame_ScrollChild_MouseOverTexture"]
+
+ local i = 1
+ local showing = 0
+ local currentText = button.text:GetText() or ""
+
+ if (object.OnMouseDownHook) then
+ local interrupt = object.OnMouseDownHook (button, buttontype, menu, scrollFrame, scrollChild, selectedTexture)
+ if (interrupt) then
+ return
+ end
+ end
+
+ for _, _table in ipairs (menu) do
+
+ local show = isOptionVisible (_table)
+
+ if (show) then
+ local _this_row = object.menus [i]
+ showing = showing + 1
+
+ if (not _this_row) then
+
+ local name = button:GetName() .. "Row" .. i
+ local parent = scrollChild
+
+ _this_row = CreateFrame ("Button", name, parent, "DetailsDropDownOptionTemplate")
+ local anchor_i = i-1
+ _this_row:SetPoint ("topleft", parent, "topleft", 5, (-anchor_i*20)-5)
+ _this_row:SetPoint ("topright", parent, "topright", -5, (-anchor_i*20)-5)
+ _this_row.object = object
+ object.menus [i] = _this_row
+ end
+
+ _this_row.icon:SetTexture (_table.icon)
+ if (_table.icon) then
+ _this_row.label:SetPoint ("left", _this_row.icon, "right", 5, 0)
+ if (_table.texcoord) then
+ _this_row.icon:SetTexCoord (unpack (_table.texcoord))
+ else
+ _this_row.icon:SetTexCoord (0, 1, 0, 1)
+ end
+ else
+ _this_row.label:SetPoint ("left", _this_row.statusbar, "left", 2, 0)
+ end
+
+ if (_table.font) then
+ _this_row.label:SetFont (_table.font, 10.5)
+ else
+ _this_row.label:SetFont ("GameFontHighlightSmall", 10.5)
+ end
+
+ _this_row.statusbar:SetTexture (_table.statusbar)
+ _this_row.label:SetText (_table.label)
+
+ if (currentText and currentText == _table.label) then
+ if (_table.icon) then
+ selectedTexture:SetPoint ("left", _this_row.icon, "right", -5, -2)
+ else
+ selectedTexture:SetPoint ("left", _this_row.statusbar, "left", 0, 0)
+ end
+
+ selectedTexture:Show()
+ selectedTexture:SetVertexColor (1, 1, 1, .3);
+ currentText = nil
+ end
+
+ if (_table.color) then
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_table.color)
+ _this_row.label:SetTextColor (_value1, _value2, _value3, _value4)
+ else
+ _this_row.label:SetTextColor (1, 1, 1, 1)
+ end
+
+ _this_row.table = _table
+
+ local labelwitdh = _this_row.label:GetStringWidth()
+ if (labelwitdh+40 > frame_witdh) then
+ frame_witdh = labelwitdh+40
+ end
+ _this_row:Show()
+
+ i = i + 1
+ end
+
+ end
+
+ if (currentText) then
+ selectedTexture:Hide()
+ else
+ selectedTexture:SetWidth (frame_witdh-20)
+ end
+
+ for i = showing+1, #object.menus do
+ object.menus [i]:Hide()
+ end
+
+ local size = object.realsizeH
+
+ if (showing*20 > size) then
+ --show scrollbar and setup scroll
+ object:ShowScroll()
+ scrollFrame:EnableMouseWheel (true)
+ object.scroll:Altura (size-35)
+ object.scroll:SetMinMaxValues (0, (showing*20) - size + 20)
+ --width
+ scrollBorder:SetWidth (frame_witdh+20)
+ scrollFrame:SetWidth (frame_witdh+20)
+ scrollChild:SetWidth (frame_witdh+20)
+ --height
+ scrollBorder:SetHeight (size+20)
+ scrollFrame:SetHeight (size)
+ scrollChild:SetHeight ((showing*20)+20)
+ --mouse over texture
+ mouseOverTexture:SetWidth (frame_witdh-7)
+
+ for index, row in ipairs (object.menus) do
+ row:SetPoint ("topright", scrollChild, "topright", -22, ((-index-1)*20)-5)
+ end
+
+ else
+ --hide scrollbar and disable wheel
+ object:HideScroll()
+ scrollFrame:EnableMouseWheel (false)
+ --width
+ scrollBorder:SetWidth (frame_witdh)
+ scrollFrame:SetWidth (frame_witdh)
+ scrollChild:SetWidth (frame_witdh)
+ --height
+ scrollBorder:SetHeight ((showing*20) + 25)
+ scrollFrame:SetHeight ((showing*20) + 25)
+ --mouse over texture
+ mouseOverTexture:SetWidth (frame_witdh-10)
+
+ for index, row in ipairs (object.menus) do
+ row:SetPoint ("topright", scrollChild, "topright", -5, ((-index-1)*20)-5)
+ end
+ end
+
+ object.scroll:SetValue (0)
+ object:Open()
+
+ else
+ --> clear menu
+
+ end
+
+ else --> click to close
+
+ object:Close()
+ end
+
+end
+
+function DetailsDropDownOnEnter (self)
+
+ if (self.MyObject.OnEnterHook) then
+ local interrupt = self.MyObject.OnEnterHook (self)
+ if (interrupt) then
+ return
+ end
+ end
+
+ self:SetBackdropColor (.2, .2, .2, .2)
+ self.arrowTexture2:Show()
+
+ if (self.MyObject.have_tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:SetType ("tooltip")
+ GameCooltip:SetColor ("main", "transparent")
+ GameCooltip:AddLine (self.MyObject.have_tooltip)
+ GameCooltip:SetOwner (self)
+ GameCooltip:ShowCooltip()
+ end
+
+ local parent = self:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient()
+ end
+ end
+
+end
+
+function DetailsDropDownOnLeave (self)
+ self:SetBackdropColor (1, 1, 1, .5)
+ self.arrowTexture2:Hide()
+
+ if (self.MyObject.OnLeaveHook) then
+ local interrupt = self.MyObject.OnLeaveHook (self)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (self.MyObject.have_tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+
+ local parent = self:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient (false)
+ end
+ end
+end
+
+function DetailsDropDownOnSizeChanged (self, w, h)
+ self.MyObject.label:SetSize (self:GetWidth()-40, 10)
+end
+
+function DetailsDropDownOnShow (self)
+ if (self.MyObject and self.MyObject.OnShowHook) then
+ local interrupt = self.MyObject.OnShowHook (self)
+ if (interrupt) then
+ return
+ end
+ end
+end
+
+function DetailsDropDownOnHide (self)
+ if (self.MyObject and self.MyObject.OnHideHook) then
+ local interrupt = self.MyObject.OnHideHook (self)
+ if (interrupt) then
+ return
+ end
+ end
+
+ self.MyObject:Close()
+end
+
+
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+
+function gump:NewDropDown (parent, container, name, member, w, h, func, default)
+
+ if (not name) then
+ return nil
+ elseif (not parent) then
+ return nil
+ end
+ if (not container) then
+ container = parent
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+ local DropDownObject = {type = "dropdown", dframework = true}
+
+ if (member) then
+ parent [member] = DropDownObject
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+ default = default or 1
+
+ --> default members:
+ --> hooks
+ DropDownObject.OnEnterHook = nil
+ DropDownObject.OnLeaveHook = nil
+ DropDownObject.OnHideHook = nil
+ DropDownObject.OnShowHook = nil
+ DropDownObject.OnMouseDownHook = nil
+ --> misc
+ DropDownObject.container = container
+ DropDownObject.have_tooltip = nil
+
+ DropDownObject.dropdown = CreateFrame ("Button", name, parent, "DetailsDropDownTemplate")
+ DropDownObject.widget = DropDownObject.dropdown
+ --_G [name] = DropDownObject
+
+ if (not APIDropDownFunctions) then
+ APIDropDownFunctions = true
+ local idx = getmetatable (DropDownObject.dropdown).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not DropDownMetaFunctions [funcName]) then
+ DropDownMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.dropdown:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ DropDownObject.dropdown.MyObject = DropDownObject
+
+ DropDownObject.dropdown:SetWidth (w)
+ DropDownObject.dropdown:SetHeight (h)
+
+ DropDownObject.func = func
+ DropDownObject.realsizeW = 150
+ DropDownObject.realsizeH = 150
+ DropDownObject.FixedValue = nil
+ DropDownObject.opened = false
+ DropDownObject.menus = {}
+ DropDownObject.myvalue = nil
+
+ DropDownObject.label = _G [name .. "_Text"]
+
+ DropDownObject.icon = _G [name .. "_IconTexture"]
+ DropDownObject.statusbar = _G [name .. "_StatusBarTexture"]
+ DropDownObject.select = _G [name .. "_SelectedTexture"]
+
+ local scroll = _G [DropDownObject.dropdown:GetName() .. "_ScrollFrame"]
+
+ DropDownObject.scroll = gump:NewScrollBar (scroll, _G [DropDownObject.dropdown:GetName() .. "_ScrollFrame".."_ScrollChild"], -20, -18)
+
+ function DropDownObject:HideScroll()
+ scroll.baixo:Hide()
+ scroll.cima:Hide()
+ scroll.slider:Hide()
+ end
+ function DropDownObject:ShowScroll()
+ scroll.baixo:Show()
+ scroll.cima:Show()
+ scroll.slider:Show()
+ end
+
+ DropDownObject:HideScroll()
+ DropDownObject.label:SetSize (DropDownObject.dropdown:GetWidth()-40, 10)
+
+ --> setup class
+ _setmetatable (DropDownObject, DropDownMetaFunctions)
+
+ --> initialize first menu selected
+ local menu = func()
+ for i = default, #menu do
+ local _table = menu [i]
+ if (not _table) then
+ break
+ end
+ if (isOptionVisible (_table)) then
+ DropDownObject:Selected (_table)
+ break
+ end
+ end
+
+ return DropDownObject
+
+end
\ No newline at end of file
diff --git a/framework/dropdown.xml b/framework/dropdown.xml
new file mode 100644
index 00000000..e1bc17f8
--- /dev/null
+++ b/framework/dropdown.xml
@@ -0,0 +1,238 @@
+
+
+
+
+
+
+
+
+
diff --git a/framework/framework.lua b/framework/framework.lua
new file mode 100644
index 00000000..b3a0fce5
--- /dev/null
+++ b/framework/framework.lua
@@ -0,0 +1,111 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _type = type
+local _unpack = unpack
+
+gump.LabelNameCounter = 1
+gump.PictureNameCounter = 1
+
+gump.debug = false
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> points
+function gump:CheckPoints (v1, v2, v3, v4, v5, object)
+
+ --bg_esq:SetPoint ("topleft", DmgRankFrame, 10, -215)
+
+ if (not v1 and not v2) then
+ return "topleft", object.widget:GetParent(), "topleft", 0, 0
+ end
+
+ if (_type (v1) == "string") then
+ local frameGlobal = _G [v1]
+ if (frameGlobal and frameGlobal.GetObjectType) then
+ return gump:CheckPoints (frameGlobal, v2, v3, v4, v5, object)
+ end
+
+ elseif (_type (v2) == "string") then
+ local frameGlobal = _G [v2]
+ if (frameGlobal and frameGlobal.GetObjectType) then
+ return gump:CheckPoints (v1, frameGlobal, v3, v4, v5, object)
+ end
+ end
+
+ if (_type (v1) == "string" and _type (v2) == "table") then --> :setpoint ("left", frame, _, _, _)
+ if (not v3 or _type (v3) == "number") then --> :setpoint ("left", frame, 10, 10)
+ v1, v2, v3, v4, v5 = v1, v2, v1, v3, v4
+ --else
+ --> :setpoint ("left", frame, "left", 10, 10)
+ end
+
+ elseif (_type (v1) == "string" and _type (v2) == "number") then --> :setpoint ("topleft", x, y)
+ v1, v2, v3, v4, v5 = v1, object.widget:GetParent(), v1, v2, v3
+
+ elseif (_type (v1) == "number") then --> :setpoint (x, y)
+ v1, v2, v3, v4, v5 = "topleft", object.widget:GetParent(), "topleft", v1, v2
+
+ elseif (_type (v1) == "table") then --> :setpoint (frame, x, y)
+ v1, v2, v3, v4, v5 = "topleft", v1, "topleft", v2, v3
+
+ end
+
+ if (not v2) then
+ v2 = object.widget:GetParent()
+ elseif (v2.dframework) then
+ v2 = v2.widget
+ end
+
+ return v1 or "topleft", v2, v3 or "topleft", v4 or 0, v5 or 0
+end
+
+
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> color scheme
+
+function gump:NewColor (_colorname, _colortable, _green, _blue, _alpha)
+
+ if (_type (_colorname) ~= "string") then
+ return _detalhes:NewError ("color name must be a string.")
+ end
+
+ if (gump.alias_text_colors [_colorname]) then
+ return _detalhes:NewError (_colorname .. " already exists.")
+ end
+
+ if (_type (_colortable) == "table") then
+ if (_colortable[1] and _colortable[2] and _colortable[3]) then
+ _colortable[4] = _colortable[4] or 1
+ gump.alias_text_colors [_colorname] = _colortable
+ else
+ return _detalhes:NewError ("invalid color table.")
+ end
+ elseif (_colortable and _green and _blue) then
+ _alpha = _alpha or 1
+ gump.alias_text_colors [_colorname] = {_colortable, _green, _blue, _alpha}
+ else
+ return _detalhes:NewError ("invalid parameter.")
+ end
+
+ return true
+end
+
+function gump:ParseColors (_arg1, _arg2, _arg3, _arg4)
+ if (_type (_arg1) == "table") then
+ _arg1, _arg2, _arg3, _arg4 = _unpack (_arg1)
+ elseif (_type (_arg1) == "string") then
+ local color = gump.alias_text_colors [_arg1]
+ if (color) then
+ _arg1, _arg2, _arg3, _arg4 = _unpack (color)
+ else
+ _arg1, _arg2, _arg3, _arg4 = _unpack (gump.alias_text_colors.none)
+ end
+ end
+
+ if (not _arg4) then
+ _arg4 = 1
+ end
+
+ return _arg1, _arg2, _arg3, _arg4
+end
\ No newline at end of file
diff --git a/framework/help.lua b/framework/help.lua
new file mode 100644
index 00000000..92e39aef
--- /dev/null
+++ b/framework/help.lua
@@ -0,0 +1,117 @@
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local APIHelpFunctions = false
+local HelpMetaFunctions = {}
+
+ local get_members_function_index = {}
+
+ HelpMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return HelpMetaFunctions [_member_requested]
+ end
+
+ local set_members_function_index = {}
+
+ HelpMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+function HelpMetaFunctions:AddHelp (width, height, x, y, buttonX, buttonY, text, anchor)
+ self.helpTable [#self.helpTable + 1] = {
+ HighLightBox = {x = x, y = y, width = width, height = height},
+ ButtonPos = { x = buttonX, y = buttonY},
+ ToolTipDir = anchor or "RIGHT",
+ ToolTipText = text
+ }
+end
+
+function HelpMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+end
+
+function HelpMetaFunctions:ShowHelp()
+ if (not HelpPlate_IsShowing (self.helpTable)) then
+ HelpPlate_Show (self.helpTable, self.frame, self.button, true)
+ else
+ HelpPlate_Hide (true)
+ end
+end
+
+local nameCounter = 1
+function _detalhes.gump:NewHelp (parent, width, height, x, y, buttonWidth, buttonHeight, name)
+
+ local help = {}
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+
+ local helpButton = CreateFrame ("button", name or "DetailsHelpButton"..nameCounter, parent, "MainHelpPlateButton")
+ nameCounter = nameCounter + 1
+
+ if (not APIHelpFunctions) then
+ APIHelpFunctions = true
+ local idx = getmetatable (helpButton).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not HelpMetaFunctions [funcName]) then
+ HelpMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.button:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ if (buttonWidth and buttonHeight) then
+ helpButton:SetWidth (buttonWidth)
+ helpButton:SetHeight (buttonHeight)
+ helpButton.I:SetWidth (buttonWidth*0.8)
+ helpButton.I:SetHeight (buttonHeight*0.8)
+ helpButton.Ring:SetWidth (buttonWidth)
+ helpButton.Ring:SetHeight (buttonHeight)
+ helpButton.Ring:SetPoint ("center", buttonWidth*.2, -buttonWidth*.2)
+ end
+
+ help.helpTable = {
+ FramePos = {x = x, y = y},
+ FrameSize = {width = width, height = height}
+ }
+
+ help.frame = parent
+ help.button = helpButton
+ help.widget = helpButton
+ help.I = helpButton.I
+ help.Ring = helpButton.Ring
+
+ helpButton:SetScript ("OnClick", function()
+ help:ShowHelp()
+ end)
+
+ setmetatable (help, HelpMetaFunctions)
+
+ return help
+
+end
\ No newline at end of file
diff --git a/framework/label.lua b/framework/label.lua
new file mode 100644
index 00000000..d7101180
--- /dev/null
+++ b/framework/label.lua
@@ -0,0 +1,259 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local _setmetatable = setmetatable --> lua local
+local _unpack = unpack --> lua local
+local _type = type --> lua local
+local _math_floor = math.floor --> lua local
+local loadstring = loadstring --> lua local
+
+local cleanfunction = function() end
+local APILabelFunctions = false
+local LabelMetaFunctions = {}
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ LabelMetaFunctions.__call = function (_table, value)
+ return self.label:SetText (value)
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> shown
+ local gmember_shown = function (_object)
+ return _object:IsShown()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.label:GetStringWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.label:GetStringHeight()
+ end
+ --> text
+ local gmember_text = function (_object)
+ return _object.label:GetText()
+ end
+ --> text color
+ local gmember_textcolor = function (_object)
+ return _object.label:GetTextColor()
+ end
+ --> text font
+ local gmember_textfont = function (_object)
+ local fontface = _object.label:GetFont()
+ return fontface
+ end
+ --> text size
+ local gmember_textsize = function (_object)
+ local _, fontsize = _object.label:GetFont()
+ return fontsize
+ end
+
+
+ local get_members_function_index = {
+ ["shown"] = gmember_shown,
+ ["width"] = gmember_width,
+ ["height"] = gmember_height,
+ ["text"] = gmember_text,
+ ["fontcolor"] = gmember_textcolor,
+ ["fontface"] = gmember_textfont,
+ ["fontsize"] = gmember_textsize,
+ ["textcolor"] = gmember_textcolor, --alias
+ ["textfont"] = gmember_textfont, --alias
+ ["textsize"] = gmember_textsize --alias
+ }
+
+ LabelMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return LabelMetaFunctions [_member_requested]
+ end
+
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> show
+ local smember_show = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (not _value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> text
+ local smember_text = function (_object, _value)
+ return _object.label:SetText (_value)
+ end
+ --> text color
+ local smember_textcolor = function (_object, _value)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_value)
+ return _object.label:SetTextColor (_value1, _value2, _value3, _value4)
+ end
+ --> text font
+ local smember_textfont = function (_object, _value)
+ return _detalhes:SetFontFace (_object.label, _value)
+ end
+ --> text size
+ local smember_textsize = function (_object, _value)
+ return _detalhes:SetFontSize (_object.label, _value)
+ end
+ --> text align
+ local smember_textalign = function (_object, _value)
+ if (_value == "<") then
+ _value = "left"
+ elseif (_value == ">") then
+ _value = "right"
+ elseif (_value == "|") then
+ _value = "center"
+ end
+ return _object.label:SetJustifyH (_value)
+ end
+ --> field size width
+ local smember_width = function (_object, _value)
+ return _object.label:SetWidth (_value)
+ end
+ --> field size height
+ local smember_height = function (_object, _value)
+ return _object.label:SetHeight (_value)
+ end
+
+ local set_members_function_index = {
+ ["show"] = smember_show,
+ ["hide"] = smember_hide,
+ ["align"] = smember_textalign,
+ ["text"] = smember_text,
+ ["width"] = smember_width,
+ ["height"] = smember_height,
+ ["fontcolor"] = smember_textcolor,
+ ["color"] = smember_textcolor,
+ ["fontface"] = smember_textfont,
+ ["fontsize"] = smember_textsize,
+ ["textcolor"] = smember_textcolor,
+ ["textfont"] = smember_textfont,
+ ["textsize"] = smember_textsize
+ }
+
+ LabelMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+
+--> show & hide
+ function LabelMetaFunctions:IsShown()
+ return self.label:IsShown()
+ end
+ function LabelMetaFunctions:Show()
+ return self.label:Show()
+ end
+ function LabelMetaFunctions:Hide()
+ return self.label:Hide()
+ end
+
+-- setpoint
+ function LabelMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+
+function gump:NewLabel (parent, container, name, member, text, font, size, color)
+
+ if (not parent) then
+ return nil
+ end
+ if (not container) then
+ container = parent
+ end
+
+ if (not name) then
+ name = "DetailsLabelNumber" .. gump.LabelNameCounter
+ gump.LabelNameCounter = gump.LabelNameCounter + 1
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+ local LabelObject = {type = "label", dframework = true}
+
+ if (member) then
+ parent [member] = LabelObject
+ --container [member] = LabelObject.label
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+ font = font or "GameFontHighlightSmall"
+
+ LabelObject.label = parent:CreateFontString (name, "OVERLAY", font)
+ LabelObject.widget = LabelObject.label
+
+ if (not APILabelFunctions) then
+ APILabelFunctions = true
+ local idx = getmetatable (LabelObject.label).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not LabelMetaFunctions [funcName]) then
+ LabelMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.label:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ LabelObject.label:SetText (text)
+
+ if (size) then
+ _detalhes:SetFontSize (LabelObject.label, size)
+ end
+
+ if (color) then
+ LabelObject.label:SetTextColor (unpack (color))
+ end
+
+ LabelObject.label:SetJustifyH ("LEFT")
+
+ setmetatable (LabelObject, LabelMetaFunctions)
+
+ return LabelObject
+end
\ No newline at end of file
diff --git a/framework/normal_bar.lua b/framework/normal_bar.lua
new file mode 100644
index 00000000..a2446f5b
--- /dev/null
+++ b/framework/normal_bar.lua
@@ -0,0 +1,702 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua locals
+local _rawget = rawget --> lua locals
+local _setmetatable = setmetatable --> lua locals
+local _unpack = unpack --> lua locals
+local _type = type --> lua locals
+local _math_floor = math.floor --> lua locals
+
+local cleanfunction = function() end
+local BarMetaFunctions = {}
+local APIBarFunctions
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ BarMetaFunctions.__call = function (_table, value)
+ if (not value) then
+ return _table.statusbar:GetValue()
+ else
+ return _table.statusbar:SetValue (value)
+ end
+ end
+
+ BarMetaFunctions.__add = function (v1, v2)
+ if (_type (v1) == "table") then
+ local v = v1.statusbar:GetValue()
+ v = v + v2
+ v1.statusbar:SetValue (v)
+ else
+ local v = v2.statusbar:GetValue()
+ v = v + v1
+ v2.statusbar:SetValue (v)
+ end
+ end
+
+ BarMetaFunctions.__sub = function (v1, v2)
+ if (_type (v1) == "table") then
+ local v = v1.statusbar:GetValue()
+ v = v - v2
+ v1.statusbar:SetValue (v)
+ else
+ local v = v2.statusbar:GetValue()
+ v = v - v1
+ v2.statusbar:SetValue (v)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> tooltip
+ local function gmember_tooltip (_object)
+ return _object:GetTooltip()
+ end
+ --> shown
+ local gmember_shown = function (_object)
+ return _object.statusbar:IsShown()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.statusbar:GetWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.statusbar:GetHeight()
+ end
+ --> value
+ local gmember_value = function (_object)
+ return _object.statusbar:GetValue()
+ end
+ --> right text
+ local gmember_rtext = function (_object)
+ return _object.textright:GetText()
+ end
+ --> left text
+ local gmember_ltext = function (_object)
+ return _object.textleft:GetText()
+ end
+ --> left color
+ local gmember_color = function (_object)
+ return _object.texture.original_colors
+ end
+ --> icon
+ local gmember_icon = function (_object)
+ return _object.icon:GetTexture()
+ end
+ --> texture
+ local gmember_texture = function (_object)
+ return _object.texture:GetTexture()
+ end
+ --> font size
+ local gmember_textsize = function (_object)
+ local _, fontsize = _object.textleft:GetFont()
+ return fontsize
+ end
+ --> font face
+ local gmember_textfont = function (_object)
+ local fontface = _object.textleft:GetFont()
+ return fontface
+ end
+ --> font color
+ local gmember_textcolor = function (_object)
+ return _object.textleft:GetTextColor()
+ end
+
+ local get_members_function_index = {
+ ["tooltip"] = gmember_tooltip,
+ ["shown"] = gmember_shown,
+ ["width"] = gmember_width,
+ ["height"] = gmember_height,
+ ["value"] = gmember_value,
+ ["lefttext"] = gmember_ltext,
+ ["righttext"] = gmember_rtext,
+ ["color"] = gmember_color,
+ ["icon"] = gmember_icon,
+ ["texture"] = gmember_texture,
+ ["fontsize"] = gmember_textsize,
+ ["fontface"] = gmember_textfont,
+ ["fontcolor"] = gmember_textcolor,
+ ["textsize"] = gmember_textsize, --alias
+ ["textfont"] = gmember_textfont, --alias
+ ["textcolor"] = gmember_textcolor --alias
+ }
+
+ BarMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return BarMetaFunctions [_member_requested]
+ end
+
+
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+ --> tooltip
+ local smember_tooltip = function (_object, _value)
+ return _object:SetTooltip (_value)
+ end
+ --> show
+ local smember_shown = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (_value) then
+ return _object:Hide()
+ else
+ return _object:Show()
+ end
+ end
+ --> width
+ local smember_width = function (_object, _value)
+ return _object.statusbar:SetWidth (_value)
+ end
+ --> height
+ local smember_height = function (_object, _value)
+ return _object.statusbar:SetHeight (_value)
+ end
+ --> statusbar value
+ local smember_value = function (_object, _value)
+ _object.statusbar:SetValue (_value)
+ return _object.div:SetPoint ("left", _object.statusbar, "left", _value * (_object.statusbar:GetWidth()/100) - 16, 0)
+ end
+ --> right text
+ local smember_rtext = function (_object, _value)
+ return _object.textright:SetText (_value)
+ end
+ --> left text
+ local smember_ltext = function (_object, _value)
+ return _object.textleft:SetText (_value)
+ end
+ --> color
+ local smember_color = function (_object, _value)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_value)
+
+ _object.statusbar:SetStatusBarColor (_value1, _value2, _value3, _value4)
+ _object.texture.original_colors = {_value1, _value2, _value3, _value4}
+ return _object.texture:SetVertexColor (_value1, _value2, _value3, _value4)
+ end
+ --> icon
+ local smember_icon = function (_object, _value)
+ if (type (_value) == "table") then
+ local _value1, _value2 = _unpack (_value)
+ _object.icon:SetTexture (_value1)
+ if (_value2) then
+ _object.icon:SetTexCoord (_unpack (_value2))
+ end
+ else
+ _object.icon:SetTexture (_value)
+ end
+ return
+ end
+ --> texture
+ local smember_texture = function (_object, _value)
+ if (type (_value) == "table") then
+ local _value1, _value2 = _unpack (_value)
+ _object.texture:SetTexture (_value1)
+ if (_value2) then
+ _object.texture:SetTexCoord (_unpack (_value2))
+ end
+ else
+ _object.texture:SetTexture (_value)
+ end
+ return
+ end
+ --> font face
+ local smember_textfont = function (_object, _value)
+ _detalhes:SetFontFace (_object.textleft, _value)
+ return _detalhes:SetFontFace (_object.textright, _value)
+ end
+ --> font size
+ local smember_textsize = function (_object, _value)
+ _detalhes:SetFontSize (_object.textleft, _value)
+ return _detalhes:SetFontSize (_object.textright, _value)
+ end
+ --> font color
+ local smember_textcolor = function (_object, _value)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_value)
+ _object.textleft:SetTextColor (_value1, _value2, _value3, _value4)
+ return _object.textright:SetTextColor (_value1, _value2, _value3, _value4)
+ end
+
+ local set_members_function_index = {
+ ["tooltip"] = smember_tooltip,
+ ["shown"] = smember_shown,
+ ["width"] = smember_width,
+ ["height"] = smember_height,
+ ["value"] = smember_value,
+ ["righttext"] = smember_rtext,
+ ["lefttext"] = smember_ltext,
+ ["color"] = smember_color,
+ ["icon"] = smember_icon,
+ ["texture"] = smember_texture,
+ ["fontsize"] = smember_textsize,
+ ["fontface"] = smember_textfont,
+ ["fontcolor"] = smember_textcolor,
+ ["textsize"] = smember_textsize, --alias
+ ["textfont"] = smember_textfont, --alias
+ ["textcolor"] = smember_textcolor --alias
+ }
+
+ BarMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+
+--> show & hide
+ function BarMetaFunctions:Show()
+ self.statusbar:Show()
+ end
+ function BarMetaFunctions:Hide()
+ self.statusbar:Hide()
+ end
+
+--> set value (status bar)
+ function BarMetaFunctions:SetValue (value)
+ if (not value) then
+ value = 0
+ end
+ self.statusbar:SetValue (value)
+ self.div:SetPoint ("left", self.statusbar, "left", value * (self.statusbar:GetWidth()/100) - 16, 0)
+ end
+
+--> set point
+ function BarMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+ end
+
+--> set sizes
+ function BarMetaFunctions:SetSize (w, h)
+ if (w) then
+ self.statusbar:SetWidth (w)
+ end
+ if (h) then
+ self.statusbar:SetHeight (h)
+ end
+ end
+
+--> set texture
+ function BarMetaFunctions:SetTexture (texture)
+ self.texture:SetTexture (texture)
+ end
+
+--> set texts
+ function BarMetaFunctions:SetLeftText (text)
+ self.textleft:SetText (text)
+ end
+ function BarMetaFunctions:SetRightText (text)
+ self.textright:SetText (text)
+ end
+
+--> set color
+ function BarMetaFunctions:SetColor (r, g, b, a)
+ r, g, b, a = gump:ParseColors (r, g, b, a)
+
+ self.texture:SetVertexColor (r, g, b, a)
+ self.statusbar:SetStatusBarColor (r, g, b, a)
+ self.texture.original_colors = {r, g, b, a}
+ end
+
+--> set icons
+ function BarMetaFunctions:SetIcon (texture, ...)
+ self.icon:SetTexture (texture)
+ if (...) then
+ local L, R, U, D = _unpack (...)
+ self.icon:SetTexCoord (L, R, U, D)
+ end
+ end
+
+--> show div
+ function BarMetaFunctions:ShowDiv (bool)
+ if (bool) then
+ self.div:Show()
+ else
+ self.div:Hide()
+ end
+ end
+
+-- tooltip
+ function BarMetaFunctions:SetTooltip (tooltip)
+ if (tooltip) then
+ return _rawset (self, "have_tooltip", tooltip)
+ else
+ return _rawset (self, "have_tooltip", nil)
+ end
+ end
+ function BarMetaFunctions:GetTooltip()
+ return _rawget (self, "have_tooltip")
+ end
+
+-- frame levels
+ function BarMetaFunctions:GetFrameLevel()
+ return self.statusbar:GetFrameLevel()
+ end
+ function BarMetaFunctions:SetFrameLevel (level, frame)
+ if (not frame) then
+ return self.statusbar:SetFrameLevel (level)
+ else
+ local framelevel = frame:GetFrameLevel (frame) + level
+ return self.statusbar:SetFrameLevel (framelevel)
+ end
+ end
+
+-- frame stratas
+ function BarMetaFunctions:SetFrameStrata()
+ return self.statusbar:GetFrameStrata()
+ end
+ function BarMetaFunctions:SetFrameStrata (strata)
+ if (_type (strata) == "table") then
+ self.statusbar:SetFrameStrata (strata:GetFrameStrata())
+ else
+ self.statusbar:SetFrameStrata (strata)
+ end
+ end
+
+--> container
+ function BarMetaFunctions:SetContainer (container)
+ self.container = container
+ end
+
+--> hooks
+ function BarMetaFunctions:SetHook (hookType, func)
+ if (func) then
+ if (hookType == "OnEnterHook") then
+ self.OnEnterHook = func
+ return true
+ elseif (hookType == "OnLeaveHook") then
+ self.OnLeaveHook = func
+ return true
+ elseif (hookType == "OnHideHook") then
+ self.OnHideHook = func
+ return true
+ elseif (hookType == "OnShowHook") then
+ self.OnShowHook = func
+ return true
+ elseif (hookType == "OnMouseDownHook") then
+ self.OnMouseDownHook = func
+ return true
+ elseif (hookType == "OnMouseUpHook") then
+ self.OnMouseUpHook = func
+ return true
+ end
+ else
+ if (hookType == "OnEnterHook") then
+ self.OnEnterHook = nil
+ return true
+ elseif (hookType == "OnLeaveHook") then
+ self.OnLeaveHook = nil
+ return true
+ elseif (hookType == "OnHideHook") then
+ self.OnHideHook = nil
+ return true
+ elseif (hookType == "OnShowHook") then
+ self.OnShowHook = nil
+ return true
+ elseif (hookType == "OnMouseDownHook") then
+ self.OnMouseDownHook = nil
+ return true
+ elseif (hookType == "OnMouseUpHook") then
+ self.OnMouseUpHook = nil
+ return true
+ end
+ end
+ return false
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> scripts
+
+ local OnEnter = function (frame)
+ if (frame.MyObject.OnEnterHook) then
+ local interrupt = frame.MyObject.OnEnterHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (not frame.MyObject.timer) then
+ local oc = frame.MyObject.texture.original_colors --original colors
+ gump:GradientEffect ( frame.MyObject.texture, "texture", oc[1], oc[2], oc[3], oc[4], oc[1]+0.2, oc[2]+0.2, oc[3]+0.2, oc[4], .2)
+ frame.MyObject.div:Show()
+ frame.MyObject.div:SetPoint ("left", frame, "left", frame:GetValue() * (frame:GetWidth()/100) - 16, 0)
+ else
+ local oc = frame.MyObject.texture.original_colors --original colors
+ gump:GradientEffect ( frame.MyObject.texture, "texture", oc[1], oc[2], oc[3], oc[4], oc[1]-0.2, oc[2]-0.2, oc[3]-0.2, oc[4]+.2, .2)
+ end
+
+ frame.MyObject.background:Show()
+
+ if (frame.MyObject.have_tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:AddLine (frame.MyObject.have_tooltip)
+ GameCooltip:ShowCooltip (frame, "tooltip")
+ end
+
+ local parent = frame:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient()
+ end
+ end
+
+ end
+
+ local OnLeave = function (frame)
+ if (frame.MyObject.OnLeaveHook) then
+ local interrupt = frame.MyObject.OnLeaveHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (not frame.MyObject.timer) then
+ local oc = frame.MyObject.texture.original_colors --original colors
+ local r, g, b, a = frame.MyObject.texture:GetVertexColor()
+ gump:GradientEffect ( frame.MyObject.texture, "texture", r, g, b, a, oc[1], oc[2], oc[3], oc[4], .2)
+ frame.MyObject.div:Hide()
+ frame.MyObject.background:Hide()
+ else
+ local oc = frame.MyObject.background.original_colors --original colors
+ local r, g, b, a = frame.MyObject.background:GetVertexColor()
+ gump:GradientEffect ( frame.MyObject.background, "texture", r, g, b, a, oc[1], oc[2], oc[3], oc[4], .2)
+ end
+
+ if (frame.MyObject.have_tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+
+ local parent = frame:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient (false)
+ end
+ end
+ end
+
+ local OnHide = function (frame)
+ if (frame.MyObject.OnHideHook) then
+ local interrupt = frame.MyObject.OnHideHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnShow = function (frame)
+ if (frame.MyObject.OnShowHook) then
+ local interrupt = frame.MyObject.OnShowHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnMouseDown = function (frame, button)
+ if (frame.MyObject.OnMouseDownHook) then
+ local interrupt = frame.MyObject.OnMouseDownHook (frame, button)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (not frame.MyObject.container.isLocked and frame.MyObject.container:IsMovable()) then
+ if (not frame.isLocked and frame:IsMovable()) then
+ frame.MyObject.container.isMoving = true
+ frame.MyObject.container:StartMoving()
+ end
+ end
+ end
+
+ local OnMouseUp = function (frame, button)
+ if (frame.MyObject.OnMouseUpHook) then
+ local interrupt = frame.MyObject.OnMouseUpHook (frame, button)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (frame.MyObject.container.isMoving) then
+ frame.MyObject.container:StopMovingOrSizing()
+ frame.MyObject.container.isMoving = false
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> timer
+
+ function BarMetaFunctions:OnTimerEnd()
+ if (self.OnTimerEndHook) then
+ local interrupt = self.OnTimerEndHook()
+ if (interrupt) then
+ return
+ end
+ end
+ self.timer_texture:Hide()
+ self.div_timer:Hide()
+ self:Hide()
+ self.timer = false
+ end
+
+ local OnUpdate = function (self, elapsed)
+ local timepct = (elapsed / self.tempo) * 100
+ self.c = self.c - (timepct*self.width/100)
+ self.remaining = self.remaining - elapsed
+ self.righttext:SetText (_math_floor (self.remaining))
+ self.timertexture:SetWidth (self.c)
+ if (self.c < 1) then
+ self:SetScript ("OnUpdate", nil)
+ self.MyObject:OnTimerEnd()
+ end
+ end
+
+ function BarMetaFunctions:SetTimer (tempo)
+
+ self.statusbar.width = self.statusbar:GetWidth()
+ self.statusbar.tempo = tempo
+ self.statusbar.remaining = tempo
+ self.statusbar.c = self.statusbar.width
+
+ self.timer_texture:Show()
+ self.timer_texture:SetWidth (self.statusbar.width)
+ self.statusbar.t = self.timer_texture
+ self (1)
+
+ self.div_timer:Show()
+ self.background:Show()
+
+ self.timer = true
+
+ self.statusbar:SetScript ("OnUpdate", OnUpdate)
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+
+function DetailsNormalBar_OnCreate (self)
+ self.texture.original_colors = {1, 1, 1, 1}
+ self.background.original_colors = {.3, .3, .3, .3}
+ self.timertexture.original_colors = {.3, .3, .3, .3}
+ return true
+end
+
+function gump:NewBar (parent, container, name, member, w, h, value)
+
+ if (not name) then
+ return nil
+ elseif (not parent) then
+ return nil
+ elseif (not container) then
+ container = parent
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+ local BarObject = {type = "bar", dframework = true}
+
+ if (member) then
+ parent [member] = BarObject
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+ --> default members:
+ --> hooks
+ BarObject.OnEnterHook = nil
+ BarObject.OnLeaveHook = nil
+ BarObject.OnHideHook = nil
+ BarObject.OnShowHook = nil
+ BarObject.OnMouseDownHook = nil
+ BarObject.OnMouseUpHook = nil
+ BarObject.OnTimerEndHook = nil
+ --> misc
+ BarObject.tooltip = nil
+ BarObject.locked = false
+ BarObject.have_tooltip = nil
+
+ BarObject.container = container
+
+ --> create widgets
+ BarObject.statusbar = CreateFrame ("statusbar", name, parent, "DetailsNormalBarTemplate")
+ BarObject.widget = BarObject.statusbar
+
+ if (not APIBarFunctions) then
+ APIBarFunctions = true
+ local idx = getmetatable (BarObject.statusbar).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not BarMetaFunctions [funcName]) then
+ BarMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.statusbar:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ BarObject.statusbar:SetHeight (h)
+ BarObject.statusbar:SetWidth (w)
+ BarObject.statusbar:SetFrameLevel (parent:GetFrameLevel()+1)
+ BarObject.statusbar:SetMinMaxValues (0, 100)
+ BarObject.statusbar:SetValue (value or 50)
+ BarObject.statusbar.MyObject = BarObject
+
+ BarObject.timer_texture = _G [name .. "_timerTexture"]
+ BarObject.timer_texture:SetWidth (w)
+ BarObject.timer_texture:SetHeight (h)
+
+ BarObject.texture = _G [name .. "_statusbarTexture"]
+ BarObject.background = _G [name .. "_background"]
+ BarObject.icon = _G [name .. "_icon"]
+ BarObject.textleft = _G [name .. "_TextLeft"]
+ BarObject.textright = _G [name .. "_TextRight"]
+ BarObject.div = _G [name .. "_sparkMouseover"]
+ BarObject.div_timer = _G [name .. "_sparkTimer"]
+
+ --> hooks
+ BarObject.statusbar:SetScript ("OnEnter", OnEnter)
+ BarObject.statusbar:SetScript ("OnLeave", OnLeave)
+ BarObject.statusbar:SetScript ("OnHide", OnHide)
+ BarObject.statusbar:SetScript ("OnShow", OnShow)
+ BarObject.statusbar:SetScript ("OnMouseDown", OnMouseDown)
+ BarObject.statusbar:SetScript ("OnMouseUp", OnMouseUp)
+
+ --> set class
+ _setmetatable (BarObject, BarMetaFunctions)
+
+ return BarObject
+end
diff --git a/framework/normal_bar.xml b/framework/normal_bar.xml
new file mode 100644
index 00000000..89793d93
--- /dev/null
+++ b/framework/normal_bar.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetStatusBarTexture (self.texture);
+ DetailsNormalBar_OnCreate (self);
+
+
+
+
\ No newline at end of file
diff --git a/framework/panel.lua b/framework/panel.lua
new file mode 100644
index 00000000..e6dea78c
--- /dev/null
+++ b/framework/panel.lua
@@ -0,0 +1,504 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+--> lua locals
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local _setmetatable = setmetatable --> lua local
+local _unpack = unpack --> lua local
+local _type = type --> lua local
+local _math_floor = math.floor --> lua local
+local loadstring = loadstring --> lua local
+
+local cleanfunction = function() end
+local PanelMetaFunctions = {}
+local APIFrameFunctions
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ PanelMetaFunctions.__call = function (_table, value)
+ --> nothing to do
+ return true
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> tooltip
+ local gmember_tooltip = function (_object)
+ return _object:GetTooltip()
+ end
+ --> shown
+ local gmember_shown = function (_object)
+ return _object:IsShown()
+ end
+ --> backdrop color
+ local gmember_color = function (_object)
+ return _object.frame:GetBackdropColor()
+ end
+ --> backdrop table
+ local gmember_backdrop = function (_object)
+ return _object.frame:GetBackdrop()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.frame:GetWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.frame:GetHeight()
+ end
+ --> locked
+ local gmember_locked = function (_object)
+ return _rawget (_object, "is_locked")
+ end
+
+ local get_members_function_index = {
+ ["tooltip"] = gmember_tooltip,
+ ["shown"] = gmember_shown,
+ ["color"] = gmember_color,
+ ["backdrop"] = gmember_backdrop,
+ ["width"] = gmember_width,
+ ["height"] = gmember_height,
+ ["locked"] = gmember_locked,
+ }
+
+ PanelMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return PanelMetaFunctions [_member_requested]
+ end
+
+
+ --> tooltip
+ local smember_tooltip = function (_object, _value)
+ return _object:SetTooltip (_value)
+ end
+ --> show
+ local smember_show = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (not _value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> backdrop color
+ local smember_color = function (_object, _value)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_value)
+ return _object:SetBackdropColor (_value1, _value2, _value3, _value4)
+ end
+ --> frame width
+ local smember_width = function (_object, _value)
+ return _object.frame:SetWidth (_value)
+ end
+ --> frame height
+ local smember_height = function (_object, _value)
+ return _object.frame:SetHeight (_value)
+ end
+
+ --> locked
+ local smember_locked = function (_object, _value)
+ if (_value) then
+ _object.frame:SetMovable (false)
+ return _rawset (_object, "is_locked", true)
+ else
+ _object.frame:SetMovable (true)
+ _rawset (_object, "is_locked", false)
+ return
+ end
+ end
+
+ --> backdrop
+ local smember_backdrop = function (_object, _value)
+ return _object.frame:SetBackdrop (_value)
+ end
+
+ --> close with right button
+ local smember_right_close = function (_object, _value)
+ return _rawset (_object, "rightButtonClose", _value)
+ end
+
+ local set_members_function_index = {
+ ["tooltip"] = smember_tooltip,
+ ["show"] = smember_show,
+ ["hide"] = smember_hide,
+ ["color"] = smember_color,
+ ["backdrop"] = smember_backdrop,
+ ["width"] = smember_width,
+ ["height"] = smember_height,
+ ["locked"] = smember_locked,
+ ["close_with_right"] = smember_right_close,
+ }
+
+ PanelMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+
+--> show & hide
+ function PanelMetaFunctions:Show()
+ self.frame:Show()
+
+ end
+ function PanelMetaFunctions:Hide()
+ self.frame:Hide()
+
+ end
+
+-- setpoint
+ function PanelMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+ end
+
+-- sizes
+ function PanelMetaFunctions:SetSize (w, h)
+ if (w) then
+ self.frame:SetWidth (w)
+ end
+ if (h) then
+ self.frame:SetHeight (h)
+ end
+ end
+
+-- clear
+ function PanelMetaFunctions:HideWidgets()
+ for widgetName, widgetSelf in pairs (self) do
+ if (type (widgetSelf) == "table" and widgetSelf.dframework) then
+ widgetSelf:Hide()
+ end
+ end
+ end
+
+-- backdrop
+ function PanelMetaFunctions:SetBackdrop (background, edge, tilesize, edgesize, tile, left, right, top, bottom)
+
+ if (_type (background) == "boolean" and not background) then
+ return self.frame:SetBackdrop (nil)
+
+ elseif (_type (background) == "table") then
+ self.frame:SetBackdrop (background)
+
+ else
+ local currentBackdrop = self.frame:GetBackdrop() or {edgeFile="Interface\\DialogFrame\\UI-DialogBox-Border", bgFile="Interface\\DialogFrame\\UI-DialogBox-Background", tile=true, tileSize=16, edgeSize=16, insets={left=1, right=0, top=0, bottom=0}}
+ currentBackdrop.bgFile = background or currentBackdrop.bgFile
+ currentBackdrop.edgeFile = edgeFile or currentBackdrop.edgeFile
+ currentBackdrop.tileSize = tilesize or currentBackdrop.tileSize
+ currentBackdrop.edgeSize = edgesize or currentBackdrop.edgeSize
+ currentBackdrop.tile = tile or currentBackdrop.tile
+ currentBackdrop.insets.left = left or currentBackdrop.insets.left
+ currentBackdrop.insets.right = left or currentBackdrop.insets.right
+ currentBackdrop.insets.top = left or currentBackdrop.insets.top
+ currentBackdrop.insets.bottom = left or currentBackdrop.insets.bottom
+ self.frame:SetBackdrop (currentBackdrop)
+ end
+ end
+
+-- backdropcolor
+ function PanelMetaFunctions:SetBackdropColor (color, arg2, arg3, arg4)
+ if (arg2) then
+ self.frame:SetBackdropColor (color, arg2, arg3, arg4 or 1)
+ self.frame.Gradient.OnLeave = {color, arg2, arg3, arg4 or 1}
+ else
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (color)
+ self.frame:SetBackdropColor (_value1, _value2, _value3, _value4)
+ self.frame.Gradient.OnLeave = {_value1, _value2, _value3, _value4}
+ end
+ end
+
+-- border color
+ function PanelMetaFunctions:SetBackdropBorderColor (color, arg2, arg3, arg4)
+ if (arg2) then
+ return self.frame:SetBackdropBorderColor (color, arg2, arg3, arg4)
+ end
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (color)
+ self.frame:SetBackdropBorderColor (_value1, _value2, _value3, _value4)
+ end
+
+-- gradient colors
+ function PanelMetaFunctions:SetGradient (FadeType, color)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (color)
+ if (FadeType == "OnEnter") then
+ self.frame.Gradient.OnEnter = {_value1, _value2, _value3, _value4}
+ elseif (FadeType == "OnLeave") then
+ self.frame.Gradient.OnLeave = {_value1, _value2, _value3, _value4}
+ end
+ end
+
+-- tooltip
+ function PanelMetaFunctions:SetTooltip (tooltip)
+ if (tooltip) then
+ return _rawset (self, "have_tooltip", tooltip)
+ else
+ return _rawset (self, "have_tooltip", nil)
+ end
+ end
+ function PanelMetaFunctions:GetTooltip()
+ return _rawget (self, "have_tooltip")
+ end
+
+-- enable and disable gradients
+ function PanelMetaFunctions:DisableGradient()
+ self.GradientEnabled = false
+ end
+ function PanelMetaFunctions:EnableGradient()
+ self.GradientEnabled = true
+ end
+
+--> hooks
+ function PanelMetaFunctions:SetHook (hookType, func)
+ if (func) then
+ _rawset (self, hookType.."Hook", func)
+ else
+ _rawset (self, hookType.."Hook", nil)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> scripts
+
+ function PanelMetaFunctions:RunGradient (cancel)
+ if (type (cancel) == "boolean" and not canceal) then
+ local _r, _g, _b, _a = self.frame:GetBackdropColor()
+ if (_r) then
+ local OnLeaveColors = self.frame.Gradient.OnLeave
+ gump:GradientEffect (self.frame, "frame", _r, _g, _b, _a, OnLeaveColors[1], OnLeaveColors[2], OnLeaveColors[3], OnLeaveColors[4], .3)
+ end
+ else
+ local _r, _g, _b, _a = self.frame:GetBackdropColor()
+ if (_r) then
+ local OnEnterColors = self.frame.Gradient.OnEnter
+ gump:GradientEffect (self.frame, "frame", _r, _g, _b, _a, OnEnterColors[1], OnEnterColors[2], OnEnterColors[3], OnEnterColors[4], .3)
+ end
+ end
+ end
+
+ local OnEnter = function (frame)
+ if (frame.MyObject.OnEnterHook) then
+ local interrupt = frame.MyObject.OnEnterHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (frame.MyObject.GradientEnabled) then
+ frame.MyObject:RunGradient()
+ end
+
+ if (frame.MyObject.have_tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:SetType ("tooltip")
+ GameCooltip:SetColor ("main", "transparent")
+ GameCooltip:AddLine (frame.MyObject.have_tooltip)
+ GameCooltip:SetOwner (frame)
+ GameCooltip:ShowCooltip()
+ end
+ end
+
+ local OnLeave = function (frame)
+ if (frame.MyObject.OnLeaveHook) then
+ local interrupt = frame.MyObject.OnLeaveHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (frame.MyObject.GradientEnabled) then
+ frame.MyObject:RunGradient (false)
+ end
+
+ if (frame.MyObject.have_tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+
+ end
+
+ local OnHide = function (frame)
+ if (frame.MyObject.OnHideHook) then
+ local interrupt = frame.MyObject.OnHideHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnShow = function (frame)
+ if (frame.MyObject.OnShowHook) then
+ local interrupt = frame.MyObject.OnShowHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnMouseDown = function (frame, button)
+ if (frame.MyObject.OnMouseDownHook) then
+ local interrupt = frame.MyObject.OnMouseDownHook (frame, button)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (frame.MyObject.container == UIParent) then
+ if (not frame.isLocked and frame:IsMovable()) then
+ frame.isMoving = true
+ frame:StartMoving()
+ end
+
+ elseif (not frame.MyObject.container.isLocked and frame.MyObject.container:IsMovable()) then
+ if (not frame.isLocked and frame:IsMovable()) then
+ frame.MyObject.container.isMoving = true
+ frame.MyObject.container:StartMoving()
+ end
+ end
+
+
+ end
+
+ local OnMouseUp = function (frame, button)
+ if (frame.MyObject.OnMouseUpHook) then
+ local interrupt = frame.MyObject.OnMouseUpHook (frame, button)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (button == "RightButton" and frame.MyObject.rightButtonClose) then
+ frame.MyObject:Hide()
+ end
+
+ if (frame.MyObject.container == UIParent) then
+ if (frame.isMoving) then
+ frame:StopMovingOrSizing()
+ frame.isMoving = false
+ end
+ else
+ if (frame.MyObject.container.isMoving) then
+ frame.MyObject.container:StopMovingOrSizing()
+ frame.MyObject.container.isMoving = false
+ end
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+function gump:NewPanel (parent, container, name, member, w, h, backdrop, backdropcolor, bordercolor)
+
+ if (not name) then
+ return nil
+ elseif (not parent) then
+ parent = UIParent
+ end
+ if (not container) then
+ container = parent
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+ local PanelObject = {type = "panel", dframework = true}
+
+ if (member) then
+ parent [member] = PanelObject
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+
+ --> default members:
+ --> hooks
+ PanelObject.OnEnterHook = nil
+ PanelObject.OnLeaveHook = nil
+ PanelObject.OnHideHook = nil
+ PanelObject.OnShowHook = nil
+ PanelObject.OnMouseDownHook = nil
+ PanelObject.OnMouseUpHook = nil
+ --> misc
+ PanelObject.is_locked = true
+ PanelObject.GradientEnabled = true
+ PanelObject.container = container
+ PanelObject.rightButtonClose = false
+
+ PanelObject.frame = CreateFrame ("frame", name, parent, "DetailsPanelTemplate")
+ PanelObject.widget = PanelObject.frame
+
+ if (not APIFrameFunctions) then
+ APIFrameFunctions = {}
+ local idx = getmetatable (PanelObject.frame).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not PanelMetaFunctions [funcName]) then
+ PanelMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.frame:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ PanelObject.frame:SetWidth (w or 100)
+ PanelObject.frame:SetHeight (h or 100)
+
+ PanelObject.frame.MyObject = PanelObject
+
+ --> hooks
+ PanelObject.frame:SetScript ("OnEnter", OnEnter)
+ PanelObject.frame:SetScript ("OnLeave", OnLeave)
+ PanelObject.frame:SetScript ("OnHide", OnHide)
+ PanelObject.frame:SetScript ("OnShow", OnShow)
+ PanelObject.frame:SetScript ("OnMouseDown", OnMouseDown)
+ PanelObject.frame:SetScript ("OnMouseUp", OnMouseUp)
+
+ _setmetatable (PanelObject, PanelMetaFunctions)
+
+ if (backdrop) then
+ PanelObject:SetBackdrop (backdrop)
+ elseif (_type (backdrop) == "boolean") then
+ PanelObject.frame:SetBackdrop (nil)
+ end
+
+ if (backdropcolor) then
+ PanelObject:SetBackdropColor (backdropcolor)
+ end
+
+ if (bordercolor) then
+ PanelObject:SetBackdropBorderColor (bordercolor)
+ end
+
+ return PanelObject
+end
\ No newline at end of file
diff --git a/framework/panel.xml b/framework/panel.xml
new file mode 100644
index 00000000..1d778e2a
--- /dev/null
+++ b/framework/panel.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self.Gradient = {
+ ["OnEnter"] = {0.3, 0.3, 0.3, 0.5},
+ ["OnLeave"] = {0.9, 0.7, 0.7, 1}
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/picture.lua b/framework/picture.lua
new file mode 100644
index 00000000..5c4818a7
--- /dev/null
+++ b/framework/picture.lua
@@ -0,0 +1,234 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local _setmetatable = setmetatable --> lua local
+local _unpack = unpack --> lua local
+local _type = type --> lua local
+local _math_floor = math.floor --> lua local
+local loadstring = loadstring --> lua local
+
+local cleanfunction = function() end
+local APIImageFunctions = false
+local ImageMetaFunctions = {}
+
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ ImageMetaFunctions.__call = function (_table, value)
+ return self.image:SetTexture (value)
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> shown
+ local gmember_shown = function (_object)
+ return _object:IsShown()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.image:GetWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.image:GetHeight()
+ end
+ --> texture
+ local gmember_texture = function (_object)
+ return _object.image:GetTexture()
+ end
+ --> alpha
+ local gmember_alpha = function (_object)
+ return _object.image:GetAlpha()
+ end
+
+ local get_members_function_index = {
+ ["shown"] = gmember_shown,
+ ["alpha"] = gmember_alpha,
+ ["width"] = gmember_width,
+ ["height"] = gmember_height,
+ ["texture"] = gmember_texture,
+ }
+
+ ImageMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return ImageMetaFunctions [_member_requested]
+ end
+
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> show
+ local smember_show = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (not _value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> texture
+ local smember_texture = function (_object, _value)
+ return _object.image:SetTexture (_value)
+ end
+ --> width
+ local smember_width = function (_object, _value)
+ return _object.image:SetWidth (_value)
+ end
+ --> height
+ local smember_height = function (_object, _value)
+ return _object.image:SetHeight (_value)
+ end
+ --> alpha
+ local smember_alpha = function (_object, _value)
+ return _object.image:SetAlpha (_value)
+ end
+ --> color
+ local smember_color = function (_object, _value)
+ local _value1, _value2, _value3 = gump:ParseColors (_value)
+ return _object.image:SetTexture (_value1, _value2, _value3)
+ end
+
+ local set_members_function_index = {
+ ["show"] = smember_show,
+ ["hide"] = smember_hide,
+ ["alpha"] = smember_alpha,
+ ["width"] = smember_width,
+ ["height"] = smember_height,
+ ["texture"] = smember_texture,
+ ["color"] = smember_color,
+ }
+
+ ImageMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+--> show & hide
+ function ImageMetaFunctions:IsShown()
+ return self.image:IsShown()
+ end
+ function ImageMetaFunctions:Show()
+ return self.image:Show()
+ end
+ function ImageMetaFunctions:Hide()
+ return self.image:Hide()
+ end
+
+-- setpoint
+ function ImageMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+ end
+
+-- sizes
+ function ImageMetaFunctions:SetSize (w, h)
+ if (w) then
+ self.image:SetWidth (w)
+ end
+ if (h) then
+ return self.image:SetHeight (h)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> scripts
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+
+function gump:NewImage (parent, container, name, member, w, h, texture, layer)
+
+ if (not parent) then
+ return nil
+ end
+ if (not container) then
+ container = parent
+ end
+
+ if (not name) then
+ name = "DetailsPictureNumber" .. gump.PictureNameCounter
+ gump.PictureNameCounter = gump.PictureNameCounter + 1
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+ local ImageObject = {type = "image", dframework = true}
+
+ if (member) then
+ parent [member] = ImageObject
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+ texture = texture or ""
+
+ ImageObject.image = parent:CreateTexture (name, layer or "OVERLAY")
+ ImageObject.widget = ImageObject.image
+
+ if (not APIImageFunctions) then
+ APIImageFunctions = true
+ local idx = getmetatable (ImageObject.image).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not ImageMetaFunctions [funcName]) then
+ ImageMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.image:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ ImageObject.image.MyObject = ImageObject
+
+ if (w) then
+ ImageObject.image:SetWidth (w)
+ end
+ if (h) then
+ ImageObject.image:SetHeight (h)
+ end
+ if (texture) then
+ ImageObject.image:SetTexture (texture)
+ end
+
+ setmetatable (ImageObject, ImageMetaFunctions)
+
+ return ImageObject
+end
\ No newline at end of file
diff --git a/framework/pictureedit.lua b/framework/pictureedit.lua
new file mode 100644
index 00000000..9480752e
--- /dev/null
+++ b/framework/pictureedit.lua
@@ -0,0 +1,479 @@
+local _detalhes = _G._detalhes
+local g = _detalhes.gump
+
+
+ local window = g:NewPanel (UIParent, _, "DetailsImageEdit", _, 100, 100, false)
+ window:SetPoint ("center", UIParent, "center")
+ window:SetResizable (true)
+ window:SetMovable (true)
+ tinsert (UISpecialFrames, "DetailsImageEdit")
+
+ local background = g:NewImage (window, _, "$parentBackground", _, _, _, nil, "background")
+ background:SetAllPoints()
+ background:SetTexture (0, 0, 0, .8)
+
+ local edit_texture = g:NewImage (window, _, "$parentImage", _, _, _, nil, "artwork")
+ edit_texture:SetPoint ("center", window, "center")
+
+ local haveHFlip = false
+ local haveVFlip = false
+
+--> Top Slider
+
+ local topCoordTexture = g:NewImage (window, _, "$parentImageTopCoord", _, _, _, _, "overlay")
+ topCoordTexture:SetPoint ("topleft", window, "topleft")
+ topCoordTexture:SetPoint ("topright", window, "topright")
+ topCoordTexture.color = "red"
+ topCoordTexture.height = 1
+ topCoordTexture.alpha = .2
+
+ local topSlider = g:NewSlider (window, _, "$parentTopSlider", "topSlider", 100, 100, 0.1, 100, 0.1, 0)
+ topSlider:SetAllPoints (window.widget)
+ topSlider:SetOrientation ("VERTICAL")
+ topSlider.backdrop = nil
+ topSlider.fractional = true
+ topSlider:SetHook ("OnEnter", function() return true end)
+ topSlider:SetHook ("OnLeave", function() return true end)
+
+ local topSliderThumpTexture = topSlider:CreateTexture (nil, "overlay")
+ topSliderThumpTexture:SetTexture (1, 1, 1)
+ topSliderThumpTexture:SetWidth (512)
+ topSliderThumpTexture:SetHeight (3)
+ topSlider:SetThumbTexture (topSliderThumpTexture)
+
+ topSlider:SetHook ("OnValueChange", function (_, _, value)
+ topCoordTexture.image:SetHeight (window.frame:GetHeight()/100*value)
+ end)
+
+ topSlider:Hide()
+
+--> Bottom Slider
+
+ local bottomCoordTexture = g:NewImage (window, _, "$parentImageBottomCoord", _, _, _, _, "overlay")
+ bottomCoordTexture:SetPoint ("bottomleft", window, "bottomleft", 0, 0)
+ bottomCoordTexture:SetPoint ("bottomright", window, "bottomright", 0, 0)
+ bottomCoordTexture.color = "red"
+ bottomCoordTexture.height = 1
+ bottomCoordTexture.alpha = .2
+
+ local bottomSlider= g:NewSlider (window, _, "$parentBottomSlider", "bottomSlider", 100, 100, 0.1, 100, 0.1, 100)
+ bottomSlider:SetAllPoints (window.widget)
+ bottomSlider:SetOrientation ("VERTICAL")
+ bottomSlider.backdrop = nil
+ bottomSlider.fractional = true
+ bottomSlider:SetHook ("OnEnter", function() return true end)
+ bottomSlider:SetHook ("OnLeave", function() return true end)
+
+ local bottomSliderThumpTexture = bottomSlider:CreateTexture (nil, "overlay")
+ bottomSliderThumpTexture:SetTexture (1, 1, 1)
+ bottomSliderThumpTexture:SetWidth (512)
+ bottomSliderThumpTexture:SetHeight (3)
+ bottomSlider:SetThumbTexture (bottomSliderThumpTexture)
+
+ bottomSlider:SetHook ("OnValueChange", function (_, _, value)
+ value = math.abs (value-100)
+ bottomCoordTexture.image:SetHeight (math.max (window.frame:GetHeight()/100*value, 1))
+ end)
+
+ bottomSlider:Hide()
+
+--> Left Slider
+
+ local leftCoordTexture = g:NewImage (window, _, "$parentImageLeftCoord", _, _, _, _, "overlay")
+ leftCoordTexture:SetPoint ("topleft", window, "topleft", 0, 0)
+ leftCoordTexture:SetPoint ("bottomleft", window, "bottomleft", 0, 0)
+ leftCoordTexture.color = "red"
+ leftCoordTexture.width = 1
+ leftCoordTexture.alpha = .2
+
+ local leftSlider = g:NewSlider (window, _, "$parentLeftSlider", "leftSlider", 100, 100, 0.1, 100, 0.1, 0.1)
+ leftSlider:SetAllPoints (window.widget)
+ leftSlider.backdrop = nil
+ leftSlider.fractional = true
+ leftSlider:SetHook ("OnEnter", function() return true end)
+ leftSlider:SetHook ("OnLeave", function() return true end)
+
+ local leftSliderThumpTexture = leftSlider:CreateTexture (nil, "overlay")
+ leftSliderThumpTexture:SetTexture (1, 1, 1)
+ leftSliderThumpTexture:SetWidth (3)
+ leftSliderThumpTexture:SetHeight (512)
+ leftSlider:SetThumbTexture (leftSliderThumpTexture)
+
+ leftSlider:SetHook ("OnValueChange", function (_, _, value)
+ leftCoordTexture.image:SetWidth (window.frame:GetWidth()/100*value)
+ end)
+
+ leftSlider:Hide()
+
+--> Right Slider
+
+ local rightCoordTexture = g:NewImage (window, _, "$parentImageRightCoord", _, _, _, _, "overlay")
+ rightCoordTexture:SetPoint ("topright", window, "topright", 0, 0)
+ rightCoordTexture:SetPoint ("bottomright", window, "bottomright", 0, 0)
+ rightCoordTexture.color = "red"
+ rightCoordTexture.width = 1
+ rightCoordTexture.alpha = .2
+
+ local rightSlider = g:NewSlider (window, _, "$parentRightSlider", "rightSlider", 100, 100, 0.1, 100, 0.1, 100)
+ rightSlider:SetAllPoints (window.widget)
+ rightSlider.backdrop = nil
+ rightSlider.fractional = true
+ rightSlider:SetHook ("OnEnter", function() return true end)
+ rightSlider:SetHook ("OnLeave", function() return true end)
+ --[
+ local rightSliderThumpTexture = rightSlider:CreateTexture (nil, "overlay")
+ rightSliderThumpTexture:SetTexture (1, 1, 1)
+ rightSliderThumpTexture:SetWidth (3)
+ rightSliderThumpTexture:SetHeight (512)
+ rightSlider:SetThumbTexture (rightSliderThumpTexture)
+ --]]
+ rightSlider:SetHook ("OnValueChange", function (_, _, value)
+ value = math.abs (value-100)
+ rightCoordTexture.image:SetWidth (math.max (window.frame:GetWidth()/100*value, 1))
+ end)
+
+ rightSlider:Hide()
+
+--> Edit Buttons
+
+ local buttonsBackground = g:NewPanel (UIParent, _, "DetailsImageEditButtonsBg", _, 115, 225)
+ buttonsBackground:SetPoint ("topleft", window, "topright", 2, 0)
+ buttonsBackground:Hide()
+ --buttonsBackground:SetMovable (true)
+ tinsert (UISpecialFrames, "DetailsImageEditButtonsBg")
+
+ local alphaFrameShown = false
+
+ local editingSide = nil
+ local lastButton = nil
+ local alphaFrame
+ local originalColor = {0.9999, 0.8196, 0}
+
+ local enableTexEdit = function (side, _, button)
+
+ if (alphaFrameShown) then
+ alphaFrame:Hide()
+ alphaFrameShown = false
+ button.text:SetTextColor (unpack (originalColor))
+ end
+
+ if (ColorPickerFrame:IsShown()) then
+ ColorPickerFrame:Hide()
+ end
+
+ if (lastButton) then
+ lastButton.text:SetTextColor (unpack (originalColor))
+ end
+
+ if (editingSide == side) then
+ window [editingSide.."Slider"]:Hide()
+ editingSide = nil
+ return
+
+ elseif (editingSide) then
+ window [editingSide.."Slider"]:Hide()
+ end
+
+ editingSide = side
+ button.text:SetTextColor (1, 1, 1)
+ lastButton = button
+
+ window [side.."Slider"]:Show()
+ end
+
+ local leftTexCoordButton = g:NewButton (buttonsBackground, _, "$parentLeftTexButton", _, 100, 20, enableTexEdit, "left", _, _, "Crop Left")
+ leftTexCoordButton:SetPoint ("topleft", window, "topright", 10, -10)
+ local rightTexCoordButton = g:NewButton (buttonsBackground, _, "$parentRightTexButton", _, 100, 20, enableTexEdit, "right", _, _, "Crop Right")
+ rightTexCoordButton:SetPoint ("topleft", window, "topright", 10, -30)
+ local topTexCoordButton = g:NewButton (buttonsBackground, _, "$parentTopTexButton", _, 100, 20, enableTexEdit, "top", _, _, "Crop Top")
+ topTexCoordButton:SetPoint ("topleft", window, "topright", 10, -50)
+ local bottomTexCoordButton = g:NewButton (buttonsBackground, _, "$parentBottomTexButton", _, 100, 20, enableTexEdit, "bottom", _, _, "Crop Bottom")
+ bottomTexCoordButton:SetPoint ("topleft", window, "topright", 10, -70)
+ leftTexCoordButton:InstallCustomTexture()
+ rightTexCoordButton:InstallCustomTexture()
+ topTexCoordButton:InstallCustomTexture()
+ bottomTexCoordButton:InstallCustomTexture()
+
+ local Alpha = g:NewButton (buttonsBackground, _, "$parentBottomAlphaButton", _, 100, 20, alpha, _, _, _, "Transparency")
+ Alpha:SetPoint ("topleft", window, "topright", 10, -110)
+ Alpha:InstallCustomTexture()
+
+ --> overlay color
+ local selectedColor = function (default)
+ if (default) then
+ edit_texture:SetVertexColor (unpack (default))
+ else
+ edit_texture:SetVertexColor (ColorPickerFrame:GetColorRGB())
+ end
+ end
+
+ local changeColor = function()
+
+ ColorPickerFrame.func = nil
+ ColorPickerFrame.opacityFunc = nil
+ ColorPickerFrame.cancelFunc = nil
+ ColorPickerFrame.previousValues = nil
+
+ local r, g, b = edit_texture:GetVertexColor()
+ ColorPickerFrame:SetColorRGB (r, g, b)
+ ColorPickerFrame:SetParent (buttonsBackground.widget)
+ ColorPickerFrame.hasOpacity = false
+ ColorPickerFrame.previousValues = {r, g, b}
+ ColorPickerFrame.func = selectedColor
+ ColorPickerFrame.cancelFunc = selectedColor
+ ColorPickerFrame:ClearAllPoints()
+ ColorPickerFrame:SetPoint ("left", buttonsBackground.widget, "right")
+ ColorPickerFrame:Show()
+
+ if (alphaFrameShown) then
+ alphaFrame:Hide()
+ alphaFrameShown = false
+ Alpha.button.text:SetTextColor (unpack (originalColor))
+ end
+
+ if (lastButton) then
+ lastButton.text:SetTextColor (unpack (originalColor))
+ if (editingSide) then
+ window [editingSide.."Slider"]:Hide()
+ end
+ end
+ end
+
+ local changeColorButton = g:NewButton (buttonsBackground, _, "$parentOverlayColorButton", _, 100, 20, changeColor, _, _, _, "Overlay Color")
+ changeColorButton:SetPoint ("topleft", window, "topright", 10, -90)
+ changeColorButton:InstallCustomTexture()
+
+ alphaFrame = g:NewPanel (buttonsBackground, _, "DetailsImageEditAlphaBg", _, 40, 225)
+ alphaFrame:SetPoint ("topleft", buttonsBackground, "topright", 2, 0)
+ alphaFrame:Hide()
+ local alphaSlider = g:NewSlider (alphaFrame, _, "$parentAlphaSlider", "alphaSlider", 30, 220, 1, 100, 1, edit_texture:GetAlpha()*100)
+ alphaSlider:SetPoint ("top", alphaFrame, "top", 0, -5)
+ alphaSlider:SetOrientation ("VERTICAL")
+ alphaSlider.thumb:SetSize (40, 30)
+ --leftSlider.backdrop = nil
+ --leftSlider.fractional = true
+
+ local alpha = function(_, _, button)
+
+ if (ColorPickerFrame:IsShown()) then
+ ColorPickerFrame:Hide()
+ end
+
+ if (lastButton) then
+ lastButton.text:SetTextColor (unpack (originalColor))
+ if (editingSide) then
+ window [editingSide.."Slider"]:Hide()
+ end
+ end
+
+ if (not alphaFrameShown) then
+ alphaFrame:Show()
+ alphaSlider:SetValue (edit_texture:GetAlpha()*100)
+ alphaFrameShown = true
+ button.text:SetTextColor (1, 1, 1)
+ else
+ alphaFrame:Hide()
+ alphaFrameShown = false
+ button.text:SetTextColor (unpack (originalColor))
+ end
+ end
+
+ Alpha.clickfunction = alpha
+
+ alphaSlider:SetHook ("OnValueChange", function (_, _, value)
+ edit_texture:SetAlpha (value/100)
+ end)
+
+ local resizer = CreateFrame ("Button", nil, window.widget)
+ resizer:SetNormalTexture ("Interface\\AddOns\\Details\\images\\ResizeGripD")
+ resizer:SetHighlightTexture ("Interface\\AddOns\\Details\\images\\ResizeGripD")
+ resizer:SetWidth (16)
+ resizer:SetHeight (16)
+ resizer:SetPoint ("BOTTOMRIGHT", window.widget, "BOTTOMRIGHT", 0, 0)
+ resizer:EnableMouse (true)
+ resizer:SetFrameLevel (window.widget:GetFrameLevel() + 2)
+
+ resizer:SetScript ("OnMouseDown", function (self, button)
+ window.widget:StartSizing ("BOTTOMRIGHT")
+ end)
+
+ resizer:SetScript ("OnMouseUp", function (self, button)
+ window.widget:StopMovingOrSizing()
+ end)
+
+ window.widget:SetScript ("OnMouseDown", function()
+ window.widget:StartMoving()
+ end)
+ window.widget:SetScript ("OnMouseUp", function()
+ window.widget:StopMovingOrSizing()
+ end)
+
+ window.widget:SetScript ("OnSizeChanged", function()
+ edit_texture.width = window.width
+ edit_texture.height = window.height
+ leftSliderThumpTexture:SetHeight (window.height)
+ rightSliderThumpTexture:SetHeight (window.height)
+ topSliderThumpTexture:SetWidth (window.width)
+ bottomSliderThumpTexture:SetWidth (window.width)
+
+ rightCoordTexture.image:SetWidth (math.max ( (window.frame:GetWidth() / 100 * math.abs (rightSlider:GetValue()-100)), 1))
+ leftCoordTexture.image:SetWidth (window.frame:GetWidth()/100*leftSlider:GetValue())
+ bottomCoordTexture:SetHeight (math.max ( (window.frame:GetHeight() / 100 * math.abs (bottomSlider:GetValue()-100)), 1))
+ topCoordTexture:SetHeight (window.frame:GetHeight()/100*topSlider:GetValue())
+ end)
+
+ --> change size
+ local resizeLabel = g:NewLabel (window, _, "$parentResizerIndicator", _, "RESIZE", _, 9)
+ resizeLabel:SetPoint ("right", resizer, "left", -2, 0)
+
+ --> flip
+ local flip = function (side)
+ if (side == 1) then
+ if (not haveHFlip) then
+ if (not haveVFlip) then
+ edit_texture:SetTexCoord (1, 0, 0, 1)
+ else
+ edit_texture:SetTexCoord (1, 0, 1, 0)
+ end
+ rightCoordTexture:Hide()
+ leftCoordTexture:Hide()
+ rightSlider:Hide()
+ leftSlider:Hide()
+ leftTexCoordButton:Disable()
+ rightTexCoordButton:Disable()
+ else
+ if (not haveVFlip) then
+ edit_texture:SetTexCoord (0, 1, 0, 1)
+ else
+ edit_texture:SetTexCoord (0, 1, 1, 0)
+ end
+ rightCoordTexture:Show()
+ leftCoordTexture:Show()
+ leftTexCoordButton:Enable()
+ rightTexCoordButton:Enable()
+ end
+ haveHFlip = not haveHFlip
+
+ elseif (side == 2) then
+ if (not haveVFlip) then
+ if (not haveHFlip) then
+ edit_texture:SetTexCoord (0, 1, 1, 0)
+ else
+ edit_texture:SetTexCoord (1, 0, 1, 0)
+ end
+ topCoordTexture:Hide()
+ bottomCoordTexture:Hide()
+ topSlider:Hide()
+ bottomSlider:Hide()
+ topTexCoordButton:Disable()
+ bottomTexCoordButton:Disable()
+ else
+ if (not haveHFlip) then
+ edit_texture:SetTexCoord (0, 1, 0, 1)
+ else
+ edit_texture:SetTexCoord (1, 0, 0, 1)
+ end
+ topCoordTexture:Show()
+ bottomCoordTexture:Show()
+ topTexCoordButton:Enable()
+ bottomTexCoordButton:Enable()
+ end
+ haveVFlip = not haveVFlip
+ end
+ end
+
+ local flipButtonH = g:NewButton (buttonsBackground, _, "$parentFlipButton", _, 100, 20, flip, 1, _, _, "Flip Horizontal")
+ flipButtonH:SetPoint ("topleft", window, "topright", 10, -140)
+ flipButtonH:InstallCustomTexture()
+ --
+ local flipButtonV = g:NewButton (buttonsBackground, _, "$parentFlipButton2", _, 100, 20, flip, 2, _, _, "Flip Vertical")
+ flipButtonV:SetPoint ("topleft", window, "topright", 10, -160)
+ flipButtonV:InstallCustomTexture()
+
+ --> accept
+ local accept = function()
+ buttonsBackground:Hide()
+ window:Hide()
+ alphaFrame:Hide()
+ ColorPickerFrame:Hide()
+
+ local coords = {}
+ if (haveHFlip) then
+ coords [1] = 1
+ coords [2] = 0
+ else
+ coords [1] = leftSlider.value/100
+ coords [2] = rightSlider.value /100
+ end
+
+ if (haveVFlip) then
+ coords [3] = 1
+ coords [4] = 0
+ else
+ coords [3] = topSlider.value/100
+ coords [4] = bottomSlider.value/100
+ end
+
+ return window.callback_func (edit_texture.width, edit_texture.height, {edit_texture:GetVertexColor()}, edit_texture:GetAlpha(), coords, window.extra_param)
+ end
+
+ local acceptButton = g:NewButton (buttonsBackground, _, "$parentAcceptButton", _, 100, 20, accept, _, _, _, "DONE")
+ acceptButton:SetPoint ("topleft", window, "topright", 10, -200)
+ acceptButton:InstallCustomTexture()
+
+ -- fazer botao de editar a cor
+ -- fazer botao de editar o tamanho
+ -- fazer botao de okey e retornar os valores
+
+
+window:Hide()
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local ttexcoord
+ function g:ImageEditor (callback, texture, texcoord, colors, extraParam)
+
+ edit_texture:SetTexture (texture)
+
+ colors = colors or {1, 1, 1, 1}
+ edit_texture:SetVertexColor (colors [1], colors [2], colors [3])
+
+ edit_texture:SetAlpha (colors [4] or 1)
+
+ texcoord = texcoord or {0, 1, 0, 1}
+ ttexcoord = texcoord
+
+ _detalhes:ScheduleTimer ("RefreshImageEditor", 0.2)
+
+ window:Show()
+ window.callback_func = callback
+ window.extra_param = extraParam
+ buttonsBackground:Show()
+ end
+
+ function _detalhes:RefreshImageEditor()
+
+ window.width = edit_texture.width
+ window.height = edit_texture.height
+
+ if (ttexcoord[1] == 1 and ttexcoord[2] == 0) then
+ haveHFlip = false
+ flip (1)
+ else
+ haveHFlip = true
+ flip (1)
+ leftSlider:SetValue (ttexcoord[1]*100)
+ rightSlider:SetValue (ttexcoord[2]*100)
+ end
+
+ if (ttexcoord[3] == 1 and ttexcoord[4] == 0) then
+ haveVFlip = false
+ flip (2)
+ else
+ haveVFlip = true
+ flip (2)
+ topSlider:SetValue (ttexcoord[3]*100)
+ bottomSlider:SetValue (ttexcoord[4]*100)
+ end
+
+ end
+
\ No newline at end of file
diff --git a/framework/slider.lua b/framework/slider.lua
new file mode 100644
index 00000000..edb88b2c
--- /dev/null
+++ b/framework/slider.lua
@@ -0,0 +1,526 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local _setmetatable = setmetatable --> lua local
+local _unpack = unpack --> lua local
+local _type = type --> lua local
+local _math_floor = math.floor --> lua local
+local loadstring = loadstring --> lua local
+
+local cleanfunction = function() end
+local APISliderFunctions = false
+local SliderMetaFunctions = {}
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ SliderMetaFunctions.__call = function (_table, value)
+ if (not value) then
+ return _table.slider:GetValue()
+ else
+ return _table.slider:SetValue (value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> tooltip
+ local gmember_tooltip = function (_object)
+ return _object:GetTooltip()
+ end
+ --> shown
+ local gmember_shown = function (_object)
+ return _object:IsShown()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.slider:GetWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.slider:GetHeight()
+ end
+ --> locked
+ local gmember_locked = function (_object)
+ return _rawget (_object, "lockdown")
+ end
+ --> fractional
+ local gmember_fractional = function (_object, _value)
+ return _rawget (_object, "useDecimals")
+ end
+
+ local get_members_function_index = {
+ ["tooltip"] = gmember_tooltip,
+ ["shown"] = gmember_shown,
+ ["width"] = gmember_width,
+ ["height"] = gmember_height,
+ ["locked"] = gmember_locked,
+ ["fractional"] = gmember_fractional,
+ }
+
+ SliderMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return SliderMetaFunctions [_member_requested]
+ end
+
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> tooltip
+ local smember_tooltip = function (_object, _value)
+ return _object:SetTooltip (_value)
+ end
+ --> show
+ local smember_show = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (not _value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> frame width
+ local smember_width = function (_object, _value)
+ return _object.slider:SetWidth (_value)
+ end
+ --> frame height
+ local smember_height = function (_object, _value)
+ return _object.slider:SetHeight (_value)
+ end
+ --> locked
+ local smember_locked = function (_object, _value)
+ if (_value) then
+ return self:Disable()
+ else
+ return self:Enable()
+ end
+ end
+ --> backdrop
+ local smember_backdrop = function (_object, _value)
+ return _object.slider:SetBackdrop (_value)
+ end
+ --> fractional
+ local smember_fractional = function (_object, _value)
+ return _rawset (_object, "useDecimals", _value)
+ end
+
+ local set_members_function_index = {
+ ["tooltip"] = smember_tooltip,
+ ["show"] = smember_show,
+ ["hide"] = smember_hide,
+ ["backdrop"] = smember_backdrop,
+ ["width"] = smember_width,
+ ["height"] = smember_height,
+ ["locked"] = smember_locked,
+ ["fractional"] = smember_fractional,
+ }
+
+ SliderMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+
+--> show & hide
+ function SliderMetaFunctions:IsShown()
+ return self.slider:IsShown()
+ end
+ function SliderMetaFunctions:Show()
+ return self.slider:Show()
+ end
+ function SliderMetaFunctions:Hide()
+ return self.slider:Hide()
+ end
+
+--> fixed value
+ function SliderMetaFunctions:SetFixedParameter (value)
+ _rawset (self, "FixedValue", value)
+ end
+
+-- thumb size
+ function SliderMetaFunctions:SetThumbSize (w, h)
+ if (not w) then
+ w = self.thumb:GetWidth()
+ end
+ if (not h) then
+ h = self.thumb:GetHeight()
+ end
+ return self.thumb:SetSize (w, h)
+ end
+
+
+-- setpoint
+ function SliderMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+ end
+
+-- sizes
+ function SliderMetaFunctions:SetSize (w, h)
+ if (w) then
+ self.slider:SetWidth (w)
+ end
+ if (h) then
+ return self.slider:SetHeight (h)
+ end
+ end
+
+-- tooltip
+ function SliderMetaFunctions:SetTooltip (tooltip)
+ if (tooltip) then
+ return _rawset (self, "have_tooltip", tooltip)
+ else
+ return _rawset (self, "have_tooltip", nil)
+ end
+ end
+ function SliderMetaFunctions:GetTooltip()
+ return _rawget (self, "have_tooltip")
+ end
+
+-- frame levels
+ function SliderMetaFunctions:GetFrameLevel()
+ return self.slider:GetFrameLevel()
+ end
+ function SliderMetaFunctions:SetFrameLevel (level, frame)
+ if (not frame) then
+ return self.slider:SetFrameLevel (level)
+ else
+ local framelevel = frame:GetFrameLevel (frame) + level
+ return self.slider:SetFrameLevel (framelevel)
+ end
+ end
+
+-- frame stratas
+ function SliderMetaFunctions:SetFrameStrata()
+ return self.slider:GetFrameStrata()
+ end
+ function SliderMetaFunctions:SetFrameStrata (strata)
+ if (_type (strata) == "table") then
+ self.slider:SetFrameStrata (strata:GetFrameStrata())
+ else
+ self.slider:SetFrameStrata (strata)
+ end
+ end
+
+-- enabled
+ function SliderMetaFunctions:IsEnabled()
+ return not _rawget (self, "lockdown")
+ end
+ function SliderMetaFunctions:Enable()
+ self.slider:Enable()
+ self.slider.lock:Hide()
+ self.slider.amt:Show()
+ return _rawset (self, "lockdown", false)
+ end
+ function SliderMetaFunctions:Disable()
+ self.slider:Disable()
+ self.slider.lock:Show()
+ self.slider.amt:Hide()
+ return _rawset (self, "lockdown", true)
+ end
+
+--> hooks
+ function SliderMetaFunctions:SetHook (hookType, func)
+ if (func) then
+ _rawset (self, hookType.."Hook", func)
+ else
+ _rawset (self, hookType.."Hook", nil)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> scripts
+
+ local OnEnter = function (slider)
+
+ if (slider.MyObject.OnEnterHook) then
+ local interrupt = slider.MyObject.OnEnterHook (slider)
+ if (interrupt) then
+ return
+ end
+ end
+
+ slider.thumb:SetAlpha (1)
+
+ if (slider.MyObject.have_tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:AddLine (slider.MyObject.have_tooltip)
+ GameCooltip:ShowCooltip (slider, "tooltip")
+ end
+
+ local parent = slider:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient()
+ end
+ end
+
+ end
+
+ local OnLeave = function (slider)
+ if (slider.MyObject.OnLeaveHook) then
+ local interrupt = slider.MyObject.OnLeaveHook (slider)
+ if (interrupt) then
+ return
+ end
+ end
+
+ slider.thumb:SetAlpha (.7)
+
+ if (slider.MyObject.have_tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+
+ local parent = slider:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient (false)
+ end
+ end
+
+ end
+
+ local OnHide = function (slider)
+ if (slider.MyObject.OnHideHook) then
+ local interrupt = slider.MyObject.OnHideHook (slider)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnShow = function (slider)
+ if (slider.MyObject.OnShowHook) then
+ local interrupt = slider.MyObject.OnShowHook (slider)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnValueChanged = function (slider)
+
+ local amt = slider:GetValue()
+
+ if (slider.MyObject.OnValueChangeHook) then
+ local interrupt = slider.MyObject.OnValueChangeHook (slider, slider.MyObject.FixedValue, amt)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (amt < 10 and amt >= 1) then
+ amt = "0"..amt
+ end
+
+ if (slider.MyObject.useDecimals) then
+ slider.amt:SetText (string.format ("%.1f", amt))
+ else
+ slider.amt:SetText (math.floor (amt))
+ end
+ slider.MyObject.value = amt
+ end
+
+
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+
+function gump:NewSwitch (parent, container, name, member, w, h, ltext, rtext, defaultv)
+
+--> early checks
+ if (not name) then
+ return nil
+ elseif (not parent) then
+ return nil
+ end
+ if (not container) then
+ container = parent
+ end
+
+--> defaults
+ ltext = ltext or "OFF"
+ rtext = rtext or "ON"
+
+ if (type (defaultv) == "boolean" and not defaultv) then
+ defaultv = 1
+ elseif (type (defaultv) == "boolean" and defaultv) then
+ defaultv = 2
+ else
+ defaultv = defaultv or 1
+ end
+
+--> build frames
+ local slider = gump:NewSlider (parent, container, name, member, w, h, 1, 2, 1, defaultv)
+
+ slider:SetHook ("OnValueChange", function (self)
+ if (slider:GetValue() == 1) then
+ slider.amt:SetText (ltext)
+ if (slider.OnSwitch) then
+ slider.OnSwitch (slider, slider.FixedValue, false)
+ end
+ else
+ slider.amt:SetText (rtext)
+ if (slider.OnSwitch) then
+ slider.OnSwitch (slider, slider.FixedValue, true)
+ end
+ end
+ return true
+ end)
+
+ slider:SetValue (1)
+ slider:SetValue (2)
+ slider:SetValue (defaultv)
+
+ return slider
+end
+
+function gump:NewSlider (parent, container, name, member, w, h, min, max, step, defaultv, isDecemal)
+
+--> early checks
+ if (not name) then
+ return nil
+ elseif (not parent) then
+ return nil
+ end
+ if (not container) then
+ container = parent
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+ local SliderObject = {type = "slider", dframework = true}
+
+ if (member) then
+ parent [member] = SliderObject
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+--> defaults
+ min = min or 1
+ max = max or 2
+ step = step or 1
+ defaultv = defaultv or min
+
+ --> default members:
+ --> hooks
+ SliderObject.OnEnterHook = nil
+ SliderObject.OnLeaveHook = nil
+ SliderObject.OnHideHook = nil
+ SliderObject.OnShowHook = nil
+ SliderObject.OnValueChangeHook = nil
+ --> misc
+ SliderObject.lockdown = false
+ SliderObject.container = container
+ SliderObject.have_tooltip = nil
+ SliderObject.FixedValue = nil
+ SliderObject.useDecimals = isDecemal or false
+
+ --SliderObject.slider = CreateFrame ("slider", name, parent, "DetailsSliderTemplate")
+ SliderObject.slider = CreateFrame ("slider", name, parent)
+ SliderObject.widget = SliderObject.slider
+
+ if (not APISliderFunctions) then
+ APISliderFunctions = true
+ local idx = getmetatable (SliderObject.slider).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not SliderMetaFunctions [funcName]) then
+ SliderMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.slider:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ SliderObject.slider.MyObject = SliderObject
+ SliderObject.slider:SetWidth (w or 232)
+ SliderObject.slider:SetHeight (h or 20)
+ SliderObject.slider:SetOrientation ("horizontal")
+ SliderObject.slider:SetMinMaxValues (min, max)
+ SliderObject.slider:SetValueStep (step)
+ SliderObject.slider:SetValue (defaultv)
+ SliderObject.value = defaultv
+
+ --SliderObject.amt = _G [name .. "_Amt"]
+ --SliderObject.lock = _G [name .. "_LockTexture"]
+ --SliderObject.thumb = _G [name .. "_ThumbTexture"]
+
+ SliderObject.slider:SetBackdrop ({edgeFile = "Interface\\Buttons\\UI-SliderBar-Border", edgeSize = 8})
+ SliderObject.slider:SetBackdropColor (0.9, 0.7, 0.7, 1.0)
+
+ SliderObject.thumb = SliderObject.slider:CreateTexture (nil, "artwork")
+ SliderObject.thumb:SetTexture ("Interface\\Buttons\\UI-ScrollBar-Knob")
+ --SliderObject.thumb:SetSize (30, 24)
+ SliderObject.thumb:SetSize (30+(h*0.2), h*1.2)
+ SliderObject.thumb:SetAlpha (0.7)
+ SliderObject.slider:SetThumbTexture (SliderObject.thumb)
+ SliderObject.slider.thumb = SliderObject.thumb
+
+ SliderObject.amt = SliderObject.slider:CreateFontString (nil, "overlay", "GameFontHighlightSmall")
+
+ local amt = defaultv
+ if (amt < 10 and amt >= 1) then
+ amt = "0"..amt
+ end
+
+ if (SliderObject.useDecimals) then
+ SliderObject.amt:SetText (string.format ("%.1f", amt))
+ else
+ SliderObject.amt:SetText (math.floor (amt))
+ end
+
+ SliderObject.amt:SetTextColor (.8, .8, .8, 1)
+ SliderObject.amt:SetPoint ("center", SliderObject.thumb, "center")
+ SliderObject.slider.amt = SliderObject.amt
+
+ --> hooks
+ SliderObject.slider:SetScript ("OnEnter", OnEnter)
+ SliderObject.slider:SetScript ("OnLeave", OnLeave)
+ SliderObject.slider:SetScript ("OnHide", OnHide)
+ SliderObject.slider:SetScript ("OnShow", OnShow)
+ SliderObject.slider:SetScript ("OnValueChanged", OnValueChanged)
+
+ _setmetatable (SliderObject, SliderMetaFunctions)
+
+ return SliderObject
+
+end
\ No newline at end of file
diff --git a/framework/split_bar.lua b/framework/split_bar.lua
new file mode 100644
index 00000000..76a43754
--- /dev/null
+++ b/framework/split_bar.lua
@@ -0,0 +1,630 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local _setmetatable = setmetatable --> lua local
+local _unpack = unpack --> lua local
+local _type = type --> lua local
+local _math_floor = math.floor --> lua local
+
+local cleanfunction = function() end
+local SplitBarMetaFunctions = {}
+local APISplitBarFunctions
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ SplitBarMetaFunctions.__call = function (_table, value)
+ if (not value) then
+ return _table.statusbar:GetValue()
+ else
+ _table.div:SetPoint ("left", _table.statusbar, "left", value * (_table.statusbar:GetWidth()/100) - 18, 0)
+ return _table.statusbar:SetValue (value)
+ end
+ end
+
+ SplitBarMetaFunctions.__add = function (v1, v2)
+ if (_type (v1) == "table") then
+ local v = v1.statusbar:GetValue()
+ v = v + v2
+ v1.div:SetPoint ("left", v1.statusbar, "left", value * (v1.statusbar:GetWidth()/100) - 18, 0)
+ v1.statusbar:SetValue (v)
+ else
+ local v = v2.statusbar:GetValue()
+ v = v + v1
+ v2.div:SetPoint ("left", v2.statusbar, "left", value * (v2.statusbar:GetWidth()/100) - 18, 0)
+ v2.statusbar:SetValue (v)
+ end
+ end
+
+ SplitBarMetaFunctions.__sub = function (v1, v2)
+ if (_type (v1) == "table") then
+ local v = v1.statusbar:GetValue()
+ v = v - v2
+ v1.div:SetPoint ("left", v1.statusbar, "left", value * (v1.statusbar:GetWidth()/100) - 18, 0)
+ v1.statusbar:SetValue (v)
+ else
+ local v = v2.statusbar:GetValue()
+ v = v - v1
+ v2.div:SetPoint ("left", v2.statusbar, "left", value * (v2.statusbar:GetWidth()/100) - 18, 0)
+ v2.statusbar:SetValue (v)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> tooltip
+ local function gmember_tooltip (_object)
+ return _object:GetTooltip()
+ end
+ --> shown
+ local gmember_shown = function (_object)
+ return _object.statusbar:IsShown()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.statusbar:GetWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.statusbar:GetHeight()
+ end
+ --> value
+ local gmember_value = function (_object)
+ return _object.statusbar:GetValue()
+ end
+ --> right text
+ local gmember_rtext = function (_object)
+ return _object.textright:GetText()
+ end
+ --> left text
+ local gmember_ltext = function (_object)
+ return _object.textleft:GetText()
+ end
+ --> right color
+ local gmember_rcolor = function (_object)
+ return _object.background.original_colors
+ end
+ --> left color
+ local gmember_lcolor = function (_object)
+ return _object.texture.original_colors
+ end
+ --> right icon
+ local gmember_ricon = function (_object)
+ return _object.iconright:GetTexture()
+ end
+ --> left icon
+ local gmember_licon = function (_object)
+ return _object.iconleft:GetTexture()
+ end
+ --> texture
+ local gmember_texture = function (_object)
+ return _object.texture:GetTexture()
+ end
+ --> font size
+ local gmember_textsize = function (_object)
+ local _, fontsize = _object.textleft:GetFont()
+ return fontsize
+ end
+ --> font face
+ local gmember_textfont = function (_object)
+ local fontface = _object.textleft:GetFont()
+ return fontface
+ end
+ --> font color
+ local gmember_textcolor = function (_object)
+ return _object.textleft:GetTextColor()
+ end
+
+ local get_members_function_index = {
+ ["tooltip"] = gmember_tooltip,
+ ["shown"] = gmember_shown,
+ ["width"] = gmember_width,
+ ["height"] = gmember_height,
+ ["value"] = gmember_value,
+ ["righttext"] = gmember_rtext,
+ ["lefttext"] = gmember_ltext,
+ ["rightcolor"] = gmember_rcolor,
+ ["leftcolor"] = gmember_lcolor,
+ ["righticon"] = gmember_ricon,
+ ["lefticon"] = gmember_licon,
+ ["texture"] = gmember_texture,
+ ["fontsize"] = gmember_textsize,
+ ["fontface"] = gmember_textfont,
+ ["fontcolor"] = gmember_textcolor,
+ ["textsize"] = gmember_textsize, --alias
+ ["textfont"] = gmember_textfont, --alias
+ ["textcolor"] = gmember_textcolor --alias
+ }
+
+ SplitBarMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return SplitBarMetaFunctions [_member_requested]
+ end
+
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> tooltip
+ local smember_tooltip = function (_object, _value)
+ return _object:SetTooltip (_value)
+ end
+ --> show
+ local smember_shown = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (_value) then
+ return _object:Hide()
+ else
+ return _object:Show()
+ end
+ end
+ --> width
+ local smember_width = function (_object, _value)
+ return _object.statusbar:SetWidth (_value)
+ end
+ --> height
+ local smember_height = function (_object, _value)
+ return _object.statusbar:SetHeight (_value)
+ end
+ --> statusbar value
+ local smember_value = function (_object, _value)
+ _object.statusbar:SetValue (_value)
+ return _object.div:SetPoint ("left", _object.statusbar, "left", _value * (_object.statusbar:GetWidth()/100) - 18, 0)
+ end
+ --> right text
+ local smember_rtext = function (_object, _value)
+ return _object.textright:SetText (_value)
+ end
+ --> left text
+ local smember_ltext = function (_object, _value)
+ return _object.textleft:SetText (_value)
+ end
+ --> right color
+ local smember_rcolor = function (_object, _value)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_value)
+ _object.background.original_colors = {_value1, _value2, _value3, _value4}
+ return _object.background:SetVertexColor (_value1, _value2, _value3, _value4)
+ end
+ --> left color
+ local smember_lcolor = function (_object, _value)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_value)
+
+ _object.statusbar:SetStatusBarColor (_value1, _value2, _value3, _value4)
+ _object.texture.original_colors = {_value1, _value2, _value3, _value4}
+ return _object.texture:SetVertexColor (_value1, _value2, _value3, _value4)
+ end
+ --> right icon
+ local smember_ricon = function (_object, _value)
+ if (type (_value) == "table") then
+ local _value1, _value2 = _unpack (_value)
+ _object.iconright:SetTexture (_value1)
+ if (_value2) then
+ _object.iconright:SetTexCoord (_unpack (_value2))
+ end
+ else
+ _object.iconright:SetTexture (_value)
+ end
+ return
+ end
+ --> left icon
+ local smember_licon = function (_object, _value)
+ if (type (_value) == "table") then
+ local _value1, _value2 = _unpack (_value)
+ _object.iconleft:SetTexture (_value1)
+ if (_value2) then
+ _object.iconleft:SetTexCoord (_unpack (_value2))
+ end
+ else
+ _object.iconleft:SetTexture (_value)
+ end
+ return
+ end
+ --> texture
+ local smember_texture = function (_object, _value)
+ if (type (_value) == "table") then
+ local _value1, _value2 = _unpack (_value)
+ _object.texture:SetTexture (_value1)
+ _object.background:SetTexture (_value1)
+ if (_value2) then
+ _object.texture:SetTexCoord (_unpack (_value2))
+ _object.background:SetTexCoord (_unpack (_value2))
+ end
+ else
+ _object.texture:SetTexture (_value)
+ _object.background:SetTexture (_value)
+ end
+ return
+ end
+ --> font face
+ local smember_textfont = function (_object, _value)
+ _detalhes:SetFontFace (_object.textleft, _value)
+ return _detalhes:SetFontFace (_object.textright, _value)
+ end
+ --> font size
+ local smember_textsize = function (_object, _value)
+ _detalhes:SetFontSize (_object.textleft, _value)
+ return _detalhes:SetFontSize (_object.textright, _value)
+ end
+ --> font color
+ local smember_textcolor = function (_object, _value)
+ local _value1, _value2, _value3, _value4 = gump:ParseColors (_value)
+ _object.textleft:SetTextColor (_value1, _value2, _value3, _value4)
+ return _object.textright:SetTextColor (_value1, _value2, _value3, _value4)
+ end
+
+ local set_members_function_index = {
+ ["tooltip"] = smember_tooltip,
+ ["shown"] = smember_shown,
+ ["width"] = smember_width,
+ ["height"] = smember_height,
+ ["value"] = smember_value,
+ ["righttext"] = smember_rtext,
+ ["lefttext"] = smember_ltext,
+ ["rightcolor"] = smember_rcolor,
+ ["leftcolor"] = smember_lcolor,
+ ["righticon"] = smember_ricon,
+ ["lefticon"] = smember_licon,
+ ["texture"] = smember_texture,
+ ["fontsize"] = smember_textsize,
+ ["fontface"] = smember_textfont,
+ ["fontcolor"] = smember_textcolor,
+ ["textsize"] = smember_textsize, --alias
+ ["textfont"] = smember_textfont, --alias
+ ["textcolor"] = smember_textcolor --alias
+ }
+
+ SplitBarMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+
+--> show & hide
+ function SplitBarMetaFunctions:Show()
+ return self.statusbar:Show()
+ end
+ function SplitBarMetaFunctions:Hide()
+ return self.statusbar:Hide()
+ end
+
+-- set split
+ function SplitBarMetaFunctions:SetSplit (value)
+ if (not value) then
+ value = self.statusbar:GetValue()
+ elseif (value < 0 or value > 100) then
+ return
+ end
+ self.statusbar:SetValue (value)
+ self.div:SetPoint ("left", self.statusbar, "left", value * (self.statusbar:GetWidth()/100) - 18, 0)
+ end
+
+-- setpoint
+ function SplitBarMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
+ v1, v2, v3, v4, v5 = gump:CheckPoints (v1, v2, v3, v4, v5, self)
+ if (not v1) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+ return self.widget:SetPoint (v1, v2, v3, v4, v5)
+ end
+
+-- sizes
+ function SplitBarMetaFunctions:SetSize (w, h)
+ if (w) then
+ self.statusbar:SetWidth (w)
+ end
+ if (h) then
+ self.statusbar:SetHeight (h)
+ end
+ end
+
+-- texture
+ function SplitBarMetaFunctions:SetTexture (texture)
+ self.background:SetTexture (texture)
+ self.texture:SetTexture (texture)
+ end
+
+-- texts
+ function SplitBarMetaFunctions:SetLeftText (text)
+ self.textleft:SetText (text)
+ end
+ function SplitBarMetaFunctions:SetRightText (text)
+ self.textright:SetText (text)
+ end
+
+-- colors
+ function SplitBarMetaFunctions:SetLeftColor (r, g, b, a)
+ r, g, b, a = gump:ParseColors (r, g, b, a)
+ self.texture:SetVertexColor (r, g, b, a)
+ self.texture.original_colors = {r, g, b, a}
+ end
+ function SplitBarMetaFunctions:SetRightColor (r, g, b, a)
+ r, g, b, a = gump:ParseColors (r, g, b, a)
+ self.background:SetVertexColor (r, g, b, a)
+ self.background.original_colors = {r, g, b, a}
+ end
+
+-- icons
+ function SplitBarMetaFunctions:SetLeftIcon (texture, ...)
+ self.iconleft:SetTexture (texture)
+ if (...) then
+ local L, R, U, D = unpack (...)
+ self.iconleft:SetTexCoord (L, R, U, D)
+ end
+ end
+ function SplitBarMetaFunctions:SetRightIcon (texture, ...)
+ self.iconright:SetTexture (texture)
+ if (...) then
+ local L, R, U, D = unpack (...)
+ self.iconright:SetTexCoord (L, R, U, D)
+ end
+ end
+
+-- tooltip
+ function SplitBarMetaFunctions:SetTooltip (tooltip)
+ if (tooltip) then
+ return _rawset (self, "have_tooltip", tooltip)
+ else
+ return _rawset (self, "have_tooltip", nil)
+ end
+ end
+ function SplitBarMetaFunctions:GetTooltip()
+ return _rawget (self, "have_tooltip")
+ end
+
+-- frame levels
+ function SplitBarMetaFunctions:GetFrameLevel()
+ return self.statusbar:GetFrameLevel()
+ end
+ function SplitBarMetaFunctions:SetFrameLevel (level, frame)
+ if (not frame) then
+ return self.statusbar:SetFrameLevel (level)
+ else
+ local framelevel = frame:GetFrameLevel (frame) + level
+ return self.statusbar:SetFrameLevel (framelevel)
+ end
+ end
+
+-- frame stratas
+ function SplitBarMetaFunctions:SetFrameStrata()
+ return self.statusbar:GetFrameStrata()
+ end
+ function SplitBarMetaFunctions:SetFrameStrata (strata)
+ if (_type (strata) == "table") then
+ self.statusbar:SetFrameStrata (strata:GetFrameStrata())
+ else
+ self.statusbar:SetFrameStrata (strata)
+ end
+ end
+
+--> hooks
+ function SplitBarMetaFunctions:SetHook (hookType, func)
+ if (func) then
+ _rawset (self, hookType.."Hook", func)
+ else
+ _rawset (self, hookType.."Hook", nil)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> scripts
+ local OnEnter = function (frame)
+ if (frame.MyObject.OnEnterHook) then
+ local interrupt = frame.MyObject.OnEnterHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+
+ local oc = frame.MyObject.texture.original_colors --original colors
+ gump:GradientEffect ( frame.MyObject.texture, "texture", oc[1], oc[2], oc[3], oc[4], oc[1]+0.2, oc[2]+0.2, oc[3]+0.2, oc[4], .2)
+ frame.MyObject.div:SetPoint ("left", frame, "left", frame:GetValue() * (frame:GetWidth()/100) - 18, 0)
+
+ if (frame.MyObject.have_tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:AddLine (frame.MyObject.have_tooltip)
+ GameCooltip:ShowCooltip (frame, "tooltip")
+ end
+
+ local parent = frame:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient()
+ end
+ end
+ end
+
+ local OnLeave = function (frame)
+ if (frame.MyObject.OnLeaveHook) then
+ local interrupt = frame.MyObject.OnLeaveHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+
+ local oc = frame.MyObject.texture.original_colors --original colors
+ local r, g, b, a = frame.MyObject.texture:GetVertexColor()
+ gump:GradientEffect ( frame.MyObject.texture, "texture", r, g, b, a, oc[1], oc[2], oc[3], oc[4], .2)
+
+ if (frame.MyObject.have_tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+
+ local parent = frame:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient (false)
+ end
+ end
+ end
+
+ local OnHide = function (frame)
+ if (frame.MyObject.OnHideHook) then
+ local interrupt = frame.MyObject.OnHideHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnShow = function (frame)
+ if (frame.MyObject.OnShowHook) then
+ local interrupt = frame.MyObject.OnShowHook (frame)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnMouseDown = function (frame, button)
+ if (frame.MyObject.OnMouseDownHook) then
+ local interrupt = frame.MyObject.OnMouseDownHook (frame, button)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (not frame.MyObject.container.isLocked and frame.MyObject.container:IsMovable()) then
+ if (not frame.isLocked and frame:IsMovable()) then
+ frame.MyObject.container.isMoving = true
+ frame.MyObject.container:StartMoving()
+ end
+ end
+ end
+
+ local OnMouseUp = function (frame, button)
+ if (frame.MyObject.OnMouseUpHook) then
+ local interrupt = frame.MyObject.OnMouseUpHook (frame, button)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (frame.MyObject.container.isMoving) then
+ frame.MyObject.container:StopMovingOrSizing()
+ frame.MyObject.container.isMoving = false
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+
+function DetailsSplitlBar_OnCreate (self)
+ self.texture.original_colors = {1, 1, 1, 1}
+ self.background.original_colors = {.5, .5, .5, 1}
+ self.spark:SetPoint ("left", self, "left", self:GetValue() * (self:GetWidth()/100) - 18, 0)
+ return true
+end
+
+function gump:NewSplitBar (parent, container, name, member, w, h)
+
+ if (not name) then
+ return nil
+ elseif (not parent) then
+ return nil
+ elseif (not container) then
+ container = parent
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+ local SplitBarObject = {type = "barsplit", dframework = true}
+
+ if (member) then
+ parent [member] = SplitBarObject
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+ --> default members:
+ --> hooks
+ SplitBarObject.OnEnterHook = nil
+ SplitBarObject.OnLeaveHook = nil
+ SplitBarObject.OnHideHook = nil
+ SplitBarObject.OnShowHook = nil
+ SplitBarObject.OnMouseDownHook = nil
+ SplitBarObject.OnMouseUpHook = nil
+ --> misc
+ SplitBarObject.tooltip = nil
+ SplitBarObject.locked = false
+ SplitBarObject.have_tooltip = nil
+ SplitBarObject.container = container
+
+ --> create widgets
+ SplitBarObject.statusbar = CreateFrame ("statusbar", name, parent, "DetailsSplitBarTemplate")
+ SplitBarObject.widget = SplitBarObject.statusbar
+
+ if (not APISplitBarFunctions) then
+ APISplitBarFunctions = true
+ local idx = getmetatable (SplitBarObject.statusbar).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not SplitBarMetaFunctions [funcName]) then
+ SplitBarMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.statusbar:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ SplitBarObject.statusbar:SetHeight (h or 200)
+ SplitBarObject.statusbar:SetWidth (w or 14)
+
+ SplitBarObject.statusbar.MyObject = SplitBarObject
+
+ SplitBarObject.textleft = _G [name .. "_TextLeft"]
+ SplitBarObject.textright = _G [name .. "_TextRight"]
+
+ SplitBarObject.iconleft = _G [name .. "_IconLeft"]
+ SplitBarObject.iconright = _G [name .. "_IconRight"]
+
+ SplitBarObject.background = _G [name .. "_StatusBarBackground"]
+ SplitBarObject.texture = _G [name .. "_StatusBarTexture"]
+
+ SplitBarObject.div = _G [name .. "_Spark"]
+
+
+ --> hooks
+ SplitBarObject.statusbar:SetScript ("OnEnter", OnEnter)
+ SplitBarObject.statusbar:SetScript ("OnLeave", OnLeave)
+ SplitBarObject.statusbar:SetScript ("OnHide", OnHide)
+ SplitBarObject.statusbar:SetScript ("OnShow", OnShow)
+ SplitBarObject.statusbar:SetScript ("OnMouseDown", OnMouseDown)
+ SplitBarObject.statusbar:SetScript ("OnMouseUp", OnMouseUp)
+
+ _setmetatable (SplitBarObject, SplitBarMetaFunctions)
+
+ return SplitBarObject
+end
\ No newline at end of file
diff --git a/framework/split_bar.xml b/framework/split_bar.xml
new file mode 100644
index 00000000..be7236c1
--- /dev/null
+++ b/framework/split_bar.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:SetStatusBarTexture (self.texture);
+ self:SetMinMaxValues (1, 100);
+ self:SetValue (50);
+ DetailsSplitlBar_OnCreate (self);
+
+
+
+
+
\ No newline at end of file
diff --git a/framework/textentry.lua b/framework/textentry.lua
new file mode 100644
index 00000000..06a9719c
--- /dev/null
+++ b/framework/textentry.lua
@@ -0,0 +1,560 @@
+--> details main objects
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+local _rawset = rawset --> lua local
+local _rawget = rawget --> lua local
+local _setmetatable = setmetatable --> lua local
+local _unpack = unpack --> lua local
+local _type = type --> lua local
+local _math_floor = math.floor --> lua local
+local loadstring = loadstring --> lua local
+local _string_len = string.len --> lua local
+
+local cleanfunction = function() end
+local APITextEntryFunctions = false
+local TextEntryMetaFunctions = {}
+
+------------------------------------------------------------------------------------------------------------
+--> metatables
+
+ TextEntryMetaFunctions.__call = function (_table, value)
+ --> unknow
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> members
+
+ --> tooltip
+ local gmember_tooltip = function (_object)
+ return _object:GetTooltip()
+ end
+ --> shown
+ local gmember_shown = function (_object)
+ return _object:IsShown()
+ end
+ --> frame width
+ local gmember_width = function (_object)
+ return _object.editbox:GetWidth()
+ end
+ --> frame height
+ local gmember_height = function (_object)
+ return _object.editbox:GetHeight()
+ end
+ --> get text
+ local gmember_text = function (_object)
+ return _object.editbox:GetText()
+ end
+
+ local get_members_function_index = {
+ ["tooltip"] = gmember_tooltip,
+ ["shown"] = gmember_shown,
+ ["width"] = gmember_width,
+ ["height"] = gmember_height,
+ ["text"] = gmember_text,
+ }
+
+ TextEntryMetaFunctions.__index = function (_table, _member_requested)
+
+ local func = get_members_function_index [_member_requested]
+ if (func) then
+ return func (_table, _member_requested)
+ end
+
+ local fromMe = _rawget (_table, _member_requested)
+ if (fromMe) then
+ return fromMe
+ end
+
+ return TextEntryMetaFunctions [_member_requested]
+ end
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> tooltip
+ local smember_tooltip = function (_object, _value)
+ return _object:SetTooltip (_value)
+ end
+ --> show
+ local smember_show = function (_object, _value)
+ if (_value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> hide
+ local smember_hide = function (_object, _value)
+ if (not _value) then
+ return _object:Show()
+ else
+ return _object:Hide()
+ end
+ end
+ --> frame width
+ local smember_width = function (_object, _value)
+ return _object.editbox:SetWidth (_value)
+ end
+ --> frame height
+ local smember_height = function (_object, _value)
+ return _object.editbox:SetHeight (_value)
+ end
+ --> set text
+ local smember_text = function (_object, _value)
+ return _object.editbox:SetText (_value)
+ end
+ --> set multiline
+ local smember_multiline = function (_object, _value)
+ if (_value) then
+ return _object.editbox:SetMultiLine (true)
+ else
+ return _object.editbox:SetMultiLine (false)
+ end
+ end
+ --> text horizontal pos
+ local smember_horizontalpos = function (_object, _value)
+ return _object.editbox:SetJustifyH (string.lower (_value))
+ end
+
+ local set_members_function_index = {
+ ["tooltip"] = smember_tooltip,
+ ["show"] = smember_show,
+ ["hide"] = smember_hide,
+ ["width"] = smember_width,
+ ["height"] = smember_height,
+ ["text"] = smember_text,
+ ["multiline"] = smember_multiline,
+ ["align"] = smember_horizontalpos,
+ }
+
+ TextEntryMetaFunctions.__newindex = function (_table, _key, _value)
+ local func = set_members_function_index [_key]
+ if (func) then
+ return func (_table, _value)
+ else
+ return _rawset (_table, _key, _value)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> methods
+
+--> set point
+ function TextEntryMetaFunctions:SetPoint (MyAnchor, SnapTo, HisAnchor, x, y, Width)
+
+ if (type (MyAnchor) == "boolean" and MyAnchor and self.space) then
+ local textWidth = self.label:GetStringWidth()+2
+ self.editbox:SetWidth (self.space - textWidth - 15)
+ return
+
+ elseif (type (MyAnchor) == "boolean" and MyAnchor and not self.space) then
+ self.space = self.label:GetStringWidth()+2 + self.editbox:GetWidth()
+ end
+
+ if (Width) then
+ self.space = Width
+ end
+
+ MyAnchor, SnapTo, HisAnchor, x, y = gump:CheckPoints (MyAnchor, SnapTo, HisAnchor, x, y, self)
+ if (not MyAnchor) then
+ print ("Invalid parameter for SetPoint")
+ return
+ end
+
+ if (self.space) then
+ self.label:ClearAllPoints()
+ self.editbox:ClearAllPoints()
+
+ self.label:SetPoint (MyAnchor, SnapTo, HisAnchor, x, y)
+ self.editbox:SetPoint ("left", self.label, "right", 2, 0)
+
+ local textWidth = self.label:GetStringWidth()+2
+ self.editbox:SetWidth (self.space - textWidth - 15)
+ else
+ self.label:ClearAllPoints()
+ self.editbox:ClearAllPoints()
+ self.editbox:SetPoint (MyAnchor, SnapTo, HisAnchor, x, y)
+ end
+
+ end
+
+--> frame levels
+ function TextEntryMetaFunctions:GetFrameLevel()
+ return self.editbox:GetFrameLevel()
+ end
+ function TextEntryMetaFunctions:SetFrameLevel (level, frame)
+ if (not frame) then
+ return self.editbox:SetFrameLevel (level)
+ else
+ local framelevel = frame:GetFrameLevel (frame) + level
+ return self.editbox:SetFrameLevel (framelevel)
+ end
+ end
+
+--> set labal description
+ function TextEntryMetaFunctions:SetLabelText (text)
+ if (text) then
+ self.label:SetText (text)
+ else
+ self.label:SetText ("")
+ end
+ self:SetPoint (true) --> refresh
+ end
+
+--> set tab order
+ function TextEntryMetaFunctions:SetNext (nextbox)
+ self.next = nextbox
+ end
+
+--> blink
+ function TextEntryMetaFunctions:Blink()
+ self.label:SetTextColor (1, .2, .2, 1)
+ end
+
+--> show & hide
+ function TextEntryMetaFunctions:IsShown()
+ return self.editbox:IsShown()
+ end
+ function TextEntryMetaFunctions:Show()
+ return self.editbox:Show()
+ end
+ function TextEntryMetaFunctions:Hide()
+ return self.editbox:Hide()
+ end
+
+-- tooltip
+ function TextEntryMetaFunctions:SetTooltip (tooltip)
+ if (tooltip) then
+ return _rawset (self, "have_tooltip", tooltip)
+ else
+ return _rawset (self, "have_tooltip", nil)
+ end
+ end
+ function TextEntryMetaFunctions:GetTooltip()
+ return _rawget (self, "have_tooltip")
+ end
+
+--> hooks
+ function TextEntryMetaFunctions:SetHook (hookType, func)
+ if (func) then
+ _rawset (self, hookType.."Hook", func)
+ else
+ _rawset (self, hookType.."Hook", nil)
+ end
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> scripts
+ local OnEnter = function (textentry)
+
+ if (textentry.MyObject.OnEnterHook) then
+ local interrupt = textentry.MyObject.OnEnterHook (textentry)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (textentry.MyObject.have_tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:SetType ("tooltip")
+ GameCooltip:SetColor ("main", "transparent")
+ GameCooltip:AddLine (textentry.MyObject.have_tooltip)
+ GameCooltip:SetOwner (textentry)
+ GameCooltip:ShowCooltip()
+ end
+
+ textentry.mouse_over = true
+
+ if (textentry:IsEnabled()) then
+ textentry:SetBackdropBorderColor (0.5, 0.5, 0.5, 1)
+ end
+
+ local parent = textentry:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient()
+ end
+ end
+
+ end
+
+ local OnLeave = function (textentry)
+ if (textentry.MyObject.OnLeaveHook) then
+ local interrupt = textentry.MyObject.OnLeaveHook (textentry)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (textentry.MyObject.have_tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+
+ textentry.mouse_over = false
+
+ if (textentry:IsEnabled()) then
+ textentry:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
+ end
+
+ local parent = textentry:GetParent().MyObject
+ if (parent and parent.type == "panel") then
+ if (parent.GradientEnabled) then
+ parent:RunGradient (false)
+ end
+ end
+ end
+
+ local OnHide = function (textentry)
+ if (textentry.MyObject.OnHideHook) then
+ local interrupt = textentry.MyObject.OnHideHook (textentry)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnShow = function (textentry)
+ if (textentry.MyObject.OnShowHook) then
+ local interrupt = textentry.MyObject.OnShowHook (textentry)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnEnterPressed = function (textentry, byScript)
+
+ if (textentry.MyObject.OnEnterPressedHook) then
+ local interrupt = textentry.MyObject.OnEnterPressedHook (textentry)
+ if (interrupt) then
+ return
+ end
+ end
+
+ local texto = _detalhes:trim (textentry:GetText())
+ if (_string_len (texto) > 0) then
+ textentry.text = texto
+ if (textentry.MyObject.func) then
+ textentry.MyObject.func (textentry.MyObject.param1, textentry.MyObject.param2, texto, textentry, byScript or textentry)
+ end
+ else
+ textentry:SetText ("")
+ textentry.MyObject.currenttext = ""
+ end
+ textentry.focuslost = true --> perdeu_focus isso aqui pra quando estiver editando e clicar em outra caixa
+ textentry:ClearFocus()
+
+ if (textentry.MyObject.tab_on_enter and textentry.MyObject.next) then
+ textentry.MyObject.next:SetFocus()
+ end
+ end
+
+ local OnEscapePressed = function (textentry)
+
+ if (textentry.MyObject.OnEscapePressedHook) then
+ local interrupt = textentry.MyObject.OnEscapePressedHook (textentry)
+ if (interrupt) then
+ return
+ end
+ end
+
+ textentry:SetText("")
+ textentry.MyObject.currenttext = ""
+ textentry.focuslost = true
+ textentry:ClearFocus()
+ end
+
+ local OnEditFocusLost = function (textentry)
+
+ if (textentry:IsShown()) then
+
+ if (textentry.MyObject.OnEditFocusLostHook) then
+ local interrupt = textentry.MyObject.OnEditFocusLostHook (textentry)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (not textentry.focuslost) then
+ local texto = _detalhes:trim (textentry:GetText())
+ if (_string_len (texto) > 0) then
+ textentry.MyObject.currenttext = texto
+ if (textentry.MyObject.func) then
+ textentry.MyObject.func (textentry.MyObject.param1, textentry.MyObject.param2, texto, textentry, nil)
+ end
+ else
+ textentry:SetText ("")
+ textentry.MyObject.currenttext = ""
+ end
+ else
+ textentry.focuslost = false
+ end
+
+ textentry.MyObject.label:SetTextColor (.8, .8, .8, 1)
+
+ end
+ end
+
+ local OnEditFocusGained = function (textentry)
+ if (textentry.MyObject.OnEditFocusGainedHook) then
+ local interrupt = textentry.MyObject.OnEditFocusGainedHook (textentry)
+ if (interrupt) then
+ return
+ end
+ end
+ textentry.MyObject.label:SetTextColor (1, 1, 1, 1)
+ end
+
+ local OnChar = function (textentry, text)
+ if (textentry.MyObject.OnCharHook) then
+ local interrupt = textentry.MyObject.OnCharHook (textentry, text)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnTextChanged = function (textentry, byUser)
+ if (textentry.MyObject.OnTextChangedHook) then
+ local interrupt = textentry.MyObject.OnTextChangedHook (textentry, byUser)
+ if (interrupt) then
+ return
+ end
+ end
+ end
+
+ local OnTabPressed = function (textentry)
+ if (textentry.MyObject.OnTabPressedHook) then
+ local interrupt = textentry.MyObject.OnTabPressedHook (textentry, byUser)
+ if (interrupt) then
+ return
+ end
+ end
+
+ if (textentry.MyObject.next) then
+ OnEnterPressed (textentry, false)
+ textentry.MyObject.next:SetFocus()
+ end
+ end
+
+ function TextEntryMetaFunctions:PressEnter (byScript)
+ OnEnterPressed (self.editbox, byScript)
+ end
+
+------------------------------------------------------------------------------------------------------------
+--> object constructor
+
+function gump:NewTextEntry (parent, container, name, member, w, h, func, param1, param2, space)
+
+ if (not name) then
+ return nil
+ elseif (not parent) then
+ return nil
+ end
+ if (not container) then
+ container = parent
+ end
+
+ if (name:find ("$parent")) then
+ name = name:gsub ("$parent", parent:GetName())
+ end
+
+ local TextEntryObject = {type = "textentry", dframework = true}
+
+ if (member) then
+ parent [member] = TextEntryObject
+ end
+
+ if (parent.dframework) then
+ parent = parent.widget
+ end
+ if (container.dframework) then
+ container = container.widget
+ end
+
+ --> default members:
+ --> hooks
+ TextEntryObject.OnEnterHook = nil
+ TextEntryObject.OnLeaveHook = nil
+ TextEntryObject.OnHideHook = nil
+ TextEntryObject.OnShowHook = nil
+ TextEntryObject.OnEnterPressedHook = nil
+ TextEntryObject.OnEscapePressedHook = nil
+ TextEntryObject.OnEditFocusGainedHook = nil
+ TextEntryObject.OnEditFocusLostHook = nil
+ TextEntryObject.OnCharHook = nil
+ TextEntryObject.OnTextChangedHook = nil
+ TextEntryObject.OnTabPressedHook = nil
+
+ --> misc
+ TextEntryObject.container = container
+ TextEntryObject.have_tooltip = nil
+
+ TextEntryObject.editbox = CreateFrame ("EditBox", name, parent, "DetailsEditBoxTemplate2")
+ TextEntryObject.widget = TextEntryObject.editbox
+
+ if (not APITextEntryFunctions) then
+ APITextEntryFunctions = true
+ local idx = getmetatable (TextEntryObject.editbox).__index
+ for funcName, funcAddress in pairs (idx) do
+ if (not TextEntryMetaFunctions [funcName]) then
+ TextEntryMetaFunctions [funcName] = function (object, ...)
+ local x = loadstring ( "return _G."..object.editbox:GetName()..":"..funcName.."(...)")
+ return x (...)
+ end
+ end
+ end
+ end
+
+ TextEntryObject.editbox.MyObject = TextEntryObject
+
+ if (not w and space) then
+ w = space
+ elseif (w and space) then
+ if (gump.debug) then
+ print ("warning: you are using width and space, try use only space for better results.")
+ end
+ end
+
+ TextEntryObject.editbox:SetWidth (w)
+ TextEntryObject.editbox:SetHeight (h)
+
+ TextEntryObject.editbox:SetJustifyH ("center")
+ TextEntryObject.editbox:EnableMouse (true)
+ TextEntryObject.editbox:SetText ("")
+ TextEntryObject.editbox:SetBackdrop ({bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ tile = true, edgeSize = 1, tileSize = 5})
+ TextEntryObject.editbox:SetBackdropColor (0, 0, 0, 0.5)
+ TextEntryObject.editbox:SetBackdropBorderColor (0.3, 0.3, 0.30, 0.80)
+ TextEntryObject.editbox:SetAutoFocus (false)
+ TextEntryObject.editbox:SetFontObject ("GameFontHighlightSmall")
+
+ TextEntryObject.func = func
+ TextEntryObject.param1 = param1
+ TextEntryObject.param2 = param2
+ TextEntryObject.next = nil
+ TextEntryObject.space = space
+ TextEntryObject.tab_on_enter = false
+
+ TextEntryObject.label = _G [name .. "_Desc"]
+
+ --> hooks
+ TextEntryObject.editbox:SetScript ("OnEnter", OnEnter)
+ TextEntryObject.editbox:SetScript ("OnLeave", OnLeave)
+ TextEntryObject.editbox:SetScript ("OnHide", OnHide)
+ TextEntryObject.editbox:SetScript ("OnShow", OnShow)
+
+ TextEntryObject.editbox:SetScript ("OnEnterPressed", OnEnterPressed)
+ TextEntryObject.editbox:SetScript ("OnEscapePressed", OnEscapePressed)
+ TextEntryObject.editbox:SetScript ("OnEditFocusLost", OnEditFocusLost)
+ TextEntryObject.editbox:SetScript ("OnEditFocusGained", OnEditFocusGained)
+ TextEntryObject.editbox:SetScript ("OnChar", OnChar)
+ TextEntryObject.editbox:SetScript ("OnTextChanged", OnTextChanged)
+ TextEntryObject.editbox:SetScript ("OnTabPressed", OnTabPressed)
+
+ _setmetatable (TextEntryObject, TextEntryMetaFunctions)
+
+ return TextEntryObject
+
+end
\ No newline at end of file
diff --git a/framework/textentry.xml b/framework/textentry.xml
new file mode 100644
index 00000000..fdecd680
--- /dev/null
+++ b/framework/textentry.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/functions/attributes.lua b/functions/attributes.lua
new file mode 100644
index 00000000..a1ce8fd6
--- /dev/null
+++ b/functions/attributes.lua
@@ -0,0 +1,157 @@
+--[[ Attributes: Damage, Heal, Energy, Miscellaneous ]]
+
+do
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+ --> Globals
+ DETAILS_ATTRIBUTE_DAMAGE = 1
+ DETAILS_ATTRIBUTE_HEAL = 2
+ DETAILS_ATTRIBUTE_ENERGY = 3
+ DETAILS_ATTRIBUTE_MISC = 4
+
+ --> Main Attributes
+ _detalhes.atributos = {
+
+ --> Attributes amount = 4: damage / heal / energy / misc
+ [0] = 4,
+
+ --[[ DAMAGE ]]
+ dano = 1, --> identifier
+ [1] = 4, --> sub attributes
+
+ --[[ HEALING ]]
+ cura = 2, --> identifier
+ [2] = 4, --> sub attributes
+
+ --[[ ENERGY ]]
+ e_energy = 3,--> identifier
+ [3] = 4, --> sub attributes
+
+ --[[ MISC ]]
+ misc = 4, --> identifier
+ [4] = 5, --> sub attributes
+
+ --[[ CUSTOM ]]
+ custom = 5,
+ [5] = false,
+
+ --[[ String Names ]]
+ lista = {
+ Loc ["STRING_ATTRIBUTE_DAMAGE"],--> Damage
+ Loc ["STRING_ATTRIBUTE_HEAL"], --> Healing
+ Loc ["STRING_ATTRIBUTE_ENERGY"], --> Energy
+ Loc ["STRING_ATTRIBUTE_MISC"], --> Misc
+ Loc ["STRING_ATTRIBUTE_CUSTOM"] --> Custom
+ }
+ }
+
+
+ --> Sub Attributes
+ _detalhes.sub_atributos = {
+ {
+ --> Damage sub classes information
+ damage_done = 1,
+ dps = 2,
+ damage_taken = 3,
+ friendly_fire = 4,
+ lista = { --[[ String Names ]]
+ Loc ["STRING_ATTRIBUTE_DAMAGE_DONE"],
+ Loc ["STRING_ATTRIBUTE_DAMAGE_DPS"],
+ Loc ["STRING_ATTRIBUTE_DAMAGE_TAKEN"],
+ Loc ["STRING_ATTRIBUTE_DAMAGE_FRIENDLYFIRE"]
+ },
+ icones = {
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_damage", {0, .125, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_damage", {.125, .25, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_damage", {.25, .375, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_damage", {.375, .5, 0, 1}}
+ }
+ },
+
+ {
+ --> Healing sub classes information
+ healing_done = 1,
+ hps = 2,
+ overheal = 3,
+ healing_tanken = 4,
+ lista = { --[[ String Names ]]
+ Loc ["STRING_ATTRIBUTE_HEAL_DONE"],
+ Loc ["STRING_ATTRIBUTE_HEAL_HPS"],
+ Loc ["STRING_ATTRIBUTE_HEAL_OVERHEAL"],
+ Loc ["STRING_ATTRIBUTE_HEAL_TAKEN"]
+ },
+
+ icones = {
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_heal", {0, .125, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_heal", {.125, .25, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_heal", {.25, .375, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_heal", {.375, .5, 0, 1}}
+ }
+ },
+
+ {
+ --> Energy sub classes information
+ mana_ganha = 1, -- id 0
+ rage_ganha = 2, -- id 1
+ energy_ganha = 3, --id 3
+ rune_ganha = 4, --id 6
+ lista = { --[[ String Names ]]
+ Loc ["STRING_ATTRIBUTE_ENERGY_MANA"],
+ Loc ["STRING_ATTRIBUTE_ENERGY_RAGE"],
+ Loc ["STRING_ATTRIBUTE_ENERGY_ENERGY"],
+ Loc ["STRING_ATTRIBUTE_ENERGY_RUNEPOWER"]
+ },
+ icones = {
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_energyze", {0, .125, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_energyze", {.125, .25, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_energyze", {.25, .375, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_energyze", {.375, .5, 0, 1}}
+ },
+ internal = {"mana", "e_rage", "e_energy", "runepower"}
+ },
+
+ {
+ --> Misc sub classes information
+ cc_break = 1,
+ ress = 2,
+ kick = 3,
+ dispell = 4,
+ deaths = 5,
+ lista = { --[[ String Names ]]
+ Loc ["STRING_ATTRIBUTE_MISC_CCBREAK"],
+ Loc ["STRING_ATTRIBUTE_MISC_RESS"],
+ Loc ["STRING_ATTRIBUTE_MISC_INTERRUPT"],
+ Loc ["STRING_ATTRIBUTE_MISC_DISPELL"],
+ Loc ["STRING_ATTRIBUTE_MISC_DEAD"],
+ },
+ icones = {
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_misc", {0, .125, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_misc", {.125, .25, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_misc", {.25, .375, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_misc", {.375, .5, 0, 1}},
+ {"Interface\\AddOns\\Details\\images\\atributos_icones_misc", {.5, .625, 0, 1}}
+ },
+ internal = {"cc_break", "ress", "interrupt", "dispell", "dead"}
+ }
+ }
+
+ function _detalhes:GetAttributeName (attribute)
+ return _detalhes.atributos.lista [attribute]
+ end
+
+ function _detalhes:GetSubAttributeName (attribute, subAttribute)
+ if (attribute == 5) then
+ local CustomObject = _detalhes.custom [subAttribute]
+ return CustomObject.name
+ end
+ return _detalhes.sub_atributos [attribute].lista [subAttribute]
+ end
+
+ function _detalhes:GetInternalSubAttributeName (attribute, subAttribute)
+ if (attribute == 3 or attribute == 4) then
+ return _detalhes.sub_atributos [attribute].internal [subAttribute]
+ end
+ end
+
+end
diff --git a/functions/boss.lua b/functions/boss.lua
new file mode 100644
index 00000000..016e97e9
--- /dev/null
+++ b/functions/boss.lua
@@ -0,0 +1,96 @@
+
+do
+
+ local _detalhes = _G._detalhes
+ _detalhes.EncounterInformation = {}
+ local _ipairs = ipairs --> lua local
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ --> return if the player is inside a raid supported by details
+ function _detalhes:IsInInstance()
+ local _, _, _, _, _, _, _, zoneMapID = GetInstanceInfo()
+ if (_detalhes.EncounterInformation [zoneMapID]) then
+ return true
+ else
+ return false
+ end
+ end
+
+ --> return the function for the boss
+ function _detalhes:GetBossFunction (mapid, bossindex)
+ local func = _detalhes.EncounterInformation [mapid] and _detalhes.EncounterInformation [mapid].encounters [bossindex] and _detalhes.EncounterInformation [mapid].encounters [bossindex].func
+ if (func) then
+ return func, _detalhes.EncounterInformation [mapid].encounters [bossindex].funcType
+ end
+ return
+ end
+
+ --> return the boss table with information about name, adds, spells, etc
+ function _detalhes:GetBossDetails (mapid, bossindex)
+ return _detalhes.EncounterInformation [mapid] and _detalhes.EncounterInformation [mapid].encounters [bossindex]
+ end
+
+ --> return a table with spells id of specified encounter
+ function _detalhes:GetEncounterSpells (mapid, bossindex)
+ local encounter = _detalhes:GetBossDetails (mapid, bossindex)
+ local habilidades_poll = {}
+ if (encounter.continuo) then
+ for index, spellid in _ipairs (encounter.continuo) do
+ habilidades_poll [spellid] = true
+ end
+ end
+ local fases = encounter.phases
+ for fase_id, fase in _ipairs (fases) do
+ if (fase.spells) then
+ for index, spellid in _ipairs (fase.spells) do
+ habilidades_poll [spellid] = true
+ end
+ end
+ end
+ return habilidades_poll
+ end
+
+ --> return a table with all boss ids from a raid instance
+ function _detalhes:GetBossIds (mapid)
+ return _detalhes.EncounterInformation [mapid] and _detalhes.EncounterInformation [mapid].boss_ids
+ end
+
+ --> return a table with all encounter names present in raid instance
+ function _detalhes:GetBossNames (mapid)
+ return _detalhes.EncounterInformation [mapid] and _detalhes.EncounterInformation [mapid].boss_names
+ end
+
+ --> return the encounter name
+ function _detalhes:GetBossName (mapid, bossindex)
+ return _detalhes.EncounterInformation [mapid] and _detalhes.EncounterInformation [mapid].boss_names [bossindex]
+ end
+
+ --> same thing as GetBossDetails, just a alias
+ function _detalhes:GetBossEncounterDetails (mapid, bossindex)
+ return _detalhes.EncounterInformation [mapid] and _detalhes.EncounterInformation [mapid].encounters [bossindex]
+ end
+
+ --> return the wallpaper for the raid instance
+ function _detalhes:GetRaidBackground (mapid)
+ return _detalhes.EncounterInformation [mapid] and _detalhes.EncounterInformation [mapid].background
+ end
+
+ --> return the boss icon
+ function _detalhes:GetBossIcon (mapid, bossindex)
+ if (_detalhes.EncounterInformation [mapid]) then
+ local line = math.ceil (bossindex / 4)
+ local x = ( bossindex - ( (line-1) * 4 ) ) / 4
+ return x-0.25, x, 0.25 * (line-1), 0.25 * line, _detalhes.EncounterInformation [mapid].icons
+ end
+ end
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> core
+
+ function _detalhes:InstallEncounter (InstanceTable)
+ _detalhes.EncounterInformation [InstanceTable.id] = InstanceTable
+ return true
+ end
+end
\ No newline at end of file
diff --git a/functions/buff.lua b/functions/buff.lua
new file mode 100644
index 00000000..62464969
--- /dev/null
+++ b/functions/buff.lua
@@ -0,0 +1,195 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+ --> initialize buffs name container
+ _detalhes.Buffs.BuffsTable = {} -- armazenara o [nome do buff] = { tabela do buff }
+ _detalhes.Buffs.__index = _detalhes.Buffs
+
+ --> switch off recording buffs by default
+ _detalhes.RecordPlayerSelfBuffs = false
+ _detalhes.RecordPlayerAbilityWithBuffs = false
+ _detalhes.RecordPlayerSelfDebuffs = false
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _pairs = pairs --> lua local
+ local _ipairs = ipairs --> lua local
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ --> return if the buff is already registred or not
+ function _detalhes.Buffs:IsRegistred (buff)
+ if (type (buff) == "number") then
+ for _, buffObject in _pairs (_detalhes.Buffs.BuffsTable) do
+ if (buffObject.id == buff) then
+ return true
+ end
+ end
+ return false
+ elseif (type (buff) == "string") then
+ for name, _ in _pairs (_detalhes.Buffs.BuffsTable) do
+ if (name == buff) then
+ return true
+ end
+ end
+ return false
+ end
+ end
+
+ --> register a new buff name
+ function _detalhes.Buffs:NewBuff (BuffName, BuffId)
+ if (not BuffName) then
+ BuffName = GetSpellInfo (BuffId)
+ end
+ if (_detalhes.Buffs.BuffsTable [BuffName]) then
+ return false
+ else
+ _detalhes.Buffs.BuffsTable [BuffName] = _detalhes.Buffs:BuildBuffTable (BuffName, BuffId)
+ end
+ end
+
+ --> remove a registred buff
+ function _detalhes.Buffs:RemoveBuff (BuffName)
+ if (not _detalhes.Buffs.BuffsTable [BuffName]) then
+ return false
+ else
+ _detalhes.Buffs.BuffsTable = _detalhes:tableRemove (_detalhes.Buffs.BuffsTable, BuffName)
+ return true
+ end
+ end
+
+ --> return a list of registred buffs
+ function _detalhes.Buffs:GetBuffList()
+ local list = {}
+ for name, _ in _pairs (_detalhes.Buffs.BuffsTable) do
+ list [#list+1] = name
+ end
+ return list
+ end
+
+ --> return a list of registred buffs ids
+ function _detalhes.Buffs:GetBuffListIds()
+ local list = {}
+ for name, buffObject in _pairs (_detalhes.Buffs.BuffsTable) do
+ list [#list+1] = buffObject.id
+ end
+ return list
+ end
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ function _detalhes.Buffs:UpdateBuff (method)
+ -- self = buff table
+ if (method == "new") then
+
+ self.start = _detalhes._tempo
+ self.castedAmt = self.castedAmt + 1
+ self.active = true
+ self.appliedAt [#self.appliedAt+1] = _detalhes.tabela_vigente:GetCombatTime()
+ _detalhes:SendEvent ("BUFF_UPDATE")
+
+ elseif (method == "refresh") then
+
+ self.refreshAmt = self.refreshAmt + 1
+ self.duration = self.duration + (_detalhes._tempo - self.start)
+ self.start = _detalhes._tempo
+ self.appliedAt [#self.appliedAt+1] = _detalhes.tabela_vigente:GetCombatTime()
+ _detalhes:SendEvent ("BUFF_UPDATE")
+
+ elseif (method == "remove") then
+
+ if (self.start) then
+ self.duration = self.duration + (_detalhes._tempo - self.start)
+ else
+ self.duration = 0
+ end
+ self.droppedAmt = self.droppedAmt + 1
+ self.start = nil
+ self.active = false
+ _detalhes:SendEvent ("BUFF_UPDATE")
+
+ end
+ end
+
+ --> build buffs
+ function _detalhes.Buffs:BuildTables()
+ _detalhes.Buffs.built = true
+ if (_detalhes.savedbuffs) then
+ for _, BuffId in _ipairs (_detalhes.savedbuffs) do
+ _detalhes.Buffs:NewBuff (nil, BuffId)
+ end
+ end
+ end
+
+ --> save buff list when addon exit
+ function _detalhes.Buffs:SaveBuffs()
+ _detalhes_database.savedbuffs = _detalhes.Buffs:GetBuffListIds()
+ end
+
+ --> construct a buff table of the new buff registred
+ function _detalhes.Buffs:BuildBuffTable (BuffName, BuffId)
+ local bufftable = {name = BuffName, id = BuffId, duration = 0, start = nil, castedAmt = 0, refreshAmt = 0, droppedAmt = 0, active = false, appliedAt = {}}
+ bufftable.IsBuff = true
+ setmetatable (bufftable, _detalhes.Buffs)
+ return bufftable
+ end
+
+
+ --> update player buffs
+ function _detalhes.Buffs:CatchBuffs()
+
+ if (not _detalhes.Buffs.built) then
+ _detalhes.Buffs:BuildTables()
+ end
+
+ for _, BuffTable in _pairs (_detalhes.Buffs.BuffsTable) do
+ if (BuffTable.active) then
+ BuffTable.start = _detalhes._tempo
+ BuffTable.castedAmt = 1
+ else
+ BuffTable.start = nil
+ BuffTable.castedAmt = 0
+ end
+
+ BuffTable.appliedAt = {}
+ BuffTable.duration = 0
+ BuffTable.refreshAmt = 0
+ BuffTable.droppedAmt = 0
+ end
+
+ --> catch buffs untracked yet
+ for buffIndex = 1, 41 do
+ local name = UnitAura ("player", buffIndex)
+ if (name) then
+ local bufftable = _detalhes.Buffs.BuffsTable [name]
+ if (bufftable and not bufftable.active) then
+ bufftable.active = true
+ bufftable.castedAmt = 1
+ bufftable.start = _detalhes._tempo
+ end
+
+ --[[
+ for index, BuffName in _pairs (_detalhes.SoloTables.BuffsTableNameCache) do
+ if (BuffName == name) then
+ local BuffObject = _detalhes.SoloTables.SoloBuffUptime [name]
+ if (not BuffObject) then
+ _detalhes.SoloTables.SoloBuffUptime [name] = {name = name, duration = 0, start = nil, castedAmt = 1, refreshAmt = 0, droppedAmt = 0, Active = true, tableIndex = index, appliedAt = {}}
+ --_detalhes.SoloTables.BuffTextEntry [index].backgroundFrame:Active()
+ end
+ end
+ end
+ --]]
+ end
+ end
+ end
diff --git a/functions/classes.lua b/functions/classes.lua
new file mode 100644
index 00000000..4588d407
--- /dev/null
+++ b/functions/classes.lua
@@ -0,0 +1,101 @@
+--[[ Declare all Details classes and container indexes ]]
+
+do
+ local _detalhes = _G._detalhes
+ local setmetatable = setmetatable
+ -------- container que armazena o cache de pets
+ _detalhes.container_pets = {}
+ _detalhes.container_pets.__index = _detalhes.container_pets
+ setmetatable (_detalhes.container_pets, _detalhes)
+
+ -------- time machine controla o tempo em combate dos jogadores
+ _detalhes.timeMachine = {}
+ _detalhes.timeMachine.__index = _detalhes.timeMachine
+ setmetatable (_detalhes.timeMachine, _detalhes)
+
+ -------- classe da tabela que armazenará todos os combates efetuados
+ _detalhes.historico = {}
+ _detalhes.historico.__index = _detalhes.historico
+ setmetatable (_detalhes.historico, _detalhes)
+
+ ---------------- classe da tabela onde serão armazenados cada combate efetuado
+ _detalhes.combate = {}
+ _detalhes.combate.__index = _detalhes.combate
+ setmetatable (_detalhes.combate, _detalhes.historico)
+
+ ------------------------ armazenas classes de jogadores ou outros derivados
+ _detalhes.container_combatentes = {}
+ _detalhes.container_combatentes.__index = _detalhes.container_combatentes
+ setmetatable (_detalhes.container_combatentes, _detalhes.combate)
+
+ -------------------------------- dano das habilidades.
+ _detalhes.atributo_damage = {}
+ _detalhes.atributo_damage.__index = _detalhes.atributo_damage
+ setmetatable (_detalhes.atributo_damage, _detalhes.container_combatentes)
+
+ -------------------------------- cura das habilidades.
+ _detalhes.atributo_heal = {}
+ _detalhes.atributo_heal.__index = _detalhes.atributo_heal
+ setmetatable (_detalhes.atributo_heal, _detalhes.container_combatentes)
+
+ -------------------------------- e_energy ganha
+ _detalhes.atributo_energy = {}
+ _detalhes.atributo_energy.__index = _detalhes.atributo_energy
+ setmetatable (_detalhes.atributo_energy, _detalhes.container_combatentes)
+
+ -------------------------------- outros atributos
+ _detalhes.atributo_misc = {}
+ _detalhes.atributo_misc.__index = _detalhes.atributo_misc
+ setmetatable (_detalhes.atributo_misc, _detalhes.container_combatentes)
+
+ -------------------------------- atributos customizados
+ _detalhes.atributo_custom = {}
+ _detalhes.atributo_custom.__index = _detalhes.atributo_custom
+ setmetatable (_detalhes.atributo_custom, _detalhes.container_combatentes)
+
+ -------------------------------- armazena as classes de habilidades usadas pelo combatente
+ _detalhes.container_habilidades = {}
+ _detalhes.container_habilidades.__index = _detalhes.container_habilidades
+ setmetatable (_detalhes.container_habilidades, _detalhes.combate)
+
+ ---------------------------------------- classe das habilidades que dão cura
+ _detalhes.habilidade_cura = {}
+ _detalhes.habilidade_cura.__index = _detalhes.habilidade_cura
+ setmetatable (_detalhes.habilidade_cura, _detalhes.container_habilidades)
+
+ ---------------------------------------- classe das habilidades que dão danos
+ _detalhes.habilidade_dano = {}
+ _detalhes.habilidade_dano.__index = _detalhes.habilidade_dano
+ setmetatable (_detalhes.habilidade_dano, _detalhes.container_habilidades)
+
+ ---------------------------------------- classe das habilidades que dão e_energy
+ _detalhes.habilidade_e_energy = {}
+ _detalhes.habilidade_e_energy.__index = _detalhes.habilidade_e_energy
+ setmetatable (_detalhes.habilidade_e_energy, _detalhes.container_habilidades)
+
+ ---------------------------------------- classe das habilidades variadas
+ _detalhes.habilidade_misc = {}
+ _detalhes.habilidade_misc.__index = _detalhes.habilidade_misc
+ setmetatable (_detalhes.habilidade_misc, _detalhes.container_habilidades)
+
+ ---------------------------------------- classe dos alvos das habilidads
+ _detalhes.alvo_da_habilidade = {}
+ _detalhes.alvo_da_habilidade.__index = _detalhes.alvo_da_habilidade
+ setmetatable (_detalhes.alvo_da_habilidade, _detalhes.container_combatentes)
+
+
+
+ --[[ Armazena os diferentes tipos de containers ]] --[[ Container Types ]]
+ _detalhes.container_type = {
+ CONTAINER_PLAYERNPC = 1,
+ CONTAINER_DAMAGE_CLASS = 2,
+ CONTAINER_HEAL_CLASS = 3,
+ CONTAINER_HEALTARGET_CLASS = 4,
+ CONTAINER_FRIENDLYFIRE = 5,
+ CONTAINER_DAMAGETARGET_CLASS = 6,
+ CONTAINER_ENERGY_CLASS = 7,
+ CONTAINER_ENERGYTARGET_CLASS = 8,
+ CONTAINER_MISC_CLASS = 9,
+ CONTAINER_MISCTARGET_CLASS = 10
+ }
+end
diff --git a/functions/events.lua b/functions/events.lua
new file mode 100644
index 00000000..d2a1df03
--- /dev/null
+++ b/functions/events.lua
@@ -0,0 +1,532 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+ --> Event types:
+ _detalhes.RegistredEvents = {
+ --> details self events
+ --> instances
+ ["DETAILS_INSTANCE_OPEN"] = {},
+ ["DETAILS_INSTANCE_CLOSE"] = {},
+ ["DETAILS_INSTANCE_SIZECHANGED"] = {},
+ ["DETAILS_INSTANCE_STARTRESIZE"] = {},
+ ["DETAILS_INSTANCE_ENDRESIZE"] = {},
+ ["DETAILS_INSTANCE_STARTSTRETCH"] = {},
+ ["DETAILS_INSTANCE_ENDSTRETCH"] = {},
+ ["DETAILS_INSTANCE_CHANGESEGMENT"] = {},
+ ["DETAILS_INSTANCE_CHANGEATTRIBUTE"] = {},
+ ["DETAILS_INSTANCE_CHANGEMODE"] = {},
+
+ --> data
+ ["DETAILS_DATA_RESET"] = {},
+ ["DETAILS_DATA_SEGMENTREMOVED"] = {},
+
+ --> combat
+ ["COMBAT_PLAYER_ENTER"] = {},
+ ["COMBAT_PLAYER_LEAVE"] = {},
+ ["COMBAT_PLAYER_TIMESTARTED"] = {},
+ ["COMBAT_BOSS_FOUND"] = {},
+
+ --> buffs
+ ["BUFF_UPDATE"] = {},
+ ["BUFF_UPDATE_DEBUFFPOWER"] = {}
+ }
+
+ local function AlreadyRegistred (_tables, _object)
+ for index, _this_object in ipairs (_tables) do
+ if (_this_object.__eventtable) then
+ if (_this_object [1] == _object) then
+ return index
+ end
+ elseif (_this_object == _object) then
+ return index
+ end
+ end
+ return false
+ end
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ --> Register a Event
+ function _detalhes:RegisterEvent (object, event, func)
+
+ -------> combat -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ if (event == "COMBAT_PLAYER_ENTER") then
+
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["COMBAT_PLAYER_ENTER"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["COMBAT_PLAYER_ENTER"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["COMBAT_PLAYER_ENTER"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "COMBAT_PLAYER_LEAVE") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["COMBAT_PLAYER_LEAVE"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["COMBAT_PLAYER_LEAVE"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["COMBAT_PLAYER_LEAVE"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "COMBAT_PLAYER_TIMESTARTED") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["COMBAT_PLAYER_TIMESTARTED"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["COMBAT_PLAYER_TIMESTARTED"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["COMBAT_PLAYER_TIMESTARTED"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "COMBAT_BOSS_FOUND") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["COMBAT_BOSS_FOUND"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["COMBAT_BOSS_FOUND"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["COMBAT_BOSS_FOUND"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ -------> buffs -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ elseif (event == "BUFF_UPDATE") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["BUFF_UPDATE"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["BUFF_UPDATE"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["BUFF_UPDATE"], object)
+ end
+ _detalhes.Buffs:CatchBuffs()
+ _detalhes.RecordPlayerSelfBuffs = true
+ _detalhes:UpdateParserGears()
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "BUFF_UPDATE_DEBUFFPOWER") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["BUFF_UPDATE_DEBUFFPOWER"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["BUFF_UPDATE_DEBUFFPOWER"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["BUFF_UPDATE_DEBUFFPOWER"], object)
+ end
+ _detalhes.RecordPlayerAbilityWithBuffs = true
+ _detalhes:UpdateDamageAbilityGears()
+ _detalhes:UpdateParserGears()
+ return true
+ else
+ return false
+ end
+
+ -------> Addon Instances -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ elseif (event == "DETAILS_INSTANCE_OPEN") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_OPEN"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_OPEN"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_OPEN"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_CLOSE") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CLOSE"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CLOSE"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CLOSE"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_SIZECHANGED") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_SIZECHANGED"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_SIZECHANGED"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_SIZECHANGED"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_STARTRESIZE") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTRESIZE"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTRESIZE"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTRESIZE"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_ENDRESIZE") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDRESIZE"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDRESIZE"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDRESIZE"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_ENDSTRETCH") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDSTRETCH"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDSTRETCH"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDSTRETCH"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_STARTSTRETCH") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTSTRETCH"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTSTRETCH"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTSTRETCH"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_CHANGESEGMENT") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGESEGMENT"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGESEGMENT"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGESEGMENT"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_CHANGEATTRIBUTE") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEATTRIBUTE"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEATTRIBUTE"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEATTRIBUTE"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_CHANGEMODE") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEMODE"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEMODE"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEMODE"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_DATA_RESET") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_DATA_RESET"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_DATA_RESET"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_DATA_RESET"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_DATA_SEGMENTREMOVED") then
+ if (not AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_DATA_SEGMENTREMOVED"], object)) then
+ if (func) then
+ tinsert (_detalhes.RegistredEvents ["DETAILS_DATA_SEGMENTREMOVED"], {object, func, __eventtable = true})
+ else
+ tinsert (_detalhes.RegistredEvents ["DETAILS_DATA_SEGMENTREMOVED"], object)
+ end
+ return true
+ else
+ return false
+ end
+
+ end
+ end
+
+
+
+
+ ------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ --> Unregister a Event
+ ------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+
+ function _detalhes:UnregisterEvent (object, event)
+
+ -------> combat -------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+ if (event == "COMBAT_PLAYER_ENTER") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["COMBAT_PLAYER_ENTER"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["COMBAT_PLAYER_ENTER"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "COMBAT_PLAYER_LEAVE") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["COMBAT_PLAYER_LEAVE"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["COMBAT_PLAYER_LEAVE"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "COMBAT_PLAYER_TIMESTARTED") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["COMBAT_PLAYER_TIMESTARTED"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["COMBAT_PLAYER_TIMESTARTED"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "COMBAT_BOSS_FOUND") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["COMBAT_BOSS_FOUND"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["COMBAT_BOSS_FOUND"], index)
+ return true
+ else
+ return false
+ end
+
+ -------> buffs -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ elseif (event == "BUFF_UPDATE") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["BUFF_UPDATE"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["BUFF_UPDATE"], index)
+ if (#_detalhes.RegistredEvents ["BUFF_UPDATE"] < 1) then
+ _detalhes.RecordPlayerSelfBuffs = true
+ _detalhes:UpdateParserGears()
+ end
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "BUFF_UPDATE_DEBUFFPOWER") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["BUFF_UPDATE_DEBUFFPOWER"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["BUFF_UPDATE_DEBUFFPOWER"], index)
+ if (#_detalhes.RegistredEvents ["BUFF_UPDATE_DEBUFFPOWER"] < 1) then
+ _detalhes.RecordPlayerAbilityWithBuffs = false
+ _detalhes:UpdateDamageAbilityGears()
+ _detalhes:UpdateParserGears()
+ end
+ return true
+ else
+ return false
+ end
+
+ -------> Addon Instances -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ elseif (event == "DETAILS_INSTANCE_OPEN") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_OPEN"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_OPEN"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_CLOSE") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CLOSE"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CLOSE"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_SIZECHANGED") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_SIZECHANGED"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_SIZECHANGED"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_STARTRESIZE") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTRESIZE"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTRESIZE"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_ENDRESIZE") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDRESIZE"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDRESIZE"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_ENDSTRETCH") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDSTRETCH"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_ENDSTRETCH"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_STARTSTRETCH") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTSTRETCH"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_STARTSTRETCH"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_CHANGESEGMENT") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGESEGMENT"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGESEGMENT"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_CHANGEATTRIBUTE") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEATTRIBUTE"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEATTRIBUTE"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_INSTANCE_CHANGEMODE") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEMODE"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_INSTANCE_CHANGEMODE"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_DATA_RESET") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_DATA_RESET"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_DATA_RESET"], index)
+ return true
+ else
+ return false
+ end
+
+ elseif (event == "DETAILS_DATA_SEGMENTREMOVED") then
+ local index = AlreadyRegistred (_detalhes.RegistredEvents ["DETAILS_DATA_SEGMENTREMOVED"], object)
+ if (index) then
+ table.remove (_detalhes.RegistredEvents ["DETAILS_DATA_SEGMENTREMOVED"], index)
+ return true
+ else
+ return false
+ end
+
+ end
+ end
+
+
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ --> Send Event
+ function _detalhes:SendEvent (event, object, ...)
+
+ --> send event to all registred plugins
+
+ if (not object) then
+
+ for _, PluginObject in ipairs (_detalhes.RegistredEvents[event]) do
+ if (PluginObject.__eventtable) then
+ if (PluginObject [1].Enabled) then
+ if (type (PluginObject [2]) == "function") then
+ PluginObject [2] (event, ...)
+ else
+ PluginObject [1] [PluginObject [2]] (event, ...)
+ end
+ end
+ else
+ if (PluginObject.Enabled) then
+ PluginObject:OnDetailsEvent (event, ...)
+ end
+ end
+ end
+
+ elseif (type (object) == "string" and object == "SEND_TO_ALL") then
+
+ for _, PluginObject in ipairs (_detalhes.RaidTables.Plugins) do
+ PluginObject:OnDetailsEvent (event)
+ end
+
+ for _, PluginObject in ipairs (_detalhes.SoloTables.Plugins) do
+ PluginObject:OnDetailsEvent (event)
+ end
+
+ for _, PluginObject in ipairs (_detalhes.ToolBar.Plugins) do
+ PluginObject:OnDetailsEvent (event)
+ end
+ else
+ --> send the event only for requested plugin
+ if (object.Enabled) then
+ object:OnDetailsEvent (event, ...)
+ end
+ end
+ end
diff --git a/functions/link.lua b/functions/link.lua
new file mode 100644
index 00000000..b3211b00
--- /dev/null
+++ b/functions/link.lua
@@ -0,0 +1,29 @@
+--[[ Link actor with his twin shadow ]]
+
+do
+ local _detalhes = _G._detalhes
+
+ local _rawget = rawget
+ local _setmetatable = setmetatable
+
+ --> default weaktable
+ _detalhes.weaktable = {__mode = "v"}
+
+ --> create link between two tables
+ function _detalhes:FazLinkagem (objeto)
+ local meus_links = _rawget (self, "links")
+ if (not meus_links) then
+ meus_links = _setmetatable ({}, _detalhes.weaktable)
+ self.links = meus_links
+ end
+ meus_links [#meus_links+1] = objeto
+ end
+
+ --> create the link
+ function _detalhes:CriaLink (link)
+ --> se tiver a tabela no overall
+ if (link) then
+ link:FazLinkagem (self)
+ end
+ end
+end
\ No newline at end of file
diff --git a/functions/playerclass.lua b/functions/playerclass.lua
new file mode 100644
index 00000000..c7df269e
--- /dev/null
+++ b/functions/playerclass.lua
@@ -0,0 +1,88 @@
+--[[ detect actor class ]]
+
+do
+
+ local _detalhes = _G._detalhes
+
+ local _pairs = pairs
+ local _ipairs = ipairs
+ local _UnitClass = UnitClass
+ local _select = select
+
+ -- try get the class from actor name
+ function _detalhes:GetClass (name)
+ local _, class = _UnitClass (name)
+
+ if (not class) then
+ for _, container in _ipairs (_detalhes.tabela_overall) do
+ local index = container._NameIndexTable [name]
+ if (index) then
+ local actor = container._ActorTable [index]
+ if (actor.classe ~= "UNGROUPPLAYER") then
+ return actor.classe, _detalhes:unpacks (_detalhes.class_coords [actor.classe] or {0.75, 1, 0.75, 1}, _detalhes.class_colors [actor.classe])
+ end
+ end
+ end
+ else
+ return class, _detalhes:unpacks (_detalhes.class_coords [class] or {0.75, 1, 0.75, 1}, _detalhes.class_colors [class])
+ end
+ end
+
+ function _detalhes:GuessClass (t)
+
+ local Actor, container, tries = t[1], t[2], t[3]
+
+ if (not Actor) then
+ return false
+ end
+
+ if (Actor.spell_tables) then --> correcao pros containers misc, precisa pegar os diferentes tipos de containers de lá
+ for spellid, _ in _pairs (Actor.spell_tables._ActorTable) do
+ local class = _detalhes.ClassSpellList [spellid]
+ if (class) then
+ Actor.classe = class
+ Actor.shadow.classe = class
+ Actor.guessing_class = nil
+
+ if (container) then
+ container.need_refresh = true
+ container.shadow.need_refresh = true
+ end
+
+ if (Actor.minha_barra) then
+ Actor.minha_barra.minha_tabela = nil
+ end
+
+ return class
+ end
+ end
+ end
+
+ local class = _detalhes:GetClass (Actor.nome)
+ if (class) then
+ Actor.classe = class
+ Actor.shadow.classe = class
+ Actor.need_refresh = true
+ Actor.shadow.need_refresh = true
+ Actor.guessing_class = nil
+
+ if (container) then
+ container.need_refresh = true
+ container.shadow.need_refresh = true
+ end
+
+ if (Actor.minha_barra) then
+ Actor.minha_barra.minha_tabela = nil
+ end
+
+ return class
+ end
+
+ if (tries and tries < 10) then
+ _detalhes:ScheduleTimer ("GuessClass", 2, {Actor, container, tries+1})
+ end
+
+ return false
+ end
+
+end
diff --git a/functions/report.lua b/functions/report.lua
new file mode 100644
index 00000000..e69de29b
diff --git a/functions/savedata.lua b/functions/savedata.lua
new file mode 100644
index 00000000..cd9fadd1
--- /dev/null
+++ b/functions/savedata.lua
@@ -0,0 +1,292 @@
+--[[this file save the data when player logout and load data and player login back again]]
+
+local _detalhes = _G._detalhes
+
+function _detalhes:SaveData()
+
+ if (_G._detalhes_saver) then
+ return
+ end
+
+ _detalhes:SaveDataOnLogout()
+end
+
+function _detalhes:SaveDataOnLogout()
+
+--> cleanup tables
+ _detalhes:PrepareTablesForSave()
+
+--> get data
+
+-- On Character
+
+ --> save instances (windows)
+ _detalhes_database.tabela_instancias = _detalhes.tabela_instancias
+ --> options data
+ --window size
+ _detalhes_database.max_window_size = _detalhes.max_window_size
+ _detalhes_database.new_window_size = _detalhes.new_window_size
+ _detalhes_database.window_clamp = _detalhes.window_clamp
+ --> text sizes
+ _detalhes_database.font_sizes = _detalhes.font_sizes
+ --tutorial
+ _detalhes_database.tutorial = _detalhes.tutorial
+ -- max segments
+ _detalhes_database.segments_amount = _detalhes.segments_amount
+ _detalhes_database.segments_amount_to_save = _detalhes.segments_amount_to_save
+ _detalhes_database.clear_ungrouped = _detalhes.clear_ungrouped
+ _detalhes_database.clear_graphic = _detalhes.clear_graphic
+ -- row animation
+ _detalhes_database.use_row_animations = _detalhes.use_row_animations
+ _detalhes_database.animate_scroll = _detalhes.animate_scroll
+ _detalhes_database.use_scroll = _detalhes.use_scroll
+ -- death log
+ _detalhes_database.deadlog_limit = _detalhes.deadlog_limit
+ -- report
+ _detalhes_database.report_lines = _detalhes.report_lines
+ _detalhes_database.report_to_who = _detalhes.report_to_who
+ -- colors
+ _detalhes_database.default_bg_color = _detalhes.default_bg_color
+ _detalhes_database.default_bg_alpha = _detalhes.default_bg_alpha
+ _detalhes_database.class_colors = _detalhes.class_colors
+ -- fades
+ _detalhes_database.row_fade_in = _detalhes.row_fade_in
+ _detalhes_database.windows_fade_in = _detalhes.windows_fade_in
+ _detalhes_database.row_fade_out = _detalhes.row_fade_out
+ _detalhes_database.windows_fade_out = _detalhes.windows_fade_out
+ -- modes
+ _detalhes_database.solo = _detalhes.solo
+ _detalhes_database.tank = _detalhes.raid
+ -- switch
+ _detalhes_database.switch = {}
+ _detalhes_database.switch.slots = _detalhes.switch.slots
+ _detalhes_database.switch.table = _detalhes.switch.table
+ -- capture
+ _detalhes_database.capture_real = _detalhes.capture_real
+ _detalhes_database.minimum_combat_time = _detalhes.minimum_combat_time
+ --> combat data
+ -- segments table
+ _detalhes_database.tabela_historico = _detalhes.tabela_historico
+ -- combat id
+ _detalhes_database.combat_id = _detalhes.combat_id
+ -- modes
+ _detalhes_database.SoloTables = {}
+ _detalhes_database.RaidTables = {}
+ --> precisa pegar o nome do plugin
+ if (_detalhes.SoloTables.Mode) then
+ _detalhes_database.SoloTables.Mode = _detalhes.SoloTables.Mode
+ _detalhes_database.SoloTables.LastSelected = _detalhes.SoloTables.Plugins [_detalhes.SoloTables.Mode].real_name
+ end
+ if (_detalhes.RaidTables.Mode) then
+ _detalhes_database.RaidTables.Mode = _detalhes.RaidTables.Mode
+ _detalhes_database.RaidTables.LastSelected = _detalhes.RaidTables.Plugins [_detalhes.RaidTables.Mode].real_name
+ end
+ --> buff data
+ _detalhes.Buffs:SaveBuffs()
+
+ --> customs
+ _detalhes_database.custom = _detalhes.custom
+
+ --> version
+ _detalhes_database.last_realversion = _detalhes.realversion
+
+-- On Account
+
+ _detalhes_global = _detalhes_global or {}
+ _detalhes_global.savedStyles = _detalhes.savedStyles
+ --max segments
+ _detalhes_global.segments_amount = _detalhes.segments_amount
+ _detalhes_global.segments_amount_to_save = _detalhes.segments_amount_to_save
+ _detalhes_global.segments_panic_mode = _detalhes.segments_panic_mode
+ -- animations
+ _detalhes_global.use_row_animations = _detalhes.use_row_animations
+ _detalhes_global.animate_scroll = _detalhes.animate_scroll
+ -- scrollbar
+ _detalhes_global.use_scroll = _detalhes.use_scroll
+ -- core
+ _detalhes_global.clear_ungrouped = _detalhes.clear_ungrouped
+ _detalhes_global.update_speed = _detalhes.update_speed
+ _detalhes_global.time_type = _detalhes.time_type
+
+ _detalhes_global.SpellOverwriteUser = _detalhes.SpellOverwriteUser
+
+ return true
+
+end
+
+local force_reset = function()
+ _detalhes.tabela_instancias = {}
+ _detalhes.tabela_historico = _detalhes.historico:NovoHistorico()
+ _detalhes.tabela_pets = _detalhes.container_pets:NovoContainer()
+ _detalhes.tabela_overall = _detalhes.combate:NovaTabela()
+ _detalhes.tabela_vigente = _detalhes.combate:NovaTabela (_, _detalhes.tabela_overall)
+ _detalhes_database = {}
+ return
+end
+
+function _detalhes:LoadData()
+
+--[[
+ if (true) then --> DEBUG, force empty data
+ return force_reset()
+end --]]
+
+ local _detalhes_database = _G._detalhes_database
+
+ if (_detalhes_database) then
+
+
+ --> build basic containers
+ _detalhes.tabela_historico = _detalhes_database.tabela_historico or _detalhes.historico:NovoHistorico() -- segments
+ _detalhes.tabela_overall = _detalhes.combate:NovaTabela() -- overall
+ _detalhes.tabela_pets = _detalhes_database.tabela_pets or _detalhes.container_pets:NovoContainer() -- pets
+
+ --> re-build all indexes and metatables
+ _detalhes:RestauraMetaTables()
+
+ --> instances (windows)
+ _detalhes.tabela_instancias = _detalhes_database.tabela_instancias or {}
+
+ --> get last combat table
+ local historico_UM = _detalhes.tabela_historico.tabelas[1]
+
+ if (historico_UM) then
+ _detalhes.tabela_vigente = historico_UM --> significa que elas eram a mesma tabela, então aqui elas se tornam a mesma tabela
+ else
+ _detalhes.tabela_vigente = _detalhes.combate:NovaTabela (_, _detalhes.tabela_overall)
+ end
+
+ _detalhes.combat_id = _detalhes_database.combat_id
+
+ if (_detalhes_database.SoloTables) then
+ if (_detalhes_database.SoloTables.Mode) then
+ _detalhes.SoloTables.Mode = _detalhes_database.SoloTables.Mode
+ _detalhes.SoloTables.LastSelected = _detalhes_database.SoloTables.LastSelected
+ else
+ _detalhes.SoloTables.Mode = 1
+ end
+ end
+
+ if (_detalhes_database.RaidTables) then
+ if (_detalhes_database.RaidTables.Mode) then
+ _detalhes.RaidTables.Mode = _detalhes_database.RaidTables.Mode
+ _detalhes.RaidTables.LastSelected = _detalhes_database.RaidTables.LastSelected
+ else
+ _detalhes.RaidTables.Mode = 1
+ end
+ end
+
+ --> load options data
+ --window size
+ _detalhes.max_window_size = _detalhes_database.max_window_size
+ _detalhes.new_window_size = _detalhes_database.new_window_size
+ _detalhes.window_clamp = _detalhes_database.window_clamp
+ -- max segments
+ _detalhes.segments_amount = _detalhes_database.segments_amount
+ _detalhes.clear_ungrouped = _detalhes_database.clear_ungrouped
+ _detalhes.clear_graphic = _detalhes_database.clear_graphic
+ --> text sizes
+ _detalhes.font_sizes = _detalhes_database.font_sizes
+ --tutorial
+ _detalhes.tutorial = _detalhes_database.tutorial
+ -- row animation
+ _detalhes.use_row_animations = _detalhes_database.use_row_animations
+ _detalhes.animate_scroll = _detalhes_database.animate_scroll
+ _detalhes.use_scroll = _detalhes_database.use_scroll
+ -- death log
+ _detalhes.deadlog_limit = _detalhes_database.deadlog_limit
+ -- report
+ _detalhes.report_lines = _detalhes_database.report_lines
+ _detalhes.report_to_who = _detalhes_database.report_to_who
+ -- colors
+ _detalhes.class_colors = _detalhes_database.class_colors
+ _detalhes.default_bg_color = _detalhes_database.default_bg_color
+ _detalhes.default_bg_alpha = _detalhes_database.default_bg_alpha
+ -- fades
+ _detalhes.row_fade_in = _detalhes_database.row_fade_in
+ _detalhes.windows_fade_in = _detalhes_database.windows_fade_in
+ _detalhes.row_fade_out = _detalhes_database.row_fade_out
+ _detalhes.windows_fade_out = _detalhes_database.windows_fade_out
+ -- modes
+ _detalhes.solo = _detalhes_database.solo
+ _detalhes.raid = _detalhes_database.tank
+ -- switch
+ if (_detalhes_database.switch) then
+ _detalhes.switch.slots = _detalhes_database.switch.slots
+ _detalhes.switch.table = _detalhes_database.switch.table
+ end
+
+ --> buffs
+ _detalhes.savedbuffs = _detalhes_database.savedbuffs
+ _detalhes.Buffs:BuildTables()
+
+ --> customs
+ _detalhes.custom = _detalhes_database.custom
+
+ --> need refresh for all containers
+ for _, container in ipairs (_detalhes.tabela_overall) do
+ container.need_refresh = true
+ end
+ for _, container in ipairs (_detalhes.tabela_vigente) do
+ container.need_refresh = true
+ end
+
+ _detalhes_database.tabela_vigente = nil
+ _detalhes_database.tabela_historico = nil
+ _detalhes_database.tabela_pets = nil
+
+ -- version
+ _detalhes.last_realversion = _detalhes_database.last_realversion or _detalhes.realversion
+
+ else
+ _detalhes.tabela_instancias = {}
+ _detalhes.tabela_historico = _detalhes.historico:NovoHistorico()
+ _detalhes.tabela_pets = _detalhes.container_pets:NovoContainer()
+ _detalhes.tabela_overall = _detalhes.combate:NovaTabela()
+ _detalhes.tabela_vigente = _detalhes.combate:NovaTabela (_, _detalhes.tabela_overall)
+ _detalhes_database = {}
+ end
+
+ -- capture
+ _detalhes.capture_real = _detalhes_database and _detalhes_database.capture_real or {
+ ["damage"] = true,
+ ["heal"] = true,
+ ["energy"] = true,
+ ["miscdata"] = true,
+ ["aura"] = true,
+ }
+ _detalhes.capture_current = {}
+ for captureType, captureValue in pairs (_detalhes.capture_real) do
+ _detalhes.capture_current [captureType] = captureValue
+ end
+ _detalhes.minimum_combat_time = _detalhes_database.minimum_combat_time
+
+
+-- On Account
+
+ local _detalhes_global = _G._detalhes_global
+
+ if (_detalhes_global) then
+ --saved styles
+ vardump (_detalhes_global.savedStyles)
+ _detalhes.savedStyles = _detalhes_global.savedStyles or _detalhes.savedStyles
+ --max segments
+ _detalhes.segments_amount = _detalhes_global.segments_amount or _detalhes.segments_amount
+ _detalhes.segments_amount_to_save = _detalhes_global.segments_amount_to_save or _detalhes.segments_amount_to_save
+ _detalhes.segments_panic_mode = _detalhes_global.segments_panic_mode or _detalhes.segments_panic_mode
+ -- row animation
+ _detalhes.use_row_animations = _detalhes_global.use_row_animations or _detalhes.use_row_animations
+ _detalhes.animate_scroll = _detalhes_global.animate_scroll or _detalhes.animate_scroll
+ -- scrollbar
+ _detalhes.use_scroll = _detalhes_global.use_scroll or _detalhes.use_scroll
+ -- core
+ _detalhes.clear_ungrouped = _detalhes_global.clear_ungrouped or _detalhes.clear_ungrouped
+ _detalhes.update_speed = _detalhes_global.update_speed or _detalhes.update_speed
+ _detalhes.time_type = _detalhes_global.time_type or _detalhes.time_type
+
+ _detalhes.SpellOverwriteUser = _detalhes_global.SpellOverwriteUser or _detalhes.SpellOverwriteUser
+
+ end
+
+ return true
+end
diff --git a/functions/slash.lua b/functions/slash.lua
new file mode 100644
index 00000000..0900a712
--- /dev/null
+++ b/functions/slash.lua
@@ -0,0 +1,206 @@
+
+
+local _detalhes = _G._detalhes
+local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+local CreateFrame = CreateFrame
+local pairs = pairs
+local UIParent = UIParent
+local UnitGUID = UnitGUID
+local tonumber= tonumber
+local LoggingCombat = LoggingCombat
+
+SLASH_DETAILS1, SLASH_DETAILS2, SLASH_DETAILS3 = "/details", "/dt", "/d"
+
+function SlashCmdList.DETAILS (msg, editbox)
+
+ local command, rest = msg:match("^(%S*)%s*(.-)$")
+
+ if (command == Loc ["STRING_SLASH_NEW"]) then
+
+ _detalhes:CriarInstancia()
+
+ elseif (command == Loc ["STRING_SLASH_DISABLE"]) then
+
+ _detalhes:CaptureSet (false, "damage", true)
+ _detalhes:CaptureSet (false, "heal", true)
+ _detalhes:CaptureSet (false, "energy", true)
+ _detalhes:CaptureSet (false, "miscdata", true)
+ _detalhes:CaptureSet (false, "aura", true)
+ print (Loc ["STRING_DETAILS1"] .. Loc ["STRING_SLASH_CAPTUREOFF"])
+
+ elseif (command == Loc ["STRING_SLASH_ENABLE"]) then
+
+ _detalhes:CaptureSet (true, "damage", true)
+ _detalhes:CaptureSet (true, "heal", true)
+ _detalhes:CaptureSet (true, "energy", true)
+ _detalhes:CaptureSet (true, "miscdata", true)
+ _detalhes:CaptureSet (true, "aura", true)
+ print (Loc ["STRING_DETAILS1"] .. Loc ["STRING_SLASH_CAPTUREON"])
+
+ elseif (command == Loc ["STRING_SLASH_OPTIONS"]) then
+
+ if (rest and tonumber (rest)) then
+ local instanceN = tonumber (rest)
+ if (instanceN > 0 and instanceN <= #_detalhes.tabela_instancias) then
+ local instance = _detalhes:GetInstance (instanceN)
+ _detalhes:OpenOptionsWindow (instance)
+ end
+ else
+ local lower_instance = _detalhes:GetLowerInstanceNumber()
+ print (_detalhes:GetInstance (lower_instance))
+ _detalhes:OpenOptionsWindow (_detalhes:GetInstance (lower_instance))
+ end
+
+
+-------- debug ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ elseif (msg == "copy") then
+ _G.DetailsCopy:Show()
+ _G.DetailsCopy.MyObject.text:HighlightText()
+ _G.DetailsCopy.MyObject.text:SetFocus()
+
+ elseif (msg == "imageedit") then
+
+ local callback = function (width, height, overlayColor, alpha, texCoords)
+ print (width, height, alpha)
+ print ("overlay: ", unpack (overlayColor))
+ print ("crop: ", unpack (texCoords))
+ end
+
+ _detalhes.gump:ImageEditor (callback, "Interface\\TALENTFRAME\\bg-paladin-holy", nil, {1, 1, 1, 1}) -- {0.25, 0.25, 0.25, 0.25}
+
+ elseif (msg == "error") then
+ a = nil + 1
+
+ --> debug
+ elseif (command == "resetcapture") then
+ _detalhes.capture_real = {
+ ["damage"] = true,
+ ["heal"] = true,
+ ["energy"] = true,
+ ["miscdata"] = true,
+ ["aura"] = true,
+ }
+ _detalhes.capture_current = _detalhes.capture_real
+ _detalhes:CaptureRefresh()
+
+ --> debug
+ elseif (msg == "opened") then
+ print ("Instances opened: " .. _detalhes.opened_windows)
+
+ --> debug, get a guid of something
+ elseif (command == "guid") then --> localize-me
+
+ local pass_guid = rest:match("^(%S*)%s*(.-)$")
+
+ if (not _detalhes.id_frame) then
+
+ local backdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ tile = true, edgeSize = 1, tileSize = 5,
+ }
+
+ _detalhes.id_frame = CreateFrame ("Frame", "DetailsID", UIParent)
+ _detalhes.id_frame:SetHeight(14)
+ _detalhes.id_frame:SetWidth(120)
+ _detalhes.id_frame:SetPoint ("center", UIParent, "center")
+ _detalhes.id_frame:SetBackdrop(backdrop)
+
+ tinsert (UISpecialFrames, "DetailsID")
+
+ _detalhes.id_frame.texto = CreateFrame ("editbox", nil, _detalhes.id_frame)
+ _detalhes.id_frame.texto:SetPoint ("topleft", _detalhes.id_frame, "topleft")
+ _detalhes.id_frame.texto:SetAutoFocus(false)
+ _detalhes.id_frame.texto:SetFontObject (GameFontHighlightSmall)
+ _detalhes.id_frame.texto:SetHeight(14)
+ _detalhes.id_frame.texto:SetWidth(120)
+ _detalhes.id_frame.texto:SetJustifyH("CENTER")
+ _detalhes.id_frame.texto:EnableMouse(true)
+ _detalhes.id_frame.texto:SetBackdrop(ManualBackdrop)
+ _detalhes.id_frame.texto:SetBackdropColor(0, 0, 0, 0.5)
+ _detalhes.id_frame.texto:SetBackdropBorderColor(0.3, 0.3, 0.30, 0.80)
+ _detalhes.id_frame.texto:SetText ("") --localize-me
+ _detalhes.id_frame.texto.perdeu_foco = nil
+
+ _detalhes.id_frame.texto:SetScript ("OnEnterPressed", function ()
+ _detalhes.id_frame.texto:ClearFocus()
+ _detalhes.id_frame:Hide()
+ end)
+
+ _detalhes.id_frame.texto:SetScript ("OnEscapePressed", function()
+ _detalhes.id_frame.texto:ClearFocus()
+ _detalhes.id_frame:Hide()
+ end)
+
+ end
+
+ _detalhes.id_frame:Show()
+
+ if (pass_guid == "-") then
+ local guid = UnitGUID ("target")
+ if (guid) then
+ print (guid.. " -> " .. tonumber (guid:sub(6, 10), 16))
+ _detalhes.id_frame.texto:SetText (""..tonumber (guid:sub(6, 10), 16))
+ _detalhes.id_frame.texto:HighlightText()
+ end
+
+ else
+ print (pass_guid.. " -> " .. tonumber (pass_guid:sub(6, 10), 16))
+ _detalhes.id_frame.texto:SetText (""..tonumber (pass_guid:sub(6, 10), 16))
+ _detalhes.id_frame.texto:HighlightText()
+ end
+
+
+ --> debug
+ elseif (msg == "id") then
+ local one, two = rest:match("^(%S*)%s*(.-)$")
+ if (one ~= "") then
+ print("NPC ID:", one:sub(-12, -9), 16)
+ print("NPC ID:", tonumber((one):sub(-12, -9), 16))
+ else
+ print("NPC ID:", tonumber((UnitGUID("target")):sub(-12, -9), 16) )
+ end
+
+ --> debug
+ elseif (msg == "debug") then
+ if (_detalhes.debug) then
+ _detalhes.debug = false
+ print ("Details Diagnostic mode OFF")
+ else
+ _detalhes.debug = true
+ print ("Details Diagnostic mode ON")
+ end
+
+ --> debug combat log
+ elseif (msg == "combatlog") then
+ if (_detalhes.isLoggingCombat) then
+ LoggingCombat (false)
+ print ("Wow combatlog record turned OFF.")
+ _detalhes.isLoggingCombat = nil
+ else
+ LoggingCombat (true)
+ print ("Wow combatlog record turned ON.")
+ _detalhes.isLoggingCombat = true
+ end
+
+ --> debug
+ elseif (msg == "gs") then
+ _detalhes:teste_grayscale()
+
+ else
+
+ --if (_detalhes.opened_windows < 1) then
+ -- _detalhes:CriarInstancia()
+ --end
+
+ print (" ")
+ print (Loc ["STRING_DETAILS1"] .. Loc ["STRING_COMMAND_LIST"])
+ print ("|cffffaeae/details " .. Loc ["STRING_SLASH_NEW"] .. "|r: " .. Loc ["STRING_SLASH_NEW_DESC"])
+ print ("|cffffaeae/details " .. Loc ["STRING_SLASH_ENABLE"] .. "|r: " .. Loc ["STRING_SLASH_ENABLE_DESC"])
+ print ("|cffffaeae/details " .. Loc ["STRING_SLASH_DISABLE"] .. "|r: " .. Loc ["STRING_SLASH_DISABLE_DESC"])
+ print ("|cffffaeae/details " .. Loc ["STRING_SLASH_OPTIONS"] .. "|r|cfffcffb0 |r: " .. Loc ["STRING_SLASH_OPTIONS_DESC"])
+ print (" ")
+
+ end
+end
diff --git a/functions/spellcache.lua b/functions/spellcache.lua
new file mode 100644
index 00000000..7772aa81
--- /dev/null
+++ b/functions/spellcache.lua
@@ -0,0 +1,99 @@
+--[[ Spell Cache store all spells shown on frames and make able to change spells name, icons, etc... ]]
+
+do
+
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> On The Fly SpellCache
+
+ local _detalhes = _G._detalhes
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+ local _rawget = rawget
+ local _rawset = rawset
+ local _setmetatable = setmetatable
+ local _GetSpellInfo = GetSpellInfo
+ local _unpack = unpack
+
+ --> default container
+ _detalhes.spellcache = {}
+ local unknowSpell = {Loc ["STRING_UNKNOWSPELL"], _, "Interface\\Icons\\Ability_Druid_Eclipse"} --> localize-me
+
+ --> reset spell cache
+ function _detalhes:ClearSpellCache()
+ _detalhes.spellcache = _setmetatable ({},
+ {__index = function (tabela, valor)
+ local esta_magia = _rawget (tabela, valor)
+ if (esta_magia) then
+ return esta_magia
+ end
+
+ --> should save only icon and name, other values are not used
+ if (valor) then --> check if spell is valid before
+ local cache = {_GetSpellInfo (valor)}
+ tabela [valor] = cache
+ return cache
+ else
+ return unknowSpell
+ end
+
+ end})
+
+ --> default overwrites
+ _rawset (_detalhes.spellcache, 1, {Loc ["STRING_MELEE"], 1, "Interface\\AddOns\\Details\\images\\melee.tga"})
+ _rawset (_detalhes.spellcache, 2, {Loc ["STRING_AUTOSHOT"], 1, "Interface\\AddOns\\Details\\images\\autoshot.tga"})
+
+ --> built-in overwrites
+ for spellId, spellTable in pairs (_detalhes.SpellOverwrite) do
+ local name, _, icon = _GetSpellInfo (spellId)
+ _rawset (_detalhes.spellcache, spellId, {spellTable.name or name, 1, spellTable.icon or icon})
+ end
+
+ --> user overwrites
+ for spellId, spellTable in pairs (_detalhes.SpellOverwriteUser) do
+ local name, _, icon = _GetSpellInfo (spellId)
+ _rawset (_detalhes.spellcache, spellId, {spellTable.name or name, 1, spellTable.icon or icon})
+ end
+ end
+
+ --> initialize spell cache
+ _detalhes:ClearSpellCache()
+
+ --> overwrite for API GetSpellInfo function
+ _detalhes.getspellinfo = function (spellid) return _unpack (_detalhes.spellcache[spellid]) end
+
+ --> overwrite SpellInfo if spell is a Dot, so GetSpellInfo will return the name modified
+ function _detalhes:SpellIsDot (spellid)
+ local nome, rank, icone = _GetSpellInfo (spellid)
+ _rawset (_detalhes.spellcache, spellid, {nome .. Loc ["STRING_DOT"], rank, icone})
+ end
+
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> Cache All Spells
+ function _detalhes:BuildSpellList()
+
+ local SpellCache = {a={}, b={}, c={}, d={}, e={}, f={}, g={}, h={}, i={}, j={}, k={}, l={}, m={}, n={}, o={}, p={}, q={}, r={}, s={}, t={}, u={}, v={}, w={}, x={}, y={}, z={}}
+ local _string_lower = string.lower
+ local _string_sub = string.sub
+ local blizzGetSpellInfo = GetSpellInfo
+
+ for spellid = 1, 160000 do
+ local name, rank, icon = blizzGetSpellInfo (spellid)
+ if (name) then
+ local index = _string_lower (_string_sub (name, 1, 1))
+ local CachedIndex = SpellCache [index]
+ if (CachedIndex) then
+ CachedIndex [spellid] = {name, icon, rank}
+ end
+ end
+ end
+
+ _detalhes.spellcachefull = SpellCache
+ return true
+ end
+
+ function _detalhes:ClearSpellList()
+ _detalhes.spellcachefull = nil
+ collectgarbage()
+ end
+
+end
\ No newline at end of file
diff --git a/functions/spells.lua b/functions/spells.lua
new file mode 100644
index 00000000..5fec15f3
--- /dev/null
+++ b/functions/spells.lua
@@ -0,0 +1,376 @@
+do
+
+ local _detalhes = _G._detalhes
+
+ _detalhes.ClassSpellList = {
+
+ --death knight
+ [77535] = "DEATHKNIGHT", --Blood Shield (heal)
+ [45470] = "DEATHKNIGHT", --Death Strike (heal)
+ [53365] = "DEATHKNIGHT", --Unholy Strength (heal)
+ [48707] = "DEATHKNIGHT", -- Anti-Magic Shell (heal)
+ [48982] = "DEATHKNIGHT", --rune tap
+ --> DK Frost
+ [49020] = "DEATHKNIGHT", --obliterate
+ [49143] = "DEATHKNIGHT", --frost strike
+ [55095] = "DEATHKNIGHT", --frost fever
+ [55078] = "DEATHKNIGHT", --blood plague
+ [49184] = "DEATHKNIGHT", --howling blast
+ --> DK Blood
+ [49998] = "DEATHKNIGHT", --death strike
+ --> DK Unholy
+ [55090] = "DEATHKNIGHT",--scourge strike
+ [47632] = "DEATHKNIGHT",--death coil
+
+ --druid
+ --> Druid Cat
+ [1822] = "DRUID", --rake
+ [1079] = "DRUID", --rip
+ [5221] = "DRUID", --shred
+ [33876] = "DRUID", --mangle
+ [33878] = "DRUID", --mangle (energy)
+ [102545] = "DRUID", --ravage!
+ [33878] = "DRUID", --mangle (energy gain)
+ [17057] = "DRUID", --bear form (energy gain)
+ [16959] = "DRUID", --primal fury (energy gain)
+ [5217] = "DRUID", --tiger's fury (energy gain)
+ [68285] = "DRUID", --leader of the pack (mana)
+ --> Druid Balance
+ [5176] = "DRUID", --wrath
+ [93402] = "DRUID", --sunfire
+ [2912] = "DRUID", --starfire
+ [8921] = "DRUID", --moonfire
+ [81070] = "DRUID", --eclipse
+ --> Druid Resto
+ [29166] = "DRUID", --innervate
+ [774] = "DRUID", --rejuvenation
+ [44203] = "DRUID", --tranquility
+ [48438] = "DRUID", --wild growth
+ [81269] = "DRUID", --shiftmend
+ [102792] = "DRUID", --wind moshroom: bloom
+ [5185] = "DRUID", --healing touch
+ [8936] = "DRUID", --regrowth
+ [33778] = "DRUID", --lifebloom
+ [48503] = "DRUID", --living seed
+ [50464] = "DRUID", --nourish
+
+ --hunter
+ [131900] = "HUNTER",--a murder of crows
+ [118253] = "HUNTER",--serpent sting
+ [77767] = "HUNTER",--cobra shot
+ [3044] = "HUNTER",--arcane shot
+ [53301] = "HUNTER",--explosive shot
+ [120361] = "HUNTER",--barrage
+
+ --mage
+ --> Mage Frost
+ [116] = "MAGE",--frost bolt
+ [30455] = "MAGE",--ice lance
+ [84721] = "MAGE",--frozen orb
+ [1449] = "MAGE",--arcane explosion
+ [113092] = "MAGE",--frost bomb
+ [115757] = "MAGE",--frost nova
+ [44614] = "MAGE",--forstfire bolt
+ [42208] = "MAGE",--blizzard
+ [11426] = "MAGE",--Ice Barrier (heal)
+ --> Mage Fire
+ [11366] = "MAGE",--pyroblast
+ [133] = "MAGE",--fireball
+ [108853] = "MAGE",--infernoblast
+ [2948] = "MAGE",--scorch
+ --> Mage Arcane
+ [30451] = "MAGE",--arcane blase
+ [12051] = "MAGE",--evocation
+
+ --monk
+ --> Monk
+ [107428] = "MONK", --rising sun kick
+ [100784] = "MONK", --blackout kick
+ [132467] = "MONK", --Chi wave
+ [107270] = "MONK", --spinning crane kick
+ [100787] = "MONK", --tiger palm
+ [123761] = "MONK", --mana tea
+ --> Mistwave
+ [119611] = "MONK", --renewing mist
+ [115310] = "MONK", --revival
+ [116670] = "MONK", --uplift
+ [115175] = "MONK", --soothing mist
+ [124041] = "MONK", --gift of the serpent
+ [124040] = "MONK", -- shi torpedo
+ [132120] = "MONK", -- enveloping mist
+ [132463] = "MONK", -- shi wave
+ [117895] = "MONK", --eminence (statue)
+ --> drunk monk
+ [115295] = "MONK", --guard
+ [115072] = "MONK", --expel harm
+
+ --paladin
+ --> Paladin Retri
+ [35395] = "PALADIN",--cruzade strike
+ [879] = "PALADIN",--exorcism
+ [85256] = "PALADIN",--templar's verdict
+ [20167] = "PALADIN",--seal of insight (mana)
+ --> Paladin Protection
+ [31935] = "PALADIN",--avenger's shield
+ [20271] = "PALADIN", --judgment
+ [35395] = "PALADIN", --cruzader strike
+ [81297] = "PALADIN", --consacration
+ [31803] = "PALADIN", --censure
+ [65148] = "PALADIN", --Sacred Shield
+ [20167] = "PALADIN", --Seal of Insight
+ --> holy
+ [86273] = "PALADIN", --illuminated healing
+ [85222] = "PALADIN", --light of dawn
+ [53652] = "PALADIN", --beacon of light
+ [82327] = "PALADIN", --holy radiance
+ [119952] = "PALADIN", --arcing light
+ [25914] = "PALADIN", --holy shock
+ [19750] = "PALADIN", --flash of light
+
+ --priest
+ [34650] = "PRIEST", --mana leech (pet)
+ --> shadow priest
+ [589] = "PRIEST", --shadow word: pain
+ [34914] = "PRIEST", --vampiric touch
+ [34919] = "PRIEST", --vampiric touch (mana)
+ [15407] = "PRIEST", --mind flay
+ [8092] = "PRIEST", --mind blast
+ [15290] = "PRIEST",-- Vampiric Embrace
+ [127626] = "PRIEST",--devouring plague (heal)
+ [2944] = "PRIEST",--devouring plague (damage)
+ --> disc priest
+ [585] = "PRIEST", --smite
+ [47666] = "PRIEST", --penance
+ [14914] = "PRIEST", --holy fire
+ [81751] = "PRIEST", --atonement
+ [47753] = "PRIEST", --divine aegis
+ --> holy priest
+ [33110] = "PRIEST", --prayer of mending
+ [77489] = "PRIEST", --mastery echo of light
+ [596] = "PRIEST", --prayer of healing
+ [34861] = "PRIEST", --circle of healing
+ [139] = "PRIEST", --renew
+ [120692] = "PRIEST", --halo
+ [2060] = "PRIEST", --greater heal
+ [110745] = "PRIEST", --divine star
+ [2061] = "PRIEST", --flash heal
+ [88686] = "PRIEST", --santuary
+ [17] = "PRIEST", --power word: shield
+ [64904] = "PRIEST", --hymn of hope
+ --> talent
+ [129250] = "PRIEST", --power word: solace
+
+ --rogue
+ [53] = "ROGUE", --backstab
+ [8680] = "ROGUE", --wound pouson
+ [2098] = "ROGUE", --eviscerate
+ [2818] = "ROGUE", --deadly poison
+ [113780] = "ROGUE", --deadly poison
+ [51723] = "ROGUE", --fan of knifes
+ [111240] = "ROGUE", --dispatch
+ [703] = "ROGUE", --garrote
+ [1943] = "ROGUE", --rupture
+ [114014] = "ROGUE", --shuriken toss
+ [16511] = "ROGUE", --hemorrhage
+ [89775] = "ROGUE", --hemorrhage
+ [8676] = "ROGUE", --amcush
+ [5374] = "ROGUE", --mutilate
+ [32645] = "ROGUE", --envenom
+ [1943] = "ROGUE", --rupture
+ [73651] = "ROGUE", --Recuperate (heal)
+ [35546] = "ROGUE", --combat potency (energy)
+ [98440] = "ROGUE", --relentless strikes (energy)
+ [51637] = "ROGUE", --venomous vim (energy)
+
+ --shaman
+ --> Shaman Elemental
+ [88765] = "SHAMAN", --rolling thunder (mana)
+ [51490] = "SHAMAN", --thunderstorm (mana)
+ [82987] = "SHAMAN", --telluric currents glyph (mana)
+ [101033] = "SHAMAN", --resurgence (mana)
+ [51505] = "SHAMAN", --lava burst
+ [8050] = "SHAMAN", --flame shock
+ [117014] = "SHAMAN", --elemental blast
+ [403] = "SHAMAN", --lightning bolt
+ [45284] = "SHAMAN", --lightning bolt
+ [421] = "SHAMAN", --chain lightining
+ --> Shaman Melee
+ [32175] = "SHAMAN", --stormstrike
+ [25504] = "SHAMAN", --windfury
+ [8042] = "SHAMAN", --earthshock
+ [26364] = "SHAMAN", --lightning shield
+ [117014] = "SHAMAN", --elemental blast
+ [73683] = "SHAMAN", --unleash flame
+ [51522] = "SHAMAN", --primal wisdom (mana)
+ [63375] = "SHAMAN", --primal wisdom (mana)
+ --> Shaman Resto
+ [114942] = "SHAMAN", --healing tide
+ [73921] = "SHAMAN", --healing rain
+ [1064] = "SHAMAN", --chain heal
+ [52042] = "SHAMAN", --healing stream totem
+ [61295] = "SHAMAN", --riptide
+ [51945] = "SHAMAN", --earthliving
+ [114083] = "SHAMAN", --restorative mists
+ [8004] = "SHAMAN", --healing surge
+
+ --warlock
+ [77799] = "WARLOCK", --fel flame
+ [63106] = "WARLOCK", --siphon life
+ [1454] = "WARLOCK", --life tap
+ --> warlock affliction
+ [103103] = "WARLOCK", --malefic grasp
+ [980] = "WARLOCK", --agony
+ [30108] = "WARLOCK", --unstable affliction
+ [172] = "WARLOCK", --corruption
+ [48181] = "WARLOCK", --haunt
+ --> warlock destruction
+ [29722] = "WARLOCK", --incenerate
+ [348] = "WARLOCK", --Immolate
+ [116858] = "WARLOCK", --Chaos Bolt
+ [114654] = "WARLOCK", --incinerate
+ [108686] = "WARLOCK", --immolate
+ [108685] = "WARLOCK", --conflagrate
+ [104233] = "WARLOCK", --rain of fire
+ --> warlock demo
+ [103964] = "WARLOCK", --touch os chaos
+ [686] = "WARLOCK", --shadow bolt
+ [114328] = "WARLOCK", --shadow bolt glyph
+ [140719] = "WARLOCK", --hellfire
+ [104027] = "WARLOCK", --soul fire
+ [603] = "WARLOCK", --doom
+ --> talents
+ [108371] = "WARLOCK", --Harvest life
+
+
+ --warrior
+ [100130] = "WARRIOR", --wild strike
+ [96103] = "WARRIOR", --raging blow
+ [12294] = "WARRIOR", --mortal strike
+ [1464] = "WARRIOR", --Slam
+ [23922] = "WARRIOR", --shield slam
+ [20243] = "WARRIOR", --devastate
+ [11800] = "WARRIOR", --dragon roar
+ [115767] = "WARRIOR", --deep wounds
+ [109128] = "WARRIOR", --charge
+ [11294] = "WARRIOR", --mortal strike
+ [109128] = "WARRIOR", --charge
+ [12880] = "WARRIOR", --enrage
+ [29842] = "WARRIOR", --undribled wrath
+ }
+
+ _detalhes.CrowdControlSpells = {
+
+ --death knight
+ [96294] = true, --chains of ice
+
+ --druid
+ --hibernate
+ [2637] = true, --hibernate
+ [339] = true, --entangling toots
+
+ --hunter
+ [3355] = true, --freezing trap
+ [24335] = true, --wyvern sting
+ [136634] = true, --narrow escape
+ [4167] = true, --web (spider)
+ [19503] = true, --scatter shot
+
+ --mage
+ [118] = true, --polymorph sheep
+ [61305] = true, --polymorph black cat
+ [28272] = true, --polymorph pig
+ [61721] = true, --polymorph rabbit
+ [61780] = true, --polymorph turkey
+ [28271] = true, --polymorph turtle
+ [122] = true, --frost nova
+ [33395] = true, --freeze
+ [111340] = true, --ice ward
+ [82691] = true, --ring of frost
+
+ --monk
+ [116706] = true, --disable
+
+ --paladin
+ [105421] = true, --blinding light
+ [20066] = true, --repentance
+ --prist
+ --shackle undead
+ [8122] = true, --psychic scream
+ [9484] = true, --shackle undead
+
+ --rogue
+ [2094] = true, --blind
+ [1776] = true, --gouge
+ [6770] = true, --sap
+ [408] = true, --kidney shot
+ [1833] = true, --cheap shot
+
+ --shaman
+ [51514] = true, --hex
+ [64695] = true, --earthgrab (earthgrab totem)
+ [76780] = true, --bind elemental
+
+ --warlock
+ [6358] = true, --seduction (succubus)
+ [115268] = true, --mesmerize (shivarra)
+ [118699] = true, --fear
+ [5484] = true, --howl of terror
+
+ --warrior
+ [5246] = true, --intimidating shout
+ [107566] = true, --staggering shout
+ }
+
+ _detalhes.AbsorbSpells = {
+
+ --priest
+ [47753] = true, --Divine Aegis (discipline)
+ [17] = true, --Power Word: Shield (discipline)
+ [114908] = true, --Spirit Shell (discipline)
+ [114214] = true, --Angelic Bulwark (talent)
+
+ --death knight
+ [48707] = true, --Anti-Magic Shell
+ [116888] = true, --Shroud of Purgatory (talent)
+ [51052] = true, --Anti-Magic Zone (talent)
+ [77535] = true, --Blood Shield
+
+ --shaman
+ [114893] = true, --Stone Bulwark (stone bulwark totem)
+
+ --paladin
+ [86273] = true, --Illuminated Healing (holy)
+ [65148] = true, --Sacred Shield (talent)
+
+ --monk
+ [116849] = true, --Life Cocoon (mistweaver)
+ [115295] = true, --Guard (brewmaster)
+ [118604] = true, --Guard (brewmaster)
+
+ --warlock
+ [6229] = true, --Twilight Ward
+ [108366] = true, --Soul Leech (talent)
+ [108416] = true, --Sacrificial Pact (talent)
+ [110913] = true, --Dark Bargain (talent)
+ [7812] = true, --Voidwalker's Sacrifice
+
+ --mage
+ [11426] = true, --Ice Barrier (talent)
+ [1463] = true, --Incanter's Ward (talent)
+
+ --warrior
+ [112048] = true, -- Shield Barrier (protection)
+
+ --others
+ [116631] = true, -- enchant "Enchant Weapon - Colossus"
+ [140380] = true, -- trinket "Inscribed Bag of Hydra-Spawn"
+
+ }
+
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+ _detalhes.SpellOverwrite = {
+ [124464] = {name = GetSpellInfo (124464) .. " " .. Loc ["STRING_MASTERY"]}, --> shadow word: pain mastery proc
+ [124465] = {name = GetSpellInfo (124465) .. " " .. Loc ["STRING_MASTERY"]} --> vampiric touch mastery proc
+ }
+
+end
\ No newline at end of file
diff --git a/functions/timedata.lua b/functions/timedata.lua
new file mode 100644
index 00000000..aa4d361a
--- /dev/null
+++ b/functions/timedata.lua
@@ -0,0 +1,162 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local _detalhes = _G._detalhes
+
+ _detalhes.timeContainer = {
+ damage_recording = 0,
+ healing_recording = 0,
+
+ have_custom = false,
+ custom_functions = {},
+ custom_attributes = {},
+
+ current_table = {} --> place holder
+ }
+ _detalhes.timeContainer.__index = _detalhes.timeContainer
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> local pointers
+
+ local _pairs = pairs
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details api functions
+
+ --> remove a capture previous registred
+ function _detalhes:UnregisterTimeCapture (captureType)
+ if (type (captureType) == "number" and captureType == 1) then
+ if (_detalhes.timeContainer.damage_recording > 1) then
+ _detalhes.timeContainer.damage_recording = _detalhes.timeContainer.damage_recording - 1
+ end
+
+ elseif (type (captureType) == "number" and captureType == 2) then
+ if (_detalhes.timeContainer.healing_recording > 1) then
+ _detalhes.timeContainer.healing_recording = _detalhes.timeContainer.healing_recording - 1
+ end
+
+ elseif (type (captureType) == "string") then
+ if (_detalhes.timeContainer.have_custom) then
+ if (_detalhes.timeContainer.custom_functions [captureType]) then
+ _detalhes.timeContainer.custom_functions [captureType] = nil
+ end
+ end
+ end
+ end
+
+ --> register a new capture
+ function _detalhes:RegisterTimeCapture (captureType, customName, attributes)
+
+ if (type (captureType) == "number" and captureType == 1) then
+ if (_detalhes.timeContainer.damage_recording < 1) then
+ _detalhes.timeContainer.current_table.damage = {}
+ _detalhes.timeContainer.current_table.damageLast = 0
+ _detalhes.timeContainer.current_table.damageMax = 0
+ end
+ _detalhes.timeContainer.damage_recording = _detalhes.timeContainer.damage_recording + 1
+
+ elseif (type (captureType) == "number" and captureType == 2) then
+ if (_detalhes.timeContainer.healing_recording < 1) then
+ _detalhes.timeContainer.current_table.healing = {}
+ _detalhes.timeContainer.current_table.healingLast = 0
+ _detalhes.timeContainer.current_table.healingMax = 0
+ end
+ _detalhes.timeContainer.healing_recording = _detalhes.timeContainer.healing_recording + 1
+
+ elseif (type (captureType) == "function") then
+ if (customName) then
+ _detalhes.timeContainer.have_custom = true
+ _detalhes.timeContainer.custom_functions [customName] = captureType
+ _detalhes.timeContainer.custom_attributes [customName] = attributes or {}
+ _detalhes.timeContainer.current_table [customName .. "Data"] = {}
+ _detalhes.timeContainer.current_table [customName .. "Attributes"] = {}
+ if (attributes) then
+ for k, v in pairs (attributes) do
+ _detalhes.timeContainer.current_table [customName .. "Attributes"][k] = v
+ end
+ end
+ end
+ end
+
+ return true
+ end
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> internal functions
+
+ function _detalhes.timeContainer:CreateTimeTable()
+ local _t = {}
+ setmetatable (_t, _detalhes.timeContainer)
+ _t.timeIndex = 1
+ --
+ if (_detalhes.timeContainer.damage_recording > 0) then
+ _t.damage = {}
+ _t.damageLast = 0
+ _t.damageMax = 0
+ end
+ --
+ if (_detalhes.timeContainer.healing_recording > 0) then
+ _t.healing = {}
+ _t.healingLast = 0
+ _t.healingMax = 0
+ end
+ --
+ if (_detalhes.timeContainer.have_custom) then
+ for customName, customFunction in _pairs (_detalhes.timeContainer.custom_functions) do
+ if (customFunction) then
+ _t [customName .. "Data"] = {}
+ _t [customName .. "Attributes"] = {}
+
+ local attributes = _detalhes.timeContainer.custom_attributes [customName]
+ local attributeTable = _t [customName .. "Attributes"]
+ for k, v in pairs (attributes) do
+ attributeTable [k] = v
+ end
+
+ end
+ end
+ end
+
+ _detalhes.timeContainer.current_table = _t
+
+ return _t
+ end
+
+ function _detalhes.timeContainer:Record()
+
+ if (self.damage_recording > 0) then
+ --> record damage
+ local currentDamage = _detalhes.tabela_vigente.totals_grupo[1]
+ local thisDamage = currentDamage - self.damageLast
+ self.damage [self.timeIndex] = thisDamage
+ if (thisDamage > self.damageMax) then
+ self.damageMax = thisDamage
+ end
+ self.damageLast = currentDamage
+ end
+
+ if (self.healing_recording > 0) then
+ --> record healing
+ local currentHealing = _detalhes.tabela_vigente.totals_grupo[2]
+ self.healing [self.timeIndex] = currentHealing - self.healingLast
+ if (currentHealing > self.healingMax) then
+ self.healingMax = currentHealing
+ end
+ self.healingLast = currentHealing
+ end
+
+ if (self.have_custom) then
+ --> record unknow, handled by function
+ for customName, customFunction in _pairs (self.custom_functions) do
+ if (customFunction) then
+ customFunction (self.timeIndex, self [customName .. "Data"], self [customName .. "Attributes"])
+ end
+ end
+ end
+
+ self.timeIndex = self.timeIndex + 1
+ end
\ No newline at end of file
diff --git a/gumps/anime.lua b/gumps/anime.lua
new file mode 100644
index 00000000..572409fd
--- /dev/null
+++ b/gumps/anime.lua
@@ -0,0 +1,14 @@
+local _detalhes = _G._detalhes
+
+--code from blizzard AlertFrames
+
+function _detalhes:PlayGlow (frame)
+ frame:Show()
+
+ frame.glow:Show()
+ frame.glow.animIn:Play()
+ frame.shine:Show()
+ frame.shine.animIn:Play()
+
+ PlaySound ("LFG_Rewards", "master")
+end
\ No newline at end of file
diff --git a/gumps/anime.xml b/gumps/anime.xml
new file mode 100644
index 00000000..31a9a28d
--- /dev/null
+++ b/gumps/anime.xml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:GetRegionParent():Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:GetParent():Hide();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ self:GetParent():Hide();
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gumps/fw_mods.lua b/gumps/fw_mods.lua
new file mode 100644
index 00000000..b7e9aca6
--- /dev/null
+++ b/gumps/fw_mods.lua
@@ -0,0 +1,707 @@
+
+local cstr = tostring
+local _string_len = string.len
+local ceil = math.ceil
+local math_floor = math.floor
+local CreateFrame = CreateFrame
+local GetTime = GetTime
+local GetCursorPosition = GetCursorPosition
+local GameTooltip = GameTooltip
+local _select = select
+
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+
+function gump:NewLabel2 (parent, container, member, text, font, size, color)
+
+ font = font or "GameFontHighlightSmall"
+
+ local newFontString = parent:CreateFontString (nil, "OVERLAY", font)
+ if (member) then
+ container [member] = newFontString
+ end
+ newFontString:SetText (text)
+
+ if (size) then
+ _detalhes:SetFontSize (newFontString, size)
+ end
+
+ if (color) then
+ newFontString:SetTextColor (unpack (color))
+ end
+
+ newFontString:SetJustifyH ("LEFT")
+
+ return newFontString
+end
+
+function gump:NewDetailsButton (parent, container, instancia, func, param1, param2, w, h, pic_up, pic_down, pic_disabled, pic_highlight, options, FrameName)
+
+ if (not parent) then
+ return nil
+ end
+
+ w = w or 16
+ h = h or 16
+ options = options or {}
+
+ local new_button = CreateFrame ("Button", FrameName, parent)
+ new_button:SetWidth (w)
+ new_button:SetHeight (h)
+
+ if (not pic_down and pic_up) then
+ pic_down = pic_up
+ end
+ if (not pic_disabled and pic_up) then
+ pic_disabled = pic_up
+ end
+ if (not pic_highlight and pic_up) then
+ pic_highlight = pic_up
+ end
+
+ new_button:SetNormalTexture (pic_up)
+ new_button:SetPushedTexture (pic_down)
+ new_button:SetDisabledTexture (pic_disabled)
+ new_button:SetHighlightTexture (pic_highlight, "ADD")
+
+ local new_text = new_button:CreateFontString (nil, "OVERLAY", "GameFontNormal")
+ new_text:SetPoint ("center", new_button, "center")
+ new_button.text = new_text
+
+ new_button.supportFrame = CreateFrame ("frame", nil, new_button)
+ new_button.supportFrame:SetPoint ("topleft", new_button, "topleft")
+ new_button.supportFrame:SetPoint ("bottomright", new_button, "bottomright")
+ new_button.supportFrame:SetFrameLevel (new_button:GetFrameLevel()+1)
+
+ new_button.supportFrame.disable_overlay = new_button.supportFrame:CreateTexture (nil, "overlay")
+ new_button.supportFrame.disable_overlay:SetTexture ("Interface\\AddOns\\Details\\images\\button_disable_overlay")
+ new_button.supportFrame.disable_overlay:SetPoint ("topleft", new_button.supportFrame, "topleft")
+ new_button.supportFrame.disable_overlay:SetPoint ("bottomright", new_button.supportFrame, "bottomright")
+ new_button.supportFrame.disable_overlay:Hide()
+
+ local rightFunction = options.rightFunc
+
+ new_button:SetScript ("OnDisable", function()
+ new_button.supportFrame.disable_overlay:Show()
+ end)
+ new_button:SetScript ("OnEnable", function()
+ new_button.supportFrame.disable_overlay:Hide()
+ end)
+
+ new_button.funcParam1 = param1
+ new_button.funcParam2 = param2
+ new_button.options = options
+
+ function new_button:ChangeOptions (_table)
+ options = _table
+ rightFunction = options.rightFunc
+ end
+
+ new_button.enter = false
+
+ new_button:SetScript ("OnMouseDown", function(self, button)
+ if (not self:IsEnabled()) then
+ return
+ end
+
+ self.mouse_down = GetTime()
+ local x, y = GetCursorPosition()
+ self.x = math_floor (x)
+ self.y = math_floor (y)
+
+ if (container) then
+ if (container:IsMovable() and not container.isLocked) then
+ container:StartMoving()
+ container.isMoving = true
+ end
+ end
+
+ if (new_button.texture) then
+ new_button.texture:SetTexCoord (0, 1, 0.5, 0.74609375)
+ end
+
+ if (options.OnGrab and options.OnGrab == "PassClick") then
+ if (rightFunction) then
+ if (button == "LeftButton") then
+ func (new_button.funcParam1, new_button.funcParam2)
+ else
+ rightFunction.func (rightFunction.param1, rightFunction.param2)
+ end
+ else
+ func (new_button.funcParam1, new_button.funcParam2)
+ end
+ end
+ end)
+
+ new_button:SetScript ("OnMouseUp", function (self, button)
+ if (not self:IsEnabled()) then
+ return
+ end
+
+ if (container) then
+ if (container.isMoving) then
+ container:StopMovingOrSizing()
+ container.isMoving = false
+ if (instancia) then
+ instancia:SaveMainWindowPosition()
+ end
+ end
+ end
+
+ if (new_button.texture) then
+ if (new_button.enter) then
+ new_button.texture:SetTexCoord (0, 1, 0.25, 0.49609375)
+ else
+ new_button.texture:SetTexCoord (0, 1, 0, 0.24609375)
+ end
+ end
+
+ local x, y = GetCursorPosition()
+ x = math_floor (x)
+ y = math_floor (y)
+ if ((self.mouse_down+0.4 > GetTime() and (x == self.x and y == self.y)) or (x == self.x and y == self.y)) then
+ if (rightFunction) then
+ if (button == "LeftButton") then
+ func (new_button.funcParam1, new_button.funcParam2)
+ else
+ rightFunction.func (rightFunction.param1, rightFunction.param2)
+ end
+ else
+ func (new_button.funcParam1, new_button.funcParam2)
+ end
+ end
+ end)
+
+ new_button.tooltip = nil
+
+ new_button:SetScript ("OnEnter", function()
+
+ new_button.enter = true
+
+ if (new_button.tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:SetType ("tooltip")
+ GameCooltip:SetColor ("main", "transparent")
+ GameCooltip:AddLine (new_button.tooltip)
+ GameCooltip:SetOwner (new_button)
+ GameCooltip:ShowCooltip()
+ end
+
+ if (new_button.texture) then
+ new_button.texture:SetTexCoord (0, 1, 0.25+(0.0078125/2), 0.5+(0.0078125/2))
+ end
+
+ if (new_button.MouseOnEnterHook) then
+ new_button.MouseOnEnterHook (new_button)
+ end
+ end)
+
+ new_button:SetScript ("OnLeave", function()
+
+ new_button.enter = false
+
+ if (new_button.tooltip) then
+ _detalhes.popup:ShowMe (false)
+ end
+
+ if (new_button.texture) then
+ new_button.texture:SetTexCoord (0, 1, 0, 0.24609375)
+ end
+
+ if (new_button.MouseOnLeaveHook) then
+ new_button.MouseOnLeaveHook (new_button)
+ end
+ end)
+
+ function new_button:ChangeIcon (icon1, icon2, icon3, icon4)
+ new_button:SetNormalTexture (icon1)
+ new_button:SetPushedTexture (icon2)
+ new_button:SetDisabledTexture (icon3)
+ new_button:SetHighlightTexture (icon4, "ADD")
+ end
+
+ function new_button:InstallCustomTexture (texture, rect)
+ new_button:SetNormalTexture(nil)
+ new_button:SetPushedTexture(nil)
+ new_button:SetDisabledTexture(nil)
+ new_button:SetHighlightTexture(nil)
+ texture = texture or "Interface\\AddOns\\Details\\images\\default_button"
+ new_button.texture = new_button:CreateTexture (nil, "background")
+
+ if (not rect) then
+ new_button.texture:SetAllPoints (new_button)
+ else
+ new_button.texture:SetPoint ("topleft", new_button, "topleft", rect.x1, rect.y1)
+ new_button.texture:SetPoint ("bottomright", new_button, "bottomright", rect.x2, rect.y2)
+ end
+
+ new_button.texture:SetTexCoord (0, 1, 0, 0.24609375)
+ new_button.texture:SetTexture (texture)
+ end
+
+ new_button.textColor = {}
+ new_button.textColor.r, new_button.textColor.g, new_button.textColor.b = new_button.text:GetTextColor()
+
+ return new_button
+end
+
+local EditBoxBackdrop = {
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ tile = true, edgeSize = 1, tileSize = 5,
+}
+
+function gump:NewTextBox (parent, container, member, func, param1, param2, w, h, options)
+
+ local editbox = CreateFrame ("EditBox", "DetailsEditBox1", parent)
+ container [member] = editbox
+ options = options or {}
+
+ editbox:SetAutoFocus (false)
+ editbox:SetFontObject (GameFontHighlightSmall)
+
+ editbox:SetWidth (w)
+ editbox:SetHeight (h)
+ editbox:SetJustifyH("CENTER")
+ editbox:EnableMouse (true)
+ editbox:SetBackdrop (EditBoxBackdrop)
+ editbox:SetBackdropColor (0, 0, 0, 0.5)
+ editbox:SetBackdropBorderColor (0.3, 0.3, 0.30, 0.80)
+ editbox:SetText ("") --localize-me
+
+ editbox.perdeu_foco = nil
+
+ editbox.text = ""
+ editbox.next = options.next
+ editbox.tooltip = options.tooltip
+ editbox.tab_on_enter = options.TabOnEnterPress
+ editbox.space = options.MySpace
+
+ gump:NewLabel (editbox, editbox, nil, "label", "", "GameFontHighlightSmall")
+ editbox ["label"]: SetPoint ("right", editbox, "left", -2, 0)
+ editbox.label:SetTextColor (.8, .8, .8, 1)
+
+ function editbox:SetPointAndSpace (MyAnchor, SnapTo, HisAnchor, x, y, Width)
+
+ if (type (MyAnchor) == "boolean" and MyAnchor and editbox.space) then
+ local textWidth = editbox ["label"]:GetStringWidth()+2
+ editbox:SetWidth (editbox.space - textWidth - 15)
+ return
+
+ elseif (not editbox.space and not Width) then
+ return
+ elseif (Width) then
+ editbox.space = Width
+ end
+
+ if (editbox.space) then
+ editbox ["label"]:ClearAllPoints()
+ editbox:ClearAllPoints()
+ editbox ["label"]:SetPoint (MyAnchor, SnapTo, HisAnchor, x, y)
+ editbox:SetPoint ("left", editbox["label"].widget, "right", 2, 0)
+
+ local textWidth = editbox ["label"]:GetStringWidth()+2
+ editbox:SetWidth (editbox.space - textWidth - 15)
+ end
+ end
+
+ function editbox:SetLabelText (text)
+ if (text) then
+ editbox ["label"]:SetText (text)
+ else
+ editbox ["label"]:SetText ("")
+ end
+
+ if (editbox.space) then
+ editbox:SetPointAndSpace (true) --> refresh
+ end
+ end
+
+ local EnterPress = function (byScript)
+
+ if (editbox.EnterHook) then
+ editbox.EnterHook()
+ end
+
+ local texto = _detalhes:trim (editbox:GetText())
+ if (_string_len (texto) > 0) then
+ editbox.text = texto
+ if (func) then
+ func (param1, param2, texto, editbox, byScript)
+ end
+ else
+ editbox:SetText ("")
+ editbox.text = ""
+ end
+ editbox.perdeu_foco = true --> isso aqui pra quando estiver editando e clicar em outra caixa
+ editbox:ClearFocus()
+
+ if (editbox.tab_on_enter and editbox.next) then
+ editbox.next:SetFocus()
+ end
+ end
+
+ function editbox:PressEnter (byScript)
+ EnterPress (byScript)
+ end
+
+ editbox:SetScript ("OnEnterPressed", EnterPress)
+
+ editbox:SetScript ("OnEscapePressed", function()
+ editbox:SetText("")
+ editbox.text = ""
+ editbox.perdeu_foco = true
+ editbox:ClearFocus()
+
+ if (editbox.OnEscapeHook) then
+ editbox.OnEscapeHook()
+ end
+ end)
+
+ editbox:SetScript ("OnEnter", function()
+ editbox.mouse_over = true
+ if (editbox:IsEnabled()) then
+ editbox:SetBackdropBorderColor (0.5, 0.5, 0.5, 1)
+ end
+ if (editbox.tooltip) then
+ GameCooltip:Reset()
+ GameCooltip:SetType ("tooltip")
+ GameCooltip:SetColor ("main", "transparent")
+ GameCooltip:AddLine (editbox.tooltip)
+ GameCooltip:SetOwner (editbox)
+ GameCooltip:ShowCooltip()
+ end
+
+ if (editbox.OnEnterHook) then
+ editbox:OnEnterHook()
+ end
+ end)
+
+ editbox:SetScript ("OnLeave", function()
+ editbox.mouse_over = false
+ if (editbox:IsEnabled()) then
+ editbox:SetBackdropBorderColor(0.3, 0.3, 0.3, 0.8)
+ end
+
+ if (not editbox:HasFocus()) then
+ --if (editbox:GetText() == "") then
+ -- editbox:SetText("insira o nome do buff")
+ --end
+ end
+
+ if (editbox.tooltip) then
+ if (not editbox.HaveMenu) then
+ _detalhes.popup:ShowMe (false)
+ end
+ end
+
+ if (editbox.OnLeaveHook) then
+ editbox:OnLeaveHook()
+ end
+
+ end)
+
+ editbox:SetScript ("OnEditFocusGained", function()
+ if (editbox.label) then
+ editbox.label:SetTextColor (1, 1, 1, 1)
+ end
+ if (editbox.OnFocusGainedHook) then
+ editbox.OnFocusGainedHook()
+ end
+ end)
+
+ editbox:SetScript ("OnEditFocusLost", function()
+
+ if (editbox:IsShown()) then
+ if (editbox.perdeu_foco == nil) then
+ local texto = _detalhes:trim (editbox:GetText())
+ if (_string_len (texto) > 0) then
+ editbox.text = texto
+ if (func) then
+ func (param1, param2, texto, editbox, nil)
+ end
+ else
+ editbox:SetText ("")
+ end
+ else
+ editbox.perdeu_foco = nil
+ end
+
+ if (editbox.label) then
+ editbox.label:SetTextColor (.8, .8, .8, 1)
+ end
+
+ if (editbox.OnFocusLostHook) then
+ editbox.OnFocusLostHook()
+ end
+ end
+ end)
+
+ editbox:SetScript ("OnChar", function (self, text)
+ if (editbox.InputHook) then
+ editbox:InputHook (text)
+ end
+ end)
+
+ editbox:SetScript ("OnTextChanged", function (self, userChanged)
+ if (editbox.TextChangeedHook and userChanged) then
+ editbox:TextChangeedHook (userChanged)
+ end
+ end)
+
+ editbox:SetScript ("OnTabPressed", function()
+ if (editbox.next) then
+ EnterPress()
+ editbox.next:SetFocus()
+ end
+ end)
+
+ editbox.SetNext = function (_, NextBox)
+ if (NextBox) then
+ editbox.next = NextBox
+ end
+ end
+
+ editbox.SetLabel = function (_, Label)
+ if (Label) then
+ editbox.label = Label
+ editbox.label:SetTextColor (.8, .8, .8, 1)
+ end
+ end
+
+ function editbox:Blink()
+ editbox.label:SetTextColor (1, .2, .2, 1)
+ end
+
+ if (options.Label) then
+ editbox:SetLabel (options.Label)
+ end
+
+ options = nil
+
+ return editbox
+end
+
+function gump:NewScrollBar (master, slave, x, y)
+
+ local slider_gump = CreateFrame ("Slider", nil, master)
+ slider_gump.scrollMax = 560 --default - tamanho da janela de fundo
+
+ -- ///// SLIDER /////
+ slider_gump:SetPoint ("TOPLEFT", master, "TOPRIGHT", x, y)
+ slider_gump.ativo = true
+
+ slider_gump.bg = slider_gump:CreateTexture (nil, "BACKGROUND")
+ slider_gump.bg:SetAllPoints (true)
+ slider_gump.bg:SetTexture (0, 0, 0, 0)
+ --coisinha do meio
+ slider_gump.thumb = slider_gump:CreateTexture (nil, "OVERLAY")
+ slider_gump.thumb:SetTexture ("Interface\\Buttons\\UI-ScrollBar-Knob")
+ slider_gump.thumb:SetSize (29, 30)
+ slider_gump:SetThumbTexture (slider_gump.thumb)
+
+ slider_gump:SetOrientation ("VERTICAL")
+ slider_gump:SetSize(16, 100)
+ slider_gump:SetMinMaxValues(0, slider_gump.scrollMax)
+ slider_gump:SetValue(0)
+ slider_gump.ultimo = 0
+
+ local botao_cima = CreateFrame ("Button", nil, master)
+
+ botao_cima:SetPoint ("BOTTOM", slider_gump, "TOP", 0, -12)
+ botao_cima.x = 0
+ botao_cima.y = -12
+
+ botao_cima:SetWidth (29)
+ botao_cima:SetHeight (32)
+ botao_cima:SetNormalTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Up")
+ botao_cima:SetPushedTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Down")
+ botao_cima:SetDisabledTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Disabled")
+ botao_cima:Show()
+ botao_cima:Disable()
+
+ local botao_baixo = CreateFrame ("Button", nil, master)
+ botao_baixo:SetPoint ("TOP", slider_gump, "BOTTOM", 0, 12)
+ botao_baixo.x = 0
+ botao_baixo.y = 12
+
+ botao_baixo:SetWidth (29)
+ botao_baixo:SetHeight (32)
+ botao_baixo:SetNormalTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Up")
+ botao_baixo:SetPushedTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Down")
+ botao_baixo:SetDisabledTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Disabled")
+ botao_baixo:Show()
+ botao_baixo:Disable()
+
+ master.baixo = botao_baixo
+ master.cima = botao_cima
+ master.slider = slider_gump
+
+ botao_baixo:SetScript ("OnMouseDown", function(self)
+ if (not slider_gump:IsEnabled()) then
+ return
+ end
+
+ local current = slider_gump:GetValue()
+ local minValue, maxValue = slider_gump:GetMinMaxValues()
+ if (current+5 < maxValue) then
+ slider_gump:SetValue (current+5)
+ else
+ slider_gump:SetValue (maxValue)
+ end
+ self.precionado = true
+ self.last_up = -0.3
+ self:SetScript ("OnUpdate", function(self, elapsed)
+ self.last_up = self.last_up + elapsed
+ if (self.last_up > 0.03) then
+ self.last_up = 0
+ local current = slider_gump:GetValue()
+ local minValue, maxValue = slider_gump:GetMinMaxValues()
+ if (current+2 < maxValue) then
+ slider_gump:SetValue (current+2)
+ else
+ slider_gump:SetValue (maxValue)
+ end
+ end
+ end)
+ end)
+ botao_baixo:SetScript ("OnMouseUp", function(self)
+ self.precionado = false
+ self:SetScript ("OnUpdate", nil)
+ end)
+
+ botao_cima:SetScript ("OnMouseDown", function(self)
+ if (not slider_gump:IsEnabled()) then
+ return
+ end
+
+ local current = slider_gump:GetValue()
+ if (current-5 > 0) then
+ slider_gump:SetValue (current-5)
+ else
+ slider_gump:SetValue (0)
+ end
+ self.precionado = true
+ self.last_up = -0.3
+ self:SetScript ("OnUpdate", function(self, elapsed)
+ self.last_up = self.last_up + elapsed
+ if (self.last_up > 0.03) then
+ self.last_up = 0
+ local current = slider_gump:GetValue()
+ if (current-2 > 0) then
+ slider_gump:SetValue (current-2)
+ else
+ slider_gump:SetValue (0)
+ end
+ end
+ end)
+ end)
+ botao_cima:SetScript ("OnMouseUp", function(self)
+ self.precionado = false
+ self:SetScript ("OnUpdate", nil)
+ end)
+ --> isso aqui pra quando o slider ativar, o scroll fica na posição zero
+ botao_cima:SetScript ("OnEnable", function (self)
+ local current = slider_gump:GetValue()
+ if (current == 0) then
+ botao_cima:Disable()
+ end
+ end)
+
+ slider_gump:SetScript ("OnValueChanged", function (self)
+ local current = self:GetValue()
+ master:SetVerticalScroll (current)
+
+ local minValue, maxValue = slider_gump:GetMinMaxValues()
+
+ if (current == minValue) then
+ botao_cima:Disable()
+ elseif (not botao_cima:IsEnabled()) then
+ botao_cima:Enable()
+ end
+
+ if (current == maxValue) then
+ botao_baixo:Disable()
+ elseif (not botao_baixo:IsEnabled()) then
+ botao_baixo:Enable()
+ end
+
+ end)
+
+ slider_gump:SetScript ("OnShow", function (self)
+ botao_cima:Show()
+ botao_baixo:Show()
+ end)
+
+ slider_gump:SetScript ("OnDisable", function (self)
+ botao_cima:Disable()
+ botao_baixo:Disable()
+ end)
+
+ slider_gump:SetScript ("OnEnable", function (self)
+ botao_cima:Enable()
+ botao_baixo:Enable()
+ end)
+
+ master:SetScript ("OnMouseWheel", function (self, delta)
+ if (not slider_gump:IsEnabled()) then
+ return
+ end
+
+ local current = slider_gump:GetValue()
+ if (delta < 0) then
+ if (current < slider_gump.scrollMax+20) then
+ slider_gump:SetValue (current + 20)
+ else
+ slider_gump:SetValue (slider_gump.scrollMax)
+ end
+ elseif (delta > 0) then
+ if (current+20 > 0) then
+ slider_gump:SetValue (current - 20)
+ else
+ slider_gump:SetValue (0)
+ end
+ end
+ end)
+
+ function slider_gump:Altura (h)
+ self:SetHeight (h)
+ end
+
+ function slider_gump:Update (desativar)
+
+ if (desativar) then
+ slider_gump:Disable()
+ slider_gump:SetValue(0)
+ slider_gump.ativo = false
+ master:EnableMouseWheel (false)
+ return
+ end
+
+ self.scrollMax = slave:GetHeight()-master:GetHeight()
+ if (self.scrollMax > 0) then
+ slider_gump:SetMinMaxValues (0, self.scrollMax)
+ if (not slider_gump.ativo) then
+ slider_gump:Enable()
+ slider_gump.ativo = true
+ master:EnableMouseWheel (true)
+ end
+ else
+ slider_gump:Disable()
+ slider_gump:SetValue(0)
+ slider_gump.ativo = false
+ master:EnableMouseWheel (false)
+ end
+ end
+
+ function slider_gump:cimaPoint (x, y)
+ botao_cima:SetPoint ("BOTTOM", slider_gump, "TOP", x, (y)-12)
+ end
+
+ function slider_gump:baixoPoint (x, y)
+ botao_baixo:SetPoint ("TOP", slider_gump, "BOTTOM", x, (y)+12)
+ end
+
+ return slider_gump
+end
diff --git a/gumps/janela_copy.lua b/gumps/janela_copy.lua
new file mode 100644
index 00000000..ce90116e
--- /dev/null
+++ b/gumps/janela_copy.lua
@@ -0,0 +1,57 @@
+do
+
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+
+--> panel
+
+ function _detalhes:CreateCopyPasteWindow()
+ local panel = DetailsFrameWork:NewPanel (UIParent, _, "DetailsCopy", _, 512, 128, false)
+ tinsert (UISpecialFrames, "DetailsCopy")
+ panel:SetFrameStrata ("FULLSCREEN")
+ panel:SetPoint ("center", UIParent, "center")
+ panel.locked = false
+
+ DetailsFrameWork:NewImage (panel, _, "$parentBackGround", "background", 512, 128, "Interface\\AddOns\\Details\\images\\copy", "background")
+ panel.background:SetPoint()
+
+ --> title
+ DetailsFrameWork:NewLabel (panel, _, "$parentTitle", "title", "Paste & Copy", "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255})
+ panel.title:SetPoint ("center", panel, "center")
+ panel.title:SetPoint ("top", panel, "top", 0, -18)
+
+ --> close
+ panel.fechar = CreateFrame ("Button", nil, panel.widget, "UIPanelCloseButton")
+ panel.fechar:SetWidth (32)
+ panel.fechar:SetHeight (32)
+ panel.fechar:SetPoint ("TOPRIGHT", panel.widget, "TOPRIGHT", -1, -8)
+ panel.fechar:SetText ("X")
+ panel.fechar:SetFrameLevel (panel:GetFrameLevel()+2)
+
+ panel.fechar:SetScript ("OnClick", function()
+ panel:Hide()
+ end)
+
+ DetailsFrameWork:NewTextEntry (panel, _, "$parentTextEntry", "text", 476, 14)
+ panel.text:SetPoint (20, -106)
+ panel.text:SetHook ("OnEditFocusLost", function() panel:Hide() end)
+ panel.text:SetHook ("OnChar", function() panel:Hide() end)
+
+ DetailsFrameWork:NewLabel (panel, _, _, "desc", "paste on your web browser address bar", "OptionsFontHighlightSmall", 12)
+ panel.desc:SetPoint (340, -54)
+ panel.desc.width = 150
+ panel.desc.height = 25
+ panel.desc.align = "|"
+ panel.desc.color = "gray"
+
+ panel:Hide()
+ end
+
+ function _detalhes:CopyPaste (link)
+ _G.DetailsCopy.MyObject.text.text = link
+ _G.DetailsCopy.MyObject.text:HighlightText()
+ _G.DetailsCopy.MyObject:Show()
+ _G.DetailsCopy.MyObject.text:SetFocus()
+
+ end
+end
\ No newline at end of file
diff --git a/gumps/janela_custom.lua b/gumps/janela_custom.lua
new file mode 100644
index 00000000..50b45131
--- /dev/null
+++ b/gumps/janela_custom.lua
@@ -0,0 +1,965 @@
+local _detalhes = _G._detalhes
+
+local AceComm = LibStub ("AceComm-3.0")
+local AceSerializer = LibStub ("AceSerializer-3.0")
+
+local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+local atributos = _detalhes.atributos
+local sub_atributos = _detalhes.sub_atributos
+--lua locals
+local _cstr = string.format
+local _math_ceil = math.ceil
+local _math_floor = math.floor
+local _ipairs = ipairs
+local _pairs = pairs
+local _string_lower = string.lower
+local _table_sort = table.sort
+local _table_insert = table.insert
+local _unpack = unpack
+
+--api locals
+local _GetSpellInfo = _detalhes.getspellinfo
+local _CreateFrame = CreateFrame
+local _GetTime = GetTime
+local _GetCursorPosition = GetCursorPosition
+local _GameTooltip = GameTooltip
+local _UIParent = UIParent
+local _GetScreenWidth = GetScreenWidth
+local _GetScreenHeight = GetScreenHeight
+local _IsAltKeyDown = IsAltKeyDown
+local _IsShiftKeyDown = IsShiftKeyDown
+local _IsControlKeyDown = IsControlKeyDown
+
+local CLASS_ICON_TCOORDS = _G.CLASS_ICON_TCOORDS
+
+local class_type_dano = _detalhes.atributos.dano
+local class_type_misc = _detalhes.atributos.misc
+local tabela_do_combate
+
+local master_container
+
+local function CreateCustomWindow()
+
+ local gump_fundo_backdrop = {
+ bgFile = "Interface\\AddOns\\Details\\images\\background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ tile = true, tileSize = 16, edgeSize = 4,
+ insets = {left = 0, right = 0, top = 0, bottom = 0}}
+
+ local frame = CreateFrame ("frame", "DetailsCustomPanel", UIParent)
+ frame:SetPoint ("center", UIParent, "center", 100, -300)
+ frame:SetWidth (512)
+ frame:SetHeight (150)
+ frame:EnableMouse (true)
+ frame:SetMovable (true)
+ frame:SetFrameLevel (1)
+
+ frame.fundo = frame:CreateTexture (nil, "border")
+ frame.fundo:SetTexture ("Interface\\AddOns\\Details\\images\\custom_bg")
+ frame.fundo:SetPoint ("topleft", frame, "topleft")
+
+ frame.move = gump:NewDetailsButton (frame, frame, _, function() end, nil, nil, 1, 1, "", "", "", "")
+ frame.move:SetPoint ("topleft", frame, "topleft")
+ frame.move:SetPoint ("bottomright", frame, "bottomright")
+ frame.move:SetFrameLevel (frame:GetFrameLevel()+1)
+
+ --> botão de fechar
+ frame.fechar = _CreateFrame ("Button", nil, frame, "UIPanelCloseButton")
+ frame.fechar:SetWidth (32)
+ frame.fechar:SetHeight (32)
+ frame.fechar:SetPoint ("TOPRIGHT", frame, "TOPRIGHT", -1, -8)
+ frame.fechar:SetText ("X")
+ frame.fechar:SetFrameLevel (frame:GetFrameLevel()+2)
+
+ frame.fechar:SetScript ("OnClick", function()
+ _detalhes:CloseCustomWindow()
+ end)
+
+ frame:SetScript ("OnHide", function()
+ _detalhes:CloseCustomWindow()
+ end)
+
+ --> help button
+ local helpButton = CreateFrame ("button", "DetailsCustomPanelHelpButton", frame, "MainHelpPlateButton")
+ helpButton:SetWidth (36)
+ helpButton:SetHeight (36)
+ helpButton.I:SetWidth (25)
+ helpButton.I:SetHeight (25)
+ helpButton.Ring:SetWidth (36)
+ helpButton.Ring:SetHeight (36)
+ helpButton.Ring:SetPoint ("center", 7, -7)
+ helpButton:SetPoint ("topright", frame, "topright", -20, -7)
+ helpButton:SetFrameLevel (frame.fechar:GetFrameLevel())
+
+ local customHelp = {
+ FramePos = {x = 0, y = -30},
+ FrameSize = {width = 512, height = 120},
+
+ [1] ={HighLightBox = {x = 15, y = -39, width = 100, height = 70},
+ ButtonPos = { x = 43, y = -50},
+ ToolTipDir = "LEFT",
+ ToolTipText = Loc ["STRING_CUSTOM_HELP1"]
+ },
+ [2] ={HighLightBox = {x = 120, y = -9, width = 170, height = 95},
+ ButtonPos = { x = 182, y = -30},
+ ToolTipDir = "RIGHT",
+ ToolTipText = Loc ["STRING_CUSTOM_HELP2"]
+ },
+ [3] ={HighLightBox = {x = 295, y = -9, width = 170, height = 75},
+ ButtonPos = { x = 363, y = -25},
+ ToolTipDir = "RIGHT",
+ ToolTipText = Loc ["STRING_CUSTOM_HELP3"]
+ },
+ [4] ={HighLightBox = {x = 470, y = -25, width = 30, height = 25},
+ ButtonPos = { x = 485, y = -15},
+ ToolTipDir = "RIGHT",
+ ToolTipText = Loc ["STRING_CUSTOM_HELP4"]
+ }
+ }
+
+ helpButton:SetScript ("OnClick", function()
+ if (not HelpPlate_IsShowing (customHelp)) then
+ HelpPlate_Show (customHelp, frame, helpButton, true)
+ else
+ HelpPlate_Hide (true)
+ end
+ end)
+
+ --> titulo
+ gump:NewLabel (frame, frame, nil, "titulo", "Custom Display", "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255})
+ frame.titulo:SetPoint ("center", frame, "center")
+ frame.titulo:SetPoint ("top", frame, "top", 0, -18)
+
+ --> icone no canto esquerdo superior
+ frame.classe_icone = frame:CreateTexture (nil, "BACKGROUND")
+ frame.classe_icone:SetPoint ("TOPLEFT", frame, "TOPLEFT", 4, 0)
+ frame.classe_icone:SetWidth (64)
+ frame.classe_icone:SetHeight (64)
+ frame.classe_icone:SetDrawLayer ("BACKGROUND", 1)
+ frame.classe_icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes_plus")
+ frame.classe_icone:SetTexCoord (0, 0.25, 0.25, 0.5)
+
+ --------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ frame.atributo = nil
+ frame.sub_atributo = nil
+
+ local SubMenu = function (atributo)
+ frame.sub_atributo = atributo
+
+ end
+
+
+ local LeftButtons = frame.fechar:CreateTexture (nil, "overlay")
+ LeftButtons:SetWidth (56)
+ LeftButtons:SetHeight (70)
+ LeftButtons:SetPoint ("left", frame, "left", 15, -29)
+ LeftButtons:SetTexture ("Interface\\Glues\\CHARACTERCREATE\\AlternateForm")
+ LeftButtons:SetTexCoord (0, 1, 0, 0.62890625)
+ LeftButtons:SetDrawLayer ("overlay", 4)
+
+ --> botão de deletar um custom
+ local DeleteButton = gump:NewDetailsButton (frame, frame, _, function()end, nil, nil, 60, 15, "", "", "", "")
+ DeleteButton.text:SetText (Loc ["STRING_CUSTOM_REMOVE"])
+ DeleteButton.text:SetJustifyH ("left")
+ DeleteButton.text:SetPoint ("left", DeleteButton, "left", 0, -1)
+ DeleteButton:SetPoint ("topleft", LeftButtons, "topleft", 34, -10)
+ DeleteButton:SetFrameLevel (frame:GetFrameLevel()+2)
+ DeleteButton:InstallCustomTexture (_, {x1 = -20, x2 = 0, y1 = -2, y2 = -2})
+ --DeleteButton.
+
+ local removeTexture = frame.fechar:CreateTexture (nil, "overlay")
+ removeTexture:SetWidth (23)
+ removeTexture:SetHeight (23)
+ removeTexture:SetTexture ("Interface\\ICONS\\Spell_BrokenHeart")
+ removeTexture:SetTexCoord (5/64, 60/64, 4/64, 62/64)
+ removeTexture:SetPoint ("topleft", LeftButtons, "topleft", 6, -8)
+ removeTexture:SetDrawLayer ("overlay", 3)
+
+ --> botão de dar broadcast em um custom
+ local BroadcastButton = gump:NewDetailsButton (frame, frame, _, function()end, nil, nil, 60, 15, "", "", "", "")
+ BroadcastButton.text:SetText (Loc ["STRING_CUSTOM_BROADCAST"])
+ BroadcastButton.text:SetJustifyH ("left")
+ BroadcastButton.text:SetPoint ("left", BroadcastButton, "left", 0, -1)
+ BroadcastButton:SetPoint ("topleft", LeftButtons, "topleft", 34, -42)
+ BroadcastButton:SetFrameLevel (frame:GetFrameLevel()+2)
+ BroadcastButton:InstallCustomTexture (_, {x1 = -20, x2 = 0, y1 = -2, y2 = -2})
+
+ local broadcastTexture = frame.fechar:CreateTexture (nil, "overlay")
+ broadcastTexture:SetWidth (23)
+ broadcastTexture:SetHeight (23)
+ broadcastTexture:SetTexture ("Interface\\ICONS\\Ability_Warrior_RallyingCry")
+ broadcastTexture:SetTexCoord (5/64, 60/64, 4/64, 62/64)
+ broadcastTexture:SetPoint ("topleft", LeftButtons, "topleft", 6, -40)
+ broadcastTexture:SetDrawLayer ("overlay", 3)
+
+
+ local fundoBrilha = frame:CreateTexture (nil, "overlay")
+ fundoBrilha:SetWidth (140)
+ fundoBrilha:SetHeight (36)
+ fundoBrilha:SetTexture ("Interface\\PetBattles\\Weather-Sunlight")
+ fundoBrilha:SetTexCoord (.3, 1, 0, 1)
+
+ local MainMenu = function (atributo)
+
+ frame.atributo = atributo
+ frame.sub_atributo = 1
+
+ fundoBrilha:SetPoint ("left", frame.MainMenu [atributo].icon , "right", -20, -10)
+
+ --[[
+ for i = 1, 5 do
+ if (sub_atributos [atributo].lista[i]) then
+ frame.SubMenu [i].text:SetText (sub_atributos [atributo].lista[i])
+ frame.SubMenu [i]:Show()
+ else
+ frame.SubMenu [i]:Hide()
+ end
+ end
+ --]]
+ end
+
+ frame.MainMenu = {}
+ frame.SubMenu = {}
+
+ do
+
+ local x = 140
+ local x2 = 170
+
+ local y = -17
+
+ local OnEnterHook = function (button)
+ button.text:SetTextColor (1, 1, 1)
+ end
+
+ local OnLeaveHook = function (button)
+ button.text:SetTextColor (button.textColor.r, button.textColor.g, button.textColor.b )
+ end
+
+ --> 4 atributos principais
+ for i = 1, 4 do
+
+ local button = gump:NewDetailsButton (frame, frame, _, MainMenu, i, nil, 120, 15, "", "", "", "")
+ button.MouseOnEnterHook = OnEnterHook
+ button.MouseOnLeaveHook = OnLeaveHook
+
+ button.textura = button:CreateTexture (nil, "overlay")
+ button.textura:SetPoint ("right", button, "left", 60, 0)
+ button.icon = button:CreateTexture (nil, "background")
+ button.icon:SetPoint ("center", button.textura, "center", 2, 0)
+ button.icon:SetTexture ("Interface\\AddOns\\Details\\images\\icon_mainwindow")
+ button.icon:SetWidth (22)
+ button.icon:SetHeight (22)
+
+ if (i == 1) then
+ button.textura:SetTexture ("Interface\\ExtraButton\\ChampionLight")
+ button.icon:SetTexCoord (32/256 * (1-1), 32/256 * 1, 0, 1)
+
+ elseif (i == 2) then
+ button.textura:SetTexture ("Interface\\ExtraButton\\Ysera")
+ button.icon:SetTexCoord (32/256 * (2-1), 32/256 * 2, 0, 1)
+ button.icon:SetPoint ("center", button.textura, "center", 3, 0)
+
+ elseif (i == 3) then
+ button.textura:SetTexture ("Interface\\ExtraButton\\FengShroud")
+ button.icon:SetTexCoord (32/256 * (3-1), 32/256 * 3, 0, 1)
+
+ elseif (i == 4) then
+ button.textura:SetTexture ("Interface\\ExtraButton\\BrewmoonKeg")
+ button.icon:SetTexCoord (32/256 * (4-1), 32/256 * 4, 0, 1)
+
+ end
+
+ button.textura:SetWidth (76)
+ button.textura:SetHeight (40)
+ button:SetPoint ("topleft", frame, "topleft", x, i*-25 + (y))
+ button.text:SetText (atributos.lista [i])
+ button.text:SetPoint ("left", button, "left", 65, 0)
+ button:SetFrameLevel (frame:GetFrameLevel()+2)
+
+ frame.MainMenu [i] = button
+ end
+
+ frame.atributo = 1
+ frame.sub_atributo = 1
+ fundoBrilha:SetPoint ("left", frame.MainMenu [1].icon , "right", -20, -10)
+
+ --> 5 atributos secundarios
+
+ --[[
+ for i = 1, 5 do
+ local button = gump:NewDetailsButton (frame, frame, _, SubMenu, i, nil, 60, 15, "", "", "", "")
+ button:SetPoint ("topleft", frame, "topleft", x2, i*-15)
+ button.text:SetPoint ("left", button, "left", 5, 0)
+ button.text:SetText ("sub menu "..i)
+ button:SetFrameLevel (frame:GetFrameLevel()+2)
+ frame.SubMenu [i] = button
+ end
+ --]]
+ end
+
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ --> Edit Boxes
+
+ local xStart = 290
+ local WidthMax = 220
+
+----------> The name of the custom
+ local MyNameSelected = function (param1, param2, texto, editbox) --print (param1, param2, texto, editbox)
+ end
+ gump:NewTextBox (frame, frame, "TextMyNameEntry", SpellIDSelected, "param_1", "param_2", 100, 15, {TabOnEnterPress = true, MySpace = WidthMax})
+ frame ["TextMyNameEntry"]:SetFrameLevel (frame:GetFrameLevel()+2)
+ frame ["TextMyNameEntry"]:SetPointAndSpace ("topleft", frame, "topleft", xStart, -45, WidthMax)
+ frame ["TextMyNameEntry"]:SetLabelText (Loc ["STRING_CUSTOM_NAME"]..":")
+
+----------> Spell Name ou ID
+ local SpellIDSelected = function (param1, param2, texto, editbox)
+ local _ThisSpellName, _, _ThisSpellIcon = _GetSpellInfo (tonumber (texto))
+ if (_ThisSpellName) then
+ frame.IconTexture = _ThisSpellIcon
+ frame.icon:SetTexture (frame.IconTexture)
+
+ if (frame ["TextMyNameEntry"].text == "") then
+ frame ["TextMyNameEntry"].text = _ThisSpellName
+ frame ["TextMyNameEntry"]:SetText (_ThisSpellName)
+ end
+ end
+ end
+
+ gump:NewTextBox (frame, frame, "TextSpellIDEntry", SpellIDSelected, "param_1", "param_2", 80, 15, {TabOnEnterPress = true, MySpace = WidthMax-20})
+ frame ["TextSpellIDEntry"]:SetFrameLevel (frame:GetFrameLevel()+2)
+ frame ["TextSpellIDEntry"]:SetPointAndSpace ("topleft", frame, "topleft", xStart, -62, WidthMax-20)
+ frame ["TextSpellIDEntry"]:SetLabelText (Loc ["STRING_CUSTOM_SPELLID"])
+
+ local openSpellEncounter = function()
+
+ end
+
+ local frameEncounterSkill = CreateFrame ("frame", nil, frame)
+ frameEncounterSkill:SetPoint ("left", frame ["TextSpellIDEntry"], "right")
+ frameEncounterSkill:SetWidth (20)
+ frameEncounterSkill:SetHeight (20)
+ frameEncounterSkill:SetFrameLevel (frame:GetFrameLevel()+2)
+ local frameEncounterSkillImage = frameEncounterSkill:CreateTexture (nil, "overlay")
+ frameEncounterSkillImage:SetPoint ("center", frameEncounterSkill)
+ frameEncounterSkillImage:SetTexture ("Interface\\Buttons\\UI-MicroButton-Raid-Up")
+ frameEncounterSkillImage:SetTexCoord (0.046875, 0.90625, 0.40625, 0.953125)
+ frameEncounterSkillImage:SetWidth (20)
+ frameEncounterSkillImage:SetHeight (16)
+
+ local GameCooltip = GameCooltip
+
+ local spellsFrame = gump:NewPanel (frame, _, "DetailsCustomSpellsFrame", "spellsFrame", 1, 1)
+ spellsFrame:SetPoint ("bottomleft", frame, "topleft", 62, -14)
+ spellsFrame:Hide()
+
+ local selectedEncounterSpell = function (spellId)
+ local nome_magia, _, icone_magia = _GetSpellInfo (spellId)
+ frame ["TextMyNameEntry"]:SetText (nome_magia)
+ frame ["TextMyNameEntry"]:PressEnter()
+ frame ["TextSpellIDEntry"]:SetText (spellId)
+ frame ["TextSpellIDEntry"]:PressEnter()
+ frame ["TextSourceEntry"]:SetText ("[all]")
+ frame ["TextSourceEntry"]:PressEnter()
+ frame.icon:SetTexture (icone_magia)
+ spellsFrame:Hide()
+ end
+
+ local spellsFrameButtons = {}
+
+ local buttonMouseOver = function (button)
+ button.MyObject.image:SetBlendMode ("ADD")
+ button.MyObject.line:SetBlendMode ("ADD")
+ button.MyObject.label:SetTextColor (1, 1, 1, 1)
+ local OnEnterColors = button:GetParent().Gradient.OnEnter
+ local _r, _g, _b, _a = button:GetParent():GetBackdropColor()
+ gump:GradientEffect (button:GetParent(), "frame", _r, _g, _b, _a, OnEnterColors[1], OnEnterColors[2], OnEnterColors[3], OnEnterColors[4], .3)
+ end
+ local buttonMouseOut = function (button)
+ button.MyObject.image:SetBlendMode ("BLEND")
+ button.MyObject.line:SetBlendMode ("BLEND")
+ button.MyObject.label:SetTextColor (.8, .8, .8, .8)
+ local _r, _g, _b, _a = button:GetParent():GetBackdropColor()
+ if (_r) then
+ local OnLeaveColors = button:GetParent().Gradient.OnLeave
+ gump:GradientEffect (button:GetParent(), "frame", _r, _g, _b, _a, OnLeaveColors[1], OnLeaveColors[2], OnLeaveColors[3], OnLeaveColors[4], .3)
+ end
+ end
+
+ local EncounterSelect = function (_, _, instanceId, bossIndex)
+
+ spellsFrame:Show()
+
+ local spells = _detalhes:GetEncounterSpells (instanceId, bossIndex)
+
+ local x = 10
+ local y = 10
+ local i = 1
+
+ for spell, _ in pairs (spells) do
+
+ local thisButton = spellsFrameButtons [i]
+
+ if (not thisButton) then
+ thisButton = gump:NewButton (spellsFrame.frame, spellsFrame.frame, "DetailsCustomSpellsFrameButton"..i, "button"..i, 80, 20, selectedEncounterSpell)
+ thisButton:SetPoint ("topleft", "DetailsCustomSpellsFrame", "topleft", x, -y)
+ local t = gump:NewImage (thisButton, thisButton, "DetailsCustomEncounterImageButton"..i, "image", 20, 20)
+ t:SetPoint ("left", thisButton)
+ thisButton:SetHook ("OnEnter", buttonMouseOver)
+ thisButton:SetHook ("OnLeave", buttonMouseOut)
+
+ local text = gump:NewLabel (thisButton, nil, "DetailsCustomSpellsFrameButton"..i.."Label", "label", "Spell", nil, 9.5, {.8, .8, .8, .8})
+ text:SetPoint ("left", t.image, "right", 2, 0)
+ text:SetWidth (73)
+ text:SetHeight (10)
+
+ local border = gump:NewImage (thisButton, thisButton, "DetailsCustomEncounterBorderButton"..i, "border", 40, 38, "Interface\\SPELLBOOK\\Spellbook-Parts")
+ border:SetTexCoord (0.00390625, 0.27734375, 0.44140625,0.69531250)
+ border:SetDrawLayer ("background")
+ border:SetPoint ("topleft", thisButton.button, "topleft", -9, 9)
+
+ local line = gump:NewImage (thisButton, thisButton, "DetailsCustomEncounterLineButton"..i, "line", 84, 25, "Interface\\SPELLBOOK\\Spellbook-Parts")
+ line:SetTexCoord (0.31250000, 0.96484375, 0.37109375, 0.52343750)
+ line:SetDrawLayer ("background")
+ line:SetPoint ("left", thisButton.button, "right", -60, -3)
+
+ table.insert (spellsFrameButtons, #spellsFrameButtons+1, thisButton)
+ end
+
+ y = y + 20
+ if (y >= 110) then
+ y = 10
+ x = x + 100
+ end
+
+ local nome_magia, _, icone_magia = _GetSpellInfo (spell)
+ thisButton.image:SetTexture (icone_magia)
+ thisButton.label:SetText (nome_magia)
+ thisButton:SetClickFunction (selectedEncounterSpell, spell)
+ thisButton:Show()
+ i = i + 1
+ end
+
+ for maxIndex = i, #spellsFrameButtons do
+ spellsFrameButtons [maxIndex]:Hide()
+ end
+
+ i = i-1
+ spellsFrame:SetSize (math.ceil (i/5)*110, math.min (i*20 + 10, 120))
+
+ end
+
+ local BuildEncounterMenu = function()
+
+ GameCooltip:Reset()
+ GameCooltip:SetType ("menu")
+ GameCooltip:SetOwner (frameEncounterSkill)
+
+ for instanceId, instanceTable in pairs (_detalhes.EncounterInformation) do
+
+ GameCooltip:AddLine (instanceTable.name, _, 1, "white")
+ GameCooltip:AddIcon (instanceTable.icon, 1, 1, 64, 32)
+
+ for index, encounterName in ipairs (instanceTable.boss_names) do
+ GameCooltip:AddMenu (2, EncounterSelect, instanceId, index, nil, encounterName, nil, true)
+ local L, R, T, B, Texture = _detalhes:GetBossIcon (instanceId, index)
+ GameCooltip:AddIcon (Texture, 2, 1, 20, 20, L, R, T, B)
+ end
+ end
+
+ GameCooltip:SetOption ("HeightAnchorMod", -10)
+ GameCooltip:ShowCooltip()
+
+ --_detalhes.EncounterInformation [instanceTable.id] = InstanceTable
+ end
+
+ frameEncounterSkill:SetScript ("OnEnter", function()
+ frameEncounterSkillImage:SetBlendMode ("ADD")
+ BuildEncounterMenu()
+ end)
+
+ frameEncounterSkill:SetScript ("OnLeave", function()
+ frameEncounterSkillImage:SetBlendMode ("BLEND")
+ end)
+
+ frame ["TextSpellIDEntry"].HaveMenu = false
+
+ frame ["TextSpellIDEntry"].OnLeaveHook = function()
+ _detalhes.popup.buttonOver = false
+ if (_detalhes.popup.ativo) then
+ local passou = 0
+ frame ["TextSpellIDEntry"]:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ if (not _detalhes.popup.mouseOver and not _detalhes.popup.buttonOver) then
+ _detalhes.popup:ShowMe (false)
+ end
+ frame ["TextSpellIDEntry"]:SetScript ("OnUpdate", nil)
+ end
+ end)
+ else
+ frame ["TextSpellIDEntry"]:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ frame ["TextSpellIDEntry"].OnFocusLostHook = function()
+ frame ["TextSpellIDEntry"].HaveMenu = false
+ end
+
+ local OnClickMenu = function (_, _, SpellID)
+ frame ["TextSpellIDEntry"]:SetText (SpellID)
+ frame ["TextSpellIDEntry"]:PressEnter()
+ frame ["TextSpellIDEntry"].HaveMenu = false
+ _detalhes.popup:ShowMe (false)
+ end
+
+ local _string_lower = string.lower
+ local _string_sub = string.sub
+
+ frame ["TextSpellIDEntry"].TextChangeedHook = function (userChanged)
+ if (not userChanged) then
+ return
+ end
+
+ local texto = frame ["TextSpellIDEntry"]:GetText()
+ texto = _detalhes:trim (texto)
+ texto = _string_lower (texto)
+
+ local index = _string_sub (texto, 1, 1)
+ local cached = _detalhes.spellcachefull [index]
+
+ if (cached) then
+
+ local CoolTip = _G.GameCooltip
+
+ CoolTip:Reset()
+ CoolTip:SetType ("menu")
+ CoolTip:SetColor ("main", "transparent")
+ CoolTip:SetOwner (frame ["TextSpellIDEntry"])
+ CoolTip:SetOption ("NoLastSelectedBar", true)
+ CoolTip:SetOption ("TextSize", 9.5)
+
+ local CoolTipTable = {}
+ local texcoord = {0, 1, 0, 1}
+ local i = 1
+
+ for SpellID, SpellTable in _pairs (cached) do
+
+ if (_string_lower (SpellTable[1]):find (texto)) then
+ local rank = SpellTable[3]
+ if (not rank or rank == "") then
+ rank = ""
+ else
+ rank = " ("..rank..")"
+ end
+
+ CoolTip:AddMenu (1, OnClickMenu, SpellID, nil, nil, SpellID..": "..SpellTable[1]..rank, SpellTable[2], true)
+
+ if (i > 20) then
+ break
+ else
+ i = i + 1
+ end
+ end
+
+ end
+
+ frame ["TextSpellIDEntry"].HaveMenu = true
+ CoolTip.buttonOver = true
+ CoolTip:ShowCooltip()
+ end
+ end
+
+----------> Source
+ local SourceSelected = function (param1, param2, texto, editbox) end
+ gump:NewTextBox (frame, frame, "TextSourceEntry", SourceSelected, "param_1", "param_2", 100, 15, {TabOnEnterPress = true, MySpace = WidthMax})
+ frame ["TextSourceEntry"]:SetFrameLevel (frame:GetFrameLevel()+2)
+ frame ["TextSourceEntry"]:SetPointAndSpace ("topleft", frame, "topleft", xStart, -79, WidthMax)
+ frame ["TextSourceEntry"]:SetLabelText (Loc ["STRING_CUSTOM_SOURCE"]..":")
+ frame ["TextSourceEntry"].InputHook = function()
+ local texto = frame ["TextSourceEntry"]:GetText()
+ texto:gsub ("[raid]", "|cFFFF00FF|r[raid]")
+ texto:gsub ("[all]", "|cFF0000FF|r[all]")
+ texto:gsub ("[player]", "|cFFFF0000|r[player]")
+ frame ["TextSourceEntry"]:SetText (texto)
+ end
+ frame ["TextSourceEntry"].EnterHook = function()
+ local texto = frame ["TextSourceEntry"]:GetText()
+ if (texto:find ("%[raid%]")) then
+ frame ["TextSourceEntry"]:SetText ("[raid]")
+ elseif (texto:find ("%[all%]")) then
+ frame ["TextSourceEntry"]:SetText ("[all]")
+ elseif (texto:find ("%[player%]")) then
+ frame ["TextSourceEntry"]:SetText ("[player]")
+ end
+ end
+
+---------> Actor Name
+ local ActorNameSelected = function (param1, param2, texto, editbox) end
+ gump:NewTextBox (frame, frame, "TextActorNameEntry", ActorNameSelected, "param_1", "param_2", 100, 15, {TabOnEnterPress = true})
+ frame ["TextActorNameEntry"]: SetFrameLevel (frame:GetFrameLevel()+2)
+ frame ["TextActorNameEntry"]:SetPointAndSpace ("topleft", frame, "topleft", xStart, -96, WidthMax)
+ frame ["TextActorNameEntry"]:SetLabelText (Loc ["STRING_CUSTOM_TARGET"]..":")
+
+ --> Tab Order
+ frame ["TextMyNameEntry"]:SetNext (frame ["TextSpellIDEntry"])
+ frame ["TextSpellIDEntry"]:SetNext (frame ["TextSourceEntry"])
+ frame ["TextSourceEntry"]:SetNext (frame ["TextActorNameEntry"])
+ frame ["TextActorNameEntry"]:SetNext (frame ["TextMyNameEntry"])
+ frame ["TextActorNameEntry"]:Disable()
+
+ --> Tooltips
+ --> localize-me
+ frame ["TextMyNameEntry"].tooltip = Loc ["STRING_CUSTOM_TOOLTIPNAME"]
+ frame ["TextSpellIDEntry"].tooltip = Loc ["STRING_CUSTOM_TOOLTIPSPELL"]
+ frame ["TextSourceEntry"].tooltip = Loc ["STRING_CUSTOM_TOOLTIPSOURCE"]
+ frame ["TextActorNameEntry"].tooltip = Loc ["STRING_CUSTOM_TOOLTIPTARGET"].."\n|cFFFF0000"..Loc ["STRING_CUSTOM_TOOLTIPNOTWORKING"]
+
+ frame.IconTexture = "Interface\\Icons\\TEMP"
+
+ local ChooseIcon = function()
+ if (not frame.IconFrame) then
+
+ frame.IconFrame = CreateFrame ("frame", "DetailsCustomPanelIcons", frame)
+
+ frame.IconFrame:SetPoint ("bottomright", frame, "topright", 0, 0)
+ frame.IconFrame:SetWidth (182)
+ frame.IconFrame:SetHeight (160)
+ frame.IconFrame:EnableMouse (true)
+ frame.IconFrame:SetMovable (true)
+ frame.IconFrame:SetBackdrop (gump_fundo_backdrop)
+ frame.IconFrame:SetBackdropBorderColor (170/255, 170/255, 170/255)
+ frame.IconFrame:SetBackdropColor (24/255, 24/255, 24/255, .8)
+ frame.IconFrame:SetFrameLevel (1)
+
+ local MACRO_ICON_FILENAMES = {};
+ frame.IconFrame:SetScript ("OnShow", function()
+
+ MACRO_ICON_FILENAMES = {};
+ MACRO_ICON_FILENAMES[1] = "INV_MISC_QUESTIONMARK";
+ local index = 2;
+ local numFlyouts = 0;
+
+ for i = 1, GetNumSpellTabs() do
+ local tab, tabTex, offset, numSpells, _ = GetSpellTabInfo(i);
+ offset = offset + 1;
+ local tabEnd = offset + numSpells;
+ for j = offset, tabEnd - 1 do
+ --to get spell info by slot, you have to pass in a pet argument
+ local spellType, ID = GetSpellBookItemInfo(j, "player");
+ if (spellType ~= "FUTURESPELL") then
+ local spellTexture = strupper(GetSpellBookItemTexture(j, "player"));
+ if ( not string.match( spellTexture, "INTERFACE\\BUTTONS\\") ) then
+ MACRO_ICON_FILENAMES[index] = gsub( spellTexture, "INTERFACE\\ICONS\\", "");
+ index = index + 1;
+ end
+ end
+ if (spellType == "FLYOUT") then
+ local _, _, numSlots, isKnown = GetFlyoutInfo(ID);
+ if (isKnown and numSlots > 0) then
+ for k = 1, numSlots do
+ local spellID, overrideSpellID, isKnown = GetFlyoutSlotInfo(ID, k)
+ if (isKnown) then
+ MACRO_ICON_FILENAMES[index] = gsub( strupper(GetSpellTexture(spellID)), "INTERFACE\\ICONS\\", "");
+ index = index + 1;
+ end
+ end
+ end
+ end
+ end
+ end
+
+ GetMacroIcons (MACRO_ICON_FILENAMES)
+ GetMacroItemIcons (MACRO_ICON_FILENAMES )
+
+ end)
+
+ frame.IconFrame:SetScript ("OnHide", function()
+ MACRO_ICON_FILENAMES = nil;
+ collectgarbage()
+ end)
+
+ frame.IconFrame.buttons = {}
+
+ local OnClickFunction = function (index)
+ local button = frame.IconFrame.buttons [index]
+ local texture = button:GetNormalTexture()
+ frame.IconTexture = "INTERFACE\\ICONS\\"..MACRO_ICON_FILENAMES [button.IconID]
+ frame.icon:SetTexture (frame.IconTexture)
+ frame.IconFrame:Hide()
+ end
+
+ for i = 0, 4 do
+ local newcheck = gump:NewDetailsButton (frame.IconFrame, frame.IconFrame, _, OnClickFunction, i+1, i+1, 30, 28, "", "", "", "", _, "DetailsIconCheckFrame"..(i+1))
+ newcheck:SetPoint ("topleft", frame.IconFrame, "topleft", 3+(i*30), -13)
+ newcheck:SetID (i+1)
+ frame.IconFrame.buttons [#frame.IconFrame.buttons+1] = newcheck
+ end
+ for i = 6, 10 do
+ local newcheck = gump:NewDetailsButton (frame.IconFrame, frame.IconFrame, _, OnClickFunction, i, i, 30, 28, "", "", "", "", _, "DetailsIconCheckFrame"..i)
+ newcheck:SetPoint ("topleft", "DetailsIconCheckFrame"..(i-5), "bottomleft", 0, -1)
+ newcheck:SetID (i)
+ frame.IconFrame.buttons [#frame.IconFrame.buttons+1] = newcheck
+ end
+ for i = 11, 15 do
+ local newcheck = gump:NewDetailsButton (frame.IconFrame, frame.IconFrame, _, OnClickFunction, i, i, 30, 28, "", "", "", "", _, "DetailsIconCheckFrame"..i)
+ newcheck:SetPoint ("topleft", "DetailsIconCheckFrame"..(i-5), "bottomleft", 0, -1)
+ newcheck:SetID (i)
+ frame.IconFrame.buttons [#frame.IconFrame.buttons+1] = newcheck
+ end
+ for i = 16, 20 do
+ local newcheck = gump:NewDetailsButton (frame.IconFrame, frame.IconFrame, _, OnClickFunction, i, i, 30, 28, "", "", "", "", _, "DetailsIconCheckFrame"..i)
+ newcheck:SetPoint ("topleft", "DetailsIconCheckFrame"..(i-5), "bottomleft", 0, -1)
+ newcheck:SetID (i)
+ frame.IconFrame.buttons [#frame.IconFrame.buttons+1] = newcheck
+ end
+ for i = 21, 25 do
+ local newcheck = gump:NewDetailsButton (frame.IconFrame, frame.IconFrame, _, OnClickFunction, i, i, 30, 28, "", "", "", "", _, "DetailsIconCheckFrame"..i)
+ newcheck:SetPoint ("topleft", "DetailsIconCheckFrame"..(i-5), "bottomleft", 0, -1)
+ newcheck:SetID (i)
+ frame.IconFrame.buttons [#frame.IconFrame.buttons+1] = newcheck
+ end
+
+ local scroll = CreateFrame ("ScrollFrame", "DetailsIconsFrame", frame.IconFrame, "ListScrollFrameTemplate")
+
+ local ChecksFrame_Update = function (self)
+ --self = self or MacroPopupFrame;
+ local numMacroIcons = #MACRO_ICON_FILENAMES;
+ local macroPopupIcon, macroPopupButton;
+ local macroPopupOffset = FauxScrollFrame_GetOffset (scroll);
+ local index;
+
+ -- Icon list
+ local texture;
+ for i = 1, 25 do
+ macroPopupIcon = _G["DetailsIconCheckFrame"..i];
+ macroPopupButton = _G["DetailsIconCheckFrame"..i];
+ index = (macroPopupOffset * 5) + i;
+ texture = MACRO_ICON_FILENAMES [index]
+ if ( index <= numMacroIcons and texture ) then
+ macroPopupButton:ChangeIcon ("INTERFACE\\ICONS\\"..texture, "INTERFACE\\ICONS\\"..texture, "INTERFACE\\ICONS\\"..texture, "INTERFACE\\ICONS\\"..texture)
+ macroPopupButton.IconID = index
+ macroPopupButton:Show();
+ else
+ macroPopupButton:Hide();
+ end
+
+ end
+
+ -- Scrollbar stuff
+ FauxScrollFrame_Update (scroll, ceil (numMacroIcons / 5) , 5, 20 );
+ end
+
+
+ scroll:SetPoint ("topleft", frame.IconFrame, "topleft", -18, -10)
+ scroll:SetWidth (170)
+ scroll:SetHeight (148)
+ scroll:SetScript ("OnVerticalScroll", function (self, offset) FauxScrollFrame_OnVerticalScroll (scroll, offset, 20, ChecksFrame_Update) end)
+ scroll.update = ChecksFrame_Update
+ frame.IconFrameScroll = scroll
+ frame.IconFrame:Hide()
+ end
+
+ frame.IconFrame:Show()
+ frame.IconFrameScroll.update (frame.IconFrameScroll)
+
+ end
+
+ local Icon
+
+ local reset = function()
+ frame ["TextMyNameEntry"]:SetText ("")
+ frame ["TextSpellIDEntry"]:SetText ("")
+ frame ["TextActorNameEntry"]:SetText ("")
+ frame ["TextSourceEntry"]:SetText ("")
+ Icon:SetTexture ("Interface\\Icons\\TEMP")
+ frame.atributo = 1
+ frame.sub_atributo = 1
+ fundoBrilha:SetPoint ("left", frame.MainMenu [1].icon , "right", -20, -10)
+ end
+
+ --> Create Button
+ local CreateFunction = function()
+
+ local Atributo = frame.atributo --> healing
+ local SubAtributo = frame.sub_atributo --> healing done
+
+ if (not Atributo or not SubAtributo) then
+ print (Loc ["STRING_CUSTOM_NOATTRIBUTO"])
+ return
+ end
+
+ if (frame ["TextMyNameEntry"]:HasFocus()) then
+ frame ["TextMyNameEntry"]:PressEnter()
+ elseif (frame ["TextSpellIDEntry"]:HasFocus())then
+ frame ["TextSpellIDEntry"]:PressEnter()
+ elseif (frame ["TextActorNameEntry"]:HasFocus())then
+ frame ["TextActorNameEntry"]:PressEnter()
+ elseif (frame ["TextSourceEntry"]:HasFocus())then
+ frame ["TextSourceEntry"]:PressEnter()
+ end
+
+ local CustomName = frame ["TextMyNameEntry"].text
+ local SpellID = frame ["TextSpellIDEntry"].text
+ local Actor = frame ["TextActorNameEntry"].text
+ local Source = frame ["TextSourceEntry"].text
+
+ if (not CustomName or string.len (CustomName) < 5) then
+ print (Loc ["STRING_CUSTOM_SHORTNAME"])
+ --print ("Nome da customizacao precisa ter pelo menos 5 letras")
+ frame ["TextMyNameEntry"]:Blink()
+ return
+ elseif (string.len (CustomName) > 32) then
+ --print ("Nome da customizacao nao pode ter mais de 32 letras")
+ print (Loc ["STRING_CUSTOM_LONGNAME"])
+ frame ["TextMyNameEntry"]:Blink()
+ return
+ end
+
+ if (string.len (SpellID) < 1) then
+ --print ("Sem id da magia")
+ print (Loc ["STRING_CUSTOM_NOSPELL"])
+ frame ["TextSpellIDEntry"]:Blink()
+ return
+ end
+
+ _detalhes.custom [#_detalhes.custom+1] = {name = CustomName, spell = SpellID, target = Actor, source = Source, inout = InOut, icon = frame.IconTexture, attribute = Atributo, sattribute = SubAtributo}
+ print (Loc ["STRING_CUSTOM_CREATED"])
+ _detalhes:CloseCustomWindow()
+ reset()
+ end
+
+ local IconButton = gump:NewDetailsButton (frame, frame, _, ChooseIcon, nil, nil, 80, 15, "", "", "", "")
+ IconButton.text:SetText (Loc ["STRING_CUSTOM_ICON"])
+ IconButton.text:SetPoint ("left", IconButton, "left", 3, 0)
+ IconButton:SetPoint ("topleft", frame, "topleft", xStart+21, -118)
+ IconButton:SetFrameLevel (frame:GetFrameLevel()+2)
+ IconButton:InstallCustomTexture (_, {x1 = -20, x2 = 0, y1 = 0, y2 = 0})
+ frame.iconbutton = IconButton
+
+ Icon = IconButton:CreateTexture (nil, "overlay")
+ Icon:SetTexture (frame.IconTexture)
+ Icon:SetPoint ("right", IconButton, "left", 0, 0)
+ Icon:SetWidth (22)
+ Icon:SetHeight (22)
+ frame.icon = Icon
+
+ local CreateButton = gump:NewDetailsButton (frame, frame, _, CreateFunction, nil, nil, 80, 15, "", "", "", "")
+ CreateButton.text:SetText (Loc ["STRING_CUSTOM_CREATE"])
+ CreateButton:SetPoint ("topleft", frame, "topleft", 413, -118)
+ CreateButton:SetFrameLevel (frame:GetFrameLevel()+2)
+ CreateButton:InstallCustomTexture (_, {x1 = -20, x2 = 0, y1 = 0, y2 = 0})
+
+ local CreateIcon = CreateButton:CreateTexture (nil, "overlay")
+ CreateIcon:SetTexture ("Interface\\Icons\\Ability_Paladin_HammeroftheRighteous")
+ CreateIcon:SetWidth (22)
+ CreateIcon:SetHeight (22)
+ CreateIcon:SetPoint ("right", CreateButton, "left")
+
+--------> Install CoolTip on Remove Button
+ local DeleteFunc = function (_, _, CustomIndex)
+ table.remove (_detalhes.custom, CustomIndex)
+ for _, instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (instancia.atributo == 5 and instancia.sub_atributo == CustomIndex) then
+ if (instancia.iniciada) then
+ instancia:TrocaTabela (nil, 1, 1, true)
+ else
+ instancia.atributo = 1
+ instancia.sub_atributo = 1
+ end
+ elseif (instancia.atributo == 5 and instancia.sub_atributo > CustomIndex) then
+ instancia.sub_atributo = instancia.sub_atributo - 1
+ instancia.m2_last [5] = 1
+ else
+ instancia.m2_last [5] = 1
+ end
+ end
+ if (#_detalhes.custom > 0) then
+ _detalhes.popup:ExecFunc (DeleteButton)
+ else
+ GameCooltip:Close()
+ end
+ _detalhes.switch:OnRemoveCustom (CustomIndex)
+ end
+
+ local CreateCustomList = function()
+ for index, custom in _ipairs (_detalhes.custom) do
+ GameCooltip:AddMenu (1, DeleteFunc, index, nil, nil, custom.name, _, true)
+ GameCooltip:AddIcon (custom.icon, 1, 1, 20, 20, 0, 1, 0, 1)
+ end
+ end
+
+ DeleteButton.CoolTip = {
+ Type = "menu",
+ BuildFunc = CreateCustomList,
+ Options = {NoLastSelectedBar = true, TextSize = 9.5, HeightAnchorMod = -10}}
+ _detalhes.popup:CoolTipInject (DeleteButton, true)
+
+ -------------------------
+
+ -------------------------> Install CoolTip on Shout Button
+
+ --> testing
+ local ShoutFunc = function (_, _, CustomIndex)
+ AceComm:SendCommMessage ("DETAILS", AceSerializer:Serialize ( _detalhes.custom [CustomIndex] ), "RAID")
+ print (Loc ["STRING_CUSTOM_BROADCASTSENT"])
+ GameCooltip:Close()
+ --AceComm:SendCommMessage ("DETAILS", AceSerializer:Serialize ( _detalhes.custom [CustomIndex] ), "WHISPER", UnitName ("player"))
+ end
+
+ local CreateCustomListForShout = function()
+ for index, custom in _ipairs (_detalhes.custom) do
+ GameCooltip:AddMenu (1, ShoutFunc, index, nil, nil, custom.name, _, true)
+ GameCooltip:AddIcon (custom.icon, 1, 1, 20, 20, 0, 1, 0, 1)
+ end
+ end
+
+ BroadcastButton.CoolTip = {
+ Type = "menu",
+ BuildFunc = CreateCustomListForShout,
+ Options = {NoLastSelectedBar = true, TextSize = 9.5, HeightAnchorMod = -10}}
+
+ GameCooltip:CoolTipInject (BroadcastButton, true)
+
+ function _detalhes:CommReceive (prefix, Msgs, distribution, target)
+ --print (prefix, Msgs, distribution, target)
+ end
+ _detalhes:RegisterComm ("DETAILS", "CommReceive")
+
+ -------------------------
+
+ _detalhes.CustomFrame = frame
+
+ tinsert (UISpecialFrames, "DetailsCustomPanel")
+ _detalhes.CustomFrame.oponed = false
+ frame:Hide()
+end
+
+function _detalhes:InitCustom()
+ CreateCustomWindow()
+ return true
+end
+
+function _detalhes:OpenCustomWindow()
+ if (InCombatLockdown()) then
+ print ("|cffFF2222"..Loc ["STRING_CUSTOM_INCOMBAT"])
+ return
+ end
+
+ if (not _detalhes.CustomFrame.oponed) then
+ _detalhes.CustomFrame.oponed = true
+ _detalhes:BuildSpellList()
+ _detalhes.CustomFrame:Show()
+ end
+end
+
+function _detalhes:CloseCustomWindow()
+ _detalhes.CustomFrame.oponed = false
+ _detalhes:ClearSpellList()
+ _detalhes.CustomFrame:Hide()
+end
+
diff --git a/gumps/janela_info.lua b/gumps/janela_info.lua
new file mode 100644
index 00000000..d060f4cb
--- /dev/null
+++ b/gumps/janela_info.lua
@@ -0,0 +1,1369 @@
+local _detalhes = _G._detalhes
+local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+--lua locals
+--local _string_len = string.len
+local _math_floor = math.floor
+local _ipairs = ipairs
+--local _pairs = pairs
+local _type = type
+--api locals
+local _CreateFrame = CreateFrame
+local _GetTime = GetTime
+local _GetSpellInfo = _detalhes.getspellinfo
+local _GetCursorPosition = GetCursorPosition
+local _unpack = unpack
+
+local atributos = _detalhes.atributos
+local sub_atributos = _detalhes.sub_atributos
+
+local info = _detalhes.janela_info
+local classe_icones = _G.CLASS_ICON_TCOORDS
+
+------------------------------------------------------------------------------------------------------------------------------
+--self = instancia
+--jogador = classe_damage ou classe_heal
+
+function _detalhes:AbreJanelaInfo (jogador)
+
+ if (not _detalhes.row_singleclick_overwrite [self.atributo] or not _detalhes.row_singleclick_overwrite [self.atributo][self.sub_atributo]) then
+ return
+ elseif (_type (_detalhes.row_singleclick_overwrite [self.atributo][self.sub_atributo]) == "function") then
+ return _detalhes.row_singleclick_overwrite [self.atributo][self.sub_atributo] (_, jogador, self)
+ end
+
+ if (self.modo == _detalhes._detalhes_props["MODO_RAID"]) then
+ return
+ end
+
+ --> _detalhes.info_jogador armazena o jogador que esta sendo mostrado na janela de detalhes
+ if (info.jogador and info.jogador == jogador) then
+ _detalhes:FechaJanelaInfo() --> se clicou na mesma barra então fecha a janela de detalhes
+ return
+ end
+
+ --> vamos passar os parâmetros para dentro da tabela da janela...
+
+ info.ativo = true --> sinaliza o addon que a janela esta aberta
+ info.atributo = self.atributo --> instancia.atributo -> grava o atributo (damage, heal, etc)
+ info.sub_atributo = self.sub_atributo --> instancia.sub_atributo -> grava o sub atributo (damage done, dps, damage taken, etc)
+
+ info.jogador = jogador --> de qual jogador (objeto classe_damage)
+ info.instancia = self --> salva a referência da instância que pediu o info
+ info.mostrando = nil
+
+ local nome = jogador.nome --> nome do jogador
+ local atributo_nome = sub_atributos[info.atributo].lista [info.sub_atributo] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] --> // nome do atributo // precisa ser o sub atributo correto???
+
+ info.nome:SetText (nome)
+
+ info.atributo_nome:SetText (atributo_nome)
+ info.atributo_nome:SetPoint ("CENTER", info.nome, "CENTER", 0, 14)
+
+ gump:TrocaBackgroundInfo (info)
+
+ gump:HidaAllBarrasInfo()
+ gump:HidaAllBarrasAlvo()
+ gump:HidaAllDetalheInfo()
+
+ gump:JI_AtualizaContainerBarras (-1)
+
+ local classe = jogador.classe
+
+ if (not classe) then
+ classe = "monster"
+ end
+
+ --info.classe_icone:SetTexture ("Interface\\AddOns\\Details\\images\\"..classe:lower()) --> top left
+ info.classe_icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes") --> top left
+
+ if (classe ~= "UNKNOW" and classe ~= "UNGROUPPLAYER") then
+
+
+ info.classe_icone:SetTexCoord (_detalhes.class_coords [classe][1], _detalhes.class_coords [classe][2], _detalhes.class_coords [classe][3], _detalhes.class_coords [classe][4])
+ if (jogador.enemy) then
+ --> completa com a borda
+ --info.classe_iconePlus:SetTexture ("Interface\\AddOns\\Details\\images\\classes_plus")
+ if (_detalhes.faction_against == "Horde") then
+ --info.classe_iconePlus:SetTexCoord (0.25, 0.5, 0, 0.25)
+ info.nome:SetTextColor (1, 91/255, 91/255, 1)
+ else
+ --info.classe_iconePlus:SetTexCoord (0, 0.25, 0, 0.25)
+ info.nome:SetTextColor (151/255, 215/255, 1, 1)
+ end
+ else
+ info.classe_iconePlus:SetTexture()
+ info.nome:SetTextColor (1, 1, 1, 1)
+ end
+ else
+ if (jogador.enemy) then
+ if (_detalhes.class_coords [_detalhes.faction_against]) then
+ info.classe_icone:SetTexCoord (_unpack (_detalhes.class_coords [_detalhes.faction_against]))
+ if (_detalhes.faction_against == "Horde") then
+ info.nome:SetTextColor (1, 91/255, 91/255, 1)
+ else
+ info.nome:SetTextColor (151/255, 215/255, 1, 1)
+ end
+ else
+ info.nome:SetTextColor (1, 1, 1, 1)
+ end
+ else
+ --info.classe_icone:SetTexture ("Interface\\AddOns\\Details\\images\\monster")
+ --info.classe_icone:SetTexCoord (0, 1, 0, 1)
+ info.classe_icone:SetTexCoord (_detalhes.class_coords ["MONSTER"][1], _detalhes.class_coords ["MONSTER"][2], _detalhes.class_coords ["MONSTER"][3], _detalhes.class_coords ["MONSTER"][4])
+ end
+
+ info.classe_iconePlus:SetTexture()
+ end
+
+ gump:Fade (info, 0)
+
+ return jogador:MontaInfo()
+end
+
+-- for beta todo: info background need a major rewrite
+function gump:TrocaBackgroundInfo()
+ if (info.atributo == 1) then --> DANO
+ if (info.sub_atributo == 1 or info.sub_atributo == 2) then --> damage done / dps
+ if (info.tipo ~= 1) then --> janela com as divisorias
+ info.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part1") --> top left
+ info.bg3:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part3") --> bottom left
+ info.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part2") --> top right
+ info.bg4:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part4") --> bottom right
+ info.targets:SetText ("Alvos:")
+ info.tipo = 1
+ end
+ elseif (info.sub_atributo == 3) then --> damage taken
+ if (info.tipo ~= 2) then --> janela com fundo diferente
+ info.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part1_sr") --> top left
+ info.bg3:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part3_sr") --> bottom left
+ info.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part2_sr") --> top right
+ info.bg4:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part4_sr") --> bottom right
+ info.targets:SetText ("Alvos:")
+ info.tipo = 2
+ end
+ elseif (info.sub_atributo == 4) then --> friendly fire
+ if (info.tipo ~= 3) then --> janela com fundo diferente
+ info.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part1_sr") --> top left
+ info.bg3:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part3_sr") --> bottom left
+ info.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part2_sr") --> top right
+ info.bg4:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part4_sr") --> bottom right
+ info.targets:SetText ("Habilidades:")
+ info.tipo = 3
+ end
+ end
+ elseif (info.atributo == 2) then --> HEALING
+ if (info.sub_atributo == 1 or info.sub_atributo == 2 or info.sub_atributo == 3) then --> damage done / dps
+ if (info.tipo ~= 1) then --> janela com as divisorias
+ info.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part1") --> top left
+ info.bg3:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part3") --> bottom left
+ info.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part2") --> top right
+ info.bg4:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part4") --> bottom right
+ info.targets:SetText ("Alvos:")
+ info.tipo = 1
+ end
+ elseif (info.sub_atributo == 4) then --> Healing taken
+ if (info.tipo ~= 2) then --> janela com fundo diferente
+ info.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part1_sr") --> top left
+ info.bg3:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part3_sr") --> bottom left
+ info.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part2_sr") --> top right
+ info.bg4:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part4_sr") --> bottom right
+ info.targets:SetText ("Alvos:")
+ info.tipo = 2
+ end
+ end
+ elseif (info.atributo == 3) then --> REGEN
+ if (info.tipo ~= 2) then --> janela com fundo diferente
+ info.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part1_sr") --> top left
+ info.bg3:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part3_sr") --> bottom left
+ info.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part2_sr") --> top right
+ info.bg4:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part4_sr") --> bottom right
+ info.targets:SetText ("Vindo de:")
+ info.tipo = 2
+ end
+
+ elseif (info.atributo == 4) then --> MISC
+ if (info.tipo ~= 2) then --> janela com fundo diferente
+ info.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part1_sr") --> top left
+ info.bg3:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part3_sr") --> bottom left
+ info.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part2_sr") --> top right
+ info.bg4:SetTexture ("Interface\\AddOns\\Details\\images\\bg_part4_sr") --> bottom right
+ info.targets:SetText ("Alvos:")
+ info.tipo = 2
+ end
+ end
+end
+
+--> self é qualquer coisa que chamar esta função
+------------------------------------------------------------------------------------------------------------------------------
+-- é chamado pelo click no X e pelo reset do historico
+function _detalhes:FechaJanelaInfo (fromEscape)
+ if (info.ativo) then --> se a janela tiver aberta
+ --janela_info:Hide()
+ if (fromEscape) then
+ gump:Fade (info, "in")
+ else
+ gump:Fade (info, 1)
+ end
+ info.ativo = false --> sinaliza o addon que a janela esta agora fechada
+
+ --_detalhes.info_jogador.detalhes = nil
+ info.jogador = nil
+ info.atributo = nil
+ info.sub_atributo = nil
+ info.instancia = nil
+
+ info.nome:SetText ("")
+ info.atributo_nome:SetText ("")
+
+ gump:JI_AtualizaContainerBarras (-1) --> reseta o frame das barras
+ end
+end
+
+--> esconde todas as barras das skills na janela de info
+------------------------------------------------------------------------------------------------------------------------------
+function gump:HidaAllBarrasInfo()
+ local barras = _detalhes.janela_info.barras1
+ for index = 1, #barras, 1 do
+ barras [index]:Hide()
+ barras [index].textura:SetStatusBarColor (1, 1, 1, 1)
+ barras [index].on_focus = false
+ end
+end
+
+--> esconde todas as barras dos alvos do jogador
+------------------------------------------------------------------------------------------------------------------------------
+function gump:HidaAllBarrasAlvo()
+ local barras = _detalhes.janela_info.barras2
+ for index = 1, #barras, 1 do
+ barras [index]:Hide()
+ end
+end
+
+--> esconde as 5 barras a direita na janela de info
+------------------------------------------------------------------------------------------------------------------------------
+function gump:HidaAllDetalheInfo()
+ for i = 1, 5 do
+ gump:HidaDetalheInfo (i)
+ end
+ for _, barra in _ipairs (info.barras3) do
+ barra:Hide()
+ end
+ _detalhes.janela_info.spell_icone:SetTexture ("")
+end
+
+
+--> seta os scripts da janela de informações
+------------------------------------------------------------------------------------------------------------------------------
+local function seta_scripts (este_gump)
+
+ --> Janela
+ este_gump:SetScript ("OnMouseDown",
+ function (self, botao)
+ if (botao == "LeftButton") then
+ self:StartMoving()
+ self.isMoving = true
+ end
+ end)
+
+ este_gump:SetScript ("OnMouseUp",
+ function (self)
+ if (self.isMoving) then
+ self:StopMovingOrSizing()
+ self.isMoving = false
+ end
+ end)
+
+ este_gump.container_barras.gump:SetScript ("OnMouseDown",
+ function (self, botao)
+ if (botao == "LeftButton") then
+ este_gump:StartMoving()
+ este_gump.isMoving = true
+ end
+ end)
+
+ este_gump.container_barras.gump:SetScript ("OnMouseUp",
+ function (self)
+ if (este_gump.isMoving) then
+ este_gump:StopMovingOrSizing()
+ este_gump.isMoving = false
+ end
+ end)
+
+ este_gump.container_detalhes:SetScript ("OnMouseDown",
+ function (self, botao)
+ if (botao == "LeftButton") then
+ este_gump:StartMoving()
+ este_gump.isMoving = true
+ end
+ end)
+
+ este_gump.container_detalhes:SetScript ("OnMouseUp",
+ function (self)
+ if (este_gump.isMoving) then
+ este_gump:StopMovingOrSizing()
+ este_gump.isMoving = false
+ end
+ end)
+
+ este_gump.container_alvos.gump:SetScript ("OnMouseDown",
+ function (self, botao)
+ if (botao == "LeftButton") then
+ este_gump:StartMoving()
+ este_gump.isMoving = true
+ end
+ end)
+
+ este_gump.container_alvos.gump:SetScript ("OnMouseUp",
+ function (self)
+ if (este_gump.isMoving) then
+ este_gump:StopMovingOrSizing()
+ este_gump.isMoving = false
+ end
+ end)
+
+ --> botão fechar
+ este_gump.fechar:SetScript ("OnClick", function(self)
+ _detalhes:FechaJanelaInfo()
+ end)
+end
+
+
+
+------------------------------------------------------------------------------------------------------------------------------
+function gump:HidaDetalheInfo (index)
+ local info = _detalhes.janela_info.grupos_detalhes [index]
+ info.nome:SetText ("")
+ info.nome2:SetText ("")
+ info.dano:SetText ("")
+ info.dano_porcento:SetText ("")
+ info.dano_media:SetText ("")
+ info.dano_dps:SetText ("")
+ info.bg:Hide()
+end
+
+--> cria a barra de detalhes a direita da janela de informações
+------------------------------------------------------------------------------------------------------------------------------
+function gump:CriaDetalheInfo (index)
+ local info = {}
+ info.nome = _detalhes.janela_info.container_detalhes:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ info.nome2 = _detalhes.janela_info.container_detalhes:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ info.dano = _detalhes.janela_info.container_detalhes:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ info.dano_porcento = _detalhes.janela_info.container_detalhes:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ info.dano_media = _detalhes.janela_info.container_detalhes:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ info.dano_dps = _detalhes.janela_info.container_detalhes:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+
+ info.bg = _CreateFrame ("StatusBar", nil, _detalhes.janela_info.container_detalhes)
+ info.bg:SetStatusBarTexture ("Interface\\AddOns\\Details\\images\\bar_detalhes2")
+ info.bg:SetMinMaxValues (0, 100)
+ info.bg:SetValue (100)
+
+ info.bg:SetWidth (219)
+ info.bg:SetHeight (47)
+
+ info.bg.overlay = info.bg:CreateTexture (nil, "ARTWORK")
+ info.bg.overlay:SetTexture ("Interface\\AddOns\\Details\\images\\overlay_detalhes")
+ info.bg.overlay:SetWidth (241)
+ info.bg.overlay:SetHeight (61)
+ info.bg.overlay:SetPoint ("TOPLEFT", info.bg, "TOPLEFT", -7, 6)
+ gump:Fade (info.bg.overlay, 1)
+
+ info.bg.reportar = gump:NewDetailsButton (info.bg, nil, nil, _detalhes.Reportar, _detalhes.janela_info, 10+index, 16, 16,
+ --_detalhes.icones.report.up, _detalhes.icones.report.down, _detalhes.icones.report.disabled)
+ "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON")
+ info.bg.reportar:SetPoint ("BOTTOMLEFT", info.bg.overlay, "BOTTOMRIGHT", -33, 10)
+ gump:Fade (info.bg.reportar, 1)
+
+ info.bg:SetScript ("OnEnter",
+ function(self)
+ gump:Fade (self.overlay, "OUT")
+ gump:Fade (self.reportar, "OUT")
+ end)
+ info.bg:SetScript ("OnLeave",
+ function(self)
+ gump:Fade (self.overlay, "IN")
+ gump:Fade (self.reportar, "IN")
+ end)
+
+ info.bg.reportar:SetScript ("OnEnter",
+ function(self)
+ gump:Fade (info.bg.overlay, "OUT")
+ gump:Fade (self, "OUT")
+ end)
+ info.bg.reportar:SetScript ("OnLeave",
+ function(self)
+ gump:Fade (info.bg.overlay, "IN")
+ gump:Fade (self, "IN")
+ end)
+
+ info.bg_end = info.bg:CreateTexture (nil, "BACKGROUND")
+ info.bg_end:SetHeight (47)
+ --este_gump.bg4:SetPoint ("BOTTOMRIGHT", este_gump, "BOTTOMRIGHT", 0, 0)
+ --este_gump.bg4:SetWidth (128)
+ --este_gump.bg4:SetHeight (256)
+ info.bg_end:SetTexture ("Interface\\AddOns\\Details\\images\\bar_detalhes2_end")
+ --info.bg = _detalhes.janela_info.container_detalhes:CreateTexture (nil, "BACKGROUND")
+ --info.bg:SetWidth (400)
+ --info.bg:SetHeight (70)
+ --info.bg:SetTexture ("Interface\\MONEYFRAME\\UI-MoneyFrame2")
+
+ _detalhes.janela_info.grupos_detalhes [index] = info
+end
+
+--> determina qual a pocisão que a barra de detalhes vai ocupar
+------------------------------------------------------------------------------------------------------------------------------
+function gump:SetaDetalheInfoAltura (index)
+ local info = _detalhes.janela_info.grupos_detalhes [index]
+ local janela = _detalhes.janela_info.container_detalhes
+ local altura = {-10, -63, -118, -173, -228}
+ local x1 = 64
+ local x2 = 160
+
+ altura = altura [index]
+
+ info.bg:SetPoint ("TOPLEFT", janela, "TOPLEFT", x1-2, altura+2)
+ info.bg_end:SetPoint ("LEFT", info.bg, "LEFT", info.bg:GetValue()*2.19, 0)
+ info.bg:Hide()
+
+ info.nome:SetPoint ("TOPLEFT", janela, "TOPLEFT", x1, altura)
+ info.nome2:SetPoint ("TOPLEFT", janela, "TOPLEFT", x2, altura)
+ info.dano:SetPoint ("TOPLEFT", janela, "TOPLEFT", x1, altura + (-20))
+ info.dano_porcento:SetPoint ("TOPLEFT", janela, "TOPLEFT", x2, altura + (-20))
+ info.dano_media:SetPoint ("TOPLEFT", janela, "TOPLEFT", x1, altura + (-30))
+ info.dano_dps:SetPoint ("TOPLEFT", janela, "TOPLEFT", x2, altura + (-30))
+end
+
+--> seta o conteúdo da barra de detalhes
+------------------------------------------------------------------------------------------------------------------------------
+function gump:SetaDetalheInfoTexto (index, p, arg1, arg2, arg3, arg4, arg5, arg6)
+ local info = _detalhes.janela_info.grupos_detalhes [index]
+
+ if (p) then
+ if (_type (p) == "table") then
+ info.bg:SetValue (p.p)
+ info.bg:SetStatusBarColor (p.c[1], p.c[2], p.c[3])
+ else
+ info.bg:SetValue (p)
+ info.bg:SetStatusBarColor (1, 1, 1)
+ end
+
+ info.bg_end:SetPoint ("LEFT", info.bg, "LEFT", (info.bg:GetValue()*2.19)-6, 0)
+ info.bg:Show()
+ end
+
+ if (info.IsPet) then
+ info.bg.PetIcon:Hide()
+ info.bg.PetText:Hide()
+ info.bg.PetDps:Hide()
+ gump:Fade (info.bg.overlay, "IN")
+ info.IsPet = false
+ end
+
+ if (arg1) then
+ info.nome:SetText (arg1)
+ end
+
+ if (arg2) then
+ info.dano:SetText (arg2)
+ end
+
+ if (arg3) then
+ info.dano_porcento:SetText (arg3)
+ end
+
+ if (arg4) then
+ info.dano_media:SetText (arg4)
+ end
+
+ if (arg5) then
+ info.dano_dps:SetText (arg5)
+ end
+
+ if (arg6) then
+ info.nome2:SetText (arg6)
+ end
+
+ info.nome:Show()
+ info.dano:Show()
+ info.dano_porcento:Show()
+ info.dano_media:Show()
+ info.dano_dps:Show()
+ info.nome2:Show()
+
+end
+
+--> cria as 5 caixas de detalhes infos que serão usados
+------------------------------------------------------------------------------------------------------------------------------
+local function cria_barras_detalhes()
+ _detalhes.janela_info.grupos_detalhes = {}
+
+ gump:CriaDetalheInfo (1)
+ gump:SetaDetalheInfoAltura (1)
+ gump:CriaDetalheInfo (2)
+ gump:SetaDetalheInfoAltura (2)
+ gump:CriaDetalheInfo (3)
+ gump:SetaDetalheInfoAltura (3)
+ gump:CriaDetalheInfo (4)
+ gump:SetaDetalheInfoAltura (4)
+ gump:CriaDetalheInfo (5)
+ gump:SetaDetalheInfoAltura (5)
+end
+
+--> cria os textos em geral da janela info
+------------------------------------------------------------------------------------------------------------------------------
+local function cria_textos (este_gump)
+ este_gump.nome = este_gump:CreateFontString (nil, "OVERLAY", "QuestFont_Large")
+ este_gump.nome:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 105, -54)
+
+ este_gump.atributo_nome = este_gump:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+
+ este_gump.targets = este_gump:CreateFontString (nil, "OVERLAY", "QuestFont_Large")
+ este_gump.targets:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 24, -235)
+ este_gump.targets:SetText ("Alvos:")
+end
+
+
+--> esquerdo superior
+local function cria_container_barras (este_gump)
+
+ local container_barras_window = _CreateFrame ("ScrollFrame", "Details_Info_ContainerBarrasScroll", este_gump)
+ local container_barras = _CreateFrame ("Frame", "Details_Info_ContainerBarras", container_barras_window)
+
+ container_barras_window:SetBackdrop({
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-gold-Border", tile = true, tileSize = 16, edgeSize = 5,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ container_barras_window:SetBackdropBorderColor (0, 0, 0, 0)
+
+ container_barras:SetBackdrop({
+ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ container_barras:SetBackdropColor (0, 0, 0, 0)
+
+ container_barras:SetAllPoints (container_barras_window)
+ container_barras:SetWidth (300)
+ container_barras:SetHeight (150)
+ container_barras:EnableMouse (true)
+ container_barras:SetResizable (false)
+ container_barras:SetMovable (true)
+
+ container_barras_window:SetWidth (300)
+ container_barras_window:SetHeight (145)
+ container_barras_window:SetScrollChild (container_barras)
+ container_barras_window:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 21, -76)
+
+ gump:NewScrollBar (container_barras_window, container_barras, 6, -17)
+ container_barras_window.slider:Altura (117)
+ container_barras_window.slider:cimaPoint (0, 1)
+ container_barras_window.slider:baixoPoint (0, -3)
+
+ container_barras_window.ultimo = 0
+
+ container_barras_window.gump = container_barras
+ --container_barras_window.slider = slider_gump
+ este_gump.container_barras = container_barras_window
+
+end
+
+function gump:JI_AtualizaContainerBarras (amt)
+
+ local container = _detalhes.janela_info.container_barras
+
+ if (amt >= 9 and container.ultimo ~= amt) then
+ local tamanho = 17*amt
+ container.gump:SetHeight (tamanho)
+ container.slider:Update()
+ container.ultimo = amt
+ elseif (amt < 8 and container.slider.ativo) then
+ container.slider:Update (true)
+ container.gump:SetHeight (140)
+ container.scroll_ativo = false
+ container.ultimo = 0
+ end
+end
+
+
+function gump:JI_AtualizaContainerAlvos (amt)
+
+ local container = _detalhes.janela_info.container_alvos
+
+ if (amt >= 6 and container.ultimo ~= amt) then
+ local tamanho = 17*amt
+ container.gump:SetHeight (tamanho)
+ container.slider:Update()
+ container.ultimo = amt
+ elseif (amt <= 5 and container.slider.ativo) then
+ container.slider:Update (true)
+ container.gump:SetHeight (100)
+ container.scroll_ativo = false
+ container.ultimo = 0
+ end
+end
+
+--> container direita
+local function cria_container_detalhes (este_gump)
+ local container_detalhes = _CreateFrame ("Frame", "Details_Info_ContainerDetalhes", este_gump)
+
+ container_detalhes:SetPoint ("TOPRIGHT", este_gump, "TOPRIGHT", -74, -76)
+ container_detalhes:SetWidth (220)
+ container_detalhes:SetHeight (270)
+ container_detalhes:EnableMouse (true)
+ container_detalhes:SetResizable (false)
+ container_detalhes:SetMovable (true)
+
+ este_gump.container_detalhes = container_detalhes
+end
+
+--> esquerdo inferior
+local function cria_container_alvos (este_gump)
+ local container_alvos_window = _CreateFrame ("ScrollFrame", "Details_Info_ContainerAlvosScroll", este_gump)
+ local container_alvos = _CreateFrame ("Frame", "Details_Info_ContainerAlvos", container_alvos_window)
+
+ container_alvos_window:SetBackdrop({
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-gold-Border", tile = true, tileSize = 16, edgeSize = 5,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ container_alvos_window:SetBackdropBorderColor (0,0,0,0)
+
+ container_alvos:SetBackdrop({
+ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ container_alvos:SetBackdropColor (50/255, 50/255, 50/255, 0.6)
+
+ container_alvos:SetAllPoints (container_alvos_window)
+ container_alvos:SetWidth (300)
+ container_alvos:SetHeight (100)
+ container_alvos:EnableMouse (true)
+ container_alvos:SetResizable (false)
+ container_alvos:SetMovable (true)
+
+ container_alvos_window:SetWidth (300)
+ container_alvos_window:SetHeight (100)
+ container_alvos_window:SetScrollChild (container_alvos)
+ container_alvos_window:SetPoint ("BOTTOMLEFT", este_gump, "BOTTOMLEFT", 20, 6) --56 default
+
+ gump:NewScrollBar (container_alvos_window, container_alvos, 7, 4)
+ container_alvos_window.slider:Altura (88)
+ container_alvos_window.slider:cimaPoint (0, 1)
+ container_alvos_window.slider:baixoPoint (0, -3)
+
+ container_alvos_window.gump = container_alvos
+ este_gump.container_alvos = container_alvos_window
+end
+
+function gump:CriaJanelaInfo()
+
+ --> cria a janela em si
+ local este_gump = info
+ este_gump:SetFrameStrata ("MEDIUM")
+
+ --> fehcar com o esc
+ tinsert (UISpecialFrames, este_gump:GetName())
+
+ --> fix para dar fadein ao apertar esc
+ este_gump:SetScript ("OnHide", function (self)
+ if (not este_gump.hidden) then --> significa que foi fechado com ESC
+ este_gump:Show()
+ _detalhes:FechaJanelaInfo(1)
+ end
+ end)
+
+ --> propriedades da janela
+ este_gump:SetPoint ("CENTER", UIParent)
+ --este_gump:SetWidth (640)
+ este_gump:SetWidth (590)
+ este_gump:SetHeight (354)
+ este_gump:EnableMouse (true)
+ este_gump:SetResizable (false)
+ este_gump:SetMovable (true)
+
+ --> joga a janela para a global
+ _detalhes.janela_info = este_gump
+
+ --> começa a montar as texturas <--
+
+ --> icone da classe no canto esquerdo superior
+ este_gump.classe_icone = este_gump:CreateTexture (nil, "BACKGROUND")
+ este_gump.classe_icone:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 4, 0)
+ este_gump.classe_icone:SetWidth (64)
+ este_gump.classe_icone:SetHeight (64)
+ este_gump.classe_icone:SetDrawLayer ("BACKGROUND", 1)
+ --> complemento do icone
+ este_gump.classe_iconePlus = este_gump:CreateTexture (nil, "BACKGROUND")
+ este_gump.classe_iconePlus:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 4, 0)
+ este_gump.classe_iconePlus:SetWidth (64)
+ este_gump.classe_iconePlus:SetHeight (64)
+ este_gump.classe_iconePlus:SetDrawLayer ("BACKGROUND", 2)
+
+ --> cria as 4 partes do fundo da janela
+
+ --> top left
+ este_gump.bg1 = este_gump:CreateTexture (nil, "BORDER")
+ este_gump.bg1:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 0, 0)
+ este_gump.bg1:SetWidth (512)
+ este_gump.bg1:SetHeight (256)
+ este_gump.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part1")
+
+ --> bottom left
+ este_gump.bg3 = este_gump:CreateTexture (nil, "BORDER")
+ --este_gump.bg3:SetPoint ("BOTTOMLEFT", este_gump, "BOTTOMLEFT", 0, 0)
+ este_gump.bg3:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 0, -256)
+ este_gump.bg3:SetWidth (512)
+ este_gump.bg3:SetHeight (128)
+ este_gump.bg3:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part3")
+
+ --> top right
+ este_gump.bg2 = este_gump:CreateTexture (nil, "BORDER")
+ este_gump.bg2:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 512, 0)
+ este_gump.bg2:SetWidth (128)
+ este_gump.bg2:SetHeight (128)
+ este_gump.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part2")
+
+ --> bottom right
+ este_gump.bg4 = este_gump:CreateTexture (nil, "BORDER")
+ --este_gump.bg4:SetPoint ("BOTTOMRIGHT", este_gump, "BOTTOMRIGHT", 0, 0)
+ --este_gump.bg4:SetPoint ("BOTTOMLEFT", este_gump, "BOTTOMLEFT", 512, 0)
+ este_gump.bg4:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 512, -128)
+ este_gump.bg4:SetWidth (128)
+ este_gump.bg4:SetHeight (256)
+ este_gump.bg4:SetTexture ("Interface\\AddOns\\Details\\images\\info_bg_part4")
+
+ --> botão de fechar
+ este_gump.fechar = _CreateFrame ("Button", nil, este_gump, "UIPanelCloseButton")
+ este_gump.fechar:SetWidth (32)
+ este_gump.fechar:SetHeight (32)
+ este_gump.fechar:SetPoint ("TOPRIGHT", este_gump, "TOPRIGHT", 5, -8)
+ este_gump.fechar:SetText ("X")
+ este_gump.fechar:SetFrameLevel (este_gump:GetFrameLevel()+2)
+
+ function este_gump:ToFront()
+ if (_detalhes.bosswindow) then
+ if (_detalhes.bosswindow:GetFrameLevel() > este_gump:GetFrameLevel()) then
+ este_gump:SetFrameLevel (este_gump:GetFrameLevel()+3)
+ _detalhes.bosswindow:SetFrameLevel (_detalhes.bosswindow:GetFrameLevel()-3)
+ end
+ end
+ end
+
+ este_gump.grab = gump:NewDetailsButton (este_gump, este_gump, _, este_gump.ToFront, nil, nil, 590, 73, "", "", "", "", {OnGrab = "PassClick"})
+ este_gump.grab:SetPoint ("topleft",este_gump, "topleft")
+ este_gump.grab:SetFrameLevel (este_gump:GetFrameLevel()+1)
+
+ --> titulo
+ gump:NewLabel (este_gump, este_gump, nil, "titulo", Loc ["STRING_PLAYER_DETAILS"], "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255})
+ este_gump.titulo:SetPoint ("center", este_gump, "center")
+ este_gump.titulo:SetPoint ("top", este_gump, "top", 0, -18)
+
+ --> cria os textos da janela
+ cria_textos (este_gump)
+
+ --> cria o frama que vai abrigar as barras das habilidades
+ cria_container_barras (este_gump)
+
+ --> cria o container que vai abrirgar as 5 barras de detalhes
+ cria_container_detalhes (este_gump)
+
+ --> cria o container onde vai abrigar os alvos do jogador
+ cria_container_alvos (este_gump)
+
+ --> cria as 5 barras de detalhes a direita da janela
+ cria_barras_detalhes()
+
+ --> seta os scripts dos frames da janela
+ seta_scripts (este_gump)
+
+ --> vai armazenar os objetos das barras de habilidade
+ este_gump.barras1 = {}
+
+ --> vai armazenar os objetos das barras de alvos
+ este_gump.barras2 = {}
+
+ --> vai armazenar os objetos das barras da caixa especial da direita
+ este_gump.barras3 = {}
+
+
+ --> botão de reportar da caixa da esquerda, onde fica as barras principais
+ este_gump.report_esquerda = gump:NewDetailsButton (este_gump, este_gump, nil, _detalhes.Reportar, este_gump, 1, 16, 16,
+ "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON")
+ este_gump.report_esquerda:SetPoint ("BOTTOMLEFT", este_gump.container_barras, "TOPLEFT", 281, 3)
+ este_gump.report_esquerda:SetFrameLevel (este_gump:GetFrameLevel()+2)
+
+ --> botão de reportar da caixa dos alvos
+ este_gump.report_alvos = gump:NewDetailsButton (este_gump, este_gump, nil, _detalhes.Reportar, este_gump, 3, 16, 16,
+ "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON")
+ este_gump.report_alvos:SetPoint ("BOTTOMRIGHT", este_gump.container_alvos, "TOPRIGHT", -2, -1)
+ este_gump.report_alvos:SetFrameLevel (3) --> solved inactive problem
+
+ --> ícone da magia selecionada para mais detalhes
+ este_gump.bg_icone_bg = este_gump:CreateTexture (nil, "ARTWORK")
+ este_gump.bg_icone_bg:SetPoint ("TOPRIGHT", este_gump, "TOPRIGHT", -15, -12)
+ este_gump.bg_icone_bg:SetTexture ("Interface\\AddOns\\Details\\images\\icone_bg_fundo")
+ este_gump.bg_icone_bg:SetDrawLayer ("ARTWORK", -1)
+ este_gump.bg_icone_bg:Show()
+
+ este_gump.bg_icone = este_gump:CreateTexture (nil, "OVERLAY")
+ este_gump.bg_icone:SetPoint ("TOPRIGHT", este_gump, "TOPRIGHT", -15, -12)
+ este_gump.bg_icone:SetTexture ("Interface\\AddOns\\Details\\images\\icone_bg")
+ este_gump.bg_icone:Show()
+
+ --este_gump:Hide()
+
+ este_gump.spell_icone = este_gump:CreateTexture (nil, "ARTWORK")
+ este_gump.spell_icone:SetPoint ("BOTTOMRIGHT", este_gump.bg_icone, "BOTTOMRIGHT", -19, 2)
+ este_gump.spell_icone:SetWidth (35)
+ este_gump.spell_icone:SetHeight (34)
+ este_gump.spell_icone:SetDrawLayer ("ARTWORK", 0)
+ este_gump.spell_icone:Show()
+
+ --> coisinhas do lado do icone
+ este_gump.apoio_icone_esquerdo = este_gump:CreateTexture (nil, "ARTWORK")
+ este_gump.apoio_icone_direito = este_gump:CreateTexture (nil, "ARTWORK")
+ este_gump.apoio_icone_esquerdo:SetTexture ("Interface\\PaperDollInfoFrame\\PaperDollSidebarTabs")
+ este_gump.apoio_icone_direito:SetTexture ("Interface\\PaperDollInfoFrame\\PaperDollSidebarTabs")
+
+ local apoio_altura = 13/256
+ este_gump.apoio_icone_esquerdo:SetTexCoord (0, 1, 0, apoio_altura)
+ este_gump.apoio_icone_direito:SetTexCoord (0, 1, apoio_altura+(1/256), apoio_altura+apoio_altura)
+
+ este_gump.apoio_icone_esquerdo:SetPoint ("bottomright", este_gump.bg_icone, "bottomleft", 42, 0)
+ este_gump.apoio_icone_direito:SetPoint ("bottomleft", este_gump.bg_icone, "bottomright", -17, 0)
+
+ este_gump.apoio_icone_esquerdo:SetWidth (64)
+ este_gump.apoio_icone_esquerdo:SetHeight (13)
+ este_gump.apoio_icone_direito:SetWidth (64)
+ este_gump.apoio_icone_direito:SetHeight (13)
+
+ --> botão de reportar da caixa da direita, onde estão os 5 quadrados
+ este_gump.report_direita = gump:NewDetailsButton (este_gump, este_gump, nil, _detalhes.Reportar, este_gump, 2, 16, 16,
+ "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON")
+ este_gump.report_direita:SetPoint ("TOPRIGHT", este_gump, "TOPRIGHT", -8, -57)
+ este_gump.report_direita:Hide()
+
+ este_gump.tipo = 1 --> tipo da janela // 1 = janela normal
+
+ return este_gump
+
+end
+
+function _detalhes.janela_info:monta_relatorio (botao)
+
+ local atributo = info.atributo
+ local sub_atributo = info.sub_atributo
+ local player = info.jogador
+ local instancia = info.instancia
+
+ local amt = _detalhes.report_lines
+
+ local report_lines
+
+ if (botao == 1) then --> botão da esquerda
+ report_lines = {"Details! " .. Loc ["STRING_ACTORFRAME_REPORTTO"] .. " " .. _detalhes.sub_atributos [atributo].lista [sub_atributo] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] .. " " .. player.nome}
+ for index, barra in _ipairs (info.barras1) do
+ if (barra:IsShown()) then
+ report_lines [#report_lines+1] = barra.texto_esquerdo:GetText().." -> ".. _detalhes:comma_value (barra.texto_direita:GetText())
+ end
+ if (index == amt) then
+ break
+ end
+ end
+
+ elseif (botao == 3) then --> botão dos alvos
+
+ if (atributo == 1 and sub_atributo == 3) then
+ print (Loc ["STRING_ACTORFRAME_NOTHING"])
+ return
+ end
+
+ report_lines = {"Details! " .. Loc ["STRING_ACTORFRAME_REPORTTARGETS"] .. " " .. _detalhes.sub_atributos [1].lista [1] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] .. " " .. player.nome}
+
+ for index, barra in _ipairs (info.barras2) do
+ if (barra:IsShown()) then
+ report_lines [#report_lines+1] = barra.texto_esquerdo:GetText().." -> ".. barra.texto_direita:GetText()
+ end
+ if (index == amt) then
+ break
+ end
+ end
+
+ elseif (botao == 2) then --> botão da direita
+
+ --> diferentes tipos de amostragem na caixa da direita
+ --dano --damage done --dps --heal
+ if ((atributo == 1 and (sub_atributo == 1 or sub_atributo == 2)) or (atributo == 2)) then
+ if (not player.detalhes) then
+ print (Loc ["STRING_ACTORFRAME_NOTHING"])
+ return
+ end
+ local nome = _GetSpellInfo (player.detalhes)
+ report_lines = {"Details! " .. Loc ["STRING_ACTORFRAME_REPORTTO"] .. " " .. _detalhes.sub_atributos [atributo].lista [sub_atributo] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] .. " " .. player.nome,
+ Loc ["STRING_ACTORFRAME_SPELLDETAILS"] .. ": " .. nome}
+
+ for i = 1, 5 do
+
+ --> pega os dados dos quadrados --> Aqui mostra o resumo de todos os quadrados...
+ local caixa = info.grupos_detalhes [i]
+ if (caixa.bg:IsShown()) then
+
+ local linha = ""
+
+ local nome2 = caixa.nome2:GetText() --> golpes
+ if (nome2 and nome2 ~= "") then
+ if (i == 1) then
+ linha = linha..nome2.." / "
+ else
+ linha = linha..caixa.nome:GetText().." "..nome2.." / "
+ end
+ end
+
+ local dano = caixa.dano:GetText() --> dano
+ if (dano and dano ~= "") then
+ linha = linha..dano.." / "
+ end
+
+ local media = caixa.dano_media:GetText() --> media
+ if (media and media ~= "") then
+ linha = linha..media.." / "
+ end
+
+ local dano_dps = caixa.dano_dps:GetText()
+ if (dano_dps and dano_dps ~= "") then
+ linha = linha..dano_dps.." / "
+ end
+
+ local dano_porcento = caixa.dano_porcento:GetText()
+ if (dano_porcento and dano_porcento ~= "") then
+ linha = linha..dano_porcento.." "
+ end
+
+ report_lines [#report_lines+1] = linha
+
+ end
+
+ if (i == amt) then
+ break
+ end
+
+ end
+
+ --dano --damage tanken (mostra as magias que o alvo usou)
+ elseif ( (atributo == 1 and sub_atributo == 3) or atributo == 3) then
+
+ report_lines = {"Details! " .. Loc ["STRING_ACTORFRAME_REPORTTO"] .. " " .. _detalhes.sub_atributos [1].lista [1] .. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] .. " " .. player.detalhes.. " " .. Loc ["STRING_ACTORFRAME_REPORTAT"] .. " " .. player.nome}
+
+ for index, barra in _ipairs (info.barras3) do
+
+ if (barra:IsShown()) then
+ report_lines [#report_lines+1] = barra.texto_esquerdo:GetText().." -> ".. barra.texto_direita:GetText()
+ end
+ if (index == amt) then
+ break
+ end
+
+ end
+ end
+
+ elseif (botao >= 11) then --> primeira caixa dos detalhes
+
+ botao = botao - 10
+
+ local nome
+ if (_type (spellid) == "string") then
+ --> is a pet
+ else
+ nome = _GetSpellInfo (player.detalhes)
+ end
+
+ if (not nome) then
+ nome = ""
+ end
+ report_lines = {"Details! " .. Loc ["STRING_ACTORFRAME_REPORTTO"] .. " " .. _detalhes.sub_atributos [atributo].lista [sub_atributo].. " " .. Loc ["STRING_ACTORFRAME_REPORTOF"] .. " " .. player.nome,
+ Loc ["STRING_ACTORFRAME_SPELLDETAILS"] .. ": " .. nome}
+
+ local caixa = info.grupos_detalhes [botao]
+
+ local linha = ""
+ local nome2 = caixa.nome2:GetText() --> golpes
+ if (nome2 and nome2 ~= "") then
+ if (i == 1) then
+ linha = linha..nome2.." / "
+ else
+ linha = linha..caixa.nome:GetText().." "..nome2.." / "
+ end
+ end
+
+ local dano = caixa.dano:GetText() --> dano
+ if (dano and dano ~= "") then
+ linha = linha..dano.." / "
+ end
+
+ local media = caixa.dano_media:GetText() --> media
+ if (media and media ~= "") then
+ linha = linha..media.." / "
+ end
+
+ local dano_dps = caixa.dano_dps:GetText()
+ if (dano_dps and dano_dps ~= "") then
+ linha = linha..dano_dps.." / "
+ end
+
+ local dano_porcento = caixa.dano_porcento:GetText()
+ if (dano_porcento and dano_porcento ~= "") then
+ linha = linha..dano_porcento.." "
+ end
+
+
+ report_lines [#report_lines+1] = linha
+
+ end
+
+ --local report_lines = {"Details! Relatorio para ".._detalhes.sub_atributos [self.atributo].lista [self.sub_atributo]}
+
+
+ --> pega o conteúdo da janela da direita
+
+ return instancia:envia_relatorio (report_lines)
+end
+
+local function SetBarraScripts (esta_barra, instancia, i)
+
+ esta_barra:SetScript ("OnEnter", --> MOUSE OVER
+ function (self)
+
+ if (info.fading_in or info.faded) then
+ return
+ end
+
+ self.mouse_over = true
+
+ --> aumenta o tamanho da barra
+ self:SetHeight (17) --> altura determinada pela instância
+ --> poe a barra com alfa 1 ao invés de 0.9
+ self:SetAlpha(1)
+
+ --> troca a cor da barra enquanto o mouse estiver em cima dela
+ self:SetBackdrop({
+ --bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", tile = true, tileSize = 16, edgeSize = 10,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ self:SetBackdropBorderColor (0.666, 0.666, 0.666)
+ self:SetBackdropColor (0.0941, 0.0941, 0.0941)
+
+ if (self.isAlvo) then --> monta o tooltip do alvo
+ --> talvez devesse escurecer a janela no fundo... pois o tooltip é transparente e pode confundir
+ GameTooltip:SetOwner (self, "ANCHOR_TOPRIGHT")
+ if (not self.minha_tabela or not self.minha_tabela:MontaTooltipAlvos (self, i)) then -- > poderia ser aprimerado para uma tailcall
+ return
+ end
+ GameTooltip:Show()
+
+ elseif (self.isMain) then
+
+ if (IsShiftKeyDown()) then
+ if (type (self.show) == "number") then
+ GameTooltip:SetOwner (self, "ANCHOR_TOPRIGHT")
+ GameTooltip:AddLine (Loc ["ABILITY_ID"] .. ": " .. self.show)
+ GameTooltip:Show()
+ end
+ end
+
+ --> da zoom no icone
+ self.icone:SetWidth (17)
+ self.icone:SetHeight (17)
+ --> poe a alfa do icone em 1.0
+ self.icone:SetAlpha (1)
+
+ --> mostrar temporariamente o conteudo da barra nas caixas de detalhes
+ if (not info.mostrando) then --> não esta mostrando nada na direita
+ info.mostrando = self --> agora o mostrando é igual a esta barra
+ info.mostrando_mouse_over = true --> o conteudo da direta esta sendo mostrado pq o mouse esta passando por cima do bagulho e não pq foi clicado
+ info.showing = i --> diz o index da barra que esta sendo mostrado na direita
+
+ --self:SetAlpha (1) -- não precisa isso pq ja tem la em cima
+ --self.minha_tabela.detalhes = self.show --> minha tabela = jogador = jogador.detales = spellid ou nome que esta sendo mostrado na direita
+ info.jogador.detalhes = self.show --> minha tabela = jogador = jogador.detales = spellid ou nome que esta sendo mostrado na direita
+ info.jogador:MontaDetalhes (self.show, self) --> passa a spellid ou nome e a barra
+ end
+ end
+
+ end)
+
+ esta_barra:SetScript ("OnLeave", --> MOUSE OUT
+ function (self)
+
+ if (self.fading_in or self.faded or not self:IsShown() or self.hidden) then
+ return
+ end
+
+ self.mouse_over = false
+
+ --> diminui o tamanho da barra
+ self:SetHeight (16)
+ --> volta com o alfa antigo da barra que era de 0.9
+ self:SetAlpha(0.9)
+
+ --> volto o background ao normal
+ self:SetBackdrop({
+ bgFile = "", edgeFile = "", tile = true, tileSize = 16, edgeSize = 32,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ self:SetBackdropBorderColor (0, 0, 0, 0)
+ self:SetBackdropColor (0, 0, 0, 0)
+
+ GameTooltip:Hide()
+
+ if (self.isMain) then
+ --> retira o zoom no icone
+ self.icone:SetWidth (14)
+ self.icone:SetHeight (14)
+ --> volta com a alfa antiga da barra
+ self.icone:SetAlpha (0.8)
+
+ --> remover o conteúdo que estava sendo mostrado na direita
+ if (info.mostrando_mouse_over) then
+ info.mostrando = nil
+ info.mostrando_mouse_over = false
+ info.showing = nil
+
+ info.jogador.detalhes = nil
+ gump:HidaAllDetalheInfo()
+ end
+ end
+
+ end)
+
+ esta_barra:SetScript ("OnMouseDown", function (self)
+
+ if (self.fading_in) then
+ return
+ end
+
+ self.mouse_down = _GetTime()
+ local x, y = _GetCursorPosition()
+ self.x = _math_floor (x)
+ self.y = _math_floor (y)
+
+ if ((not info.isLocked) or (info.isLocked == 0)) then
+ info:StartMoving()
+ info.isMoving = true
+ end
+
+ end)
+
+ esta_barra:SetScript ("OnMouseUp", function (self)
+
+ if (self.fading_in) then
+ return
+ end
+
+ if (info.isMoving) then
+ info:StopMovingOrSizing()
+ info.isMoving = false
+ --instancia:SaveMainWindowPosition() --> precisa fazer algo pra salvar o trem
+ end
+
+ local x, y = _GetCursorPosition()
+ x = _math_floor (x)
+ y = _math_floor (y)
+ if ((self.mouse_down+0.4 > _GetTime() and (x == self.x and y == self.y)) or (x == self.x and y == self.y)) then
+ --> setar os textos
+
+ if (self.isMain) then --> se não for uma barra de alvo
+
+ local barra_antiga = info.mostrando --> ??
+
+ --> on_focus = quando a barra esta precionada
+
+ if (barra_antiga and not info.mostrando_mouse_over) then
+
+ barra_antiga.textura:SetStatusBarColor (1, 1, 1, 1) --> volta a textura normal
+ barra_antiga.on_focus = false --> não esta mais no foco
+
+ --> CLICOU NA MESMA BARRA
+ if (barra_antiga == self) then -->
+ info.mostrando_mouse_over = true
+ return
+
+ --> CLICOU EM OUTRA BARRA
+ else --> clicou em outra barra e trocou o foco
+ barra_antiga:SetAlpha (.9) --> volta a alfa antiga
+
+ info.mostrando = self
+ info.showing = i
+
+ info.jogador.detalhes = self.show
+ info.jogador:MontaDetalhes (self.show, self)
+
+ self:SetAlpha (1)
+ self.textura:SetStatusBarColor (129/255, 125/255, 69/255, 1)
+ self.on_focus = true
+ return
+ end
+ end
+
+ --> NÃO TINHA BARRAS PRECIONADAS
+ -- info.mostrando = self
+ info.mostrando_mouse_over = false
+ self:SetAlpha (1)
+ self.textura:SetStatusBarColor (129/255, 125/255, 69/255, 1)
+ self.on_focus = true
+ end
+
+ end
+ end)
+end
+
+local function CriaTexturaBarra (instancia, barra)
+ barra.textura = _CreateFrame ("StatusBar", nil, barra)
+ barra.textura:SetAllPoints (barra)
+ --barra.textura:SetStatusBarTexture (instancia.barrasInfo.textura)
+ barra.textura:SetStatusBarTexture (_detalhes.default_texture)
+ barra.textura:SetStatusBarColor(.5, .5, .5, 0)
+ barra.textura:SetMinMaxValues(0,100)
+
+ barra.texto_esquerdo = barra.textura:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ barra.texto_esquerdo:SetPoint ("LEFT", barra.textura, "LEFT", 22, 0)
+ barra.texto_esquerdo:SetJustifyH ("LEFT")
+ barra.texto_esquerdo:SetTextColor (1,1,1,1)
+
+ barra.texto_direita = barra.textura:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ barra.texto_direita:SetPoint ("RIGHT", barra.textura, "RIGHT", -2)
+ barra.texto_direita:SetJustifyH ("RIGHT")
+ barra.texto_direita:SetTextColor (1,1,1,1)
+
+ barra.textura:Show()
+end
+
+function gump:CriaNovaBarraInfo1 (instancia, index)
+
+ if (_detalhes.janela_info.barras1 [index]) then
+ print ("erro a barra "..index.." ja existe na janela de detalhes...")
+ return
+ end
+
+ local janela = info.container_barras.gump
+
+ local esta_barra = _CreateFrame ("Button", "Details_infobox1_bar_"..index, info.container_barras.gump)
+ esta_barra:SetWidth (300) --> tamanho da barra de acordo com o tamanho da janela
+ esta_barra:SetHeight (16) --> altura determinada pela instância
+
+ local y = (index-1)*17 --> 17 é a altura da barra
+ y = y*-1 --> baixo
+
+ esta_barra:SetPoint ("LEFT", janela, "LEFT")
+ esta_barra:SetPoint ("RIGHT", janela, "RIGHT")
+ esta_barra:SetPoint ("TOP", janela, "TOP", 0, y)
+ esta_barra:SetFrameLevel (janela:GetFrameLevel() + 1)
+
+ esta_barra:EnableMouse (true)
+ esta_barra:RegisterForClicks ("LeftButtonDown","RightButtonUp")
+
+ CriaTexturaBarra (instancia, esta_barra)
+
+ --> icone
+ esta_barra.icone = esta_barra.textura:CreateTexture (nil, "OVERLAY")
+ esta_barra.icone:SetWidth (14)
+ esta_barra.icone:SetHeight (14)
+ esta_barra.icone:SetPoint ("RIGHT", esta_barra.textura, "LEFT", 20, 0)
+
+ esta_barra:SetAlpha(0.9)
+ esta_barra.icone:SetAlpha (0.8)
+
+ esta_barra.isMain = true
+
+ SetBarraScripts (esta_barra, instancia, index)
+
+ info.barras1 [index] = esta_barra --> barra adicionada
+
+ esta_barra.textura:SetStatusBarColor (1, 1, 1, 1) --> isso aqui é a parte da seleção e desceleção
+ esta_barra.on_focus = false --> isso aqui é a parte da seleção e desceleção
+
+ return esta_barra
+end
+
+function gump:CriaNovaBarraInfo2 (instancia, index)
+
+ if (_detalhes.janela_info.barras2 [index]) then
+ print ("erro a barra "..index.." ja existe na janela de detalhes...")
+ return
+ end
+
+ local janela = info.container_alvos.gump
+
+ local esta_barra = _CreateFrame ("Button", "Details_infobox2_bar_"..index, info.container_alvos.gump)
+ esta_barra:SetWidth (300) --> tamanho da barra de acordo com o tamanho da janela
+ esta_barra:SetHeight (16) --> altura determinada pela instância
+
+ local y = (index-1)*17 --> 17 é a altura da barra
+ y = y*-1 --> baixo
+
+ esta_barra:SetPoint ("LEFT", janela, "LEFT")
+ esta_barra:SetPoint ("RIGHT", janela, "RIGHT")
+ esta_barra:SetPoint ("TOP", janela, "TOP", 0, y)
+ esta_barra:SetFrameLevel (janela:GetFrameLevel() + 1)
+
+ esta_barra:EnableMouse (true)
+ esta_barra:RegisterForClicks ("LeftButtonDown","RightButtonUp")
+
+ CriaTexturaBarra (instancia, esta_barra)
+
+ --> icone
+ esta_barra.icone = esta_barra.textura:CreateTexture (nil, "OVERLAY")
+ esta_barra.icone:SetWidth (14)
+ esta_barra.icone:SetHeight (14)
+ esta_barra.icone:SetPoint ("RIGHT", esta_barra.textura, "LEFT", 0+20, 0)
+
+ esta_barra:SetAlpha(0.9)
+ esta_barra.icone:SetAlpha (0.8)
+
+ esta_barra.isAlvo = true
+
+ SetBarraScripts (esta_barra, instancia, index)
+
+ info.barras2 [index] = esta_barra --> barra adicionada
+
+ return esta_barra
+end
+
+local x_start = 62
+local y_start = -10
+
+function gump:CriaNovaBarraInfo3 (instancia, index)
+
+ if (_detalhes.janela_info.barras3 [index]) then
+ print ("erro a barra "..index.." ja existe na janela de detalhes...")
+ return
+ end
+
+ local janela = info.container_detalhes
+
+ local esta_barra = CreateFrame ("Button", "Details_infobox3_bar_"..index, janela)
+ esta_barra:SetWidth (220) --> tamanho da barra de acordo com o tamanho da janela
+ esta_barra:SetHeight (16) --> altura determinada pela instância
+
+ local y = (index-1)*17 --> 17 é a altura da barra
+ y = y*-1 --> baixo
+
+ esta_barra:SetPoint ("LEFT", janela, "LEFT", x_start, 0)
+ esta_barra:SetPoint ("RIGHT", janela, "RIGHT", 59, 0)
+ esta_barra:SetPoint ("TOP", janela, "TOP", 0, y+y_start)
+
+ esta_barra:EnableMouse (true)
+
+ CriaTexturaBarra (instancia, esta_barra)
+
+ --> icone
+ esta_barra.icone = esta_barra.textura:CreateTexture (nil, "OVERLAY")
+ esta_barra.icone:SetWidth (14)
+ esta_barra.icone:SetHeight (14)
+ esta_barra.icone:SetPoint ("RIGHT", esta_barra.textura, "LEFT", 0+20, 0)
+
+ esta_barra:SetAlpha(0.9)
+ esta_barra.icone:SetAlpha (0.8)
+
+ esta_barra.isDetalhe = true
+
+ SetBarraScripts (esta_barra, instancia, index)
+
+ info.barras3 [index] = esta_barra --> barra adicionada
+
+ return esta_barra
+end
diff --git a/gumps/janela_options.lua b/gumps/janela_options.lua
new file mode 100644
index 00000000..2b56a951
--- /dev/null
+++ b/gumps/janela_options.lua
@@ -0,0 +1,640 @@
+local _detalhes = _G._detalhes
+local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0")
+
+local g = _detalhes.gump
+
+function _detalhes:OpenOptionsWindow (instance)
+
+ GameCooltip:Close()
+ local window = _G.DetailsOptionsWindow
+
+ if (not window) then
+
+-- Details Overall -------------------------------------------------------------------------------------------------------------------------------------------------
+
+ -- Most of details widgets have the same 6 first parameters: parent, container, global name, parent key, width, height
+
+ window = g:NewPanel (UIParent, _, "DetailsOptionsWindow", _, 500, 300)
+ window.instance = instance
+ tinsert (UISpecialFrames, "DetailsOptionsWindow")
+ window:SetPoint ("center", UIParent, "Center")
+ window.locked = false
+ window.close_with_right = true
+
+ g:NewLabel (window, _, "$parentTitle", "title", "Options for Details!")
+ window.title:SetPoint (10, -10)
+
+ local close = g:NewLabel (window, _, "$parentRightMouseClose", nil, "|TInterface\\TUTORIALFRAME\\UI-TUTORIAL-FRAME:20:20:0:1:512:512:8:70:328:409|t right click to close this panel")
+ close:SetPoint ("bottomleft", window, "bottomleft", 5, 5)
+
+ --------------- Max Segments
+ g:NewLabel (window, _, "$parentSliderLabel", "segmentsLabel", "max segments")
+ window.segmentsLabel:SetPoint (10, -35)
+ --
+ g:NewSlider (window, _, "$parentSlider", "segmentsSlider", 120, 20, 1, 25, 1, _detalhes.segments_amount) -- min, max, step, defaultv
+ window.segmentsSlider:SetPoint ("left", window.segmentsLabel, "right")
+ window.segmentsSlider:SetHook ("OnValueChange", function (self, _, amount) --> slider, fixedValue, sliderValue
+ _detalhes.segments_amount = amount
+ end)
+ window.segmentsSlider.tooltip = "This option control how many fights you want to maintain.\nAs overall data work dynamic with segments stored,\nfeel free to adjust this number to be comfortable for you.\nHigh value may increase the memory use,\nbut doesn't affect your game framerate."
+
+ --------------- Max Segments Saved
+ g:NewLabel (window, _, "$parentLabelSegmentsSave", "segmentsSaveLabel", "segments saved on logout")
+ window.segmentsSaveLabel:SetPoint (10, -50)
+ --
+ g:NewSlider (window, _, "$parentSliderSegmentsSave", "segmentsSliderToSave", 80, 20, 1, 5, 1, _detalhes.segments_amount_to_save) -- min, max, step, defaultv
+ window.segmentsSliderToSave:SetPoint ("left", window.segmentsSaveLabel, "right")
+ window.segmentsSliderToSave:SetHook ("OnValueChange", function (self, _, amount) --> slider, fixedValue, sliderValue
+ _detalhes.segments_amount_to_save = amount
+ end)
+ window.segmentsSliderToSave.tooltip = "How many segments will be saved on logout.\nHigher values may increase the time between a\nlogout button click and your character selection screen.\nIf you rarely check last day data, it`s high recommeded save only 1."
+
+ --------------- Panic Mode
+ g:NewLabel (window, _, "$parentPanicModeLabel", "panicModeLabel", "panic mode")
+ window.panicModeLabel:SetPoint (10, -65)
+ --
+ g:NewSwitch (window, _, "$parentPanicModeSlider", "panicModeSlider", 60, 20, _, _, _detalhes.segments_panic_mode)
+ window.panicModeSlider:SetPoint ("left", window.panicModeLabel, "right")
+ window.panicModeSlider.OnSwitch = function (self, _, value) --> slider, fixedValue, sliderValue
+ _detalhes.segments_panic_mode = value
+ end
+ window.panicModeSlider.tooltip = "If enabled, when you are in a raid encounter\nand get dropped from the game, a disconnect for intance,\nDetails! immediately erase all segments\nmaking the disconnect process faster."
+
+ --------------- Animate Rows
+ g:NewLabel (window, _, "$parentAnimateLabel", "animateLabel", "animate rows")
+ window.animateLabel:SetPoint (10, -80)
+ --
+ g:NewSwitch (window, _, "$parentAnimateSlider", "animateSlider", 60, 20, _, _, _detalhes.use_row_animations) -- ltext, rtext, defaultv
+ window.animateSlider:SetPoint ("left",window.animateLabel, "right")
+ window.animateSlider.OnSwitch = function (self, _, value) --> slider, fixedValue, sliderValue (false, true)
+ _detalhes.use_row_animations = value
+ end
+
+ --------------- Clear Ungrouped
+ --[[
+ g:NewLabel (window, _, "$parentClearUngroupedLabel", "clearungroupedLabel", "delete ungrouped on logout")
+ window.clearungroupedLabel:SetPoint (10, -65)
+ --
+ g:NewSwitch (window, _, "$parentClearUngroupedSlider", "clearungroupedSlider", 60, 20, _, _, _detalhes.clear_ungrouped) -- ltext, rtext, defaultv
+ window.clearungroupedSlider:SetPoint ("left", window.clearungroupedLabel, "right")
+ window.clearungroupedSlider.OnSwitch = function (self, _, value) --> slider, fixedValue, sliderValue
+ _detalhes.clear_ungrouped = value
+ end
+ window.clearungroupedSlider.tooltip = "erase actors without a group when you logout."
+ --]]
+
+ --------------- Use Scroll Bar
+ g:NewLabel (window, _, "$parentUseScrollLabel", "scrollLabel", "show scroll bar")
+ window.scrollLabel:SetPoint (10, -95)
+ --
+ g:NewSwitch (window, _, "$parentUseScrollSlider", "scrollSlider", 60, 20, _, _, _detalhes.use_scroll) -- ltext, rtext, defaultv
+ window.scrollSlider:SetPoint ("left", window.scrollLabel, "right")
+ window.scrollSlider.OnSwitch = function (self, _, value) --> slider, fixedValue, sliderValue
+ _detalhes.use_scroll = value
+ if (not value) then
+ for index = 1, #_detalhes.tabela_instancias do
+ local instance = _detalhes.tabela_instancias [index]
+ if (instance.baseframe) then --fast check if instance already been initialized
+ instance:EsconderScrollBar (true, true)
+ end
+ end
+ end
+ --hard instances reset
+ _detalhes:InstanciaCallFunction (_detalhes.gump.Fade, "in", nil, "barras")
+ _detalhes:InstanciaCallFunction (_detalhes.AtualizaSegmentos) -- atualiza o instancia.showing para as novas tabelas criadas
+ _detalhes:InstanciaCallFunction (_detalhes.AtualizaSoloMode_AfertReset) -- verifica se precisa zerar as tabela da janela solo mode
+ _detalhes:InstanciaCallFunction (_detalhes.ResetaGump) --_detalhes:ResetaGump ("de todas as instancias")
+ _detalhes:AtualizaGumpPrincipal (-1, true) --atualiza todas as instancias
+ end
+
+ --------------- Animate scroll bar
+ g:NewLabel (window, _, "$parentAnimateScrollLabel", "animatescrollLabel", "animate scroll")
+ window.animatescrollLabel:SetPoint (10, -110)
+ --
+ g:NewSwitch (window, _, "$parentClearAnimateScrollSlider", "animatescrollSlider", 60, 20, _, _, _detalhes.animate_scroll) -- ltext, rtext, defaultv
+ window.animatescrollSlider:SetPoint ("left", window.animatescrollLabel, "right")
+ window.animatescrollSlider.OnSwitch = function (self, _, value) --> slider, fixedValue, sliderValue
+ _detalhes.animate_scroll = value
+ end
+
+ --------------- Update Speed
+ g:NewLabel (window, _, "$parentUpdateSpeedLabel", "updatespeedLabel", "update speed")
+ window.updatespeedLabel:SetPoint (10, -125)
+ --
+ g:NewSlider (window, _, "$parentSliderUpdateSpeed", "updatespeedSlider", 160, 20, 0.3, 2, 0.1, _detalhes.update_speed, true) --parent, container, name, member, w, h, min, max, step, defaultv
+ window.updatespeedSlider:SetPoint ("left", window.updatespeedLabel, "right")
+ window.updatespeedSlider:SetThumbSize (50)
+ window.updatespeedSlider.useDecimals = true
+ local updateColor = function (slider, value)
+ if (value < 1) then
+ slider.amt:SetTextColor (1, value, 0)
+ elseif (value > 1) then
+ slider.amt:SetTextColor (-(value-2), 1, 0)
+ else
+ slider.amt:SetTextColor (1, 1, 0)
+ end
+ end
+ window.updatespeedSlider:SetHook ("OnValueChange", function (self, _, amount)
+ _detalhes:CancelTimer (_detalhes.atualizador)
+ _detalhes.update_speed = amount
+ _detalhes.atualizador = _detalhes:ScheduleRepeatingTimer ("AtualizaGumpPrincipal", _detalhes.update_speed, -1)
+ updateColor (self, amount)
+ end)
+ updateColor (window.updatespeedSlider, _detalhes.update_speed)
+
+ window.updatespeedSlider.tooltip = "delay between each update,\nCPU usage may increase with low values."
+
+ --------------- Time Type
+ g:NewLabel (window, _, "$parentTimeTypeLabel", "timetypeLabel", "time measure")
+ window.timetypeLabel:SetPoint (10, -143)
+ --
+ local onSelectTimeType = function (_, _, timetype)
+ _detalhes.time_type = timetype
+ _detalhes:AtualizaGumpPrincipal (-1, true)
+ end
+ local timetypeOptions = {
+ {value = 1, label = "Chronometer", onclick = onSelectTimeType, icon = "Interface\\Icons\\INV_Misc_PocketWatch_01", desc = "The effective time are based on the actions of the actor\nand his activity time are paused when he is idle during combat."},
+ {value = 2, label = "Continuous", onclick = onSelectTimeType, icon = "Interface\\Icons\\INV_Misc_Gear_03", desc = "Activity time is the same for all the actors where the\ncombat time is used to measure the effectiveness of all actors."}
+ }
+ local buildTimeTypeMenu = function()
+ return timetypeOptions
+ end
+ g:NewDropDown (window, _, "$parentTTDropdown", "timetypeDropdown", 160, 20, buildTimeTypeMenu, nil) -- func, default
+ window.timetypeDropdown:SetPoint ("left", window.timetypeLabel, "right")
+
+
+-- Current Instalnce --------------------------------------------------------------------------------------------------------------------------------------------
+
+ --------------- Row textures
+ g:NewLabel (window, _, "$parentTextureLabel", "textureLabel", "row style")
+ window.textureLabel:SetPoint (250, -30)
+ --
+ local onSelectTexture = function (_, instance, textureName)
+ instance.barrasInfo.textura = SharedMedia:Fetch ("statusbar", textureName)
+ instance.barrasInfo.textureName = textureName
+ instance:RefreshBars()
+ end
+ local textures = SharedMedia:HashTable ("statusbar")
+ local texTable = {}
+ for name, texturePath in pairs (textures) do
+ texTable[#texTable+1] = {value = name, label = name, statusbar = texturePath, onclick = onSelectTexture}
+ end
+ local buildTextureMenu = function() return texTable end
+ g:NewDropDown (window, _, "$parentTextureDropdown", "textureDropdown", 160, 20, buildTextureMenu, nil) -- func, default
+ window.textureDropdown:SetPoint ("left", window.textureLabel, "right", 2)
+
+ --------------- Text Sizes
+ g:NewLabel (window, _, "$parentFontSizeLabel", "fonsizeLabel", "font size")
+ window.fonsizeLabel:SetPoint (250, -65)
+ --
+ g:NewSlider (window, _, "$parentSliderFontSize", "fonsizeSlider", 90, 20, 9, 13, .5, tonumber (instance.barrasInfo.fontSize)) --parent, container, name, member, w, h, min, max, step, defaultv
+ window.fonsizeSlider:SetPoint ("left", window.fonsizeLabel, "right")
+ window.fonsizeSlider:SetThumbSize (50)
+ window.fonsizeSlider.useDecimals = true
+ window.fonsizeSlider:SetHook ("OnValueChange", function (self, instance, amount)
+ instance.barrasInfo.fontSize = amount
+ instance:RefreshBars()
+ end)
+
+ --------------- Text Fonts
+ local onSelectFont = function (_, instance, fontName)
+ instance.barrasInfo.font = SharedMedia:Fetch ("font", fontName)
+ instance.barrasInfo.fontName = fontName
+ instance:RefreshBars()
+ end
+
+ local fontObjects = SharedMedia:HashTable ("font")
+ local fontTable = {}
+ for name, fontPath in pairs (fontObjects) do
+ fontTable[#fontTable+1] = {value = name, label = name, onclick = onSelectFont, font = fontPath}
+ end
+ local buildFontMenu = function() return fontTable end
+
+ g:NewLabel (window, _, "$parentFontLabel", "fontLabel", "select font style")
+ window.fontLabel:SetPoint (250, -82)
+ --
+ g:NewDropDown (window, _, "$parentFontDropdown", "fontDropdown", 160, 20, buildFontMenu, nil)
+ window.fontDropdown:SetPoint ("left", window.fontLabel, "right", 2)
+
+ --------------- Instance Color
+
+ g:NewLabel (window, _, "$parentInstanceColorLabel", "instancecolor", "instance color")
+ window.instancecolor:SetPoint (250, -115)
+
+ local selectedColor = function()
+ local r, g, b = ColorPickerFrame:GetColorRGB()
+ local a = OpacitySliderFrame:GetValue()
+
+ window.instancecolortexture:SetTexture (r, g, b)
+ window.instancecolortexture:SetAlpha (a)
+
+ window.instance.color[1], window.instance.color[2], window.instance.color[3], window.instance.color[4] = r, g, b, a
+ window.instance:InstanceColor (r, g, b, a)
+ end
+
+ local canceledColor = function()
+ local c = ColorPickerFrame.previousValues
+ window.instancecolortexture:SetTexture (c [1], c [2], c [3])
+ window.instancecolortexture:SetAlpha (c [4])
+
+ window.instance.color[1], window.instance.color[2], window.instance.color[3], window.instance.color[4] = c [1], c [2], c [3], c [4]
+ window.instance:InstanceColor (c [1], c [2], c [3], c [4])
+
+ ColorPickerFrame.func = nil
+ ColorPickerFrame.opacityFunc = nil
+ ColorPickerFrame.cancelFunc = nil
+ end
+
+ local selectedAlpha = function()
+ local r, g, b = ColorPickerFrame:GetColorRGB()
+ local a = OpacitySliderFrame:GetValue()
+
+ window.instancecolortexture:SetTexture (r, g, b)
+ window.instancecolortexture:SetAlpha (a)
+
+ window.instance.color[1], window.instance.color[2], window.instance.color[3], window.instance.color[4] = r, g, b, a
+ window.instance:InstanceColor (r, g, b, a)
+
+ end
+
+ local colorpick = function()
+ ColorPickerFrame:SetColorRGB (unpack (window.instance.color))
+ ColorPickerFrame.hasOpacity = false
+ ColorPickerFrame.opacity = window.instance.color[4] or 1
+ ColorPickerFrame.previousValues = window.instance.color
+ ColorPickerFrame.func = selectedColor
+ ColorPickerFrame.opacityFunc = selectedAlpha
+ ColorPickerFrame.cancelFunc = canceledColor
+ ColorPickerFrame:SetParent (window.widget)
+ ColorPickerFrame:Show()
+ end
+
+ g:NewImage (window, _, "$parentInstanceColorTexture", "instancecolortexture", 100, 12)
+ window.instancecolortexture:SetPoint ("left", window.instancecolor, "right", 2)
+ window.instancecolortexture:SetTexture (1, 1, 1)
+
+ g:NewButton (window, _, "$parentInstanceColorButton", "instancecolorbutton", 200, 20, colorpick)
+ window.instancecolorbutton:SetPoint ("left", window.instancecolor, "right", 2)
+
+ --------------- Background
+
+ local onSelectSecTexture = function (self, instance, texturePath)
+ instance:InstanceWallpaper (texturePath)
+ end
+
+ local subMenu = {
+
+ ["ARCHEOLOGY"] = {
+ {value = [[Interface\ARCHEOLOGY\Arch-BookCompletedLeft]], label = "Book Wallpaper", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-BookCompletedLeft]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\Arch-BookItemLeft]], label = "Book Wallpaper 2", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-BookItemLeft]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\Arch-Race-DraeneiBIG]], label = "Draenei", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-Race-DraeneiBIG]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\Arch-Race-DwarfBIG]], label = "Dwarf", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-Race-DwarfBIG]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\Arch-Race-NightElfBIG]], label = "Night Elf", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-Race-NightElfBIG]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\Arch-Race-OrcBIG]], label = "Orc", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-Race-OrcBIG]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\Arch-Race-PandarenBIG]], label = "Pandaren", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-Race-PandarenBIG]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\Arch-Race-TrollBIG]], label = "Troll", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-Race-TrollBIG]], texcoord = nil},
+
+ {value = [[Interface\ARCHEOLOGY\ArchRare-AncientShamanHeaddress]], label = "Ancient Shaman", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-AncientShamanHeaddress]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-BabyPterrodax]], label = "Baby Pterrodax", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-BabyPterrodax]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-ChaliceMountainKings]], label = "Chalice Mountain Kings", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-ChaliceMountainKings]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-ClockworkGnome]], label = "Clockwork Gnomes", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-ClockworkGnome]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-QueenAzsharaGown]], label = "Queen Azshara Gown", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-QueenAzsharaGown]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-QuilinStatue]], label = "Quilin Statue", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-QuilinStatue]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\Arch-TempRareSketch]], label = "Rare Sketch", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\Arch-TempRareSketch]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-ScepterofAzAqir]], label = "Scepter of Az Aqir", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-ScepterofAzAqir]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-ShriveledMonkeyPaw]], label = "Shriveled Monkey Paw", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-ShriveledMonkeyPaw]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-StaffofAmmunrae]], label = "Staff of Ammunrae", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-StaffofAmmunrae]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-TinyDinosaurSkeleton]], label = "Tiny Dinosaur", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-TinyDinosaurSkeleton]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-TyrandesFavoriteDoll]], label = "Tyrandes Favorite Doll", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-TyrandesFavoriteDoll]], texcoord = nil},
+ {value = [[Interface\ARCHEOLOGY\ArchRare-ZinRokhDestroyer]], label = "ZinRokh Destroyer", onclick = onSelectSecTexture, icon = [[Interface\ARCHEOLOGY\ArchRare-ZinRokhDestroyer]], texcoord = nil},
+ },
+
+ ["DEATHKNIGHT"] = {
+ {value = [[Interface\TALENTFRAME\bg-deathknight-blood]], label = "Blood", onclick = onSelectSecTexture, icon = [[Interface\ICONS\Spell_Deathknight_BloodPresence]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-deathknight-frost]], label = "Frost", onclick = onSelectSecTexture, icon = [[Interface\ICONS\Spell_Deathknight_FrostPresence]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-deathknight-unholy]], label = "Unholy", onclick = onSelectSecTexture, icon = [[Interface\ICONS\Spell_Deathknight_UnholyPresence]], texcoord = nil}
+ },
+
+ ["DRESSUP"] = {
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-BloodElf1]], label = "Blood Elf", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.5, 0.625, 0.75, 1}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-DeathKnight1]], label = "Death Knight", onclick = onSelectSecTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["DEATHKNIGHT"]},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Draenei1]], label = "Draenei", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.5, 0.625, 0.5, 0.75}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Dwarf1]], label = "Dwarf", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.125, 0.25, 0, 0.25}},
+ {value = [[Interface\DRESSUPFRAME\DRESSUPBACKGROUND-GNOME1]], label = "Gnome", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.25, 0.375, 0, 0.25}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Goblin1]], label = "Goblin", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.625, 0.75, 0.75, 1}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Human1]], label = "Human", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0, 0.125, 0.75, 1}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-NightElf1]], label = "Night Elf", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.375, 0.5, 0, 0.25}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Orc1]], label = "Orc", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.375, 0.5, 0.25, 0.5}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Pandaren1]], label = "Pandaren", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.75, 0.875, 0.5, 0.75}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Tauren1]], label = "Tauren", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0, 0.125, 0.25, 0.5}},
+ {value = [[Interface\DRESSUPFRAME\DRESSUPBACKGROUND-TROLL1]], label = "Troll", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.25, 0.375, 0.75, 1}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Scourge1]], label = "Undead", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.125, 0.25, 0.75, 1}},
+ {value = [[Interface\DRESSUPFRAME\DressUpBackground-Worgen1]], label = "Worgen", onclick = onSelectSecTexture, icon = [[Interface\Glues\CHARACTERCREATE\UI-CHARACTERCREATE-RACES]], texcoord = {0.625, 0.75, 0, 0.25}},
+ },
+
+ ["DRUID"] = {
+ {value = [[Interface\TALENTFRAME\bg-druid-bear]], label = "Guardian", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_racial_bearform]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-druid-restoration]], label = "Restoration", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_nature_healingtouch]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-druid-cat]], label = "Feral", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_shadow_vampiricaura]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-druid-balance]], label = "Balance", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_nature_starfall]], texcoord = nil}
+ },
+
+ ["HUNTER"] = {
+ {value = [[Interface\TALENTFRAME\bg-hunter-beastmaster]], label = "Beast Mastery", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_hunter_bestialdiscipline]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-hunter-marksman]], label = "Marksmanship", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_hunter_focusedaim]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-hunter-survival]], label = "Survival", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_hunter_camouflage]], texcoord = nil}
+ },
+
+ ["MAGE"] = {
+ {value = [[Interface\TALENTFRAME\bg-mage-arcane]], label = "Arcane", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_holy_magicalsentry]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-mage-fire]], label = "Fire", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_fire_firebolt02]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-mage-frost]], label = "Frost", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_frost_frostbolt02]], texcoord = nil}
+ },
+
+ ["MONK"] = {
+ {value = [[Interface\TALENTFRAME\bg-monk-brewmaster]], label = "Brewmaster", onclick = onSelectSecTexture, icon = [[Interface\ICONS\monk_stance_drunkenox]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-monk-mistweaver]], label = "Mistweaver", onclick = onSelectSecTexture, icon = [[Interface\ICONS\monk_stance_wiseserpent]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-monk-battledancer]], label = "Windwalker", onclick = onSelectSecTexture, icon = [[Interface\ICONS\monk_stance_whitetiger]], texcoord = nil}
+ },
+
+ ["PALADIN"] = {
+ {value = [[Interface\TALENTFRAME\bg-paladin-holy]], label = "Holy", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_holy_holybolt]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-paladin-protection]], label = "Protection", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_paladin_shieldofthetemplar]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-paladin-retribution]], label = "Retribution", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_holy_auraoflight]], texcoord = nil}
+ },
+
+ ["PRIEST"] = {
+ {value = [[Interface\TALENTFRAME\bg-priest-discipline]], label = "Discipline", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_holy_powerwordshield]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-priest-holy]], label = "Holy", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_holy_guardianspirit]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-priest-shadow]], label = "Shadow", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_shadow_shadowwordpain]], texcoord = nil}
+ },
+
+ ["ROGUE"] = {
+ {value = [[Interface\TALENTFRAME\bg-rogue-assassination]], label = "Assassination", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_rogue_eviscerate]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-rogue-combat]], label = "Combat", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_backstab]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-rogue-subtlety]], label = "Subtlety", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_stealth]], texcoord = nil}
+ },
+
+ ["SHAMAN"] = {
+ {value = [[Interface\TALENTFRAME\bg-shaman-elemental]], label = "Elemental", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_nature_lightning]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-shaman-enhancement]], label = "Enhancement", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_nature_lightningshield]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-shaman-restoration]], label = "Restoration", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_nature_magicimmunity]], texcoord = nil}
+ },
+
+ ["WARLOCK"] = {
+ {value = [[Interface\TALENTFRAME\bg-warlock-affliction]], label = "Affliction", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_shadow_deathcoil]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-warlock-demonology]], label = "Demonology", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_shadow_metamorphosis]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-warlock-destruction]], label = "Destruction", onclick = onSelectSecTexture, icon = [[Interface\ICONS\spell_shadow_rainoffire]], texcoord = nil}
+ },
+ ["WARRIOR"] = {
+ {value = [[Interface\TALENTFRAME\bg-warrior-arms]], label = "Arms", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_warrior_savageblow]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-warrior-fury]], label = "Fury", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_warrior_innerrage]], texcoord = nil},
+ {value = [[Interface\TALENTFRAME\bg-warrior-protection]], label = "Protection", onclick = onSelectSecTexture, icon = [[Interface\ICONS\ability_warrior_defensivestance]], texcoord = nil}
+ },
+ }
+
+ local buildBackgroundMenu2 = function()
+ return subMenu [window.backgroundDropdown.value] or {label = "-- -- --", value = 0}
+ end
+
+ local onSelectMainTexture = function (_, instance, choose)
+ window.backgroundDropdown2:Select (choose)
+ end
+
+ local backgroundTable = {
+ {value = "ARCHEOLOGY", label = "Archeology", onclick = onSelectMainTexture, icon = [[Interface\ARCHEOLOGY\Arch-Icon-Marker]]},
+ {value = "DEATHKNIGHT", label = "Death Knight", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["DEATHKNIGHT"]},
+ {value = "DRESSUP", label = "Class Background", onclick = onSelectMainTexture, icon = [[Interface\ICONS\INV_Chest_Cloth_17]]},
+ {value = "DRUID", label = "Druid", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["DRUID"]},
+ {value = "HUNTER", label = "Hunter", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["HUNTER"]},
+ {value = "MAGE", label = "Mage", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["MAGE"]},
+ {value = "MONK", label = "Monk", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["MONK"]},
+ {value = "PALADIN", label = "Paladin", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["PALADIN"]},
+ {value = "PRIEST", label = "Priest", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["PRIEST"]},
+ {value = "ROGUE", label = "Rogue", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["ROGUE"]},
+ {value = "SHAMAN", label = "Shaman", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["SHAMAN"]},
+ {value = "WARLOCK", label = "Warlock", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["WARLOCK"]},
+ {value = "WARRIOR", label = "Warrior", onclick = onSelectMainTexture, icon = _detalhes.class_icons_small, texcoord = _detalhes.class_coords ["WARRIOR"]},
+ }
+ local buildBackgroundMenu = function() return backgroundTable end
+
+ g:NewLabel (window, _, "$parentBackgroundLabel", "backgroundLabel", "instance wallpaper")
+ window.backgroundLabel:SetPoint (250, -145)
+ --
+ g:NewSwitch (window, _, "$parentUseBackgroundSlider", "useBackgroundSlider", 60, 20, _, _, window.instance.wallpaper.enabled)
+ window.useBackgroundSlider:SetPoint ("left", window.backgroundLabel, "right")
+ window.useBackgroundSlider.OnSwitch = function (self, instance, value) --> slider, fixedValue, sliderValue
+ instance.wallpaper.enabled = value
+ if (value) then
+ instance:InstanceWallpaper (true)
+ _G.DetailsOptionsWindowBackgroundDropdown.MyObject:Enable()
+ _G.DetailsOptionsWindowBackgroundDropdown2.MyObject:Enable()
+
+ else
+ instance:InstanceWallpaper (false)
+ _G.DetailsOptionsWindowBackgroundDropdown.MyObject:Disable()
+ _G.DetailsOptionsWindowBackgroundDropdown2.MyObject:Disable()
+ end
+ end
+ --
+ g:NewDropDown (window, _, "$parentBackgroundDropdown", "backgroundDropdown", 120, 20, buildBackgroundMenu, nil)
+ window.backgroundDropdown:SetPoint (250, -160)
+ --
+ g:NewDropDown (window, _, "$parentBackgroundDropdown2", "backgroundDropdown2", 120, 20, buildBackgroundMenu2, nil)
+ window.backgroundDropdown2:SetPoint (370, -160)
+
+
+ local onSelectAnchor = function (_, instance, anchor)
+ instance:InstanceWallpaper (nil, anchor)
+ end
+ local anchorMenu = {
+ {value = "all", label = "Fill", onclick = onSelectAnchor},
+ {value = "center", label = "Center", onclick = onSelectAnchor},
+ {value = "stretchLR", label = "Stretch Left-Right", onclick = onSelectAnchor},
+ {value = "stretchTB", label = "Stretch Top-Bottom", onclick = onSelectAnchor},
+ {value = "topleft", label = "Top Left", onclick = onSelectAnchor},
+ {value = "bottomleft", label = "Bottom Left", onclick = onSelectAnchor},
+ {value = "topright", label = "Top Right", onclick = onSelectAnchor},
+ {value = "bottomright", label = "Bottom Right", onclick = onSelectAnchor},
+ }
+ local buildAnchorMenu = function()
+ return anchorMenu
+ end
+
+ local callmeback = function (width, height, overlayColor, alpha, texCoords)
+ local tinstance = _G ["DetailsOptionsWindow"].MyObject.instance
+ tinstance:InstanceWallpaper (nil, nil, alpha, texCoords, width, height, overlayColor)
+ end
+
+ local startImageEdit = function()
+ local tinstance = _G ["DetailsOptionsWindow"].MyObject.instance
+ g:ImageEditor (callmeback, tinstance.wallpaper.texture, tinstance.wallpaper.texcoord, tinstance.wallpaper.overlay)
+ end
+
+ g:NewLabel (window, _, "$parentAnchorLabel", "anchorLabel", "align")
+ window.anchorLabel:SetPoint (250, -185)
+ --
+ g:NewDropDown (window, _, "$parentAnchorDropdown", "anchorDropdown", 100, 20, buildAnchorMenu, nil)
+ window.anchorDropdown:SetPoint ("left", window.anchorLabel, "right", 2)
+ --
+ g:NewButton (window, _, "$parentEditImage", "editImage", 100, 18, startImageEdit, nil, nil, nil, "edit image")
+ window.editImage:InstallCustomTexture()
+ window.editImage:SetPoint ("left", window.anchorDropdown, "right", 2)
+
+----------------------- Save Style Text Entry and Button -----------------------------------------
+
+ ----- style name
+ g:NewTextEntry (window, _, "$parentSaveStyleName", "saveStyleName", nil, 20, _, _, _, 178) --width will be auto adjusted if space parameter is passed
+ window.saveStyleName:SetLabelText ("style name:")
+ window.saveStyleName:SetPoint (250, -280)
+
+ local saveStyleFunc = function()
+ if (not window.saveStyleName.text or window.saveStyleName.text == "") then
+ print ("Give a name for your style.")
+ return
+ end
+ local savedObject = {
+ name = window.saveStyleName.text,
+ texture = window.textureDropdown.value,
+ fontSize = tonumber (window.fonsizeSlider.value),
+ fontFace = window.fontDropdown.value,
+ color = window.instance.color,
+ wallpaper = instance.wallpaper
+ }
+ _detalhes.savedStyles [#_detalhes.savedStyles+1] = savedObject
+ window.saveStyleName.text = ""
+ end
+ ----- add style button
+ g:NewButton (window, _, "$parentSaveStyleButton", "saveStyle", 32, 19, saveStyleFunc, nil, nil, nil, "save")
+ window.saveStyle:InstallCustomTexture()
+ window.saveStyle:SetPoint ("left", window.saveStyleName, "right", 2)
+
+ ----- load style button
+ g:NewButton (window, _, "$parentLoadStyleButton", "loadStyle", 32, 19, nil, nil, nil, nil, "load")
+ window.loadStyle:InstallCustomTexture()
+ window.loadStyle:SetPoint ("left", window.saveStyle, "right", 2)
+
+ local loadStyle = function (_, instance, index)
+ local style = _detalhes.savedStyles [index]
+ --texture
+ instance.barrasInfo.textura = SharedMedia:Fetch ("statusbar", style.texture)
+ instance.barrasInfo.textureName = style.texture
+ --fontface
+ instance.barrasInfo.font = SharedMedia:Fetch ("font", style.fontFace)
+ instance.barrasInfo.fontName = style.fontFace
+ --fontsize
+ instance.barrasInfo.fontSize = tonumber (style.fontSize)
+ --color
+ instance:InstanceColor (style.color)
+ --wallpaper
+ instance:InstanceWallpaper (style.wallpaper)
+ --refresh
+ instance:RefreshBars()
+ --update options
+
+ _G.DetailsOptionsWindowInstanceColorTexture.MyObject:SetTexture (unpack (style.color))
+ _G.DetailsOptionsWindowTextureDropdown.MyObject:Select (style.texture)
+ _G.DetailsOptionsWindowFontDropdown.MyObject:Select (style.fontFace)
+ _G.DetailsOptionsWindowSliderFontSize.MyObject:SetValue (style.fontSize)
+ end
+
+ local createLoadMenu = function()
+ for index, _table in ipairs (_detalhes.savedStyles) do
+ GameCooltip:AddLine (_table.name)
+ GameCooltip:AddMenu (1, loadStyle, index)
+ end
+ end
+ window.loadStyle.CoolTip = {Type = "menu", BuildFunc = createLoadMenu, FixedValue = instance}
+ GameCooltip:CoolTipInject (window.loadStyle)
+
+ ------ remove style button
+ g:NewButton (window, _, "$parentRemoveStyleButton", "removeStyle", 12, 19, nil, nil, nil, nil, "x")
+ window.removeStyle:InstallCustomTexture()
+ window.removeStyle:SetPoint ("left", window.loadStyle, "right", 2)
+
+ local removeStyle = function (_, _, index)
+ table.remove (_detalhes.savedStyles, index)
+ if (#_detalhes.savedStyles > 0) then
+ GameCooltip:ExecFunc (window.removeStyle)
+ else
+ GameCooltip:Close()
+ end
+ end
+
+ local createRemoveMenu = function()
+ for index, _table in ipairs (_detalhes.savedStyles) do
+ GameCooltip:AddLine (_table.name)
+ GameCooltip:AddMenu (1, removeStyle, index)
+ end
+ end
+ window.removeStyle.CoolTip = {Type = "menu", BuildFunc = createRemoveMenu}
+ GameCooltip:CoolTipInject (window.removeStyle)
+
+ ------ apply to all button
+ local applyToAll = function()
+ for _, this_instance in ipairs (_detalhes.tabela_instancias) do
+ if (this_instance:IsAtiva() and this_instance.meu_id ~= instance.meu_id) then
+ --texture
+ this_instance.barrasInfo.textura = SharedMedia:Fetch ("statusbar", window.textureDropdown.value)
+ this_instance.barrasInfo.textureName = window.textureDropdown.value
+ --fontface
+ this_instance.barrasInfo.font = SharedMedia:Fetch ("font", window.fontDropdown.value)
+ this_instance.barrasInfo.fontName = window.fontDropdown.value
+ --fontsize
+ this_instance.barrasInfo.fontSize = window.fonsizeSlider.value
+ --color
+ this_instance:InstanceColor (window.instance.color)
+ --wallpaper
+ this_instance:InstanceWallpaper (window.instance.wallpaper)
+ --refresh
+ this_instance:RefreshBars()
+ end
+ end
+ end
+
+ g:NewButton (window, _, "$parentToAllStyleButton", "applyToAll", 130, 14, applyToAll, nil, nil, nil, "apply to all instances")
+ window.applyToAll:InstallCustomTexture()
+ window.applyToAll:SetPoint ("bottomright", window.removeStyle, "topright", 1, 3)
+
+ end
+
+
+----------------------------------------------------------------------------------------
+--> Show
+
+ _G.DetailsOptionsWindowTextureDropdown.MyObject:SetFixedParameter (instance)
+ _G.DetailsOptionsWindowTextureDropdown.MyObject:Select (instance.barrasInfo.textureName)
+ --
+ _G.DetailsOptionsWindowFontDropdown.MyObject:SetFixedParameter (instance)
+ _G.DetailsOptionsWindowFontDropdown.MyObject:Select (instance.barrasInfo.fontName)
+ --
+ _G.DetailsOptionsWindowSliderFontSize.MyObject:SetFixedParameter (instance)
+ _G.DetailsOptionsWindowSliderFontSize.MyObject:SetValue (instance.barrasInfo.fontSize)
+ --
+ _G.DetailsOptionsWindowUseBackgroundSlider.MyObject:SetFixedParameter (instance)
+ _G.DetailsOptionsWindowBackgroundDropdown.MyObject:SetFixedParameter (instance)
+ _G.DetailsOptionsWindowBackgroundDropdown2.MyObject:SetFixedParameter (instance)
+ _G.DetailsOptionsWindowAnchorDropdown.MyObject:SetFixedParameter (instance)
+ _G.DetailsOptionsWindowBackgroundDropdown.MyObject:Select (instance.wallpaper.texture)
+
+ if (instance.wallpaper.enabled) then
+ _G.DetailsOptionsWindowBackgroundDropdown.MyObject:Enable()
+ _G.DetailsOptionsWindowBackgroundDropdown2.MyObject:Enable()
+ _G.DetailsOptionsWindowUseBackgroundSlider.MyObject:SetValue (2)
+ else
+ _G.DetailsOptionsWindowBackgroundDropdown.MyObject:Disable()
+ _G.DetailsOptionsWindowBackgroundDropdown2.MyObject:Disable()
+ _G.DetailsOptionsWindowUseBackgroundSlider.MyObject:SetValue (1)
+ end
+ --
+ _G.DetailsOptionsWindowTTDropdown.MyObject:Select (_detalhes.time_type, true)
+ --
+ _G.DetailsOptionsWindowInstanceColorTexture.MyObject:SetTexture (unpack (instance.color))
+ --
+ GameCooltip:SetFixedParameter (_G.DetailsOptionsWindowLoadStyleButton, instance)
+
+ _G.DetailsOptionsWindow.MyObject.instance = instance
+ window:Show()
+
+end
diff --git a/gumps/janela_principal.lua b/gumps/janela_principal.lua
new file mode 100644
index 00000000..9e05ea26
--- /dev/null
+++ b/gumps/janela_principal.lua
@@ -0,0 +1,3134 @@
+local _detalhes = _G._detalhes
+local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+local atributos = _detalhes.atributos
+local sub_atributos = _detalhes.sub_atributos
+local segmentos = _detalhes.segmentos
+
+--lua locals
+local _cstr = tostring
+local _math_ceil = math.ceil
+local _math_floor = math.floor
+local _ipairs = ipairs
+local _pairs = pairs
+local _string_lower = string.lower
+--api locals
+local _CreateFrame = CreateFrame
+local _GetTime = GetTime
+local _GetCursorPosition = GetCursorPosition
+local _GameTooltip = GameTooltip
+local _UIParent = UIParent
+local _GetScreenWidth = GetScreenWidth
+local _GetScreenHeight = GetScreenHeight
+local _IsAltKeyDown = IsAltKeyDown
+local _IsShiftKeyDown = IsShiftKeyDown
+local _IsControlKeyDown = IsControlKeyDown
+local modo_raid = _detalhes._detalhes_props["MODO_RAID"]
+local modo_alone = _detalhes._detalhes_props["MODO_ALONE"]
+local modo_grupo = _detalhes._detalhes_props["MODO_GROUP"]
+local modo_all = _detalhes._detalhes_props["MODO_ALL"]
+
+local gump_fundo_backdrop = {
+ --bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16,
+ bgFile = "Interface\\AddOns\\Details\\images\\background", tile = true, tileSize = 16,
+ insets = {left = 0, right = 0, top = 0, bottom = 0}}
+
+function _detalhes:ScheduleUpdate (instancia)
+ instancia.barraS = {nil, nil}
+ instancia.update = true
+ if (instancia.showing) then
+ instancia.showing [instancia.atributo].need_refresh = true
+ end
+end
+
+function _detalhes:AtualizarScrollBar (x)
+
+ local cabe = self.barrasInfo.cabem --> quantas barras cabem na janela
+
+ if (not self.barraS[1]) then --primeira vez que as barras estão aparecendo
+ self.barraS[1] = 1 --primeira barra
+ if (cabe < x) then --se a quantidade a ser mostrada for maior que o que pode ser mostrado
+ self.barraS[2] = cabe -- B = o que pode ser mostrado
+ else
+ self.barraS[2] = x -- contrário B = o que esta sendo mostrado
+ end
+ end
+
+ if (not self.rolagem) then
+ if (x > cabe) then --> Ligar a ScrollBar
+ self.barrasInfo.mostrando = x
+
+ if (not self.baseframe.isStretching) then
+ self:MostrarScrollBar()
+ end
+ self.need_rolagem = true
+
+ self.barraS[2] = cabe --> B é o total que cabe na barra
+ else --> Do contrário B é o total de barras
+ self.barrasInfo.mostrando = x
+ self.barraS[2] = x
+ end
+ else
+ if (x > self.barrasInfo.mostrando) then --> tem mais barras mostrando agora do que na última atualização
+ self.barrasInfo.mostrando = x
+ local nao_mostradas = self.barrasInfo.mostrando - self.barrasInfo.cabem
+ local slider_height = nao_mostradas*self.barrasInfo.alturaReal
+ self.scroll.scrollMax = slider_height
+ self.scroll:SetMinMaxValues (0, slider_height)
+
+ else --> diminuiu a quantidade, acontece depois de uma coleta de lixo
+ self.barrasInfo.mostrando = x
+ local nao_mostradas = self.barrasInfo.mostrando - self.barrasInfo.cabem
+
+ if (nao_mostradas < 1) then --> se estiver mostrando menos do que realmente cabe não precisa scrollbar
+ self:EsconderScrollBar()
+ else
+ --> contrário, basta atualizar o tamanho da scroll
+ local slider_height = nao_mostradas*self.barrasInfo.alturaReal
+ self.scroll.scrollMax = slider_height
+ self.scroll:SetMinMaxValues (0, slider_height)
+ end
+
+ end
+ end
+
+ if (self.update) then
+ self.update = false
+ self.v_barras = true
+ return _detalhes:EsconderBarrasNaoUsadas (self)
+ end
+end
+
+--> self é a janela das barras
+local function move_barras (self, elapsed)
+ self._move_func.time = self._move_func.time+elapsed
+ if (self._move_func.time > 0.01) then
+ if (self._move_func.instancia.bgdisplay_loc == self._move_func._end) then --> se o tamanho atual é igual ao final declarado
+ self:SetScript ("OnUpdate", nil)
+ self._move_func = nil
+ else
+ self._move_func.time = 0
+ self._move_func.instancia.bgdisplay_loc = self._move_func.instancia.bgdisplay_loc + self._move_func.inc --> inc é -1 ou 1 e irá crescer ou diminuir a janela
+
+ for index = 1, self._move_func.instancia.barrasInfo.cabem do
+ self._move_func.instancia.barras [index]:SetWidth (self:GetWidth()+self._move_func.instancia.bgdisplay_loc-3)
+ end
+ self._move_func.instancia.bgdisplay:SetPoint ("BOTTOMRIGHT", self, "BOTTOMRIGHT", self._move_func.instancia.bgdisplay_loc, 0)
+
+ self._move_func.instancia.bar_mod = self._move_func.instancia.bgdisplay_loc+(-3)
+
+ --> verifica o tamanho do text
+ for i = 1, #self._move_func.instancia.barras do
+ local esta_barra = self._move_func.instancia.barras [i]
+ _detalhes:name_space (esta_barra)
+ end
+ end
+ end
+end
+
+--> self é a instância
+function _detalhes:MoveBarrasTo (destino)
+ local janela = self.baseframe
+
+ janela._move_func = {
+ window = self.baseframe,
+ instancia = self,
+ time = 0
+ }
+
+ if (destino > self.bgdisplay_loc) then
+ janela._move_func.inc = 1
+ else
+ janela._move_func.inc = -1
+ end
+ janela._move_func._end = destino
+ janela:SetScript ("OnUpdate", move_barras)
+end
+
+function _detalhes:MostrarScrollBar (sem_animacao)
+
+ if (self.rolagem) then
+ return
+ end
+
+ if (not _detalhes.use_scroll) then
+ self.baseframe:EnableMouseWheel (true)
+ self.scroll:Enable()
+ self.scroll:SetValue (0)
+ self.rolagem = true
+ return
+ end
+
+ local main = self.baseframe
+ local mover_para = self.largura_scroll*-1
+
+ if (not sem_animacao and _detalhes.animate_scroll) then
+ self:MoveBarrasTo (mover_para)
+ else
+ --> set size of rows
+ for index = 1, self.barrasInfo.cabem do
+ self.barras [index]:SetWidth (self.baseframe:GetWidth()+mover_para -3) --> -3 distance between row end and scroll start
+ end
+ --> move the semi-background to the left (which moves the scroll)
+ self.bgdisplay:SetPoint ("BOTTOMRIGHT", self.baseframe, "BOTTOMRIGHT", mover_para, 0)
+
+ self.bar_mod = mover_para + (-3)
+ self.bgdisplay_loc = mover_para
+
+ --> cancel movement if any
+ if (self.baseframe:GetScript ("OnUpdate") and self.baseframe:GetScript ("OnUpdate") == move_barras) then
+ self.baseframe:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ local nao_mostradas = self.barrasInfo.mostrando - self.barrasInfo.cabem
+ local slider_height = nao_mostradas*self.barrasInfo.alturaReal
+ self.scroll.scrollMax = slider_height
+ self.scroll:SetMinMaxValues (0, slider_height)
+
+ self.rolagem = true
+ self.scroll:Enable()
+ main:EnableMouseWheel (true)
+
+ self.scroll:SetValue (0) --> set value pode chamar o atualizador
+ self.baseframe.button_down:Enable()
+ main.resize_direita:SetPoint ("BOTTOMRIGHT", main, "BOTTOMRIGHT", self.largura_scroll*-1, 0)
+
+ if (main.isLocked) then
+ main.lock_button:SetPoint ("BOTTOMRIGHT", main, "BOTTOMRIGHT", self.largura_scroll*-1, 0)
+ end
+
+end
+
+function _detalhes:EsconderScrollBar (sem_animacao, force)
+
+ if (not self.rolagem) then
+ return
+ end
+
+ if (not _detalhes.use_scroll and not force) then
+ self.scroll:Disable()
+ self.baseframe:EnableMouseWheel (false)
+ self.rolagem = false
+ return
+ end
+
+ local main = self.baseframe
+
+ if (not sem_animacao and _detalhes.animate_scroll) then
+ self:MoveBarrasTo (self.barrasInfo.espaco.direita + 3) -->
+ else
+ for index = 1, self.barrasInfo.cabem do
+ self.barras [index]:SetWidth (self.baseframe:GetWidth() - 5) --> -5 space between row end and window right border
+ end
+ self.bgdisplay:SetPoint ("BOTTOMRIGHT", self.baseframe, "BOTTOMRIGHT", 0, 0) -- voltar o background na pocição inicial
+ self.bar_mod = 0 -- zera o bar mod, uma vez que as barras vão estar na pocisão inicial
+ self.bgdisplay_loc = -2
+ if (self.baseframe:GetScript ("OnUpdate") and self.baseframe:GetScript ("OnUpdate") == move_barras) then
+ self.baseframe:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ self.rolagem = false
+ self.scroll:Disable()
+ main:EnableMouseWheel (false)
+
+ main.resize_direita:SetPoint ("BOTTOMRIGHT", main, "BOTTOMRIGHT", 0, 0)
+ if (main.isLocked) then
+ main.lock_button:SetPoint ("BOTTOMRIGHT", main, "BOTTOMRIGHT", 0, 0)
+ end
+end
+
+local function resize_fade (instancia, modo)
+ if (instancia.modo ~= _detalhes._detalhes_props["MODO_ALONE"] and not instancia.baseframe.isLocked) then
+ gump:Fade (instancia.baseframe.resize_direita, modo, 1.0)
+ gump:Fade (instancia.baseframe.resize_esquerda, modo, 1.0)
+ gump:Fade (instancia.baseframe.lock_button, modo, 1.0)
+
+ if (_string_lower (modo) == "out") then
+ for _, instancia_id in _pairs (instancia.snap) do
+ if (instancia_id) then
+ gump:Fade (instancia.botao_separar, modo, 1.0)
+ break
+ end
+ end
+ else
+ gump:Fade (instancia.botao_separar, "in", 1.0)
+ end
+
+ end
+end
+
+local function VPL (instancia, esta_instancia)
+ --> conferir esquerda
+ if (instancia.ponto4.x < esta_instancia.ponto1.x) then --> a janela esta a esquerda
+ if (instancia.ponto4.x+20 > esta_instancia.ponto1.x) then --> a janela esta a menos de 20 pixels de distância
+ if (instancia.ponto4.y < esta_instancia.ponto1.y + 20 and instancia.ponto4.y > esta_instancia.ponto1.y - 20) then --> a janela esta a +20 ou -20 pixels de distância na vertical
+ return 1
+ end
+ end
+ end
+ return nil
+end
+
+local function VPB (instancia, esta_instancia)
+ --> conferir baixo
+ if (instancia.ponto1.y+20 < esta_instancia.ponto2.y-16) then --> a janela esta em baixo
+ if (instancia.ponto1.x > esta_instancia.ponto2.x-20 and instancia.ponto1.x < esta_instancia.ponto2.x+20) then --> a janela esta a 20 pixels de distância para a esquerda ou para a direita
+ if (instancia.ponto1.y+20 > esta_instancia.ponto2.y-16-20) then --> esta a 20 pixels de distância
+ return 2
+ end
+ end
+ end
+ return nil
+end
+
+local function VPR (instancia, esta_instancia)
+ --> conferir lateral direita
+ if (instancia.ponto2.x > esta_instancia.ponto3.x) then --> a janela esta a direita
+ if (instancia.ponto2.x-20 < esta_instancia.ponto3.x) then --> a janela esta a menos de 20 pixels de distância
+ if (instancia.ponto2.y < esta_instancia.ponto3.y + 20 and instancia.ponto2.y > esta_instancia.ponto3.y - 20) then --> a janela esta a +20 ou -20 pixels de distância na vertical
+ return 3
+ end
+ end
+ end
+ return nil
+end
+
+local function VPT (instancia, esta_instancia)
+ --> conferir cima
+ if (instancia.ponto3.y-16 > esta_instancia.ponto4.y+20) then --> a janela esta em cima
+ if (instancia.ponto3.x > esta_instancia.ponto4.x-20 and instancia.ponto3.x < esta_instancia.ponto4.x+20) then --> a janela esta a 20 pixels de distância para a esquerda ou para a direita
+ if (esta_instancia.ponto4.y+20+20 > instancia.ponto3.y-16) then
+ return 4
+ end
+ end
+ end
+ return nil
+end
+
+local function move_janela (BaseFrame, iniciando, instancia)
+
+ local instancia_alvo = _detalhes.tabela_instancias [instancia.meu_id-1]
+
+ if (iniciando) then
+
+ BaseFrame.isMoving = true
+ instancia:BaseFrameSnap()
+ BaseFrame:StartMoving()
+
+ local _, ClampLeft, ClampRight = instancia:InstanciasHorizontais()
+ local _, ClampBottom, ClampTop = instancia:InstanciasVerticais()
+
+ if (ClampTop == 0) then
+ ClampTop = 33
+ end
+ if (ClampBottom == 0) then
+ ClampBottom = 13
+ end
+
+ BaseFrame:SetClampRectInsets (-ClampLeft-8, ClampRight, ClampTop, -ClampBottom)
+
+ if (instancia_alvo) then
+
+ local tempo_fades = 1.0
+ local nao_anexados = {true, true, true, true}
+
+ for lado, snap_to in _pairs (instancia_alvo.snap) do
+ if (snap_to) then
+ if (snap_to == instancia.meu_id) then
+ tempo_fades = nil
+ break
+ end
+ nao_anexados [lado] = false
+ end
+ end
+
+ for lado = 1, 4 do
+ if (instancia_alvo.horizontalSnap and instancia.verticalSnap) then
+ nao_anexados [lado] = false
+ elseif (instancia_alvo.horizontalSnap and lado == 2) then
+ nao_anexados [lado] = false
+ elseif (instancia_alvo.horizontalSnap and lado == 4) then
+ nao_anexados [lado] = false
+ elseif (instancia_alvo.verticalSnap and lado == 1) then
+ nao_anexados [lado] = false
+ elseif (instancia_alvo.verticalSnap and lado == 3) then
+ nao_anexados [lado] = false
+ end
+ end
+
+ local tempo_movendo = 1
+
+ local need_start = not instancia_alvo.iniciada
+ local need_activation = not instancia_alvo.ativa
+
+ if (need_start) then --> se a instância não tiver sido aberta ainda
+
+ instancia_alvo:RestauraJanela (instancia_alvo.meu_id, true) --> problema do solo era aqui
+ if (instancia_alvo:IsSoloMode()) then
+ _detalhes.SoloTables:switch()
+ end
+ instancia_alvo.ativa = false --> isso não ta legal
+ instancia_alvo:SaveMainWindowPosition()
+ instancia_alvo:RestoreMainWindowPosition()
+ gump:Fade (instancia_alvo.baseframe, 1)
+ gump:Fade (instancia_alvo.baseframe.cabecalho.ball, 1)
+ gump:Fade (instancia_alvo.baseframe.cabecalho.atributo_icon, 1)
+ need_start = false
+ end
+
+ BaseFrame:SetScript ("OnUpdate", function (self, elapsed)
+
+ if (tempo_movendo and tempo_movendo < 0) then
+
+ if (need_activation) then --> se a instância estiver fechada
+ gump:Fade (instancia_alvo.baseframe, "ALPHA", 0.2)
+ gump:Fade (instancia_alvo.baseframe.cabecalho.ball, "ALPHA", 0.2)
+ gump:Fade (instancia_alvo.baseframe.cabecalho.atributo_icon, "ALPHA", 0.2)
+ instancia_alvo:SaveMainWindowPosition()
+ instancia_alvo:RestoreMainWindowPosition()
+ need_activation = false
+
+ elseif (tempo_fades) then
+ for lado, livre in _ipairs (nao_anexados) do
+ if (livre) then
+ if (lado == 1) then
+ instancia_alvo.h_esquerda:Show()
+ UIFrameFlash (instancia_alvo.h_esquerda, tempo_fades, tempo_fades, 2.0, false, 0, 0)
+ elseif (lado == 2) then
+ instancia_alvo.h_baixo:Show()
+ UIFrameFlash (instancia_alvo.h_baixo, tempo_fades, tempo_fades, 2.0, false, 0, 0)
+ elseif (lado == 3) then
+ instancia_alvo.h_direita:Show()
+ UIFrameFlash (instancia_alvo.h_direita, tempo_fades, tempo_fades, 2.0, false, 0, 0)
+ elseif (lado == 4) then
+ instancia_alvo.h_cima:Show()
+ UIFrameFlash (instancia_alvo.h_cima, tempo_fades, tempo_fades, 2.0, false, 0, 0)
+ end
+ end
+ end
+
+ tempo_movendo = 1
+ else
+ BaseFrame:SetScript ("OnUpdate", nil)
+ tempo_movendo = 1
+ end
+
+ else
+ tempo_movendo = tempo_movendo - elapsed
+ end
+ end)
+ end
+
+ else
+
+ BaseFrame:StopMovingOrSizing()
+ BaseFrame.isMoving = false
+ BaseFrame:SetScript ("OnUpdate", nil)
+
+ BaseFrame:SetClampRectInsets (unpack (_detalhes.window_clamp))
+
+ if (instancia_alvo) then
+ instancia:AtualizaPontos()
+
+ local esquerda, baixo, direita, cima
+ local meu_id = instancia.meu_id --> id da instância que esta sendo movida
+
+ local isVertical = instancia_alvo.verticalSnap
+ local isHorizontal = instancia_alvo.horizontalSnap
+
+ local isSelfVertical = instancia.verticalSnap
+ local isSelfHorizontal = instancia.horizontalSnap
+
+ local _R, _T, _L, _B
+
+ if (isVertical and not isSelfHorizontal) then
+ _T, _B = VPB (instancia, instancia_alvo), VPT (instancia, instancia_alvo)
+ elseif (isHorizontal and not isSelfVertical) then
+ _R, _L = VPL (instancia, instancia_alvo), VPR (instancia, instancia_alvo)
+ elseif (not isVertical and not isHorizontal) then
+ _R, _T, _L, _B = VPL (instancia, instancia_alvo), VPB (instancia, instancia_alvo), VPR (instancia, instancia_alvo), VPT (instancia, instancia_alvo)
+ end
+
+ if (_L) then
+ if (not instancia:EstaAgrupada (instancia_alvo, _L)) then
+ esquerda = instancia_alvo.meu_id
+ instancia.horizontalSnap = true
+ instancia_alvo.horizontalSnap = true
+ end
+ end
+
+ if (_B) then
+ if (not instancia:EstaAgrupada (instancia_alvo, _B)) then
+ baixo = instancia_alvo.meu_id
+ instancia.verticalSnap = true
+ instancia_alvo.verticalSnap = true
+ end
+ end
+
+ if (_R) then
+ if (not instancia:EstaAgrupada (instancia_alvo, _R)) then
+ direita = instancia_alvo.meu_id
+ instancia.horizontalSnap = true
+ instancia_alvo.horizontalSnap = true
+ end
+ end
+
+ if (_T) then
+ if (not instancia:EstaAgrupada (instancia_alvo, _T)) then
+ cima = instancia_alvo.meu_id
+ instancia.verticalSnap = true
+ instancia_alvo.verticalSnap = true
+ end
+ end
+
+ if (esquerda or baixo or direita or cima) then
+ instancia:agrupar_janelas ({esquerda, baixo, direita, cima})
+ end
+
+ for _, esta_instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (not esta_instancia:IsAtiva() and esta_instancia.iniciada) then
+ esta_instancia:ResetaGump()
+ gump:Fade (esta_instancia.baseframe, "in", 0.2)
+ gump:Fade (esta_instancia.baseframe.cabecalho.ball, "in", 0.2)
+ gump:Fade (esta_instancia.baseframe.cabecalho.atributo_icon, "in", 0.2)
+
+ if (esta_instancia.modo == modo_raid) then
+ _detalhes.raid = nil
+ elseif (esta_instancia.modo == modo_alone) then
+ _detalhes.SoloTables:switch()
+ _detalhes.solo = nil
+ end
+
+ elseif (esta_instancia:IsAtiva()) then
+ esta_instancia:SaveMainWindowPosition()
+ esta_instancia:RestoreMainWindowPosition()
+ end
+ end
+ end
+ end
+end
+
+local function BGFrame_scripts (BG, BaseFrame, instancia)
+
+ BG:SetScript("OnEnter", function(self)
+ resize_fade (instancia, "out")
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+ end)
+
+ BG:SetScript("OnLeave", function(self)
+ resize_fade (instancia, "in")
+ gump:Fade (BaseFrame.button_stretch, -1)
+ end)
+
+ BG:SetScript ("OnMouseDown", function (frame, button)
+ if (BaseFrame.isMoving) then
+ move_janela (BaseFrame, false, instancia)
+ instancia:SaveMainWindowPosition()
+ return
+ end
+
+ if (not BaseFrame.isLocked and button == "LeftButton") then
+ move_janela (BaseFrame, true, instancia) --> novo movedor da janela
+ elseif (button == "RightButton") then
+ _detalhes.switch:ShowMe (instancia)
+ end
+ end)
+
+ BG:SetScript ("OnMouseUp", function (frame)
+ if (BaseFrame.isMoving) then
+ move_janela (BaseFrame, false, instancia) --> novo movedor da janela
+ instancia:SaveMainWindowPosition()
+ end
+ end)
+end
+
+function gump:RegisterForDetailsMove (frame, instancia)
+
+ frame:SetScript ("OnMouseDown", function (frame, button)
+ if (not instancia.baseframe.isLocked and button == "LeftButton") then
+ move_janela (instancia.baseframe, true, instancia) --> novo movedor da janela
+ end
+ end)
+
+ frame:SetScript ("OnMouseUp", function (frame)
+ if (instancia.baseframe.isMoving) then
+ move_janela (instancia.baseframe, false, instancia) --> novo movedor da janela
+ instancia:SaveMainWindowPosition()
+ end
+ end)
+end
+
+--> scripts do base frame
+local function BFrame_scripts (BaseFrame, instancia)
+
+ BaseFrame:SetScript("OnSizeChanged", function(self)
+ instancia:SaveMainWindowPosition()
+ instancia:ReajustaGump()
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, instancia)
+ end)
+
+ BaseFrame:SetScript("OnEnter", function(self)
+ resize_fade (instancia, "out")
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+ end)
+
+ BaseFrame:SetScript("OnLeave", function(self)
+ resize_fade (instancia, "in")
+ gump:Fade (BaseFrame.button_stretch, -1)
+ end)
+
+ BaseFrame:SetScript ("OnMouseDown", function (frame, button)
+ if (not BaseFrame.isLocked and button == "LeftButton") then
+ move_janela (BaseFrame, true, instancia) --> novo movedor da janela
+ end
+ end)
+
+ BaseFrame:SetScript ("OnMouseUp", function (frame)
+ if (BaseFrame.isMoving) then
+ move_janela (BaseFrame, false, instancia) --> novo movedor da janela
+ instancia:SaveMainWindowPosition()
+ end
+ end)
+
+end
+
+local function BackGroundDisplay_scripts (BackGroundDisplay, BaseFrame, instancia)
+
+ BackGroundDisplay:SetScript ("OnEnter", function(self)
+ resize_fade (instancia, "out")
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+ end)
+
+ BackGroundDisplay:SetScript ("OnLeave", function(self)
+ resize_fade (instancia, "in")
+ gump:Fade (BaseFrame.button_stretch, -1)
+ end)
+end
+
+local function instancias_horizontais (instancia, largura, esquerda, direita)
+ if (esquerda) then
+ for lado, esta_instancia in _pairs (instancia.snap) do
+ if (lado == 1) then --> movendo para esquerda
+ local instancia = _detalhes.tabela_instancias [esta_instancia]
+ instancia.baseframe:SetWidth (largura)
+ instancia.auto_resize = true
+ instancia:ReajustaGump()
+ instancia.auto_resize = false
+ instancias_horizontais (instancia, largura, true, false)
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, instancia)
+ end
+ end
+ end
+
+ if (direita) then
+ for lado, esta_instancia in _pairs (instancia.snap) do
+ if (lado == 3) then --> movendo para esquerda
+ local instancia = _detalhes.tabela_instancias [esta_instancia]
+ instancia.baseframe:SetWidth (largura)
+ instancia.auto_resize = true
+ instancia:ReajustaGump()
+ instancia.auto_resize = false
+ instancias_horizontais (instancia, largura, false, true)
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, instancia)
+ end
+ end
+ end
+end
+
+local function instancias_verticais (instancia, altura, esquerda, direita)
+ if (esquerda) then
+ for lado, esta_instancia in _pairs (instancia.snap) do
+ if (lado == 1) then --> movendo para esquerda
+ local instancia = _detalhes.tabela_instancias [esta_instancia]
+ instancia.baseframe:SetHeight (altura)
+ instancia.auto_resize = true
+ instancia:ReajustaGump()
+ instancia.auto_resize = false
+ instancias_verticais (instancia, altura, true, false)
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, instancia)
+ end
+ end
+ end
+
+ if (direita) then
+ for lado, esta_instancia in _pairs (instancia.snap) do
+ if (lado == 3) then --> movendo para esquerda
+ local instancia = _detalhes.tabela_instancias [esta_instancia]
+ instancia.baseframe:SetHeight (altura)
+ instancia.auto_resize = true
+ instancia:ReajustaGump()
+ instancia.auto_resize = false
+ instancias_verticais (instancia, altura, false, true)
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, instancia)
+ end
+ end
+ end
+end
+
+function _detalhes:InstanciasVerticais (instancia)
+
+ instancia = self or instancia
+
+ local linha_vertical, baixo, cima = {}, 0, 0
+
+ local checking = instancia
+ local first = true
+
+ local check_index_anterior = _detalhes.tabela_instancias [instancia.meu_id-1]
+ if (check_index_anterior) then --> possiu uma instância antes de mim
+ if (check_index_anterior.snap[4] and check_index_anterior.snap[4] == instancia.meu_id) then --> o index negativo vai para baixo
+ for i = instancia.meu_id-1, 1, -1 do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if (esta_instancia.snap[4] and esta_instancia.snap [4] == checking.meu_id) then
+ linha_vertical [#linha_vertical+1] = esta_instancia
+ if (first) then
+ baixo = baixo + esta_instancia.baseframe:GetHeight()+48
+ first = false
+ else
+ baixo = baixo + esta_instancia.baseframe:GetHeight()+34
+ end
+ checking = esta_instancia
+ else
+ break
+ end
+ end
+ elseif (check_index_anterior.snap[2] and check_index_anterior.snap[2] == instancia.meu_id) then --> o index negativo vai para cima
+ for i = instancia.meu_id-1, 1, -1 do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if (esta_instancia.snap[2] and esta_instancia.snap[2] == checking.meu_id) then
+ linha_vertical [#linha_vertical+1] = esta_instancia
+ if (first) then
+ cima = cima + esta_instancia.baseframe:GetHeight() + 64
+ first = false
+ else
+ cima = cima + esta_instancia.baseframe:GetHeight() + 34
+ end
+ checking = esta_instancia
+ else
+ break
+ end
+ end
+ end
+ end
+
+ checking = instancia
+ first = true
+
+ local check_index_posterior = _detalhes.tabela_instancias [instancia.meu_id+1]
+ if (check_index_posterior) then
+ if (check_index_posterior.snap[4] and check_index_posterior.snap[4] == instancia.meu_id) then --> o index posterior vai para a esquerda
+ for i = instancia.meu_id+1, #_detalhes.tabela_instancias do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if (esta_instancia.snap[4] and esta_instancia.snap[4] == checking.meu_id) then
+ linha_vertical [#linha_vertical+1] = esta_instancia
+ if (first) then
+ baixo = baixo + esta_instancia.baseframe:GetHeight()+48
+ first = true
+ else
+ baixo = baixo + esta_instancia.baseframe:GetHeight()+34
+ end
+ checking = esta_instancia
+ else
+ break
+ end
+ end
+ elseif (check_index_posterior.snap[2] and check_index_posterior.snap[2] == instancia.meu_id) then --> o index posterior vai para a direita
+ for i = instancia.meu_id+1, #_detalhes.tabela_instancias do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if (esta_instancia.snap[2] and esta_instancia.snap[2] == checking.meu_id) then
+ linha_vertical [#linha_vertical+1] = esta_instancia
+ if (first) then
+ cima = cima + esta_instancia.baseframe:GetHeight() + 64
+ first = false
+ else
+ cima = cima + esta_instancia.baseframe:GetHeight() + 34
+ end
+ checking = esta_instancia
+ else
+ break
+ end
+ end
+ end
+ end
+
+
+
+ return linha_vertical, baixo, cima
+
+end
+
+--[[
+ lado 4
+ -----------------------------------------
+ | |
+lado 1 | | lado 3
+ | |
+ | |
+ -----------------------------------------
+ lado 2
+--]]
+
+function _detalhes:InstanciasHorizontais (instancia)
+
+ instancia = self or instancia
+
+ local linha_horizontal, esquerda, direita = {}, 0, 0
+
+ local top, bottom = 0, 0
+
+ local checking = instancia
+
+ local check_index_anterior = _detalhes.tabela_instancias [instancia.meu_id-1]
+ if (check_index_anterior) then --> possiu uma instância antes de mim
+ if (check_index_anterior.snap[3] and check_index_anterior.snap[3] == instancia.meu_id) then --> o index negativo vai para a esquerda
+ for i = instancia.meu_id-1, 1, -1 do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if (esta_instancia.snap[3]) then
+ if (esta_instancia.snap[3] == checking.meu_id) then
+ linha_horizontal [#linha_horizontal+1] = esta_instancia
+ esquerda = esquerda + esta_instancia.baseframe:GetWidth()
+ checking = esta_instancia
+ end
+ else
+ break
+ end
+ end
+ elseif (check_index_anterior.snap[1] and check_index_anterior.snap[1] == instancia.meu_id) then --> o index negativo vai para a direita
+ for i = instancia.meu_id-1, 1, -1 do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if (esta_instancia.snap[1]) then
+ if (esta_instancia.snap[1] == checking.meu_id) then
+ linha_horizontal [#linha_horizontal+1] = esta_instancia
+ direita = direita + esta_instancia.baseframe:GetWidth()
+ checking = esta_instancia
+ end
+ else
+ break
+ end
+ end
+ end
+ end
+
+ checking = instancia
+
+ local check_index_posterior = _detalhes.tabela_instancias [instancia.meu_id+1]
+ if (check_index_posterior) then
+ if (check_index_posterior.snap[3] and check_index_posterior.snap[3] == instancia.meu_id) then --> o index posterior vai para a esquerda
+ for i = instancia.meu_id+1, #_detalhes.tabela_instancias do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if (esta_instancia.snap[3]) then
+ if (esta_instancia.snap[3] == checking.meu_id) then
+ linha_horizontal [#linha_horizontal+1] = esta_instancia
+ esquerda = esquerda + esta_instancia.baseframe:GetWidth()
+ checking = esta_instancia
+ end
+ else
+ break
+ end
+ end
+ elseif (check_index_posterior.snap[1] and check_index_posterior.snap[1] == instancia.meu_id) then --> o index posterior vai para a direita
+ for i = instancia.meu_id+1, #_detalhes.tabela_instancias do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if (esta_instancia.snap[1]) then
+ if (esta_instancia.snap[1] == checking.meu_id) then
+ linha_horizontal [#linha_horizontal+1] = esta_instancia
+ direita = direita + esta_instancia.baseframe:GetWidth()
+ checking = esta_instancia
+ end
+ else
+ break
+ end
+ end
+ end
+ end
+
+ return linha_horizontal, esquerda, direita, bottom, top
+
+end
+
+local resizeTooltip = {
+ {text = "|cff33CC00Click|cffEEEEEE: ".. Loc ["STRING_RESIZE_COMMON"]},
+
+ {text = "+|cff33CC00 Click|cffEEEEEE: " .. Loc ["STRING_RESIZE_HORIZONTAL"]},
+ {icon = "Interface\\AddOns\\Details\\images\\key_shift", width = 24, height = 14, l = 0, r = 1, t = 0, b =0.640625},
+
+ {text = "+|cff33CC00 Click|cffEEEEEE: " .. Loc ["STRING_RESIZE_VERTICAL"]},
+ {icon = "Interface\\AddOns\\Details\\images\\key_alt", width = 24, height = 14, l = 0, r = 1, t = 0, b =0.640625},
+
+ {text = "+|cff33CC00 Click|cffEEEEEE: " .. Loc ["STRING_RESIZE_ALL"]},
+ {icon = "Interface\\AddOns\\Details\\images\\key_ctrl", width = 24, height = 14, l = 0, r = 1, t = 0, b =0.640625}
+}
+
+--> search key: ~resizescript
+local function resize_scripts (resizer, instancia, ScrollBar, side)
+
+ resizer:SetScript ("OnMouseDown", function (self, button)
+
+ _detalhes.popup:ShowMe (false) --> Hide Cooltip
+
+ if (not self:GetParent().isLocked and button == "LeftButton" and instancia.modo ~= _detalhes._detalhes_props["MODO_ALONE"]) then
+ self:GetParent().isResizing = true
+ instancia:BaseFrameSnap()
+
+ local isVertical = instancia.verticalSnap
+ local isHorizontal = instancia.horizontalSnap
+
+ local agrupadas
+ if (instancia.verticalSnap) then
+ agrupadas = instancia:InstanciasVerticais()
+ elseif (instancia.horizontalSnap) then
+ agrupadas = instancia:InstanciasHorizontais()
+ end
+
+ instancia.stretchToo = agrupadas
+ if (instancia.stretchToo and #instancia.stretchToo > 0) then
+ for _, esta_instancia in ipairs (instancia.stretchToo) do
+ esta_instancia.baseframe._place = esta_instancia:SaveMainWindowPosition()
+ esta_instancia.baseframe.isResizing = true
+ end
+ end
+
+ ----------------
+
+ if (side == "<") then
+ if (_IsShiftKeyDown()) then
+ instancia.baseframe:StartSizing("LEFT")
+ instancia.eh_horizontal = true
+ elseif (_IsAltKeyDown()) then
+ instancia.baseframe:StartSizing("TOP")
+ instancia.eh_vertical = true
+ elseif (_IsControlKeyDown()) then
+ instancia.baseframe:StartSizing("BOTTOMLEFT")
+ instancia.eh_tudo = true
+ else
+ instancia.baseframe:StartSizing("BOTTOMLEFT")
+ end
+
+ elseif (side == ">") then
+ if (_IsShiftKeyDown()) then
+ instancia.baseframe:StartSizing("RIGHT")
+ instancia.eh_horizontal = true
+ elseif (_IsAltKeyDown()) then
+ instancia.baseframe:StartSizing("TOP")
+ instancia.eh_vertical = true
+ elseif (_IsControlKeyDown()) then
+ instancia.baseframe:StartSizing("BOTTOMRIGHT")
+ instancia.eh_tudo = true
+ else
+ instancia.baseframe:StartSizing("BOTTOMRIGHT")
+ end
+
+ end
+
+ _detalhes:SendEvent ("DETAILS_INSTANCE_STARTRESIZE", nil, instancia)
+
+ end
+ end)
+
+ resizer:SetScript ("OnMouseUp", function (self,button)
+
+ if (self:GetParent().isResizing) then
+
+ self:GetParent():StopMovingOrSizing()
+ self:GetParent().isResizing = false
+
+ if (instancia.stretchToo and #instancia.stretchToo > 0) then
+ for _, esta_instancia in ipairs (instancia.stretchToo) do
+ esta_instancia.baseframe:StopMovingOrSizing()
+ esta_instancia.baseframe.isResizing = false
+ esta_instancia:ReajustaGump()
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, esta_instancia)
+ end
+ instancia.stretchToo = nil
+ end
+
+ local largura = instancia.baseframe:GetWidth()
+ local altura = instancia.baseframe:GetHeight()
+
+ if (instancia.eh_horizontal) then
+ instancias_horizontais (instancia, largura, true, true)
+ instancia.eh_horizontal = nil
+ end
+
+ --if (instancia.eh_vertical) then
+ instancias_verticais (instancia, altura, true, true)
+ instancia.eh_vertical = nil
+ --end
+
+ _detalhes:SendEvent ("DETAILS_INSTANCE_ENDRESIZE", nil, instancia)
+
+ if (instancia.eh_tudo) then
+ for _, esta_instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (esta_instancia:IsAtiva() and esta_instancia.modo ~= _detalhes._detalhes_props["MODO_ALONE"]) then
+ esta_instancia.baseframe:ClearAllPoints()
+ esta_instancia:SaveMainWindowPosition()
+ esta_instancia:RestoreMainWindowPosition()
+ end
+ end
+
+ for _, esta_instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (esta_instancia:IsAtiva() and esta_instancia ~= instancia and esta_instancia.modo ~= _detalhes._detalhes_props["MODO_ALONE"]) then
+ esta_instancia.baseframe:SetWidth (largura)
+ esta_instancia.baseframe:SetHeight (altura)
+ esta_instancia.auto_resize = true
+ esta_instancia:ReajustaGump()
+ esta_instancia.auto_resize = false
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, esta_instancia)
+ end
+ end
+
+ instancia.eh_tudo = nil
+ end
+
+ instancia:BaseFrameSnap()
+
+ for _, esta_instancia in _ipairs (_detalhes.tabela_instancias) do
+ if (esta_instancia:IsAtiva()) then
+ esta_instancia:SaveMainWindowPosition()
+ esta_instancia:RestoreMainWindowPosition()
+ end
+ end
+ end
+ end)
+
+ resizer:SetScript ("OnEnter", function(self)
+ if (instancia.modo ~= _detalhes._detalhes_props["MODO_ALONE"] and not instancia.baseframe.isLocked) then
+ gump:Fade (self, "out", 0.1)
+ self.mostrando = true
+
+ _G.GameCooltip:Reset()
+ _G.GameCooltip:SetType ("tooltip")
+ _G.GameCooltip:AddFromTable (resizeTooltip)
+ _G.GameCooltip:SetOption ("NoLastSelectedBar", true)
+ _G.GameCooltip:SetOwner (resizer)
+ _G.GameCooltip:ShowCooltip()
+
+ end
+ end)
+
+ resizer:SetScript ("OnLeave", function(self)
+ if (not self.movendo) then
+ gump:Fade (self, -1, 3.0)
+ end
+
+ _detalhes.popup:ShowMe (false)
+
+ self.mostrando = false
+ end)
+end
+
+
+local function lock_button_scripts (button, instancia)
+ button:SetScript ("OnEnter", function(self)
+ if (instancia.modo ~= _detalhes._detalhes_props["MODO_ALONE"]) then
+ gump:Fade (self, "out", 0.1)
+ self.label:SetTextColor (1, 1, 1, .6)
+ self.mostrando = true
+ end
+ end)
+
+ button:SetScript ("OnLeave", function(self)
+ gump:Fade (self, -1, 3.0)
+ self.label:SetTextColor (.3, .3, .3, .4)
+ self.mostrando = false
+ end)
+end
+
+local lockFunctionOnClick = function (button)
+ local BaseFrame = button:GetParent()
+ if (BaseFrame.isLocked) then
+ BaseFrame.isLocked = false
+ BaseFrame.instance.isLocked = false
+ button.label:SetText (Loc ["STRING_LOCK_WINDOW"])
+ button:SetWidth (button.label:GetStringWidth()+2)
+ gump:Fade (BaseFrame.resize_direita, 0)
+ gump:Fade (BaseFrame.resize_esquerda, 0)
+ button:ClearAllPoints()
+ button:SetPoint ("right", BaseFrame.resize_direita, "left", -1, 1.5)
+ else
+ BaseFrame.isLocked = true
+ BaseFrame.instance.isLocked = true
+ button.label:SetText (Loc ["STRING_UNLOCK_WINDOW"])
+ button:SetWidth (button.label:GetStringWidth()+2)
+ button:ClearAllPoints()
+ button:SetPoint ("bottomright", BaseFrame, "bottomright", -3, 0)
+ gump:Fade (BaseFrame.resize_direita, 1)
+ gump:Fade (BaseFrame.resize_esquerda, 1)
+ end
+end
+
+local function bota_separar_script (botao, instancia)
+ botao:SetScript ("OnEnter", function (self)
+ if (instancia.modo ~= _detalhes._detalhes_props["MODO_ALONE"]) then
+ gump:Fade (self, "out", 0.1)
+ self.mostrando = true
+ end
+ end)
+
+ botao:SetScript ("OnLeave", function (self)
+ if (not self.movendo) then
+ gump:Fade (self, "in", 3.0)
+ end
+ self.mostrando = false
+ end)
+end
+
+local function barra_scripts (esta_barra, instancia, i)
+ esta_barra:SetScript ("OnEnter", function (self)
+ self.mouse_over = true
+ resize_fade (instancia, "out")
+ gump:Fade (instancia.baseframe.button_stretch, "alpha", 0.3)
+
+ _GameTooltip:SetOwner (self, "ANCHOR_TOPRIGHT")
+ if (not instancia:MontaTooltip (i)) then
+ return
+ end
+
+ _GameTooltip:Show()
+ --
+ self:SetBackdrop({
+ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
+ tile = true, tileSize = 16,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ self:SetBackdropColor (0.588, 0.588, 0.588, 0.7)
+ end)
+
+ esta_barra:SetScript ("OnLeave", function(self)
+ self.mouse_over = false
+ resize_fade (instancia, "in")
+ gump:Fade (instancia.baseframe.button_stretch, -1)
+
+ _GameTooltip:Hide()
+ _detalhes.popup:ShowMe (false)
+
+ self:SetBackdrop({
+ bgFile = "", edgeFile = "", tile = true, tileSize = 16, edgeSize = 32,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+
+ self:SetBackdropBorderColor (0, 0, 0, 0)
+ self:SetBackdropColor (0, 0, 0, 0)
+ end)
+
+ esta_barra:SetScript ("OnMouseDown", function (self, button)
+
+ if (esta_barra.fading_in) then
+ return
+ end
+
+ --if (button == "leftButton") then
+ self.mouse_down = _GetTime()
+ self.button = button
+ local x, y = _GetCursorPosition()
+ self.x = _math_floor (x)
+ self.y = _math_floor (y)
+
+ local parent = instancia.baseframe
+ if ((not parent.isLocked) or (parent.isLocked == 0)) then
+ _GameTooltip:Hide() --> fecha o tooltip
+ move_janela (parent, true, instancia) --> novo movedor da janela
+ end
+
+ --end
+
+ end)
+
+ esta_barra:SetScript ("OnMouseUp", function (self, button)
+
+ local parent = instancia.baseframe
+ if (parent.isMoving) then
+
+ move_janela (parent, false, instancia) --> novo movedor da janela
+ instancia:SaveMainWindowPosition()
+ _GameTooltip:SetOwner (self, "ANCHOR_TOPRIGHT")
+ if (instancia:MontaTooltip (i)) then
+ _GameTooltip:Show()
+ end
+
+ end
+
+ local x, y = _GetCursorPosition()
+ x = _math_floor (x)
+ y = _math_floor (y)
+
+ if (self.mouse_down and (self.mouse_down+0.4 > _GetTime() and (x == self.x and y == self.y)) or (x == self.x and y == self.y)) then
+ --> a única maneira de abrir a janela de info é por aqui...
+
+ if (self.button == "LeftButton") then
+ if (instancia.atributo == 5 or _IsShiftKeyDown()) then
+ --> report
+ return _detalhes:ReportSingleLine (instancia, self)
+ end
+ instancia:AbreJanelaInfo (self.minha_tabela)
+ else
+ _detalhes.switch:ShowMe (instancia)
+ end
+
+ end
+ end)
+
+ esta_barra:SetScript ("OnClick", function(self, button)
+
+ end)
+end
+
+function _detalhes:ReportSingleLine (instancia, barra)
+
+ local reportar
+ if (instancia.atributo == 5) then --> custom
+ reportar = {"Details! " .. Loc ["STRING_CUSTOM_REPORT"] .. " " ..instancia.customName}
+ else
+ reportar = {"Details! " .. Loc ["STRING_REPORT"] .. " " .. _detalhes.sub_atributos [instancia.atributo].lista [instancia.sub_atributo]}
+ end
+
+ reportar [#reportar+1] = barra.texto_esquerdo:GetText().." "..barra.texto_direita:GetText()
+
+ return _detalhes:Reportar (reportar, {_no_current = true, _no_inverse = true, _custom = true})
+end
+
+local function button_stretch_scripts (BaseFrame, BackGroundDisplay, instancia)
+ local button = BaseFrame.button_stretch
+
+ button:SetScript ("OnEnter", function (self)
+ self.mouse_over = true
+ gump:Fade (self, "out")
+ end)
+ button:SetScript ("OnLeave", function (self)
+ self.mouse_over = false
+ gump:Fade (self, -1)
+ end)
+
+ button:SetScript ("OnMouseDown", function(self)
+
+ if (instancia:IsSoloMode()) then
+ return
+ end
+
+ instancia:EsconderScrollBar (true)
+ BaseFrame._place = instancia:SaveMainWindowPosition()
+ BaseFrame.isResizing = true
+ BaseFrame.isStretching = true
+ BaseFrame:SetFrameStrata ("TOOLTIP")
+
+ local _r, _g, _b, _a = BaseFrame:GetBackdropColor()
+ gump:GradientEffect ( BaseFrame, "frame", _r, _g, _b, _a, _r, _g, _b, 0.9, 1.5)
+ if (instancia.wallpaper.enabled) then
+ _r, _g, _b = BaseFrame.wallpaper:GetVertexColor()
+ _a = BaseFrame.wallpaper:GetAlpha()
+ gump:GradientEffect (BaseFrame.wallpaper, "texture", _r, _g, _b, _a, _r, _g, _b, 0.05, 0.5)
+ end
+
+ BaseFrame:StartSizing ("TOP")
+
+ local linha_horizontal = {}
+
+ local checking = instancia
+ for i = instancia.meu_id-1, 1, -1 do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if ((esta_instancia.snap[1] and esta_instancia.snap[1] == checking.meu_id) or (esta_instancia.snap[3] and esta_instancia.snap[3] == checking.meu_id)) then
+ linha_horizontal [#linha_horizontal+1] = esta_instancia
+ checking = esta_instancia
+ else
+ break
+ end
+ end
+
+ checking = instancia
+ for i = instancia.meu_id+1, #_detalhes.tabela_instancias do
+ local esta_instancia = _detalhes.tabela_instancias [i]
+ if ((esta_instancia.snap[1] and esta_instancia.snap[1] == checking.meu_id) or (esta_instancia.snap[3] and esta_instancia.snap[3] == checking.meu_id)) then
+ linha_horizontal [#linha_horizontal+1] = esta_instancia
+ checking = esta_instancia
+ else
+ break
+ end
+ end
+
+ instancia.stretchToo = linha_horizontal
+ if (#instancia.stretchToo > 0) then
+ for _, esta_instancia in ipairs (instancia.stretchToo) do
+ esta_instancia:EsconderScrollBar (true)
+ esta_instancia.baseframe._place = esta_instancia:SaveMainWindowPosition()
+ esta_instancia.baseframe.isResizing = true
+ esta_instancia.baseframe.isStretching = true
+ esta_instancia.baseframe:SetFrameStrata ("TOOLTIP")
+
+ local _r, _g, _b, _a = esta_instancia.baseframe:GetBackdropColor()
+ gump:GradientEffect ( esta_instancia.baseframe, "frame", _r, _g, _b, _a, _r, _g, _b, 0.9, 1.5)
+ _detalhes:SendEvent ("DETAILS_INSTANCE_STARTSTRETCH", nil, esta_instancia)
+
+ if (esta_instancia.wallpaper.enabled) then
+ _r, _g, _b = esta_instancia.baseframe.wallpaper:GetVertexColor()
+ _a = esta_instancia.baseframe.wallpaper:GetAlpha()
+ gump:GradientEffect (esta_instancia.baseframe.wallpaper, "texture", _r, _g, _b, _a, _r, _g, _b, 0.05, 0.5)
+ end
+
+ end
+ end
+
+ _detalhes:SnapTextures (true)
+
+ _detalhes:SendEvent ("DETAILS_INSTANCE_STARTSTRETCH", nil, instancia)
+ end)
+
+ button:SetScript ("OnMouseUp", function(self)
+
+ if (instancia:IsSoloMode()) then
+ return
+ end
+
+ if (BaseFrame.isResizing) then
+ BaseFrame:StopMovingOrSizing()
+ BaseFrame.isResizing = false
+ instancia:RestoreMainWindowPosition (BaseFrame._place)
+ instancia:ReajustaGump()
+ BaseFrame.isStretching = false
+ if (instancia.need_rolagem) then
+ instancia:MostrarScrollBar (true)
+ end
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, instancia)
+
+ if (instancia.stretchToo and #instancia.stretchToo > 0) then
+ for _, esta_instancia in ipairs (instancia.stretchToo) do
+ esta_instancia.baseframe:StopMovingOrSizing()
+ esta_instancia.baseframe.isResizing = false
+ esta_instancia:RestoreMainWindowPosition (esta_instancia.baseframe._place)
+ esta_instancia:ReajustaGump()
+ esta_instancia.baseframe.isStretching = false
+ if (esta_instancia.need_rolagem) then
+ esta_instancia:MostrarScrollBar (true)
+ end
+ _detalhes:SendEvent ("DETAILS_INSTANCE_SIZECHANGED", nil, esta_instancia)
+
+ local _r, _g, _b, _a = esta_instancia.baseframe:GetBackdropColor()
+ gump:GradientEffect ( esta_instancia.baseframe, "frame", _r, _g, _b, _a, _detalhes.default_bg_color, _detalhes.default_bg_color, _detalhes.default_bg_color, _detalhes.default_bg_alpha, 0.5)
+
+ if (esta_instancia.wallpaper.enabled) then
+ _r, _g, _b = esta_instancia.baseframe.wallpaper:GetVertexColor()
+ _a = esta_instancia.baseframe.wallpaper:GetAlpha()
+ gump:GradientEffect (esta_instancia.baseframe.wallpaper, "texture", _r, _g, _b, _a, _r, _g, _b, esta_instancia.baseframe.wallpaper.alpha, 1.0)
+ end
+
+ esta_instancia.baseframe:SetFrameStrata ("LOW")
+ esta_instancia.baseframe.button_stretch:SetFrameStrata ("FULLSCREEN")
+ _detalhes:SendEvent ("DETAILS_INSTANCE_ENDSTRETCH", nil, esta_instancia.baseframe)
+ end
+ instancia.stretchToo = nil
+ end
+
+ end
+
+ local _r, _g, _b, _a = BaseFrame:GetBackdropColor()
+ gump:GradientEffect ( BaseFrame, "frame", _r, _g, _b, _a, _detalhes.default_bg_color, _detalhes.default_bg_color, _detalhes.default_bg_color, _detalhes.default_bg_alpha, 0.5)
+ if (instancia.wallpaper.enabled) then
+ _r, _g, _b = BaseFrame.wallpaper:GetVertexColor()
+ _a = BaseFrame.wallpaper:GetAlpha()
+ gump:GradientEffect (BaseFrame.wallpaper, "texture", _r, _g, _b, _a, _r, _g, _b, instancia.wallpaper.alpha, 1.0)
+ end
+
+ BaseFrame:SetFrameStrata ("LOW")
+ BaseFrame.button_stretch:SetFrameStrata ("FULLSCREEN")
+
+ _detalhes:SnapTextures (false)
+
+ _detalhes:SendEvent ("DETAILS_INSTANCE_ENDSTRETCH", nil, instancia)
+ end)
+end
+
+local function button_down_scripts (main_frame, BackGroundDisplay, instancia, ScrollBar)
+ main_frame.button_down:SetScript ("OnMouseDown", function(self)
+ if (not ScrollBar:IsEnabled()) then
+ return
+ end
+
+ local B = instancia.barraS[2]
+ if (B < instancia.barrasInfo.mostrando) then
+ ScrollBar:SetValue (ScrollBar:GetValue() + instancia.barrasInfo.alturaReal)
+ end
+
+ self.precionado = true
+ self.last_up = -0.3
+ self:SetScript ("OnUpdate", function(self, elapsed)
+ self.last_up = self.last_up + elapsed
+ if (self.last_up > 0.03) then
+ self.last_up = 0
+ B = instancia.barraS[2]
+ if (B < instancia.barrasInfo.mostrando) then
+ ScrollBar:SetValue (ScrollBar:GetValue() + instancia.barrasInfo.alturaReal)
+ else
+ self:Disable()
+ end
+ end
+ end)
+ end)
+
+ main_frame.button_down:SetScript ("OnMouseUp", function(self)
+ self.precionado = false
+ self:SetScript ("OnUpdate", nil)
+ end)
+end
+
+local function button_up_scripts (main_frame, BackGroundDisplay, instancia, ScrollBar)
+
+ main_frame.button_up:SetScript ("OnMouseDown", function(self)
+ if (not ScrollBar:IsEnabled()) then
+ return
+ end
+
+ local A = instancia.barraS[1]
+ if (A > 1) then
+ ScrollBar:SetValue (ScrollBar:GetValue() - instancia.barrasInfo.alturaReal)
+ end
+
+ self.precionado = true
+ self.last_up = -0.3
+ self:SetScript ("OnUpdate", function(self, elapsed)
+ self.last_up = self.last_up + elapsed
+ if (self.last_up > 0.03) then
+ self.last_up = 0
+ A = instancia.barraS[1]
+ if (A > 1) then
+ ScrollBar:SetValue (ScrollBar:GetValue() - instancia.barrasInfo.alturaReal)
+ else
+ self:Disable()
+ end
+ end
+ end)
+ end)
+
+ main_frame.button_up:SetScript ("OnMouseUp", function(self)
+ self.precionado = false
+ self:SetScript ("OnUpdate", nil)
+ end)
+
+ main_frame.button_up:SetScript ("OnEnable", function (self)
+ local current = ScrollBar:GetValue()
+ if (current == 0) then
+ main_frame.button_up:Disable()
+ end
+ end)
+end
+
+local function iterate_scroll_scripts (BackGroundDisplay, BackGroundFrame, BaseFrame, ScrollBar, instancia)
+
+ BaseFrame:SetScript ("OnMouseWheel",
+ function (self, delta)
+ if (delta > 0) then --> rolou pra cima
+ local A = instancia.barraS[1]
+ if (A > 1) then
+ ScrollBar:SetValue (ScrollBar:GetValue() - instancia.barrasInfo.alturaReal)
+ else
+ ScrollBar:SetValue (0)
+ ScrollBar.ultimo = 0
+ BaseFrame.button_up:Disable()
+ end
+ elseif (delta < 0) then --> rolou pra baixo
+ local B = instancia.barraS[2]
+ if (B < instancia.barrasInfo.mostrando) then
+ ScrollBar:SetValue (ScrollBar:GetValue() + instancia.barrasInfo.alturaReal)
+ else
+ local _, maxValue = ScrollBar:GetMinMaxValues()
+ ScrollBar:SetValue (maxValue)
+ ScrollBar.ultimo = maxValue
+ BaseFrame.button_down:Disable()
+ end
+ end
+
+ end)
+
+ ScrollBar:SetScript ("OnValueChanged", function(self)
+ local ultimo = self.ultimo
+ local meu_valor = self:GetValue()
+ if (ultimo == meu_valor) then --> não mudou
+ return
+ end
+
+ --> shortcut
+ local minValue, maxValue = ScrollBar:GetMinMaxValues()
+ if (minValue == meu_valor) then
+ instancia.barraS[1] = 1
+ instancia.barraS[2] = instancia.barrasInfo.cabem
+ instancia:AtualizaGumpPrincipal (instancia, true)
+ self.ultimo = meu_valor
+ BaseFrame.button_up:Disable()
+ return
+ elseif (maxValue == meu_valor) then
+ local min = instancia.barrasInfo.mostrando -instancia.barrasInfo.cabem
+ min = min+1
+ if (min < 1) then
+ min = 1
+ end
+ instancia.barraS[1] = min
+ instancia.barraS[2] = instancia.barrasInfo.mostrando
+ instancia:AtualizaGumpPrincipal (instancia, true)
+ self.ultimo = meu_valor
+ BaseFrame.button_down:Disable()
+ return
+ end
+
+ if (not BaseFrame.button_up:IsEnabled()) then
+ BaseFrame.button_up:Enable()
+ end
+ if (not BaseFrame.button_down:IsEnabled()) then
+ BaseFrame.button_down:Enable()
+ end
+
+ if (meu_valor > ultimo) then --> scroll down
+
+ local B = instancia.barraS[2]
+ if (B < instancia.barrasInfo.mostrando) then --> se o valor maximo não for o máximo de barras a serem mostradas
+ local precisa_passar = ((B+1) * instancia.barrasInfo.alturaReal) - (instancia.barrasInfo.alturaReal*instancia.barrasInfo.cabem)
+ if (meu_valor > precisa_passar) then --> o valor atual passou o valor que precisa passar pra locomover
+ local diff = meu_valor - ultimo --> pega a diferença de H
+ diff = diff / instancia.barrasInfo.alturaReal --> calcula quantas barras ele pulou
+ diff = _math_ceil (diff) --> arredonda para cima
+ if (instancia.barraS[2]+diff > instancia.barrasInfo.mostrando and ultimo > 0) then
+ instancia.barraS[1] = instancia.barrasInfo.mostrando - (instancia.barrasInfo.cabem-1)
+ instancia.barraS[2] = instancia.barrasInfo.mostrando
+ else
+ instancia.barraS[2] = instancia.barraS[2]+diff
+ instancia.barraS[1] = instancia.barraS[1]+diff
+ end
+ instancia:AtualizaGumpPrincipal (instancia, true)
+ end
+ end
+ else --> scroll up
+ local A = instancia.barraS[1]
+ if (A > 1) then
+ local precisa_passar = (A-1) * instancia.barrasInfo.alturaReal
+ if (meu_valor < precisa_passar) then
+ --> calcula quantas barras passou
+ local diff = ultimo - meu_valor
+ diff = diff / instancia.barrasInfo.alturaReal
+ diff = _math_ceil (diff)
+ if (instancia.barraS[1]-diff < 1) then
+ instancia.barraS[2] = instancia.barrasInfo.cabem
+ instancia.barraS[1] = 1
+ else
+ instancia.barraS[2] = instancia.barraS[2]-diff
+ instancia.barraS[1] = instancia.barraS[1]-diff
+ end
+
+ instancia:AtualizaGumpPrincipal (instancia, true)
+ end
+ end
+ end
+ self.ultimo = meu_valor
+ end)
+end
+
+--> inicio
+function gump:CriaJanelaPrincipal (ID, instancia, criando)
+
+ local BaseFrame = _CreateFrame ("ScrollFrame", "DetailsBaseFrame"..ID, _UIParent)
+ BaseFrame.instance = instancia
+ BaseFrame:SetFrameStrata ("LOW")
+ BaseFrame:SetFrameLevel (2)
+
+ local BackGroundFrame = _CreateFrame ("ScrollFrame", "Details_WindowFrame"..ID, BaseFrame) --> janela principal
+ local BackGroundDisplay = _CreateFrame ("Frame", "Details_GumpFrame"..ID, BackGroundFrame) --corpo
+ BackGroundFrame:SetFrameLevel (3)
+ BackGroundDisplay:SetFrameLevel (3)
+
+ local SwitchButton = gump:NewDetailsButton (BackGroundDisplay, BaseFrame, _, function() end, nil, nil, 1, 1, "", "", "", "",
+ {rightFunc = {func = function() _detalhes.switch:ShowMe (instancia) end, param1 = nil, param2 = nil}})
+
+ SwitchButton:SetPoint ("topleft", BackGroundDisplay, "topleft")
+ SwitchButton:SetPoint ("bottomright", BackGroundDisplay, "bottomright")
+ SwitchButton:SetFrameLevel (BackGroundDisplay:GetFrameLevel()+1)
+
+ local ScrollBar = _CreateFrame ("Slider", "Details_ScrollBar"..ID, BackGroundDisplay) --> scroll
+ --ScrollBar:SetFrameLevel (BaseFrame:GetFrameLevel()+5)
+
+-- textura da scroll bar
+-------------------------------------------------------------------------------------------------------------------------------------------------
+ --> scroll image-node up
+ BaseFrame.scroll_up = BackGroundDisplay:CreateTexture (nil, "BACKGROUND")
+ BaseFrame.scroll_up:SetPoint ("TOPLEFT", BackGroundDisplay, "TOPRIGHT", 0, 0)
+ --BaseFrame.scroll_up:SetTexture ("Interface\\AddOns\\Details\\images\\scroll_up")
+ BaseFrame.scroll_up:SetTexture ("Interface\\AddOns\\Details\\images\\scrollbar")
+ BaseFrame.scroll_up:SetWidth (32)
+ BaseFrame.scroll_up:SetHeight (32)
+ BaseFrame.scroll_up:SetTexCoord (0, 1, 0, 0.25)
+
+ --> scroll image-node down
+ BaseFrame.scroll_down = BackGroundDisplay:CreateTexture (nil, "BACKGROUND")
+ BaseFrame.scroll_down:SetPoint ("BOTTOMLEFT", BackGroundDisplay, "BOTTOMRIGHT", 0, 0)
+ BaseFrame.scroll_down:SetTexture ("Interface\\AddOns\\Details\\images\\scrollbar")
+ BaseFrame.scroll_down:SetWidth (32)
+ BaseFrame.scroll_down:SetHeight (32)
+ BaseFrame.scroll_down:SetTexCoord (0, 1, 0.751, 1)
+
+ --> scroll image-node middle
+ BaseFrame.scroll_middle = BackGroundDisplay:CreateTexture (nil, "BACKGROUND")
+ BaseFrame.scroll_middle:SetPoint ("TOP", BaseFrame.scroll_up, "BOTTOM", 0, 8)
+ BaseFrame.scroll_middle:SetPoint ("BOTTOM", BaseFrame.scroll_down, "TOP", 0, -11)
+ BaseFrame.scroll_middle:SetTexture ("Interface\\AddOns\\Details\\images\\scrollbar")
+ BaseFrame.scroll_middle:SetWidth (32)
+ BaseFrame.scroll_middle:SetHeight (64)
+ BaseFrame.scroll_middle:SetTexCoord (0, 1, 0.251, 0.75)
+
+ --> três botões scroll up, down, window strech
+ BaseFrame.button_up = _CreateFrame ("Button", nil, BackGroundDisplay)
+ BaseFrame.button_down = _CreateFrame ("Button", nil, BackGroundDisplay)
+ BaseFrame.button_stretch = _CreateFrame ("Button", nil, BaseFrame)
+
+ BaseFrame.button_stretch:SetPoint ("BOTTOM", BaseFrame, "TOP", 0, 20)
+ BaseFrame.button_stretch:SetPoint ("RIGHT", BaseFrame, "RIGHT", -27, 0)
+ BaseFrame.button_stretch:SetFrameStrata ("FULLSCREEN")
+
+ BaseFrame.button_stretch:SetWidth (32)
+ BaseFrame.button_stretch:SetHeight (16)
+ BaseFrame.button_stretch:SetNormalTexture ("Interface\\AddOns\\Details\\images\\grab")
+ BaseFrame.button_stretch:SetPushedTexture ("Interface\\AddOns\\Details\\images\\grab_over")
+ BaseFrame.button_stretch:SetDisabledTexture ("Interface\\AddOns\\Details\\images\\grab")
+ gump:Fade (BaseFrame.button_stretch, -1)
+
+ BaseFrame.button_stretch:Show()
+
+ BaseFrame.button_up:SetWidth (29)
+ BaseFrame.button_up:SetHeight (32)
+ BaseFrame.button_up:SetNormalTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Up")
+ BaseFrame.button_up:SetPushedTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Down")
+ BaseFrame.button_up:SetDisabledTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Disabled")
+ BaseFrame.button_up:Disable()
+
+ BaseFrame.button_down:SetWidth (29)
+ BaseFrame.button_down:SetHeight (32)
+ BaseFrame.button_down:SetNormalTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Up")
+ BaseFrame.button_down:SetPushedTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Down")
+ BaseFrame.button_down:SetDisabledTexture ("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Disabled")
+ BaseFrame.button_down:Disable()
+
+ BaseFrame.button_up:SetPoint ("TOPRIGHT", BaseFrame.scroll_up, "TOPRIGHT", -4, 3)
+ BaseFrame.button_down:SetPoint ("BOTTOMRIGHT", BaseFrame.scroll_down, "BOTTOMRIGHT", -4, -6)
+
+ ScrollBar:SetPoint ("TOP", BaseFrame.button_up, "BOTTOM", 0, 12)
+ ScrollBar:SetPoint ("BOTTOM", BaseFrame.button_down, "TOP", 0, -12)
+ ScrollBar:SetPoint ("LEFT", BackGroundDisplay, "RIGHT", 3, 0)
+ ScrollBar:Show()
+
+ button_stretch_scripts (BaseFrame, BackGroundDisplay, instancia)
+
+ button_down_scripts (BaseFrame, BackGroundDisplay, instancia, ScrollBar)
+ button_up_scripts (BaseFrame, BackGroundDisplay, instancia, ScrollBar)
+
+
+--slider
+-------------------------------------------------------------------------------------------------------------------------------------------------
+ ScrollBar.scrollMax = 0 --default - tamanho da janela de fundo
+
+ -- coisinha do meio
+ ScrollBar.thumb = ScrollBar:CreateTexture (nil, "OVERLAY")
+ ScrollBar.thumb:SetTexture ("Interface\\Buttons\\UI-ScrollBar-Knob")
+ ScrollBar.thumb:SetSize (29, 30)
+ ScrollBar:SetThumbTexture (ScrollBar.thumb)
+
+ ScrollBar:SetOrientation ("VERTICAL")
+ ScrollBar:SetMinMaxValues(0, ScrollBar.scrollMax)
+ ScrollBar:SetValue(0)
+ ScrollBar.ultimo = 0
+
+-- janela principal
+-------------------------------------------------------------------------------------------------------------------------------------------------
+
+ BaseFrame:SetClampedToScreen (true)
+ BaseFrame:SetClampRectInsets (unpack (_detalhes.window_clamp))
+
+ BaseFrame:SetWidth (_detalhes.new_window_size.width)
+ BaseFrame:SetHeight (_detalhes.new_window_size.height)
+
+ BaseFrame:SetPoint ("CENTER", _UIParent)
+ BaseFrame:EnableMouseWheel (false)
+ BaseFrame:EnableMouse (true)
+ BaseFrame:SetMovable (true)
+ BaseFrame:SetResizable (true)
+ BaseFrame:SetMinResize (150, 40)
+ BaseFrame:SetMaxResize (_detalhes.max_window_size.width, _detalhes.max_window_size.height)
+
+ BaseFrame:SetBackdrop (gump_fundo_backdrop)
+ BaseFrame:SetBackdropColor (_detalhes.default_bg_color, _detalhes.default_bg_color, _detalhes.default_bg_color, _detalhes.default_bg_alpha)
+ --BaseFrame:SetBackdropColor (0, 0, 0, 1)
+
+-- fundo
+-------------------------------------------------------------------------------------------------------------------------------------------------
+
+ BackGroundFrame:SetAllPoints (BaseFrame)
+ BackGroundFrame:SetScrollChild (BackGroundDisplay)
+
+ BackGroundDisplay:SetResizable (true)
+ BackGroundDisplay:SetPoint ("TOPLEFT", BaseFrame, "TOPLEFT")
+ BackGroundDisplay:SetPoint ("BOTTOMRIGHT", BaseFrame, "BOTTOMRIGHT")
+ BackGroundDisplay:SetBackdrop (gump_fundo_backdrop)
+ BackGroundDisplay:SetBackdropColor (_detalhes.default_bg_color, _detalhes.default_bg_color, _detalhes.default_bg_color, _detalhes.default_bg_alpha)
+ --BackGroundDisplay:SetBackdropColor (0, 0, 0, 1)
+
+
+-- congelamento da instância
+-------------------------------------------------------------------------------------------------------------------------------------------------
+
+ instancia.freeze_icon = BaseFrame:CreateTexture (nil, "OVERLAY")
+ instancia.freeze_icon:SetTexture ("Interface\\CHARACTERFRAME\\Disconnect-Icon")
+ instancia.freeze_icon:SetWidth (64)
+ instancia.freeze_icon:SetHeight (64)
+ instancia.freeze_icon:SetPoint ("center", BackGroundDisplay, "center")
+ instancia.freeze_icon:SetPoint ("left", BackGroundDisplay, "left")
+ instancia.freeze_icon:Hide()
+
+ instancia.freeze_texto = BaseFrame:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ instancia.freeze_texto:SetHeight (64)
+ instancia.freeze_texto:SetPoint ("left", instancia.freeze_icon, "right", -18, 0)
+ instancia.freeze_texto:SetTextColor (1, 1, 1)
+ instancia.freeze_texto:SetText (Loc ["STRING_FREEZE"])
+ instancia.freeze_texto:Hide()
+
+ instancia._version = BaseFrame:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ instancia._version:SetPoint ("left", BackGroundDisplay, "left", 20, 0)
+ instancia._version:SetTextColor (1, 1, 1)
+ instancia._version:SetText ("this is a early alpha version (1) of Details\nyou can help us sending bug reports\nuse the blue button.")
+ if (not _detalhes.initializing) then
+ instancia._version:Hide()
+ end
+
+ BaseFrame.wallpaper = BaseFrame:CreateTexture (nil, "border")
+ BaseFrame.wallpaper:Hide()
+
+--cria os 2 resizers
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ BaseFrame.resize_direita = _CreateFrame ("Button", "Details_Resize_Direita"..ID, BaseFrame)
+ BaseFrame.resize_direita:SetNormalTexture ("Interface\\AddOns\\Details\\images\\ResizeGripD")
+ BaseFrame.resize_direita:SetHighlightTexture ("Interface\\AddOns\\Details\\images\\ResizeGripD")
+ BaseFrame.resize_direita:SetWidth (16)
+ BaseFrame.resize_direita:SetHeight (16)
+ BaseFrame.resize_direita:SetPoint ("BOTTOMRIGHT", BaseFrame, "BOTTOMRIGHT", 0, 0)
+ BaseFrame.resize_direita:EnableMouse (true)
+ BaseFrame.resize_direita:SetFrameLevel (BaseFrame:GetFrameLevel() + 6)
+
+ --> lock window button
+ BaseFrame.lock_button = _CreateFrame ("Button", "Details_Lock_Button"..ID, BaseFrame)
+ BaseFrame.lock_button:SetPoint ("right", BaseFrame.resize_direita, "left", -1, 1.5)
+ BaseFrame.lock_button:SetFrameLevel (BaseFrame:GetFrameLevel() + 6)
+ BaseFrame.lock_button:SetWidth (40)
+ BaseFrame.lock_button:SetHeight (16)
+ BaseFrame.lock_button.label = BaseFrame.lock_button:CreateFontString (nil, "overlay", "GameFontNormal")
+ BaseFrame.lock_button.label:SetPoint ("right", BaseFrame.lock_button, "right")
+ BaseFrame.lock_button.label:SetTextColor (.3, .3, .3, .4)
+ BaseFrame.lock_button.label:SetJustifyH ("right")
+ BaseFrame.lock_button.label:SetText (Loc ["STRING_LOCK_WINDOW"])
+ BaseFrame.lock_button:SetWidth (BaseFrame.lock_button.label:GetStringWidth()+2)
+ BaseFrame.lock_button:SetScript ("OnClick", lockFunctionOnClick)
+
+ --> options window button
+ --[[
+ BaseFrame.options_button = _CreateFrame ("Button", "Details_Options_Button"..ID, BaseFrame)
+ BaseFrame.options_button:SetPoint ("right", BaseFrame.lock_button, "left", -1, 0)
+ BaseFrame.options_button:SetFrameLevel (BaseFrame:GetFrameLevel() + 3) --> lower then normal rows
+ BaseFrame.options_button:SetWidth (40)
+ BaseFrame.options_button:SetHeight (16)
+ BaseFrame.options_button.label = BaseFrame.options_button:CreateFontString (nil, "overlay", "GameFontNormal")
+ BaseFrame.options_button.label:SetPoint ("right", BaseFrame.options_button, "right")
+ BaseFrame.options_button.label:SetTextColor (.3, .3, .3, .4)
+ BaseFrame.options_button.label:SetJustifyH ("right")
+ BaseFrame.options_button.label:SetText (Loc ["STRING_OPTIONS_WINDOW"])
+ --]]
+
+ BaseFrame.resize_esquerda = _CreateFrame ("Button", "Details_Resize_Esquerda"..ID, BaseFrame)
+ BaseFrame.resize_esquerda:SetNormalTexture ("Interface\\AddOns\\Details\\images\\ResizeGripL")
+ BaseFrame.resize_esquerda:SetHighlightTexture ("Interface\\AddOns\\Details\\images\\ResizeGripL")
+ BaseFrame.resize_esquerda:SetWidth (16)
+ BaseFrame.resize_esquerda:SetHeight (16)
+ BaseFrame.resize_esquerda:SetPoint ("BOTTOMLEFT", BaseFrame, "BOTTOMLEFT", 0, 0)
+ BaseFrame.resize_esquerda:EnableMouse (true)
+ BaseFrame.resize_esquerda:SetFrameLevel (BaseFrame:GetFrameLevel() + 6)
+
+ gump:Fade (BaseFrame.resize_esquerda, "in", 3.0)
+ gump:Fade (BaseFrame.resize_direita, "in", 3.0)
+
+ if (instancia.isLocked) then
+ instancia.isLocked = not instancia.isLocked
+ lockFunctionOnClick (BaseFrame.lock_button)
+ end
+
+ gump:Fade (BaseFrame.lock_button, -1, 3.0)
+
+
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+--seta os scripts dos frames
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+
+
+ BFrame_scripts (BaseFrame, instancia)
+
+ --BackGroundDisplay_scripts (BackGroundDisplay, BaseFrame, instancia)
+
+ BGFrame_scripts (SwitchButton, BaseFrame, instancia)
+ BGFrame_scripts (BackGroundDisplay, BaseFrame, instancia)
+ --BGFrame_scripts (BackGroundFrame, BaseFrame, instancia)
+
+ iterate_scroll_scripts (BackGroundDisplay, BackGroundFrame, BaseFrame, ScrollBar, instancia)
+
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+--chama função para criar o cabeçalho
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ gump:CriaCabecalho (BaseFrame, instancia)
+
+
+-- cria as duas barras laterais
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+ --> barra borda direita lateral
+
+ --> barra borda esquerda lateral
+ BaseFrame.barra_esquerda = BaseFrame.cabecalho.fechar:CreateTexture (nil, "ARTWORK")
+ BaseFrame.barra_esquerda:SetTexture ("Interface\\AddOns\\Details\\images\\bar_main_leftright")
+ BaseFrame.barra_esquerda:SetTexCoord (0.5, 1, 0, 1)
+ BaseFrame.barra_esquerda:SetWidth (16)
+ BaseFrame.barra_esquerda:SetPoint ("TOPLEFT", BaseFrame, "TOPLEFT", -8, 0)
+ BaseFrame.barra_esquerda:SetPoint ("BOTTOMLEFT", BaseFrame, "BOTTOMLEFT", -8, -14)
+
+ BaseFrame.barra_direita = BaseFrame.cabecalho.fechar:CreateTexture (nil, "ARTWORK")
+ BaseFrame.barra_direita:SetTexture ("Interface\\AddOns\\Details\\images\\bar_main_leftright")
+ BaseFrame.barra_direita:SetTexCoord (0, 0.5, 0, 1)
+ BaseFrame.barra_direita:SetWidth (16)
+ BaseFrame.barra_direita:SetPoint ("TOPRIGHT", BaseFrame, "TOPRIGHT", 8, 0)
+ BaseFrame.barra_direita:SetPoint ("BOTTOMRIGHT", BaseFrame, "BOTTOMRIGHT", 8, -14)
+
+
+--chama função para criar o rodapé
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ gump:CriaRodape (BaseFrame, instancia)
+
+------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+-- BETA -- botão de separar as instâncias que estão agrupadas
+ instancia.botao_separar = gump:NewDetailsButton (BaseFrame.cabecalho.fechar, _, instancia, instancia.Desagrupar, instancia, -1, 13, 13,
+ "Interface\\AddOns\\Details\\images\\cadeado", "Interface\\AddOns\\Details\\images\\cadeado", "Interface\\AddOns\\Details\\images\\cadeado", "Interface\\AddOns\\Details\\images\\cadeado")
+ instancia.botao_separar:SetPoint ("BOTTOM", BaseFrame.resize_direita, "TOP", -1, 0)
+ instancia.botao_separar:SetFrameLevel (BaseFrame:GetFrameLevel() + 5)
+
+ gump:Fade (instancia.botao_separar, "in", 3.0)
+
+ resize_scripts (BaseFrame.resize_direita, instancia, ScrollBar, ">")
+ resize_scripts (BaseFrame.resize_esquerda, instancia, ScrollBar, "<")
+ lock_button_scripts (BaseFrame.lock_button, instancia)
+
+ bota_separar_script (instancia.botao_separar, instancia)
+
+--------------------------------- BORDAS HIGHLIGHT
+ instancia.h_cima = BaseFrame.cabecalho.fechar:CreateTexture (nil, "OVERLAY")
+ instancia.h_cima:SetTexture ("Interface\\AddOns\\Details\\images\\highlight_updown")
+ instancia.h_cima:SetTexCoord (0, 1, 0.5, 1)
+ instancia.h_cima:SetPoint ("topleft", BaseFrame.cabecalho.top_bg, "bottomleft", -10, 37)
+ instancia.h_cima:SetPoint ("topright", BaseFrame.cabecalho.ball_r, "bottomright", -33, 37)
+ instancia.h_cima:Hide()
+
+ instancia.h_baixo = BaseFrame.cabecalho.fechar:CreateTexture (nil, "OVERLAY")
+ instancia.h_baixo:SetTexture ("Interface\\AddOns\\Details\\images\\highlight_updown")
+ instancia.h_baixo:SetTexCoord (0, 1, 0, 0.5)
+ instancia.h_baixo:SetPoint ("topleft", BaseFrame.rodape.esquerdo, "bottomleft", 16, 17)
+ instancia.h_baixo:SetPoint ("topright", BaseFrame.rodape.direita, "bottomright", -16, 17)
+ instancia.h_baixo:Hide()
+
+ instancia.h_esquerda = BaseFrame.cabecalho.fechar:CreateTexture (nil, "OVERLAY")
+ instancia.h_esquerda:SetTexture ("Interface\\AddOns\\Details\\images\\highlight_leftright")
+ instancia.h_esquerda:SetTexCoord (0.5, 1, 0, 1)
+ instancia.h_esquerda:SetPoint ("topleft", BaseFrame.barra_esquerda, "topleft", -8, 0)
+ instancia.h_esquerda:SetPoint ("bottomleft", BaseFrame.barra_esquerda, "bottomleft", -8, 0)
+ instancia.h_esquerda:Hide()
+
+ instancia.h_direita = BaseFrame.cabecalho.fechar:CreateTexture (nil, "OVERLAY")
+ instancia.h_direita:SetTexture ("Interface\\AddOns\\Details\\images\\highlight_leftright")
+ instancia.h_direita:SetTexCoord (0, 0.5, 1, 0)
+ instancia.h_direita:SetPoint ("topleft", BaseFrame.barra_direita, "topleft", 8, 18)
+ instancia.h_direita:SetPoint ("bottomleft", BaseFrame.barra_direita, "bottomleft", 8, 0)
+ instancia.h_direita:Hide()
+
+ --instancia.botao_separar:Hide()
+
+ if (criando) then
+ local CProps = {
+ ["altura"] = 100,
+ ["largura"] = 200,
+ ["barras"] = 50,
+ ["barrasvisiveis"] = 0,
+ ["x"] = 0,
+ ["y"] = 0,
+ ["w"] = 0,
+ ["h"] = 0
+ }
+ instancia.locs = CProps
+ end
+
+ --> background shadow color debug
+ --[[
+ local white_frame = _CreateFrame ("Frame", "DetailsWhiteFrame", _UIParent)
+ white_frame:SetFrameStrata ("LOW")
+ white_frame:SetFrameLevel (0)
+
+ white_frame:SetSize (400, 250)
+ white_frame:SetPoint ("topleft", BaseFrame.cabecalho.ball, "topleft")
+ white_frame:SetBackdrop({
+ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
+ tile = true, tileSize = 16,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ white_frame:SetBackdropColor (255/255, 255/255, 255/255, 1)
+ local white_texture = white_frame:CreateTexture (nil, "artwork")
+ white_texture:SetAllPoints (white_frame)
+ white_texture:SetTexture (1, 1, 1, 1)
+ white_frame:Show()
+ --]]
+
+ return BaseFrame, BackGroundFrame, BackGroundDisplay, ScrollBar
+
+end
+
+function gump:CreateSplitBars (barra, instancia)
+
+ barra.split = {}
+ local size = barra:GetHeight()
+
+ --> barra superior
+ barra.split.barra = _CreateFrame ("StatusBar", nil, barra)
+ barra.split.barra:SetFrameLevel (barra.statusbar:GetFrameLevel()+2)
+ barra.split.barra:SetAllPoints (barra)
+ barra.split.barra:SetMinMaxValues (0, 100)
+ barra.split.barra:SetValue (100)
+
+ barra.split.barra.textura = barra.split.barra:CreateTexture (nil, "ARTWORK")
+ barra.split.barra.textura:SetHorizTile (false)
+ barra.split.barra.textura:SetVertTile (false)
+ barra.split.barra.textura:SetTexture ([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
+ barra.split.barra:SetStatusBarColor (1, 1, 1, 1)
+ barra.split.barra:SetStatusBarTexture (barra.split.barra.textura)
+
+ barra.split.barra.icone = barra.split.barra:CreateTexture (nil, "OVERLAY")
+ barra.split.barra.icone:SetPoint ("left", barra.split.barra, "left")
+ barra.split.barra.icone:SetHeight (size)
+ barra.split.barra.icone:SetWidth (size)
+ barra.split.barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+ barra.split.barra.icone:SetTexCoord (.75, 1, .75, 1)
+
+ barra.split.barra.texto = barra.split.barra:CreateFontString (nil, "OVERLAY", "GameFontHighlight")
+ barra.split.barra.texto:SetPoint ("left", barra.split.barra.icone, "right", 3, 0)
+ barra.split.barra.texto:SetJustifyH ("left")
+ barra.split.barra.texto:SetNonSpaceWrap (true)
+
+ instancia:SetFontSize (barra.split.barra.texto, size*0.75)
+ _detalhes.font_pool:add (barra.split.barra.texto)
+
+ --> barra inferior
+ barra.split.background = _CreateFrame ("StatusBar", nil, barra)
+ barra.split.background:SetAllPoints (barra)
+ barra.split.background:SetFrameLevel (barra.statusbar:GetFrameLevel()+1)
+ barra.split.background:SetMinMaxValues (0, 100)
+ barra.split.background:SetValue (100)
+
+ barra.split.background.textura = barra.split.background:CreateTexture (nil, "ARTWORK")
+ barra.split.background.textura:SetHorizTile (false)
+ barra.split.background.textura:SetVertTile (false)
+ barra.split.background.textura:SetTexture ([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
+ barra.split.background:SetStatusBarColor (1, 1, 1, 1)
+ barra.split.background:SetStatusBarTexture (barra.split.background.textura)
+
+ barra.split.background.icone = barra.split.barra:CreateTexture (nil, "OVERLAY")
+ barra.split.background.icone:SetPoint ("right", barra.split.background, "right")
+ barra.split.background.icone:SetHeight (size)
+ barra.split.background.icone:SetWidth (size)
+ barra.split.background.icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+ barra.split.background.icone:SetTexCoord (.75, 1, .75, 1)
+
+ barra.split.background.texto = barra.split.barra:CreateFontString (nil, "OVERLAY", "GameFontHighlight")
+ barra.split.background.texto:SetPoint ("right", barra.split.background.icone, "left", -3, 0)
+ barra.split.background.texto:SetJustifyH ("right")
+ barra.split.background.texto:SetNonSpaceWrap (true)
+
+ instancia:SetFontSize (barra.split.background.texto, size*0.75)
+ _detalhes.font_pool:add (barra.split.background.texto)
+
+ barra.split.div = barra.split.barra:CreateTexture (nil, "OVERLAY")
+ barra.split.div:SetTexture ("Interface\\AddOns\\Details\\images\\bar_detalhes2_end")
+ barra.split.div:SetHeight (size)
+ barra.split.div:SetWidth (10)
+
+end
+
+--> Alias
+function gump:NewRow (instancia, index)
+ return gump:CriaNovaBarra (instancia, index)
+end
+
+function gump:CriaNovaBarra (instancia, index)
+
+ local BaseFrame = instancia.baseframe
+ local esta_barra = _CreateFrame ("Button", "DetailsBarra_"..instancia.meu_id.."_"..index, BaseFrame)
+ local y = instancia.barrasInfo.alturaReal*(index-1)
+
+ y = y*-1
+
+ esta_barra:SetPoint ("TOPLEFT", BaseFrame, "TOPLEFT", instancia.barrasInfo.espaco.esquerda, y)
+ esta_barra:SetHeight (instancia.barrasInfo.altura) --> altura determinada pela instância
+ esta_barra:SetWidth (BaseFrame:GetWidth()+instancia.barrasInfo.espaco.direita)
+
+ esta_barra:SetFrameLevel (BaseFrame:GetFrameLevel() + 4)
+
+ esta_barra.last_value = 0
+ esta_barra.w_mod = 0
+
+ esta_barra:EnableMouse (true)
+ esta_barra:RegisterForClicks ("LeftButtonDown", "RightButtonDown")
+
+ esta_barra.statusbar = _CreateFrame ("StatusBar", nil, esta_barra)
+ esta_barra.statusbar:SetAllPoints (esta_barra)
+
+ esta_barra.textura = esta_barra.statusbar:CreateTexture (nil, "ARTWORK")
+ esta_barra.textura:SetHorizTile (false)
+ esta_barra.textura:SetVertTile (false)
+ esta_barra.textura:SetTexture (instancia.barrasInfo.textura)
+
+ esta_barra.statusbar:SetStatusBarColor (0, 0, 0, 0)
+ esta_barra.statusbar:SetStatusBarTexture (esta_barra.textura)
+
+ esta_barra.statusbar:SetMinMaxValues (0, 100)
+ esta_barra.statusbar:SetValue (100)
+
+ local icone_classe = esta_barra.statusbar:CreateTexture (nil, "OVERLAY")
+ icone_classe:SetPoint ("left", esta_barra.statusbar, "left")
+ icone_classe:SetHeight (instancia.barrasInfo.altura)
+ icone_classe:SetWidth (instancia.barrasInfo.altura)
+ icone_classe:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+ icone_classe:SetTexCoord (.75, 1, .75, 1)
+ esta_barra.icone_classe = icone_classe
+
+ esta_barra.texto_esquerdo = esta_barra.statusbar:CreateFontString (nil, "OVERLAY", "GameFontHighlight")
+
+ esta_barra.texto_esquerdo:SetPoint ("LEFT", esta_barra.icone_classe, "right", 3, 0)
+ esta_barra.texto_esquerdo:SetJustifyH ("LEFT")
+ esta_barra.texto_esquerdo:SetNonSpaceWrap (true)
+
+ local icone_terceiro = esta_barra.statusbar:CreateTexture (nil, "OVERLAY")
+ icone_terceiro:SetPoint ("left", esta_barra.statusbar, "left", 2, 0)
+ icone_terceiro:SetHeight (instancia.barrasInfo.altura)
+ icone_terceiro:SetWidth (instancia.barrasInfo.altura)
+ esta_barra.icone_terceiro = icone_terceiro
+ esta_barra.icone_terceiro:Hide()
+
+ esta_barra.texto_direita = esta_barra.statusbar:CreateFontString (nil, "OVERLAY", "GameFontHighlight")
+
+ esta_barra.texto_direita:SetPoint ("RIGHT", esta_barra.statusbar, "RIGHT")
+ esta_barra.texto_direita:SetJustifyH ("RIGHT")
+
+ instancia:SetFontSize (esta_barra.texto_esquerdo, instancia.barrasInfo.fontSize)
+ instancia:SetFontFace (esta_barra.texto_esquerdo, instancia.barrasInfo.font)
+ _detalhes.font_pool:add (esta_barra.texto_esquerdo)
+
+ instancia:SetFontSize (esta_barra.texto_direita, instancia.barrasInfo.fontSize)
+ instancia:SetFontFace (esta_barra.texto_direita, instancia.barrasInfo.font)
+ _detalhes.font_pool:add (esta_barra.texto_direita)
+
+
+
+ --> inicia os scripts da barra
+ barra_scripts (esta_barra, instancia, index)
+
+ gump:Fade (esta_barra, 1) --> hida a barra
+
+ return esta_barra
+end
+
+function _detalhes:InstanceWallpaper (texture, anchor, alpha, texcoord, width, height, overlay)
+
+ local wallpaper = self.wallpaper
+
+ if (type (texture) == "boolean" and texture) then
+ texture, anchor, alpha, texcoord, width, height, overlay = wallpaper.texture, wallpaper.anchor, wallpaper.alpha, wallpaper.texcoord, wallpaper.width, wallpaper.height, wallpaper.overlay
+
+ elseif (type (texture) == "boolean" and not texture) then
+ self.wallpaper.enabled = false
+ return gump:Fade (self.baseframe.wallpaper, "in")
+
+ elseif (type (texture) == "table") then
+ anchor = texture.anchor or wallpaper.anchor
+ alpha = texture.alpha or wallpaper.alpha
+ texcoord = texture.texcoord or wallpaper.texcoord
+ width = texture.width or wallpaper.width
+ height = texture.height or wallpaper.height
+ overlay = texture.overlay or wallpaper.overlay
+ texture = texture.texture or wallpaper.texture
+ else
+ texture = texture or wallpaper.texture
+ anchor = anchor or wallpaper.anchor
+ alpha = alpha or wallpaper.alpha
+ texcoord = texcoord or wallpaper.texcoord
+ width = width or wallpaper.width
+ height = height or wallpaper.height
+ overlay = overlay or wallpaper.overlay
+ end
+
+ if (not wallpaper.texture and not texture) then
+ local spec = GetSpecialization()
+ if (spec) then
+ local _, _, _, _, _background = GetSpecializationInfo (spec)
+ if (_background) then
+ texture = "Interface\\TALENTFRAME\\".._background
+ end
+ end
+
+ texcoord = {0, 1, 0, 0.7}
+ alpha = 0.5
+ width, height = self:GetSize()
+ anchor = "all"
+ end
+
+ local t = self.baseframe.wallpaper
+
+ t:ClearAllPoints()
+
+ if (anchor == "all") then
+ t:SetPoint ("topleft", self.baseframe, "topleft")
+ t:SetPoint ("bottomright", self.baseframe, "bottomright")
+ elseif (anchor == "center") then
+ t:SetPoint ("center", self.baseframe, "center")
+ elseif (anchor == "stretchLR") then
+ t:SetPoint ("center", self.baseframe, "center")
+ t:SetPoint ("left", self.baseframe, "left")
+ t:SetPoint ("right", self.baseframe, "right")
+ elseif (anchor == "stretchTB") then
+ t:SetPoint ("center", self.baseframe, "center")
+ t:SetPoint ("top", self.baseframe, "top")
+ t:SetPoint ("bottom", self.baseframe, "bottom")
+ else
+ t:SetPoint (anchor, self.baseframe, anchor)
+ end
+
+ t:SetTexture (texture)
+ t:SetAlpha (alpha)
+ t:SetTexCoord (unpack (texcoord))
+ t:SetWidth (width)
+ t:SetHeight (height)
+ t:SetVertexColor (unpack (overlay))
+
+ wallpaper.enabled = true
+ wallpaper.texture = texture
+ wallpaper.anchor = anchor
+ wallpaper.alpha = alpha
+ wallpaper.texcoord = texcoord
+ wallpaper.width = width
+ wallpaper.height = height
+ wallpaper.overlay = overlay
+
+ if (t.faded) then
+ gump:Fade (t, "out")
+ else
+ gump:Fade (t, "AlphaAnim", alpha)
+ end
+end
+
+
+function _detalhes:InstanceColor (red, green, blue, alpha)
+ if (type (red) ~= "number") then
+ red, green, blue, alpha = gump:ParseColors (red)
+ end
+
+ self.baseframe.rodape.esquerdo:SetVertexColor (red, green, blue)
+ self.baseframe.rodape.esquerdo:SetAlpha (alpha)
+ self.baseframe.rodape.direita:SetVertexColor (red, green, blue)
+ self.baseframe.rodape.direita:SetAlpha (alpha)
+ self.baseframe.rodape.top_bg:SetVertexColor (red, green, blue)
+ self.baseframe.rodape.top_bg:SetAlpha (alpha)
+
+ self.baseframe.cabecalho.ball_r:SetVertexColor (red, green, blue)
+ self.baseframe.cabecalho.ball_r:SetAlpha (alpha)
+ self.baseframe.cabecalho.ball:SetVertexColor (red, green, blue)
+ self.baseframe.cabecalho.ball:SetAlpha (alpha)
+ self.baseframe.cabecalho.top_bg:SetVertexColor (red, green, blue)
+ self.baseframe.cabecalho.top_bg:SetAlpha (alpha)
+
+ self.baseframe.barra_esquerda:SetVertexColor (red, green, blue)
+ self.baseframe.barra_esquerda:SetAlpha (alpha)
+ self.baseframe.barra_direita:SetVertexColor (red, green, blue)
+ self.baseframe.barra_direita:SetAlpha (alpha)
+
+ self.color[1], self.color[2], self.color[3], self.color[4] = red, green, blue, alpha
+end
+
+function gump:CriaRodape (BaseFrame, instancia)
+
+ BaseFrame.rodape = {}
+
+ --> esquerdo
+ BaseFrame.rodape.esquerdo = BaseFrame.cabecalho.fechar:CreateTexture (nil, "OVERLAY")
+ BaseFrame.rodape.esquerdo:SetPoint ("TOPRIGHT", BaseFrame, "BOTTOMLEFT", 48, 0)
+ BaseFrame.rodape.esquerdo:SetTexture ("Interface\\AddOns\\Details\\images\\bar_down_left")
+
+ --> direito
+ BaseFrame.rodape.direita = BaseFrame.cabecalho.fechar:CreateTexture (nil, "OVERLAY")
+ BaseFrame.rodape.direita:SetPoint ("TOPLEFT", BaseFrame, "BOTTOMRIGHT", -16, 0)
+ BaseFrame.rodape.direita:SetTexture ("Interface\\AddOns\\Details\\images\\bar_down_right")
+
+ --> barra centro
+ BaseFrame.rodape.top_bg = BaseFrame:CreateTexture (nil, "BACKGROUND")
+ BaseFrame.rodape.top_bg:SetTexture ("Interface\\AddOns\\Details\\images\\bar_topdown_center")
+ BaseFrame.rodape.top_bg:SetTexCoord (0, 1, 0.5, 1)
+ BaseFrame.rodape.top_bg:SetHeight (32)
+ BaseFrame.rodape.top_bg:SetPoint ("LEFT", BaseFrame.rodape.esquerdo, "RIGHT", -48, 0)
+ BaseFrame.rodape.top_bg:SetPoint ("RIGHT", BaseFrame.rodape.direita, "LEFT", 16, 0)
+
+ local StatusBarLeftAnchor = CreateFrame ("frame", nil, BaseFrame)
+ StatusBarLeftAnchor:SetPoint ("left", BaseFrame.rodape.top_bg, "left", 5, 10)
+ StatusBarLeftAnchor:SetWidth (1)
+ StatusBarLeftAnchor:SetHeight (1)
+ BaseFrame.rodape.StatusBarLeftAnchor = StatusBarLeftAnchor
+
+ local StatusBarCenterAnchor = CreateFrame ("frame", nil, BaseFrame)
+ StatusBarCenterAnchor:SetPoint ("center", BaseFrame.rodape.top_bg, "center", 0, 10)
+ StatusBarCenterAnchor:SetWidth (1)
+ StatusBarCenterAnchor:SetHeight (1)
+
+ --[[ --create a line showing the center point of window
+ local centerLineGuide = StatusBarCenterAnchor:CreateTexture(nil,"overlay")
+ centerLineGuide:SetWidth (1)
+ centerLineGuide:SetHeight (20)
+ centerLineGuide:SetPoint ("center", StatusBarCenterAnchor, "center")
+ centerLineGuide:SetTexture (1, 1, 1, 1)
+ --]]
+
+ BaseFrame.rodape.StatusBarCenterAnchor = StatusBarCenterAnchor
+
+ --> frame invisível
+ BaseFrame.DOWNFrame = _CreateFrame ("frame", nil, BaseFrame)
+ BaseFrame.DOWNFrame:SetPoint ("LEFT", BaseFrame.rodape.esquerdo, "RIGHT", 0, 10)
+ BaseFrame.DOWNFrame:SetPoint ("RIGHT", BaseFrame.rodape.direita, "LEFT", 0, 10)
+ BaseFrame.DOWNFrame:SetHeight (14)
+
+ BaseFrame.DOWNFrame:Show()
+ BaseFrame.DOWNFrame:EnableMouse (true)
+ BaseFrame.DOWNFrame:SetMovable (true)
+ BaseFrame.DOWNFrame:SetResizable (true)
+
+ BGFrame_scripts (BaseFrame.DOWNFrame, BaseFrame, instancia)
+end
+
+function _detalhes:CheckConsolidates()
+ for meu_id, instancia in ipairs (_detalhes.tabela_instancias) do
+ if (instancia.consolidate and meu_id ~= _detalhes.lower_instance) then
+ instancia:UnConsolidateIcons()
+ end
+ end
+end
+
+function _detalhes:ConsolidateIcons()
+ self.consolidate = true
+ self.consolidateButton:Show()
+ return self:DefaultIcons()
+end
+
+function _detalhes:UnConsolidateIcons()
+ self.consolidate = false
+ print (self.consolidateButton:GetObjectType())
+ self.consolidateButton:Hide()
+ return self:DefaultIcons()
+end
+
+function _detalhes:DefaultIcons (_mode, _segment, _attributes, _report)
+
+ if (_mode == nil) then
+ _mode = self.icons[1]
+ end
+ if (_segment == nil) then
+ _segment = self.icons[2]
+ end
+ if (_attributes == nil) then
+ _attributes = self.icons[3]
+ end
+ if (_report == nil) then
+ _report = self.icons[4]
+ end
+
+ if (self.consolidate and not self.consolidateButton:IsShown()) then
+ self.consolidateButton:Show()
+ elseif (not self.consolidate and self.consolidateButton:IsShown()) then
+ self.consolidateButton:Hide()
+ end
+
+ local baseToolbar = self.baseframe.cabecalho
+ local icons = {baseToolbar.modo_selecao, baseToolbar.segmento, baseToolbar.atributo, baseToolbar.report}
+ local options = {_mode, _segment, _attributes, _report}
+ local anchors = {{0, 0}, {0, 0}, {0, 0}, {-6, 0}}
+
+ for index = 1, #icons do
+ if (type (options[index]) == "boolean") then
+ if (options[index]) then
+ icons [index]:Show()
+ self.icons[index] = true
+ else
+ icons [index]:Hide()
+ self.icons[index] = false
+ end
+ end
+ end
+
+ local _gotFirst = false
+ for index = 1, #icons do
+ local _thisIcon = icons [index]
+ if (_thisIcon:IsShown()) then
+ if (not _gotFirst) then
+
+ _thisIcon:ClearAllPoints()
+ if (self.consolidate) then
+ _thisIcon:SetPoint ("TOPLEFT", self.consolidateFrame, "TOPLEFT", -3, -5)
+ _thisIcon:SetParent (self.consolidateFrame)
+ else
+ _thisIcon:SetPoint ("BOTTOMLEFT", baseToolbar.ball, "BOTTOMRIGHT", 0 + anchors[index][1], 2 + anchors[index][2])
+ _thisIcon:SetParent (self.baseframe)
+ _thisIcon:SetFrameLevel (self.baseframe.UPFrame:GetFrameLevel()+1)
+ end
+
+ _gotFirst = true
+ else
+ for dex = index-1, 1, -1 do
+ local _thisIcon2 = icons [dex]
+ if (_thisIcon2:IsShown()) then
+ _thisIcon:ClearAllPoints()
+ if (self.consolidate) then
+ _thisIcon:SetPoint ("topleft", _thisIcon2, "bottomleft", anchors[index][1], anchors[index][2]-2)
+ _thisIcon:SetParent (self.consolidateFrame)
+ else
+ _thisIcon:SetPoint ("left", _thisIcon2, "right", 0 + anchors[index][1], 0 + anchors[index][2])
+ _thisIcon:SetParent (self.baseframe)
+ _thisIcon:SetFrameLevel (self.baseframe.UPFrame:GetFrameLevel()+1)
+ end
+ break
+ end
+ end
+ end
+ end
+ end
+
+ for index = #icons, 1, -1 do
+ if (icons [index]:IsShown()) then
+ self.lastIcon = icons [index]
+ break
+ end
+ end
+
+ if (not self.lastIcon) then
+ self.lastIcon = baseToolbar.ball
+ end
+
+ _detalhes.ToolBar:ReorganizeIcons()
+
+ return true
+end
+
+
+function gump:CriaCabecalho (BaseFrame, instancia)
+
+-- texturas da barra superior
+-------------------------------------------------------------------------------------------------------------------------------------------------
+
+ BaseFrame.cabecalho = {}
+
+ --> FECHAR INSTANCIA ----------------------------------------------------------------------------------------------------------------------------------------------------
+ BaseFrame.cabecalho.fechar = _CreateFrame ("Button", nil, BaseFrame, "UIPanelCloseButton")
+ BaseFrame.cabecalho.fechar:SetWidth (32)
+ BaseFrame.cabecalho.fechar:SetHeight (32)
+
+ BaseFrame.cabecalho.fechar:SetPoint ("BOTTOMRIGHT", BaseFrame, "TOPRIGHT", 5, -6)
+
+ BaseFrame.cabecalho.fechar:SetScript ("OnClick", function()
+ BaseFrame.cabecalho.fechar:Disable()
+ instancia:DesativarInstancia()
+ if (_detalhes.opened_windows == 0) then --> não há mais instâncias abertas, então manda msg alertando...
+ print (Loc ["STRING_CLOSEALL"])
+ end
+ end)
+
+ BaseFrame.cabecalho.fechar:SetText ("x")
+ BaseFrame.cabecalho.fechar:SetScript ("OnEnter", function (self)
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+ end)
+ BaseFrame.cabecalho.fechar:SetScript ("OnLeave", function (self)
+ gump:Fade (BaseFrame.button_stretch, -1)
+ end)
+
+ BaseFrame.cabecalho.fechar:SetFrameLevel (5)
+
+ --> bola do canto esquedo superior
+ BaseFrame.cabecalho.ball_point = BaseFrame.cabecalho.fechar:CreateTexture (nil, "OVERLAY")
+ BaseFrame.cabecalho.ball_point:SetPoint ("BOTTOMLEFT", BaseFrame, "TOPLEFT", -37, 0)
+ BaseFrame.cabecalho.ball_point:SetWidth (64)
+ BaseFrame.cabecalho.ball_point:SetHeight (32)
+ --BaseFrame.cabecalho.ball_point:SetTexture ("Interface\\AddOns\\Details\\images\\ball_left")
+
+ --> icone do atributo que esta sendo mostrado
+ BaseFrame.cabecalho.atributo_icon = _detalhes.listener:CreateTexture (nil, "ARTWORK")
+ BaseFrame.cabecalho.atributo_icon:SetPoint ("TOPRIGHT", BaseFrame.cabecalho.ball_point, "TOPRIGHT", -1, 1)
+ BaseFrame.cabecalho.atributo_icon:SetTexture ("Interface\\AddOns\\Details\\images\\icon_mainwindow")
+ BaseFrame.cabecalho.atributo_icon:SetWidth (32)
+ BaseFrame.cabecalho.atributo_icon:SetHeight (32)
+
+ BaseFrame.cabecalho.ball = _detalhes.listener:CreateTexture (nil, "OVERLAY")
+ BaseFrame.cabecalho.ball:SetPoint ("BOTTOMLEFT", BaseFrame, "TOPLEFT", -37, 0)
+ BaseFrame.cabecalho.ball:SetWidth (64)
+ BaseFrame.cabecalho.ball:SetHeight (64)
+ BaseFrame.cabecalho.ball:SetTexture ("Interface\\AddOns\\Details\\images\\ball_left")
+
+ BaseFrame.cabecalho.atributo_icon:Hide()
+ BaseFrame.cabecalho.ball:Hide()
+
+ --> bola do canto direito superior
+ BaseFrame.cabecalho.ball_r = BaseFrame:CreateTexture (nil, "BACKGROUND")
+ BaseFrame.cabecalho.ball_r:SetPoint ("BOTTOMRIGHT", BaseFrame, "TOPRIGHT", 32, 0)
+ BaseFrame.cabecalho.ball_r:SetWidth (64)
+ BaseFrame.cabecalho.ball_r:SetHeight (32)
+ BaseFrame.cabecalho.ball_r:SetTexture ("Interface\\AddOns\\Details\\images\\bar_top_right")
+
+ --> barra centro
+ BaseFrame.cabecalho.top_bg = BaseFrame:CreateTexture (nil, "BACKGROUND")
+ BaseFrame.cabecalho.top_bg:SetPoint ("LEFT", BaseFrame.cabecalho.ball, "RIGHT", 0, -16)
+ BaseFrame.cabecalho.top_bg:SetPoint ("RIGHT", BaseFrame.cabecalho.ball_r, "LEFT")
+ BaseFrame.cabecalho.top_bg:SetTexture ("Interface\\AddOns\\Details\\images\\bar_top_center")
+
+ --BaseFrame.cabecalho.top_bg:SetTexture ("Interface\\AddOns\\Details\\images\\bar_topdown_center")
+ --BaseFrame.cabecalho.top_bg:SetTexCoord (0, 1, 0, 0.49609375)
+ --BaseFrame.cabecalho.top_bg:SetHeight (31)
+
+ --> frame invisível
+ BaseFrame.UPFrame = _CreateFrame ("frame", nil, BaseFrame)
+ BaseFrame.UPFrame:SetPoint ("LEFT", BaseFrame.cabecalho.ball, "RIGHT", 0, -25)
+ BaseFrame.UPFrame:SetPoint ("RIGHT", BaseFrame.cabecalho.ball_r, "LEFT", 0, -25)
+ BaseFrame.UPFrame:SetHeight (20)
+
+ BaseFrame.UPFrame:Show()
+ BaseFrame.UPFrame:EnableMouse (true)
+ BaseFrame.UPFrame:SetMovable (true)
+ BaseFrame.UPFrame:SetResizable (true)
+
+ BGFrame_scripts (BaseFrame.UPFrame, BaseFrame, instancia)
+
+
+--BaseFrame.UPFrame:SetScript ("OnMouseDown", function() print ("hello world")end)
+
+-- botões
+-------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local CoolTip = _G.GameCooltip
+
+ --> SELEÇÃO DO MODO ----------------------------------------------------------------------------------------------------------------------------------------------------
+ BaseFrame.cabecalho.modo_selecao = gump:NewDetailsButton (BaseFrame, _, instancia, instancia.AlteraModo, instancia, -2, 16, 16,
+ "Interface\\GossipFrame\\HealerGossipIcon")
+ BaseFrame.cabecalho.modo_selecao:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+
+ BaseFrame.cabecalho.modo_selecao:SetPoint ("BOTTOMLEFT", BaseFrame.cabecalho.ball, "BOTTOMRIGHT", 0, 2)
+
+ --> Generating Cooltip menu from table template
+ local modeMenuTable = {
+ {text = Loc ["STRING_MODE_SELF"]},
+ {func = instancia.AlteraModo, param1 = 1},
+ {icon = "Interface\\AddOns\\Details\\images\\modo_icones", l = 0, r = 32/256, t = 0, b = 1, width = 20, height = 20},
+ {text = Loc ["STRING_HELP_MODESELF"], type = 2},
+ {icon = [[Interface\TUTORIALFRAME\TutorialFrame-QuestionMark]], type = 2, width = 16, height = 16, l = 8/64, r = 1 - (8/64), t = 8/64, b = 1 - (8/64)},
+
+ {text = Loc ["STRING_MODE_GROUP"]},
+ {func = instancia.AlteraModo, param1 = 2},
+ {icon = "Interface\\AddOns\\Details\\images\\modo_icones", l = 32/256, r = 32/256*2, t = 0, b = 1, width = 20, height = 20},
+ {text = Loc ["STRING_HELP_MODEGROUP"], type = 2},
+ {icon = [[Interface\TUTORIALFRAME\TutorialFrame-QuestionMark]], type = 2, width = 16, height = 16, l = 8/64, r = 1 - (8/64), t = 8/64, b = 1 - (8/64)},
+
+ {text = Loc ["STRING_MODE_ALL"]},
+ {func = instancia.AlteraModo, param1 = 3},
+ {icon = "Interface\\AddOns\\Details\\images\\modo_icones", l = 32/256*2, r = 32/256*3, t = 0, b = 1, width = 20, height = 20},
+ {text = Loc ["STRING_HELP_MODEALL"], type = 2},
+ {icon = [[Interface\TUTORIALFRAME\TutorialFrame-QuestionMark]], type = 2, width = 16, height = 16, l = 8/64, r = 1 - (8/64), t = 8/64, b = 1 - (8/64)},
+
+ {text = Loc ["STRING_MODE_RAID"]},
+ {func = instancia.AlteraModo, param1 = 4},
+ {icon = "Interface\\AddOns\\Details\\images\\modo_icones", l = 32/256*3, r = 32/256*4, t = 0, b = 1, width = 20, height = 20},
+ {text = Loc ["STRING_HELP_MODERAID"], type = 2},
+ {icon = [[Interface\TUTORIALFRAME\TutorialFrame-QuestionMark]], type = 2, width = 16, height = 16, l = 8/64, r = 1 - (8/64), t = 8/64, b = 1 - (8/64)},
+
+ {text = Loc ["STRING_OPTIONS_WINDOW"]},
+ {func = _detalhes.OpenOptionsWindow},
+ {icon = "Interface\\AddOns\\Details\\images\\modo_icones", l = 32/256*4, r = 32/256*5, t = 0, b = 1, width = 20, height = 20},
+ --{icon = "Interface\\HELPFRAME\\OpenTicketIcon", width = 24, height = 20}
+ }
+
+ --> Cooltip raw method for enter/leave show/hide
+ BaseFrame.cabecalho.modo_selecao:SetScript ("OnEnter", function (self)
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+
+ _detalhes.popup.buttonOver = true
+ BaseFrame.cabecalho.button_mouse_over = true
+
+ local passou = 0
+ if (_detalhes.popup.active) then
+ passou = 0.3
+ end
+
+ local checked = instancia.modo or 2
+
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ self:SetScript ("OnUpdate", nil)
+
+ CoolTip:Reset()
+ CoolTip:SetType ("menu")
+ CoolTip:AddFromTable (modeMenuTable)
+ CoolTip:SetLastSelected ("main", checked)
+ CoolTip:SetFixedParameter (instancia)
+ CoolTip:SetColor ("main", "transparent")
+
+ CoolTip:SetOption ("TextSize", _detalhes.font_sizes.menus)
+ CoolTip:SetOption ("ButtonHeightMod", -5)
+ CoolTip:SetOption ("ButtonsYMod", -5)
+ CoolTip:SetOption ("YSpacingMod", 1)
+ CoolTip:SetOption ("FixedHeight", 106)
+ CoolTip:SetOption ("FixedWidth", 106)
+ CoolTip:SetOption ("FixedWidthSub", 146)
+ CoolTip:SetOption ("SubMenuIsTooltip", true)
+
+ if (_detalhes.tutorial.main_help_button > 9) then
+ CoolTip:SetOption ("IgnoreSubMenu", true)
+ end
+
+ if (instancia.consolidate) then
+ CoolTip:SetOwner (self, "topleft", "topright", 3)
+ else
+ CoolTip:SetOwner (self)
+ end
+ CoolTip:ShowCooltip()
+ end
+ end)
+ end)
+
+ BaseFrame.cabecalho.modo_selecao:SetScript ("OnLeave", function (self)
+ gump:Fade (BaseFrame.button_stretch, -1)
+
+ _detalhes.popup.buttonOver = false
+ BaseFrame.cabecalho.button_mouse_over = false
+
+ if (_detalhes.popup.active) then
+ local passou = 0
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ if (not _detalhes.popup.mouseOver and not _detalhes.popup.buttonOver) then
+ _detalhes.popup:ShowMe (false)
+ end
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+ else
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+
+ --> SELECIONAR O SEGMENTO ----------------------------------------------------------------------------------------------------------------------------------------------------
+ BaseFrame.cabecalho.segmento = gump:NewDetailsButton (BaseFrame, _, instancia, instancia.TrocaTabela, instancia, -2, 16, 16, "Interface\\GossipFrame\\TrainerGossipIcon")
+ BaseFrame.cabecalho.segmento:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+
+ BaseFrame.cabecalho.segmento:SetPoint ("left", BaseFrame.cabecalho.modo_selecao, "right", 0, 0)
+
+ --> Cooltip raw method for show/hide onenter/onhide
+ BaseFrame.cabecalho.segmento:SetScript ("OnEnter", function (self)
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+
+ _detalhes.popup.buttonOver = true
+ BaseFrame.cabecalho.button_mouse_over = true
+
+ local passou = 0
+ if (_detalhes.popup.active) then
+ passou = 0.3
+ end
+
+ local checked = instancia.segmento+2
+
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+
+ --> here we are using normal Add calls
+ CoolTip:Reset()
+ CoolTip:SetType ("menu")
+ CoolTip:SetFixedParameter (instancia)
+ CoolTip:SetColor ("main", "transparent")
+
+ ----------- overall
+
+ CoolTip:AddLine (segmentos.overall_standard, _, 1, "white")
+ CoolTip:AddMenu (1, instancia.TrocaTabela, -1)
+ CoolTip:AddIcon ("Interface\\QUESTFRAME\\UI-Quest-BulletPoint", "main", "left", 16, 16)
+
+ CoolTip:AddLine ("Enemy:", "--x--x--", 2, "white", "white")--localize-me
+
+ if (not _detalhes.tabela_overall.end_time) then
+ if (_detalhes.in_combat) then
+ local decorrido = _detalhes._tempo - _detalhes.tabela_overall.start_time
+ local minutos, segundos = _math_floor (decorrido/60), _math_floor (decorrido%60)
+ CoolTip:AddLine ("Time:", minutos.."m "..segundos.."s", 2, "white", "white") --localize-me
+ else
+ CoolTip:AddLine ("Time:", "--x--x--", 2, "white", "white") --localize-me
+ end
+ else
+ local decorrido = (_detalhes.tabela_overall.end_time) - _detalhes.tabela_overall.start_time
+ local minutos, segundos = _math_floor (decorrido/60), _math_floor (decorrido%60)
+ CoolTip:AddLine ("Time:", minutos.."m "..segundos.."s", 2, "white", "white") --localize-me
+ end
+
+ local earlyFight = ""
+ for i = _detalhes.segments_amount, 1, -1 do
+ if (_detalhes.tabela_historico.tabelas [i]) then
+ earlyFight = _detalhes.tabela_historico.tabelas [i].data_inicio
+ break
+ end
+ end
+ CoolTip:AddLine ("Start:", earlyFight, 2, "white", "white")--localize-me
+
+ local lastFight = ""
+ for i = 1, _detalhes.segments_amount do
+ if (_detalhes.tabela_historico.tabelas [i] and _detalhes.tabela_historico.tabelas [i].data_fim ~= 0) then
+ lastFight = _detalhes.tabela_historico.tabelas [i].data_fim
+ break
+ end
+ end
+ CoolTip:AddLine ("End:", lastFight, 2, "white", "white")--localize-me
+
+ ----------- current
+
+ CoolTip:AddLine (segmentos.current_standard, _, 1, "white")
+ CoolTip:AddMenu (1, instancia.TrocaTabela, 0)
+ CoolTip:AddIcon ("Interface\\QUESTFRAME\\UI-Quest-BulletPoint", "main", "left", 16, 16)
+
+ local enemy = _detalhes.tabela_vigente.is_boss and _detalhes.tabela_vigente.is_boss.name or _detalhes.tabela_vigente.enemy or "--x--x--"
+ CoolTip:AddLine ("Enemy:", enemy, 2, "white", "white")--localize-me
+
+ if (not _detalhes.tabela_vigente.end_time) then
+ if (_detalhes.in_combat) then
+ local decorrido = _detalhes._tempo - _detalhes.tabela_vigente.start_time
+ local minutos, segundos = _math_floor (decorrido/60), _math_floor (decorrido%60)
+ CoolTip:AddLine ("Time:", minutos.."m "..segundos.."s", 2, "white", "white") --localize-me
+ else
+ CoolTip:AddLine ("Time:", "--x--x--", 2, "white", "white") --localize-me
+ end
+ else
+ local decorrido = (_detalhes.tabela_vigente.end_time) - _detalhes.tabela_vigente.start_time
+ local minutos, segundos = _math_floor (decorrido/60), _math_floor (decorrido%60)
+ CoolTip:AddLine ("Time:", minutos.."m "..segundos.."s", 2, "white", "white") --localize-me
+ end
+
+
+ CoolTip:AddLine ("Start:", _detalhes.tabela_vigente.data_inicio, 2, "white", "white")--localize-me
+ CoolTip:AddLine ("End:", _detalhes.tabela_vigente.data_fim or "in progress", 2, "white", "white") --localize-me
+
+ ----------- segments
+
+ for i = 1, _detalhes.segments_amount do
+ CoolTip:AddLine (segmentos.past..i, _, 1, "white")
+ CoolTip:AddMenu (1, instancia.TrocaTabela, i)
+ CoolTip:AddIcon ("Interface\\QUESTFRAME\\UI-Quest-BulletPoint", "main", "left", 16, 16)
+
+ local thisCombat = _detalhes.tabela_historico.tabelas [i]
+ if (thisCombat) then
+ local enemy = thisCombat.is_boss and thisCombat.is_boss.name or thisCombat.enemy or "--x--x--"
+ CoolTip:AddLine ("Enemy:", enemy, 2, "white", "white")--localize-me
+
+ local decorrido = (thisCombat.end_time or _detalhes._tempo) - thisCombat.start_time
+ local minutos, segundos = _math_floor (decorrido/60), _math_floor (decorrido%60)
+ CoolTip:AddLine ("Time:", minutos.."m "..segundos.."s", 2, "white", "white")--localize-me
+
+ CoolTip:AddLine ("Start:", thisCombat.data_inicio, 2, "white", "white")--localize-me
+ CoolTip:AddLine ("End:", thisCombat.data_fim or "in progress", 2, "white", "white") --localize-me
+ else
+ CoolTip:AddLine ("Waiting a combat...", _, 2)--localize-me
+ end
+ end
+
+ CoolTip:SetLastSelected ("main", checked)
+
+ if (instancia.consolidate) then
+ CoolTip:SetOwner (self, "topleft", "topright", 3)
+ else
+ CoolTip:SetOwner (self)
+ end
+
+ CoolTip:SetOption ("TextSize", _detalhes.font_sizes.menus)
+ CoolTip:SetOption ("SubMenuIsTooltip", true)
+
+ CoolTip:SetOption ("ButtonHeightMod", -4)
+ CoolTip:SetOption ("ButtonsYMod", -4)
+ CoolTip:SetOption ("YSpacingMod", 4)
+
+ CoolTip:SetOption ("ButtonHeightModSub", 4)
+ CoolTip:SetOption ("ButtonsYModSub", 0)
+ CoolTip:SetOption ("YSpacingModSub", -4)
+
+ CoolTip:ShowCooltip()
+
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+ end)
+
+ --> Cooltip raw method
+ BaseFrame.cabecalho.segmento:SetScript ("OnLeave", function (self)
+ gump:Fade (BaseFrame.button_stretch, -1)
+
+ _detalhes.popup.buttonOver = false
+ BaseFrame.cabecalho.button_mouse_over = false
+
+ if (_detalhes.popup.active) then
+ local passou = 0
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ if (not _detalhes.popup.mouseOver and not _detalhes.popup.buttonOver) then
+ _detalhes.popup:ShowMe (false)
+ end
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+ else
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+
+ --> SELECIONAR O ATRIBUTO ----------------------------------------------------------------------------------------------------------------------------------------------------
+ BaseFrame.cabecalho.atributo = gump:NewDetailsButton (BaseFrame, _, instancia, instancia.TrocaTabela, instancia, -3, 16, 16, "Interface\\AddOns\\Details\\images\\sword")
+ BaseFrame.cabecalho.atributo:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+ BaseFrame.cabecalho.atributo:SetPoint ("left", BaseFrame.cabecalho.segmento, "right", 0, 0)
+
+ --> Cooltip automatic method through Injection
+
+ --> First we declare the function which will build the menu
+ local BuildAttributeMenu = function()
+ if (_detalhes.solo and _detalhes.solo == instancia.meu_id) then
+ return _detalhes:MontaSoloOption (instancia)
+ elseif (_detalhes.raid and _detalhes.raid == instancia.meu_id) then
+ return _detalhes:MontaRaidOption (instancia)
+ else
+ return _detalhes:MontaAtributosOption (instancia)
+ end
+ end
+
+ --> Now we create a table with some parameters
+ --> your frame need to have a member called CoolTip
+ BaseFrame.cabecalho.atributo.CoolTip = {
+ Type = "menu", --> the type, menu tooltip tooltipbars
+ BuildFunc = BuildAttributeMenu, --> called when user mouse over the frame
+ OnEnterFunc = function() BaseFrame.cabecalho.button_mouse_over = true; gump:Fade (BaseFrame.button_stretch, "alpha", 0.3) end,
+ OnLeaveFunc = function() BaseFrame.cabecalho.button_mouse_over = false; gump:Fade (BaseFrame.button_stretch, -1) end,
+ FixedValue = instancia,
+ Options = function()
+ if (instancia.consolidate) then
+ return {Anchor = instancia.consolidateFrame, MyAnchor = "topleft", RelativeAnchor = "topright", TextSize = _detalhes.font_sizes.menus}
+ else
+ return {TextSize = _detalhes.font_sizes.menus}
+ end
+ end}
+
+ --> install cooltip
+ _detalhes.popup:CoolTipInject (BaseFrame.cabecalho.atributo)
+
+ --> REPORTAR ----------------------------------------------------------------------------------------------------------------------------------------------------
+ BaseFrame.cabecalho.report = gump:NewDetailsButton (BaseFrame, _, instancia, _detalhes.Reportar, instancia, nil, 16, 16,
+ "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON", "Interface\\COMMON\\VOICECHAT-ON")
+ BaseFrame.cabecalho.report:SetPoint ("left", BaseFrame.cabecalho.atributo, "right", -6, 0)
+ BaseFrame.cabecalho.report:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+ BaseFrame.cabecalho.report:SetScript ("OnEnter", function()
+ _detalhes.popup.button_over = true
+ BaseFrame.cabecalho.button_mouse_over = true
+ end)
+ BaseFrame.cabecalho.report:SetScript ("OnLeave", function()
+ _detalhes.popup.button_over = false
+ BaseFrame.cabecalho.button_mouse_over = false
+ end)
+
+ --> BOSS INFO ----------------------------------------------------------------------------------------------------------------------------------------------------
+ --BaseFrame.cabecalho.boss_info = gump:NewDetailsButton (BaseFrame, BaseFrame, instancia, _detalhes.AbrirEncounterWindow, instancia, nil, 16, 16,
+ --"Interface\\COMMON\\help-i", "Interface\\COMMON\\help-i", "Interface\\COMMON\\help-i", "Interface\\COMMON\\help-i")
+ --BaseFrame.cabecalho.boss_info:SetPoint ("left", BaseFrame.cabecalho.report, "right", 1, 0)
+ --BaseFrame.cabecalho.boss_info:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+
+ --> NOVA INSTANCIA ----------------------------------------------------------------------------------------------------------------------------------------------------
+ BaseFrame.cabecalho.novo = _CreateFrame ("Button", nil, BaseFrame, "OptionsButtonTemplate")
+ BaseFrame.cabecalho.novo:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+
+ BaseFrame.cabecalho.novo:SetWidth (30)
+ BaseFrame.cabecalho.novo:SetHeight (15)
+ BaseFrame.cabecalho.novo:SetPoint ("RIGHT", BaseFrame.cabecalho.fechar, "LEFT", 1, 0)
+ BaseFrame.cabecalho.novo:SetScript ("OnClick", function() _detalhes:CriarInstancia(_, true); _detalhes.popup:ShowMe (false) end)
+ BaseFrame.cabecalho.novo:SetText ("#"..instancia.meu_id)
+
+ --> cooltip through inject
+ --> OnClick Function [1] caller [2] fixed param [3] param1 [4] param2
+ local OnClickNovoMenu = function (_, _, id)
+ _detalhes.CriarInstancia (_, _, id)
+ _detalhes.popup:ExecFunc (BaseFrame.cabecalho.novo)
+ end
+
+ --> Build Menu Function
+ local BuildClosedInstanceMenu = function()
+
+ local ClosedInstances = {}
+
+ for index = 1, #_detalhes.tabela_instancias, 1 do
+
+ local _this_instance = _detalhes.tabela_instancias [index]
+
+ if (not _this_instance.ativa) then --> só reabre se ela estiver ativa
+
+ --> pegar o que ela ta mostrando
+ local atributo = _this_instance.atributo
+ local sub_atributo = _this_instance.sub_atributo
+
+ if (atributo == 5) then --> custom
+
+ local CustomObject = _detalhes.custom [sub_atributo]
+
+ --> as addmenu dont support textcoords we need to add in parts, first adding text and menu, after we add the icon
+ --> text and menu can be added in one call if doesnt need more details like color or right text
+ CoolTip:AddMenu (1, OnClickNovoMenu, index, nil, nil, "#".. index .. " " .. _detalhes.atributos.lista [atributo] .. " - " .. CustomObject.name, _, true)
+ CoolTip:AddIcon (CustomObject.icon, 1, 1, 20, 20, 0, 1, 0, 1)
+
+ else
+ local modo = _this_instance.modo
+
+ if (modo == 1) then --alone
+
+ atributo = _detalhes.SoloTables.Mode or 1
+ local SoloInfo = _detalhes.SoloTables.Menu [atributo]
+ CoolTip:AddMenu (1, OnClickNovoMenu, index, nil, nil, "#".. index .. " " .. SoloInfo [1], _, true)
+ CoolTip:AddIcon (SoloInfo [2], 1, 1, 20, 20, 0, 1, 0, 1)
+
+ elseif (modo == 4) then --raid
+
+ atributo = _detalhes.RaidTables.Mode or 1
+ local RaidInfo = _detalhes.RaidTables.Menu [atributo]
+ CoolTip:AddMenu (1, OnClickNovoMenu, index, nil, nil, "#".. index .. " " .. RaidInfo [1], _, true)
+ CoolTip:AddIcon (RaidInfo [2], 1, 1, 20, 20, 0, 1, 0, 1)
+
+ else
+
+ CoolTip:AddMenu (1, OnClickNovoMenu, index, nil, nil, "#".. index .. " " .. _detalhes.atributos.lista [atributo] .. " - " .. _detalhes.sub_atributos [atributo].lista [sub_atributo], _, true)
+ CoolTip:AddIcon (_detalhes.sub_atributos [atributo].icones[sub_atributo] [1], 1, 1, 20, 20, unpack (_detalhes.sub_atributos [atributo].icones[sub_atributo] [2]))
+ end
+ end
+
+
+ end
+ end
+ return ClosedInstances
+ end
+
+ --> Inject Options Table
+ BaseFrame.cabecalho.novo.CoolTip = {
+ --> cooltip type "menu" "tooltip" "tooltipbars"
+ Type = "menu",
+ --> will call for build menu
+ BuildFunc = BuildClosedInstanceMenu,
+ --> a hook for OnEnterScript
+ OnEnterFunc = function() gump:Fade (BaseFrame.button_stretch, "alpha", 0.3) end,
+ --> a hook for OnLeaveScript
+ OnLeaveFunc = function() gump:Fade (BaseFrame.button_stretch, -1) end,
+ --> instancia is the first parameter sent after click, before parameters
+ FixedValue = instancia,
+ Options = {TextSize = 10, NoLastSelectedBar = true}}
+
+ --> Inject
+ _detalhes.popup:CoolTipInject (BaseFrame.cabecalho.novo)
+
+ --> RESETAR HISTORICO ----------------------------------------------------------------------------------------------------------------------------------------------------
+ if (not _detalhes.ResetButton) then
+
+ _detalhes.ResetButtonInstance = instancia.meu_id
+ _detalhes.ResetButtonMode = 1
+
+ function _detalhes:ResetButtonSnapTo (instancia)
+ if (type (instancia) == "number") then
+ instancia = _detalhes:GetInstance (instancia)
+ end
+
+ if (instancia.baseframe:GetWidth() < 215) then
+ _detalhes.ResetButtonMode = 2
+ else
+ _detalhes.ResetButtonMode = 1
+ end
+
+ _detalhes.ResetButton:SetParent (instancia.baseframe)
+ _detalhes.ResetButton2:SetParent (instancia.baseframe)
+ _detalhes.ResetButton:SetPoint ("RIGHT", instancia.baseframe.cabecalho.novo, "LEFT")
+ _detalhes.ResetButton2:SetPoint ("RIGHT", instancia.baseframe.cabecalho.novo, "LEFT", 3, 0)
+ _detalhes.ResetButton:SetFrameLevel (instancia.baseframe.UPFrame:GetFrameLevel()+1)
+ _detalhes.ResetButton2:SetFrameLevel (instancia.baseframe.UPFrame:GetFrameLevel()+1)
+
+ if (_detalhes.ResetButtonMode == 1) then
+ gump:Fade (_detalhes.ResetButton, 0)
+ gump:Fade (_detalhes.ResetButton2, 1)
+ else
+ gump:Fade (_detalhes.ResetButton, 1)
+ gump:Fade (_detalhes.ResetButton2, 0)
+ end
+
+ end
+
+-----------------> big button
+ _detalhes.ResetButton = _CreateFrame ("Button", nil, BaseFrame, "OptionsButtonTemplate")
+ _detalhes.ResetButton:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+ _detalhes.ResetButton:SetWidth (50)
+ _detalhes.ResetButton:SetHeight (15)
+ _detalhes.ResetButton:SetPoint ("RIGHT", BaseFrame.cabecalho.novo, "LEFT")
+
+ _detalhes.ResetButton:SetText (Loc ["STRING_ERASE"])
+
+ _detalhes.ResetButton:SetScript ("OnClick", function() _detalhes.tabela_historico:resetar() end)
+ _detalhes.ResetButton:SetScript ("OnEnter", function (self)
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+ end)
+ _detalhes.ResetButton:SetScript ("OnLeave", function (self)
+ gump:Fade (BaseFrame.button_stretch, -1)
+ if (_detalhes.popup.active) then
+ local passou = 0
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ if (not _detalhes.popup.mouse_over and not _detalhes.popup.button_over) then
+ _detalhes.popup:ShowMe (false)
+ end
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+ else
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+
+----------------> small button
+ _detalhes.ResetButton2 = _CreateFrame ("Button", nil, BaseFrame, "OptionsButtonTemplate")
+ _detalhes.ResetButton2:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+ _detalhes.ResetButton2:SetWidth (22)
+ _detalhes.ResetButton2:SetHeight (15)
+ _detalhes.ResetButton2:SetPoint ("RIGHT", BaseFrame.cabecalho.novo, "LEFT", 2, 0)
+
+ local text = _detalhes.ResetButton2:CreateFontString (nil, "overlay", "GameFont_Gigantic")
+ text:SetText ("-")
+ _detalhes.ResetButton2:SetFontString (text)
+ _detalhes.ResetButton2:SetNormalFontObject ("GameFont_Gigantic")
+ _detalhes.ResetButton2:SetHighlightFontObject ("GameFont_Gigantic")
+
+ _detalhes.ResetButton2:SetScript ("OnClick", function() _detalhes.tabela_historico:resetar() end)
+ _detalhes.ResetButton2:SetScript ("OnEnter", function (self)
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+ end)
+ _detalhes.ResetButton2:SetScript ("OnLeave", function (self)
+ gump:Fade (BaseFrame.button_stretch, -1)
+ if (_detalhes.popup.active) then
+ local passou = 0
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ if (not _detalhes.popup.mouse_over and not _detalhes.popup.button_over) then
+ _detalhes.popup:ShowMe (false)
+ end
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+ else
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+
+ end
+
+--> fim botão reset
+
+--> Botão de Ajuda ----------------------------------------------------------------------------------------------------------------------------------------------------
+
+ if (instancia.meu_id == 1 and _detalhes.tutorial.main_help_button < 10) then
+
+ _detalhes.tutorial.main_help_button = _detalhes.tutorial.main_help_button + 1
+
+ --> help button
+ local helpButton = CreateFrame ("button", "DetailsMainWindowHelpButton", BaseFrame, "MainHelpPlateButton")
+ helpButton:SetWidth (28)
+ helpButton:SetHeight (28)
+ helpButton.I:SetWidth (22)
+ helpButton.I:SetHeight (22)
+ helpButton.Ring:SetWidth (28)
+ helpButton.Ring:SetHeight (28)
+ helpButton.Ring:SetPoint ("center", 5, -6)
+
+ helpButton:SetPoint ("topright", BaseFrame, "topleft", 37, 37)
+
+ helpButton:SetFrameLevel (0)
+ helpButton:SetFrameStrata ("LOW")
+
+ local mainWindowHelp = {
+ FramePos = {x = 0, y = 10},
+ FrameSize = {width = 300, height = 85},
+
+ --> modo, segmento e atributo
+ [1] ={HighLightBox = {x = 25, y = 10, width = 60, height = 20},
+ ButtonPos = { x = 32, y = 40},
+ ToolTipDir = "RIGHT",
+ ToolTipText = Loc ["STRING_HELP_MENUS"]
+ },
+ --> delete
+ [2] ={HighLightBox = {x = 195, y = 10, width = 47, height = 20},
+ ButtonPos = { x = 197, y = 5},
+ ToolTipDir = "LEFT",
+ ToolTipText = Loc ["STRING_HELP_ERASE"]
+ },
+ --> menu da instancia
+ [3] ={HighLightBox = {x = 244, y = 10, width = 30, height = 20},
+ ButtonPos = { x = 237, y = 5},
+ ToolTipDir = "RIGHT",
+ ToolTipText = Loc ["STRING_HELP_INSTANCE"]
+ },
+ --> stretch
+ [4] ={HighLightBox = {x = 244, y = 30, width = 30, height = 20},
+ ButtonPos = { x = 237, y = 57},
+ ToolTipDir = "RIGHT",
+ ToolTipText = Loc ["STRING_HELP_STRETCH"]
+ },
+ --> status bar
+ [5] ={HighLightBox = {x = 0, y = -101, width = 300, height = 20},
+ ButtonPos = { x = 126, y = -88},
+ ToolTipDir = "LEFT",
+ ToolTipText = Loc ["STRING_HELP_STATUSBAR"]
+ },
+ --> switch menu
+ [6] ={HighLightBox = {x = 0, y = -10, width = 300, height = 95},
+ ButtonPos = { x = 127, y = -37},
+ ToolTipDir = "LEFT",
+ ToolTipText = Loc ["STRING_HELP_SWITCH"]
+ },
+ --> resizer
+ [7] ={HighLightBox = {x = 250, y = -81, width = 50, height = 20},
+ ButtonPos = { x = 253, y = -52},
+ ToolTipDir = "RIGHT",
+ ToolTipText = Loc ["STRING_HELP_RESIZE"]
+ },
+ }
+
+ helpButton:SetScript ("OnClick", function()
+ if (not HelpPlate_IsShowing (mainWindowHelp)) then
+
+ instancia:SetSize (300, 95)
+
+ HelpPlate_Show (mainWindowHelp, BaseFrame, helpButton, true)
+ else
+ HelpPlate_Hide (true)
+ end
+ end)
+
+ end
+
+---------> consolidate frame ----------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local consolidateFrame = CreateFrame ("frame", nil, _detalhes.listener)
+ consolidateFrame:SetWidth (21)
+ consolidateFrame:SetHeight (83)
+ consolidateFrame:SetFrameLevel (BaseFrame:GetFrameLevel()-1)
+ consolidateFrame:SetPoint ("BOTTOMLEFT", BaseFrame.cabecalho.ball, "BOTTOMRIGHT", 0, 20)
+ consolidateFrame:SetFrameStrata ("FULLSCREEN")
+ consolidateFrame:Hide()
+ instancia.consolidateFrame = consolidateFrame
+
+---------> consolidate texture
+
+ local frameTexture = consolidateFrame:CreateTexture (nil, "background")
+ frameTexture:SetTexture ("Interface\\AddOns\\Details\\images\\consolidate_frame")
+ frameTexture:SetPoint ("top", consolidateFrame, "top", .5, 0)
+ frameTexture:SetWidth (32)
+ frameTexture:SetHeight (83)
+ frameTexture:SetTexCoord (0, 1, 0, 0.6484375)
+
+---------> consolidate button
+
+ local consolidateButton = CreateFrame ("button", nil, BaseFrame)
+ consolidateButton:SetWidth (16)
+ consolidateButton:SetHeight (16)
+ consolidateButton:SetFrameLevel (BaseFrame.UPFrame:GetFrameLevel()+1)
+ consolidateButton:SetPoint ("BOTTOMLEFT", BaseFrame.cabecalho.ball, "BOTTOMRIGHT", -2, 2)
+
+ local normal_texture = consolidateButton:CreateTexture (nil, "overlay")
+ --normal_texture:SetTexture ("Interface\\AddOns\\Details\\images\\consolidate_frame")
+ normal_texture:SetTexture ("Interface\\GossipFrame\\HealerGossipIcon")
+ normal_texture:SetVertexColor (.9, .8, 0)
+ --normal_texture:SetTexCoord (0, .5, 0.875, 1)
+ --normal_texture:SetTexCoord (0, 0.375, 0.75, 0.875)
+ normal_texture:SetWidth (16)
+ normal_texture:SetHeight (16)
+ normal_texture:SetPoint ("center", consolidateButton, "center")
+
+ consolidateButton:Hide()
+ instancia.consolidateButton = consolidateButton
+ instancia.consolidateButtonTexture = normal_texture
+
+---------> consolidate scripts
+
+ consolidateFrame:SetScript ("OnEnter", function (self)
+ consolidateFrame.mouse_over = true
+ self:SetScript ("OnUpdate", nil)
+ end)
+
+ consolidateFrame:SetScript ("OnLeave", function (self)
+ consolidateFrame.mouse_over = false
+ local passou = 0
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.5) then
+ if (not _detalhes.popup.active and not BaseFrame.cabecalho.button_mouse_over) then
+ consolidateFrame:Hide()
+ --normal_texture:SetTexCoord (0, .5, 0.875, 1)
+ normal_texture:SetBlendMode ("BLEND")
+ self:SetScript ("OnUpdate", nil)
+ end
+ passou = 0
+ end
+ end)
+ end)
+
+ consolidateButton:SetScript ("OnEnter", function (self)
+ gump:Fade (BaseFrame.button_stretch, "alpha", 0.3)
+ local passou = 0
+ consolidateFrame:SetScript ("OnUpdate", nil)
+ --normal_texture:SetTexCoord (.5, 1, 0.875, 1)
+ normal_texture:SetBlendMode ("ADD")
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ consolidateFrame:Show()
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+ end)
+
+ consolidateButton:SetScript ("OnLeave", function (self)
+ gump:Fade (BaseFrame.button_stretch, -1)
+ local passou = 0
+ self:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ if (not consolidateFrame.mouse_over and not BaseFrame.cabecalho.button_mouse_over and not _detalhes.popup.active) then
+ consolidateFrame:Hide()
+ normal_texture:SetBlendMode ("BLEND")
+ --normal_texture:SetTexCoord (0, .5, 0.875, 1)
+ end
+ self:SetScript ("OnUpdate", nil)
+ end
+ end)
+ end)
+
+
+
+end
diff --git a/gumps/janela_report.lua b/gumps/janela_report.lua
new file mode 100644
index 00000000..66dace77
--- /dev/null
+++ b/gumps/janela_report.lua
@@ -0,0 +1,482 @@
+local Loc = LibStub ("AceLocale-3.0"):GetLocale ( "Details" )
+
+local _detalhes = _G._detalhes
+local gump = _detalhes.gump
+
+--lua locals
+local _cstr = tostring --> lua local
+local _math_ceil = math.ceil --> lua local
+local _math_floor = math.floor --> lua local
+local _string_len = string.len --> lua local
+local _pairs = pairs --> lua local
+local _tinsert = tinsert --> lua local
+local _IsInRaid = IsInRaid --> lua local
+
+local _CreateFrame = CreateFrame --> wow api locals
+local _IsInGuild = IsInGuild --> wow api locals
+local _GetChannelList = GetChannelList --> wow api locals
+local _UIParent = UIParent --> wow api locals
+
+--> got weird errors with globals, not sure why
+local _UIDropDownMenu_SetSelectedID = UIDropDownMenu_SetSelectedID --> wow api locals
+local _UIDropDownMenu_CreateInfo = UIDropDownMenu_CreateInfo --> wow api locals
+local _UIDropDownMenu_AddButton = UIDropDownMenu_AddButton --> wow api locals
+local _UIDropDownMenu_Initialize = UIDropDownMenu_Initialize --> wow api locals
+local _UIDropDownMenu_SetWidth = UIDropDownMenu_SetWidth --> wow api locals
+local _UIDropDownMenu_SetButtonWidth = UIDropDownMenu_SetButtonWidth --> wow api locals
+local _UIDropDownMenu_SetSelectedValue = UIDropDownMenu_SetSelectedValue --> wow api locals
+local _UIDropDownMenu_JustifyText = UIDropDownMenu_JustifyText --> wow api locals
+local _UISpecialFrames = UISpecialFrames --> wow api locals
+
+
+--> details API functions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ function _detalhes:SendReportLines (lines)
+ if (type (lines) == "string") then
+ lines = {lines}
+ elseif (type (lines) ~= "table") then
+ return _detalhes:NewError ("SendReportLines parameter 1 must be a table or string.")
+ end
+ return _detalhes:envia_relatorio (lines, true)
+ end
+
+ function _detalhes:SendReportWindow (func, _current, _inverse, _slider)
+
+ if (type (func) ~= "function") then
+ return _detalhes:NewError ("SendReportWindow parameter 1 must be a function.")
+ end
+
+ if (not _detalhes.janela_report) then
+ _detalhes.janela_report = gump:CriaJanelaReport()
+ end
+
+ if (_current) then
+ _G ["Details_Report_CB_1"]:Enable()
+ _G ["Details_Report_CB_1Text"]:SetTextColor (1, 1, 1, 1)
+ else
+ _G ["Details_Report_CB_1"]:Disable()
+ _G ["Details_Report_CB_1Text"]:SetTextColor (.5, .5, .5, 1)
+ end
+
+ if (_inverse) then
+ _G ["Details_Report_CB_2"]:Enable()
+ _G ["Details_Report_CB_2Text"]:SetTextColor (1, 1, 1, 1)
+ else
+ _G ["Details_Report_CB_2"]:Disable()
+ _G ["Details_Report_CB_2Text"]:SetTextColor (.5, .5, .5, 1)
+ end
+
+ if (_slider) then
+ _detalhes.janela_report.slider:Enable()
+ _detalhes.janela_report.slider.lockTexture:Hide()
+ _detalhes.janela_report.slider.amt:Show()
+ else
+ _detalhes.janela_report.slider:Disable()
+ _detalhes.janela_report.slider.lockTexture:Show()
+ _detalhes.janela_report.slider.amt:Hide()
+ end
+
+ if (_detalhes.janela_report.ativa) then
+ UIFrameFlash (_detalhes.janela_report, 0.2, 0.2, 0.19, true, 0, 0)
+ end
+
+ _detalhes.janela_report.ativa = true
+ _detalhes.janela_report.enviar:SetScript ("OnClick", function() func (_G ["Details_Report_CB_1"]:GetChecked(), _G ["Details_Report_CB_2"]:GetChecked(), _detalhes.report_lines) end)
+
+ gump:Fade (_detalhes.janela_report, 0)
+
+ return true
+ end
+
+
+--> internal details report functions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ function _detalhes:Reportar (param2, options)
+
+ if (not _detalhes.janela_report) then
+ _detalhes.janela_report = gump:CriaJanelaReport()
+ end
+
+ --> trabalha com as opções:
+ if (options and options._no_current) then
+ _G ["Details_Report_CB_1"]:Disable()
+ _G ["Details_Report_CB_1Text"]:SetTextColor (.5, .5, .5, 1)
+ else
+ _G ["Details_Report_CB_1"]:Enable()
+ _G ["Details_Report_CB_1Text"]:SetTextColor (1, 1, 1, 1)
+ end
+
+ if (options and options._no_inverse) then
+ _G ["Details_Report_CB_2"]:Disable()
+ _G ["Details_Report_CB_2Text"]:SetTextColor (.5, .5, .5, 1)
+ else
+ _G ["Details_Report_CB_2"]:Enable()
+ _G ["Details_Report_CB_2Text"]:SetTextColor (1, 1, 1, 1)
+ end
+
+ _detalhes.janela_report.slider:Enable()
+ _detalhes.janela_report.slider.lockTexture:Hide()
+ _detalhes.janela_report.slider.amt:Show()
+
+ if (options) then
+ _detalhes.janela_report.enviar:SetScript ("OnClick", function() self:monta_relatorio (param2, options._custom) end)
+ else
+ _detalhes.janela_report.enviar:SetScript ("OnClick", function() self:monta_relatorio (param2) end)
+ end
+
+ if (_detalhes.janela_report.ativa) then
+ UIFrameFlash (_detalhes.janela_report, 0.2, 0.2, 0.19, true, 0, 0)
+ end
+
+ _detalhes.janela_report.ativa = true
+ gump:Fade (_detalhes.janela_report, 0)
+ end
+
+--> build report frame gump -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+--> script
+ local function seta_scripts (este_gump)
+ --> Janela
+ este_gump:SetScript ("OnMouseDown",
+ function (self, botao)
+ if (botao == "LeftButton") then
+ self:StartMoving()
+ self.isMoving = true
+ end
+ end)
+
+ este_gump:SetScript ("OnMouseUp",
+ function (self)
+ if (self.isMoving) then
+ self:StopMovingOrSizing()
+ self.isMoving = false
+ end
+ end)
+ end
+
+--> dropdown menus
+
+ local function cria_drop_down (este_gump)
+
+ local selecionar = _CreateFrame ("Button", "Details_Report_DropDown", este_gump, "UIDropDownMenuTemplate")
+ este_gump.select = selecionar
+
+ selecionar:SetPoint ("topleft", este_gump, "topleft", 93, -53)
+
+ local function OnClick (self)
+ _UIDropDownMenu_SetSelectedID (selecionar, self:GetID())
+ _detalhes.report_where = self.value
+ end
+
+ local lista = {
+ {Loc ["STRING_REPORTFRAME_PARTY"], "PARTY", function() return GetNumSubgroupMembers() > 0 end},
+ {Loc ["STRING_REPORTFRAME_RAID"], "RAID", _IsInRaid},
+ {Loc ["STRING_REPORTFRAME_GUILD"], "GUILD", _IsInGuild},
+ {Loc ["STRING_REPORTFRAME_OFFICERS"], "OFFICER", _IsInGuild},
+ {Loc ["STRING_REPORTFRAME_WHISPER"], "WHISPER"},
+ {Loc ["STRING_REPORTFRAME_WHISPERTARGET"], "WHISPER2"},
+ {Loc ["STRING_REPORTFRAME_SAY"], "SAY"}
+ }
+
+ local function initialize (self, level)
+ local info = _UIDropDownMenu_CreateInfo()
+
+ for i = 8, #lista do
+ lista [i] = nil
+ end
+
+ local channels = {_GetChannelList()} --> coloca o resultado em uma tabela .. {id1, canal1, id2, canal2}
+ for i = 1, #channels, 2 do --> total de canais
+ lista [#lista+1] = {channels [i]..". "..channels [i+1], "CHANNEL|"..channels [i+1]}
+ end
+
+ for index, v in _pairs (lista) do
+
+ if (not v[3] or (type (v[3]) == "function" and v[3]())) then
+ info = _UIDropDownMenu_CreateInfo()
+ info.text = v[1]
+ info.value = v[2]
+ info.func = OnClick
+ _UIDropDownMenu_AddButton (info, level)
+ end
+ end
+ end
+
+ _UIDropDownMenu_Initialize (selecionar, initialize)
+ _UIDropDownMenu_SetWidth (selecionar, 165)
+ _UIDropDownMenu_SetButtonWidth (selecionar, 120)
+ _UIDropDownMenu_SetSelectedValue (selecionar, "WHISPER")
+ _detalhes.report_where = "WHISPER"
+ _UIDropDownMenu_JustifyText (selecionar, "LEFT")
+ end
+
+--> slider
+
+ local function cria_slider (este_gump)
+
+ este_gump.linhas_amt = este_gump:CreateFontString (nil, "OVERLAY", "GameFontHighlight")
+ este_gump.linhas_amt:SetText (Loc ["STRING_REPORTFRAME_LINES"])
+ este_gump.linhas_amt:SetTextColor (.9, .9, .9, 1)
+ este_gump.linhas_amt:SetPoint ("bottomleft", este_gump, "bottomleft", 58, 12)
+ _detalhes:SetFontSize (este_gump.linhas_amt, 10)
+
+ local slider = _CreateFrame ("Slider", "Details_Report_Slider", este_gump)
+ este_gump.slider = slider
+ slider:SetPoint ("bottomleft", este_gump, "bottomleft", 58, -7)
+
+ slider.thumb = slider:CreateTexture (nil, "artwork")
+ slider.thumb:SetTexture ("Interface\\Buttons\\UI-ScrollBar-Knob")
+ slider.thumb:SetSize (30, 24)
+ slider.thumb:SetAlpha (0.7)
+
+ local lockTexture = slider:CreateTexture (nil, "overlay")
+ lockTexture:SetPoint ("center", slider.thumb, "center", -1, -1)
+ lockTexture:SetTexture ("Interface\\Buttons\\CancelButton-Up")
+ lockTexture:SetWidth (29)
+ lockTexture:SetHeight (24)
+ lockTexture:Hide()
+ slider.lockTexture = lockTexture
+
+ slider:SetThumbTexture (slider.thumb) --depois
+ slider:SetOrientation ("HORIZONTAL")
+ slider:SetMinMaxValues (1, 25)
+ slider:SetValueStep (1)
+ slider:SetWidth (232)
+ slider:SetHeight (20)
+
+ local last_value = _detalhes.report_lines or 5
+ slider:SetValue (last_value)
+
+ slider.amt = slider:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ local amt = slider:GetValue()
+ if (amt < 10) then
+ amt = "0"..amt
+ end
+ slider.amt:SetText (amt)
+ slider.amt:SetTextColor (.8, .8, .8, 1)
+
+ slider.amt:SetPoint ("center", slider.thumb, "center")
+
+ slider:SetScript ("OnValueChanged", function (self)
+ local amt = self:GetValue()
+ _detalhes.report_lines = amt
+ if (amt < 10) then
+ amt = "0"..amt
+ end
+ self.amt:SetText (amt)
+ end)
+
+ slider:SetScript ("OnEnter", function (self)
+ slider.thumb:SetAlpha (1)
+ end)
+
+ slider:SetScript ("OnLeave", function (self)
+ slider.thumb:SetAlpha (0.7)
+ end)
+
+ end
+
+--> whisper taget field
+
+ local function cria_wisper_field (este_gump)
+
+ este_gump.wisp_who = este_gump:CreateFontString (nil, "OVERLAY", "GameFontHighlight")
+ este_gump.wisp_who:SetText (Loc ["STRING_REPORTFRAME_WHISPER"] .. ":")
+ este_gump.wisp_who:SetTextColor (1, 1, 1, 1)
+
+ este_gump.wisp_who:SetPoint ("topleft", este_gump.select, "topleft", 28, -30)
+
+ _detalhes:SetFontSize (este_gump.wisp_who, 10)
+
+ --editbox
+ local editbox = _CreateFrame ("EditBox", nil, este_gump)
+ este_gump.editbox = editbox
+
+ editbox:SetAutoFocus (false)
+ editbox:SetFontObject ("GameFontHighlightSmall")
+
+ editbox:SetPoint ("TOPLEFT", este_gump.select, "TOPLEFT", 78, -28)
+
+ editbox:SetHeight (14)
+ editbox:SetWidth (120)
+ editbox:SetJustifyH ("LEFT")
+ editbox:EnableMouse(true)
+ editbox:SetBackdrop ({
+ bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ edgeFile = "Interface\\ChatFrame\\ChatFrameBackground",
+ tile = true, edgeSize = 1, tileSize = 5,
+ })
+ editbox:SetBackdropColor(0, 0, 0, 0.0)
+ editbox:SetBackdropBorderColor(0.0, 0.0, 0.0, 0.0)
+
+ local last_value = _detalhes.report_to_who or ""
+ editbox:SetText (last_value)
+ editbox.perdeu_foco = nil
+ editbox.focus = false
+
+ editbox:SetScript ("OnEnterPressed", function ()
+ local texto = _detalhes:trim (editbox:GetText())
+ if (_string_len (texto) > 0) then
+ _detalhes.report_to_who = texto
+ editbox:AddHistoryLine (texto)
+ editbox:SetText (texto)
+ else
+ _detalhes.report_to_who = ""
+ editbox:SetText ("")
+ end
+ editbox.perdeu_foco = true --> isso aqui pra quando estiver editando e clicar em outra caixa
+ editbox:ClearFocus()
+ end)
+
+ editbox:SetScript ("OnEscapePressed", function()
+ editbox:SetText("")
+ _detalhes.report_to_who = ""
+ editbox.perdeu_foco = true
+ editbox:ClearFocus()
+ end)
+
+ editbox:SetScript ("OnEnter", function()
+ editbox.mouse_over = true
+ editbox:SetBackdropColor(0.1, 0.1, 0.1, 0.7)
+ if (editbox:GetText() == "" and not editbox.focus) then
+ editbox:SetText (Loc ["STRING_REPORTFRAME_INSERTNAME"])
+ end
+ end)
+
+ editbox:SetScript ("OnLeave", function()
+ editbox.mouse_over = false
+ editbox:SetBackdropColor(0.0, 0.0, 0.0, 0.0)
+ if (not editbox:HasFocus()) then
+ if (editbox:GetText() == Loc ["STRING_REPORTFRAME_INSERTNAME"]) then
+ editbox:SetText("")
+ end
+ end
+ end)
+
+ editbox:SetScript ("OnEditFocusGained", function()
+ if (editbox:GetText() == Loc ["STRING_REPORTFRAME_INSERTNAME"]) then
+ editbox:SetText("")
+ end
+
+ if (editbox:GetText() ~= "") then
+ --> selecionar todo o texto
+ editbox:HighlightText (0, editbox:GetNumLetters())
+ end
+
+ editbox.focus = true
+ end)
+
+ editbox:SetScript ("OnEditFocusLost", function()
+ if (editbox.perdeu_foco == nil) then
+ local texto = _detalhes:trim (editbox:GetText())
+ if (_string_len (texto) > 0) then
+ _detalhes.report_to_who = texto
+ else
+ _detalhes.report_to_who = ""
+ editbox:SetText ("")
+ end
+ else
+ editbox.perdeu_foco = nil
+ end
+
+ editbox.focus = false
+ end)
+ end
+
+--> both check buttons
+
+ function cria_check_buttons (este_gump)
+ local checkbox = _CreateFrame ("CheckButton", "Details_Report_CB_1", este_gump, "ChatConfigCheckButtonTemplate")
+ checkbox:SetPoint ("topleft", este_gump.wisp_who, "bottomleft", -25, -4)
+ _G [checkbox:GetName().."Text"]:SetText (Loc ["STRING_REPORTFRAME_CURRENT"])
+ _detalhes:SetFontSize (_G [checkbox:GetName().."Text"], 10)
+ checkbox.tooltip = Loc ["STRING_REPORTFRAME_CURRENTINFO"]
+ checkbox:SetHitRectInsets (0, -35, 0, 0)
+
+ local checkbox2 = _CreateFrame ("CheckButton", "Details_Report_CB_2", este_gump, "ChatConfigCheckButtonTemplate")
+ checkbox2:SetPoint ("topleft", este_gump.wisp_who, "bottomleft", 35, -4)
+ _G [checkbox2:GetName().."Text"]:SetText (Loc ["STRING_REPORTFRAME_REVERT"])
+ _detalhes:SetFontSize (_G [checkbox2:GetName().."Text"], 10)
+ checkbox2.tooltip = Loc ["STRING_REPORTFRAME_REVERTINFO"]
+ checkbox2:SetHitRectInsets (0, -35, 0, 0)
+ end
+
+--> frame creation function
+
+ function gump:CriaJanelaReport()
+
+ local este_gump = _CreateFrame ("Frame", "DetailsReportWindow", _UIParent)
+ este_gump:SetFrameStrata ("HIGH")
+
+ _tinsert (_UISpecialFrames, este_gump:GetName())
+
+ este_gump:SetScript ("OnHide", function (self)
+ if (not este_gump.hidden or este_gump.fading_in) then --> trick to fade an window closed by pressing escape
+ este_gump:Show()
+ gump:Fade (este_gump, "in")
+ _detalhes.janela_report.ativa = false
+ end
+ end)
+
+ este_gump:SetPoint ("CENTER", UIParent)
+ este_gump:SetWidth (320)
+ este_gump:SetHeight (128)
+ este_gump:EnableMouse (true)
+ este_gump:SetResizable (false)
+ este_gump:SetMovable (true)
+
+ _detalhes.janela_report = este_gump
+
+ --> icone
+ este_gump.icone = este_gump:CreateTexture (nil, "BACKGROUND")
+ este_gump.icone:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 40, -10)
+ este_gump.icone:SetTexture ("Interface\\AddOns\\Details\\images\\report_frame_icons") --> top left
+ este_gump.icone:SetWidth (64)
+ este_gump.icone:SetHeight (64)
+ este_gump.icone:SetTexCoord (1/256, 64/256, 1/256, 64/256) --left right top bottom
+
+ --> cria as 2 partes do fundo da janela
+ este_gump.bg1 = este_gump:CreateTexture (nil, "BORDER")
+ este_gump.bg1:SetPoint ("TOPLEFT", este_gump, "TOPLEFT", 0, 0)
+ este_gump.bg1:SetTexture ("Interface\\AddOns\\Details\\images\\report_frame1") --> top left
+
+ este_gump.bg2 = este_gump:CreateTexture (nil, "BORDER")
+ este_gump.bg2:SetPoint ("TOPRIGHT", este_gump, "TOPRIGHT", 0, 0)
+ este_gump.bg2:SetTexture ("Interface\\AddOns\\Details\\images\\report_frame2") --> top right
+
+ --> botão de fechar
+ este_gump.fechar = CreateFrame ("Button", nil, este_gump, "UIPanelCloseButton")
+ este_gump.fechar:SetWidth (32)
+ este_gump.fechar:SetHeight (32)
+ este_gump.fechar:SetPoint ("TOPRIGHT", este_gump, "TOPRIGHT", -20, -23)
+ este_gump.fechar:SetText ("X")
+ este_gump.fechar:SetScript ("OnClick", function()
+ gump:Fade (este_gump, 1)
+ _detalhes.janela_report.ativa = false
+ end)
+
+ este_gump.titulo = este_gump:CreateFontString (nil, "OVERLAY", "GameFontHighlightLeft")
+ este_gump.titulo:SetText (Loc ["STRING_REPORTFRAME_WINDOW_TITLE"])
+ este_gump.titulo:SetTextColor (0.999, 0.819, 0, 1)
+ este_gump.titulo:SetPoint ("topleft", este_gump, "topleft", 120, -33)
+
+ seta_scripts (este_gump)
+
+ cria_drop_down (este_gump)
+ cria_slider (este_gump)
+ cria_wisper_field (este_gump)
+ cria_check_buttons (este_gump)
+
+ este_gump.enviar = _CreateFrame ("Button", nil, este_gump, "OptionsButtonTemplate")
+
+ este_gump.enviar:SetPoint ("topleft", este_gump.editbox, "topleft", 61, -19)
+
+ este_gump.enviar:SetWidth (60)
+ este_gump.enviar:SetHeight (15)
+ este_gump.enviar:SetText (Loc ["STRING_REPORTFRAME_SEND"])
+
+ gump:Fade (este_gump, 1)
+
+ return este_gump
+
+ end
\ No newline at end of file
diff --git a/gumps/switch.lua b/gumps/switch.lua
new file mode 100644
index 00000000..0093ce64
--- /dev/null
+++ b/gumps/switch.lua
@@ -0,0 +1,328 @@
+local _detalhes = _G._detalhes
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ( "Details" )
+
+local gump = _detalhes.gump
+
+--lua locals
+local _unpack = unpack
+local _math_floor = math.floor
+
+--api locals
+do
+ local _CreateFrame = CreateFrame
+ local _UIParent = UIParent
+
+ local gump_fundo_backdrop = {
+ bgFile = "Interface\\AddOns\\Details\\images\\background",
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ tile = true, tileSize = 16, edgeSize = 4,
+ insets = {left = 0, right = 0, top = 0, bottom = 0}}
+
+ local frame = _CreateFrame ("frame", "DetailsSwitchPanel", _UIParent)
+ frame:SetPoint ("center", _UIParent, "center", 500, -300)
+ frame:SetWidth (250)
+ frame:SetHeight (100)
+ frame:SetBackdrop (gump_fundo_backdrop)
+ frame:SetBackdropBorderColor (170/255, 170/255, 170/255)
+ frame:SetBackdropColor (24/255, 24/255, 24/255, .8)
+
+ function _detalhes.switch:CloseMe()
+ _detalhes.switch.frame:Hide()
+ _detalhes.switch.frame:SetBackdropColor (24/255, 24/255, 24/255, .8)
+ end
+
+ --> limitação: não tenho como pegar o base frame da instância por aqui
+ frame.close = gump:NewDetailsButton (frame, frame, _, function() end, nil, nil, 1, 1, "", "", "", "", {rightFunc = {func = _detalhes.switch.CloseMe, param1 = nil, param2 = nil}})
+ frame.close:SetPoint ("topleft", frame, "topleft")
+ frame.close:SetPoint ("bottomright", frame, "bottomright")
+ frame.close:SetFrameLevel (frame:GetFrameLevel()+1)
+ frame:Hide()
+
+ _detalhes.switch.frame = frame
+end
+
+_detalhes.switch.buttons = {}
+_detalhes.switch.slots = _detalhes.switch.slots or 6
+_detalhes.switch.showing = 0
+_detalhes.switch.table = _detalhes.switch.table or {}
+_detalhes.switch.current_instancia = nil
+_detalhes.switch.current_button = nil
+_detalhes.switch.height_necessary = (30*_detalhes.switch.slots)/2
+
+--_detalhes:DelayMsg ("altura necessaria: " .. _detalhes.switch.height_necessary)
+--_detalhes:DelayMsg ("slots: " .. _detalhes.switch.slots)
+
+function _detalhes.switch:ShowMe (instancia)
+ _detalhes.switch.current_instancia = instancia
+ _detalhes.switch.frame:SetFrameLevel (instancia.baseframe:GetFrameLevel() + 5)
+ _detalhes.switch.frame:SetPoint ("topleft", instancia.baseframe, "topleft", 2, 0)
+ _detalhes.switch.frame:SetPoint ("bottomright", instancia.baseframe, "bottomright", -2, 0)
+
+ _detalhes.switch.frame:SetBackdropColor (24/255, 24/255, 24/255, .8)
+ local _r, _g, _b, _a = _detalhes.switch.frame:GetBackdropColor()
+ gump:GradientEffect (_detalhes.switch.frame, "frame", _r, _g, _b, _a, _r, _g, _b, 1, 1)
+
+ local altura = instancia.baseframe:GetHeight()
+ local mostrar_quantas = _math_floor (altura / 30)*2
+
+ if (_detalhes.switch.mostrar_quantas ~= mostrar_quantas) then
+ for i = 1, #_detalhes.switch.buttons do
+ if (i <= mostrar_quantas) then
+ _detalhes.switch.buttons [i]:Show()
+ else
+ _detalhes.switch.buttons [i]:Hide()
+ end
+ end
+
+ if (#_detalhes.switch.buttons < mostrar_quantas) then
+ _detalhes.switch.slots = mostrar_quantas
+ _detalhes.switch:Update()
+ end
+
+ _detalhes.switch.mostrar_quantas = mostrar_quantas
+ end
+
+ _detalhes.switch:Resize()
+
+ _detalhes.switch.frame:Show()
+end
+
+function _detalhes.switch:Config (_,_, atributo, sub_atributo)
+ if (not sub_atributo) then
+ return
+ end
+
+ _detalhes.switch.table [_detalhes.switch.current_button].atributo = atributo
+ _detalhes.switch.table [_detalhes.switch.current_button].sub_atributo = sub_atributo
+ _detalhes.switch:Update()
+end
+
+function _detalhes:FastSwitch (_this)
+ _detalhes.switch.current_button = _this.button
+
+ if (not _this.atributo) then --> botão direito
+
+ GameCooltip:Reset()
+ GameCooltip:SetType (3)
+ GameCooltip:SetFixedParameter (_detalhes.switch.current_instancia)
+ GameCooltip:SetOwner (_detalhes.switch.buttons [_this.button])
+ _detalhes:MontaAtributosOption (_detalhes.switch.current_instancia, _detalhes.switch.Config)
+ GameCooltip:SetColor (1, nil)
+ GameCooltip:SetColor (2, nil)
+ GameCooltip:ShowCooltip()
+
+ --_detalhes.popup:ShowMe (_detalhes.switch.buttons [_this.button], _detalhes.switch.current_instancia, menu, sub_menu, "Interface\\AddOns\\Details\\images\\atributos_icones", 256, _, _, _, {["NoFade"] = true})
+ else --> botão esquerdo
+ if (_detalhes.switch.current_instancia.modo == _detalhes._detalhes_props["MODO_ALONE"]) then
+ _detalhes.switch.current_instancia:AlteraModo (_detalhes.switch.current_instancia, _detalhes.switch.current_instancia.LastModo)
+ elseif (_detalhes.switch.current_instancia.modo == _detalhes._detalhes_props["MODO_RAID"]) then
+ _detalhes.switch.current_instancia:AlteraModo (_detalhes.switch.current_instancia, _detalhes.switch.current_instancia.LastModo)
+ end
+ _detalhes.switch.current_instancia:TrocaTabela (_detalhes.switch.current_instancia.segmento, _this.atributo, _this.sub_atributo)
+ _detalhes.switch.CloseMe()
+ end
+end
+
+-- nao tem suporte a solo mode tank mode
+-- nao tem suporte a custom até agora, não sei como vai ficar
+
+function _detalhes.switch:InitSwitch()
+ return _detalhes.switch:Update()
+end
+
+function _detalhes.switch:OnRemoveCustom (CustomIndex)
+ for i = 1, _detalhes.switch.slots do
+ local options = _detalhes.switch.table [i]
+ if (options and options.atributo == 5 and options.sub_atributo == CustomIndex) then
+ --> precisa resetar esse aqui
+ options.atributo = nil
+ options.sub_atributo = nil
+ _detalhes.switch:Update()
+ end
+ end
+end
+
+function _detalhes.switch:Update()
+
+ local slots = _detalhes.switch.slots
+ local x = 10
+ local y = 10
+ local jump = false
+
+ for i = 1, slots do
+
+ local options = _detalhes.switch.table [i]
+ if (not options) then
+ options = {atributo = nil, sub_atributo = nil}
+ _detalhes.switch.table [i] = options
+ end
+
+ local button = _detalhes.switch.buttons [i]
+ if (not button) then
+ button = _detalhes.switch:NewSwitchButton (_detalhes.switch.frame, i, x, y, jump)
+ button:SetFrameLevel (_detalhes.switch.frame:GetFrameLevel()+2)
+ _detalhes.switch.showing = _detalhes.switch.showing + 1
+ end
+
+ local param2Table = {
+ ["instancia"] = _detalhes.switch.current_instancia,
+ ["button"] = i,
+ ["atributo"] = options.atributo,
+ ["sub_atributo"] = options.sub_atributo
+ }
+
+ button.funcParam2 = param2Table
+ button.button2.funcParam2 = param2Table
+
+ local icone
+ local coords
+ local name
+
+ if (options.sub_atributo) then
+ if (options.atributo == 5) then --> custom
+ local CustomObject = _detalhes.custom [options.sub_atributo]
+ if (not CustomObject) then --> ele já foi deletado
+ icone = "Interface\\ICONS\\Ability_DualWield"
+ coords = {0, 1, 0, 1}
+ name = Loc ["STRING_SWITCH_CLICKME"]
+ else
+ icone = CustomObject.icon
+ coords = {0, 1, 0, 1}
+ name = CustomObject.name
+ end
+ else
+ icone = _detalhes.sub_atributos [options.atributo].icones [options.sub_atributo] [1]
+ coords = _detalhes.sub_atributos [options.atributo].icones [options.sub_atributo] [2]
+ name = _detalhes.sub_atributos [options.atributo].lista [options.sub_atributo]
+ end
+ else
+ icone = "Interface\\ICONS\\Ability_DualWield"
+ coords = {0, 1, 0, 1}
+ name = Loc ["STRING_SWITCH_CLICKME"]
+ end
+
+ button.button2.texto:SetText (name)
+
+ button.textureNormal:SetTexture (icone, true)
+ button.textureNormal:SetTexCoord (_unpack (coords))
+ button.texturePushed:SetTexture (icone, true)
+ button.texturePushed:SetTexCoord (_unpack (coords))
+ button.textureH:SetTexture (icone, true)
+ button.textureH:SetTexCoord (_unpack (coords))
+ button:ChangeIcon (button.textureNormal, button.texturePushed, _, button.textureH)
+
+ if (jump) then
+ x = x - 125
+ y = y + 30
+ jump = false
+ else
+ x = x + 125
+ jump = true
+ end
+
+ end
+end
+
+function _detalhes.switch:Resize()
+
+ local x = 10
+ local y = 10
+ local xPlus = (_detalhes.switch.current_instancia:GetSize()/2)-5
+ local frame = _detalhes.switch.frame
+
+ for index, button in ipairs (_detalhes.switch.buttons) do
+
+ if (button.rightButton) then
+ button:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.textureNormal:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.texturePushed:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.textureH:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.button2.texto:SetSize (xPlus - 30, 12)
+ button.button2:SetPoint ("bottomright", button, "bottomright", xPlus - 30, 0)
+ button.line:SetWidth (xPlus - 15)
+ button.line2:SetWidth (xPlus - 15)
+ x = x - xPlus
+ y = y + 30
+ jump = false
+ else
+ button:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.textureNormal:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.texturePushed:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.textureH:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.button2.texto:SetSize (xPlus - 30, 12)
+ button.button2:SetPoint ("topleft", button, "topright", 1, 0)
+ button.button2:SetPoint ("bottomright", button, "bottomright", xPlus - 30, 0)
+ button.line:SetWidth (xPlus - 20)
+ button.line2:SetWidth (xPlus - 20)
+ x = x + xPlus
+ jump = true
+ end
+
+ end
+end
+
+function _detalhes.switch:NewSwitchButton (frame, index, x, y, rightButton)
+
+ local paramTable = {
+ ["instancia"] = _detalhes.switch.current_instancia,
+ ["button"] = index,
+ ["atributo"] = nil,
+ ["sub_atributo"] = nil
+ }
+
+ local button = gump:NewDetailsButton (frame, frame, _, _detalhes.FastSwitch, nil, paramTable, 15, 15, "", "", "", "",
+ {rightFunc = {func = _detalhes.FastSwitch, param1 = nil, param2 = {atributo = nil, button = index}}, OnGrab = "PassClick"})
+ button:SetPoint ("topleft", frame, "topleft", x, -y)
+ button.rightButton = rightButton
+
+ button.fundo = button:CreateTexture (nil, "background")
+ button.fundo:SetTexture ("Interface\\SPELLBOOK\\Spellbook-Parts")
+ button.fundo:SetTexCoord (0.00390625, 0.27734375, 0.44140625,0.69531250)
+ button.fundo:SetWidth (34)
+ button.fundo:SetHeight (32)
+ button.fundo:SetPoint ("topleft", button, "topleft", -9, 9)
+
+ button.line = button:CreateTexture (nil, "background")
+ button.line:SetTexture ("Interface\\SPELLBOOK\\Spellbook-Parts")
+ button.line:SetTexCoord (0.31250000, 0.96484375, 0.37109375, 0.52343750)
+ button.line:SetWidth (85)
+ button.line:SetHeight (25)
+ button.line:SetPoint ("left", button, "right", 0, -3)
+
+ button.line2 = button:CreateTexture (nil, "background")
+ button.line2:SetTexture ("Interface\\SPELLBOOK\\Spellbook-Parts")
+ button.line2:SetTexCoord (0.31250000, 0.96484375, 0.37109375, 0.52343750)
+ button.line2:SetWidth (85)
+ button.line2:SetHeight (25)
+ button.line2:SetPoint ("left", button, "right", 0, -3)
+
+ local button2 = gump:NewDetailsButton (button, button, _, _detalhes.FastSwitch, nil, paramTable, 1, 1, button.line, "", "", button.line2,
+ {rightFunc = {func = _detalhes.switch.CloseMe, param1 = nil, param2 = nil}, OnGrab = "PassClick"})
+ button2:SetPoint ("topleft", button, "topright", 1, 0)
+ button2:SetPoint ("bottomright", button, "bottomright", 90, 0)
+ button.button2 = button2
+
+ button.textureNormal = frame:CreateTexture (nil, "overlay")
+ button.textureNormal:SetWidth (15)
+ button.textureNormal:SetHeight (15)
+ button.textureNormal:SetPoint ("topleft", frame, "topleft", x, -y)
+
+ button.texturePushed = frame:CreateTexture (nil, "overlay")
+ button.texturePushed:SetWidth (15)
+ button.texturePushed:SetHeight (15)
+ button.texturePushed:SetPoint ("topleft", frame, "topleft", x, -y)
+
+ button.textureH = frame:CreateTexture (nil, "overlay")
+ button.textureH:SetWidth (15)
+ button.textureH:SetHeight (15)
+ button.textureH:SetPoint ("topleft", frame, "topleft", x, -y)
+
+ gump:NewLabel (button2, button2, nil, "texto", "", "GameFontHighlightSmall")
+ button2.texto:SetPoint ("left", button, "right", 4, -1)
+ button2.texto:SetNonSpaceWrap (true)
+
+ _detalhes.switch.buttons [index] = button
+
+ return button
+end
diff --git a/gumps/toolbar_button.xml b/gumps/toolbar_button.xml
new file mode 100644
index 00000000..dfba5b7b
--- /dev/null
+++ b/gumps/toolbar_button.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+ DetailsToolbarButtonOnEnter (self);
+
+
+
+ DetailsToolbarButtonOnLeave (self);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/images/ResizeGripD.tga b/images/ResizeGripD.tga
new file mode 100644
index 00000000..5329cd28
Binary files /dev/null and b/images/ResizeGripD.tga differ
diff --git a/images/ResizeGripL.tga b/images/ResizeGripL.tga
new file mode 100644
index 00000000..00dd18b2
Binary files /dev/null and b/images/ResizeGripL.tga differ
diff --git a/images/TrainerGossipIcon.tga b/images/TrainerGossipIcon.tga
new file mode 100644
index 00000000..098ac927
Binary files /dev/null and b/images/TrainerGossipIcon.tga differ
diff --git a/images/atributos_icones.tga b/images/atributos_icones.tga
new file mode 100644
index 00000000..477548fd
Binary files /dev/null and b/images/atributos_icones.tga differ
diff --git a/images/atributos_icones_damage.tga b/images/atributos_icones_damage.tga
new file mode 100644
index 00000000..22b9324c
Binary files /dev/null and b/images/atributos_icones_damage.tga differ
diff --git a/images/atributos_icones_energyze.tga b/images/atributos_icones_energyze.tga
new file mode 100644
index 00000000..00658b72
Binary files /dev/null and b/images/atributos_icones_energyze.tga differ
diff --git a/images/atributos_icones_heal.tga b/images/atributos_icones_heal.tga
new file mode 100644
index 00000000..3719b22d
Binary files /dev/null and b/images/atributos_icones_heal.tga differ
diff --git a/images/atributos_icones_misc.tga b/images/atributos_icones_misc.tga
new file mode 100644
index 00000000..1ce6fd13
Binary files /dev/null and b/images/atributos_icones_misc.tga differ
diff --git a/images/autoshot.tga b/images/autoshot.tga
new file mode 100644
index 00000000..0a92ebb0
Binary files /dev/null and b/images/autoshot.tga differ
diff --git a/images/background.tga b/images/background.tga
new file mode 100644
index 00000000..8978d43d
Binary files /dev/null and b/images/background.tga differ
diff --git a/images/ball_left.tga b/images/ball_left.tga
new file mode 100644
index 00000000..6869fe10
Binary files /dev/null and b/images/ball_left.tga differ
diff --git a/images/bar4.tga b/images/bar4.tga
new file mode 100644
index 00000000..8a2b77a3
Binary files /dev/null and b/images/bar4.tga differ
diff --git a/images/bar_detalhes2.tga b/images/bar_detalhes2.tga
new file mode 100644
index 00000000..6c1c696e
Binary files /dev/null and b/images/bar_detalhes2.tga differ
diff --git a/images/bar_detalhes2_end.tga b/images/bar_detalhes2_end.tga
new file mode 100644
index 00000000..20febbd5
Binary files /dev/null and b/images/bar_detalhes2_end.tga differ
diff --git a/images/bar_down_left.tga b/images/bar_down_left.tga
new file mode 100644
index 00000000..a1a6e45e
Binary files /dev/null and b/images/bar_down_left.tga differ
diff --git a/images/bar_down_left_snap.tga b/images/bar_down_left_snap.tga
new file mode 100644
index 00000000..3ce5a458
Binary files /dev/null and b/images/bar_down_left_snap.tga differ
diff --git a/images/bar_down_right.tga b/images/bar_down_right.tga
new file mode 100644
index 00000000..790965b4
Binary files /dev/null and b/images/bar_down_right.tga differ
diff --git a/images/bar_main_leftright.tga b/images/bar_main_leftright.tga
new file mode 100644
index 00000000..15893db0
Binary files /dev/null and b/images/bar_main_leftright.tga differ
diff --git a/images/bar_top_center.tga b/images/bar_top_center.tga
new file mode 100644
index 00000000..049ac06e
Binary files /dev/null and b/images/bar_top_center.tga differ
diff --git a/images/bar_top_right.tga b/images/bar_top_right.tga
new file mode 100644
index 00000000..442de8bc
Binary files /dev/null and b/images/bar_top_right.tga differ
diff --git a/images/bar_topdown_center.tga b/images/bar_topdown_center.tga
new file mode 100644
index 00000000..e34d1f96
Binary files /dev/null and b/images/bar_topdown_center.tga differ
diff --git a/images/bg_part1.tga b/images/bg_part1.tga
new file mode 100644
index 00000000..7914a902
Binary files /dev/null and b/images/bg_part1.tga differ
diff --git a/images/bg_part1_sr.tga b/images/bg_part1_sr.tga
new file mode 100644
index 00000000..a9e27308
Binary files /dev/null and b/images/bg_part1_sr.tga differ
diff --git a/images/bg_part2.tga b/images/bg_part2.tga
new file mode 100644
index 00000000..da0beb48
Binary files /dev/null and b/images/bg_part2.tga differ
diff --git a/images/bg_part2_sr.tga b/images/bg_part2_sr.tga
new file mode 100644
index 00000000..b0b18581
Binary files /dev/null and b/images/bg_part2_sr.tga differ
diff --git a/images/bg_part3.tga b/images/bg_part3.tga
new file mode 100644
index 00000000..a2aa0559
Binary files /dev/null and b/images/bg_part3.tga differ
diff --git a/images/bg_part3_sr.tga b/images/bg_part3_sr.tga
new file mode 100644
index 00000000..8732eb40
Binary files /dev/null and b/images/bg_part3_sr.tga differ
diff --git a/images/bg_part4_sr.tga b/images/bg_part4_sr.tga
new file mode 100644
index 00000000..92342a6b
Binary files /dev/null and b/images/bg_part4_sr.tga differ
diff --git a/images/button_disable_overlay.tga b/images/button_disable_overlay.tga
new file mode 100644
index 00000000..fe0af111
Binary files /dev/null and b/images/button_disable_overlay.tga differ
diff --git a/images/cadeado.tga b/images/cadeado.tga
new file mode 100644
index 00000000..e5c0a53f
Binary files /dev/null and b/images/cadeado.tga differ
diff --git a/images/classes.tga b/images/classes.tga
new file mode 100644
index 00000000..6fcfd4cb
Binary files /dev/null and b/images/classes.tga differ
diff --git a/images/classes_plus.tga b/images/classes_plus.tga
new file mode 100644
index 00000000..a1ee6b00
Binary files /dev/null and b/images/classes_plus.tga differ
diff --git a/images/classes_small.tga b/images/classes_small.tga
new file mode 100644
index 00000000..3e96d77d
Binary files /dev/null and b/images/classes_small.tga differ
diff --git a/images/clock.tga b/images/clock.tga
new file mode 100644
index 00000000..1bbb4698
Binary files /dev/null and b/images/clock.tga differ
diff --git a/images/consolidate_frame.tga b/images/consolidate_frame.tga
new file mode 100644
index 00000000..932f580c
Binary files /dev/null and b/images/consolidate_frame.tga differ
diff --git a/images/cooltip_selected.tga b/images/cooltip_selected.tga
new file mode 100644
index 00000000..b1ef6dd7
Binary files /dev/null and b/images/cooltip_selected.tga differ
diff --git a/images/copy.tga b/images/copy.tga
new file mode 100644
index 00000000..2f1594d7
Binary files /dev/null and b/images/copy.tga differ
diff --git a/images/custom_bg.tga b/images/custom_bg.tga
new file mode 100644
index 00000000..4001e2d1
Binary files /dev/null and b/images/custom_bg.tga differ
diff --git a/images/default_button.tga b/images/default_button.tga
new file mode 100644
index 00000000..d4e34495
Binary files /dev/null and b/images/default_button.tga differ
diff --git a/images/espadas.tga b/images/espadas.tga
new file mode 100644
index 00000000..ffbd4dd2
Binary files /dev/null and b/images/espadas.tga differ
diff --git a/images/grab.tga b/images/grab.tga
new file mode 100644
index 00000000..51e9db9c
Binary files /dev/null and b/images/grab.tga differ
diff --git a/images/grab_over.tga b/images/grab_over.tga
new file mode 100644
index 00000000..9577e13d
Binary files /dev/null and b/images/grab_over.tga differ
diff --git a/images/highlight_leftright.tga b/images/highlight_leftright.tga
new file mode 100644
index 00000000..92417cb3
Binary files /dev/null and b/images/highlight_leftright.tga differ
diff --git a/images/highlight_updown.tga b/images/highlight_updown.tga
new file mode 100644
index 00000000..21b6a87c
Binary files /dev/null and b/images/highlight_updown.tga differ
diff --git a/images/icon_mainwindow.tga b/images/icon_mainwindow.tga
new file mode 100644
index 00000000..5e96591e
Binary files /dev/null and b/images/icon_mainwindow.tga differ
diff --git a/images/icone_bg.tga b/images/icone_bg.tga
new file mode 100644
index 00000000..9acf0a8f
Binary files /dev/null and b/images/icone_bg.tga differ
diff --git a/images/icone_bg_fundo.tga b/images/icone_bg_fundo.tga
new file mode 100644
index 00000000..150552e9
Binary files /dev/null and b/images/icone_bg_fundo.tga differ
diff --git a/images/icones_barra.tga b/images/icones_barra.tga
new file mode 100644
index 00000000..c3558c06
Binary files /dev/null and b/images/icones_barra.tga differ
diff --git a/images/info_bg_part1.tga b/images/info_bg_part1.tga
new file mode 100644
index 00000000..a81a3e30
Binary files /dev/null and b/images/info_bg_part1.tga differ
diff --git a/images/info_bg_part2.tga b/images/info_bg_part2.tga
new file mode 100644
index 00000000..e216bcfb
Binary files /dev/null and b/images/info_bg_part2.tga differ
diff --git a/images/info_bg_part3.tga b/images/info_bg_part3.tga
new file mode 100644
index 00000000..a2aa0559
Binary files /dev/null and b/images/info_bg_part3.tga differ
diff --git a/images/info_bg_part4.tga b/images/info_bg_part4.tga
new file mode 100644
index 00000000..34126a06
Binary files /dev/null and b/images/info_bg_part4.tga differ
diff --git a/images/key_alt.tga b/images/key_alt.tga
new file mode 100644
index 00000000..d8b042a5
Binary files /dev/null and b/images/key_alt.tga differ
diff --git a/images/key_ctrl.tga b/images/key_ctrl.tga
new file mode 100644
index 00000000..70a80eec
Binary files /dev/null and b/images/key_ctrl.tga differ
diff --git a/images/key_shift.tga b/images/key_shift.tga
new file mode 100644
index 00000000..ee102f6a
Binary files /dev/null and b/images/key_shift.tga differ
diff --git a/images/melee.tga b/images/melee.tga
new file mode 100644
index 00000000..eb8dd7dd
Binary files /dev/null and b/images/melee.tga differ
diff --git a/images/modo_icones.tga b/images/modo_icones.tga
new file mode 100644
index 00000000..f803b6bc
Binary files /dev/null and b/images/modo_icones.tga differ
diff --git a/images/monster.tga b/images/monster.tga
new file mode 100644
index 00000000..2204e785
Binary files /dev/null and b/images/monster.tga differ
diff --git a/images/overlay_detalhes.tga b/images/overlay_detalhes.tga
new file mode 100644
index 00000000..d611f458
Binary files /dev/null and b/images/overlay_detalhes.tga differ
diff --git a/images/report_frame1.tga b/images/report_frame1.tga
new file mode 100644
index 00000000..de57e299
Binary files /dev/null and b/images/report_frame1.tga differ
diff --git a/images/report_frame2.tga b/images/report_frame2.tga
new file mode 100644
index 00000000..dac00ed1
Binary files /dev/null and b/images/report_frame2.tga differ
diff --git a/images/report_frame_icons.tga b/images/report_frame_icons.tga
new file mode 100644
index 00000000..832b6d0e
Binary files /dev/null and b/images/report_frame_icons.tga differ
diff --git a/images/scroll_down.tga b/images/scroll_down.tga
new file mode 100644
index 00000000..e4f91dc1
Binary files /dev/null and b/images/scroll_down.tga differ
diff --git a/images/scroll_middle.tga b/images/scroll_middle.tga
new file mode 100644
index 00000000..61ce8cbc
Binary files /dev/null and b/images/scroll_middle.tga differ
diff --git a/images/scroll_up.tga b/images/scroll_up.tga
new file mode 100644
index 00000000..ca3d5770
Binary files /dev/null and b/images/scroll_up.tga differ
diff --git a/images/scrollbar.tga b/images/scrollbar.tga
new file mode 100644
index 00000000..580245bd
Binary files /dev/null and b/images/scrollbar.tga differ
diff --git a/images/small_icons.tga b/images/small_icons.tga
new file mode 100644
index 00000000..1582a5e7
Binary files /dev/null and b/images/small_icons.tga differ
diff --git a/images/sword.tga b/images/sword.tga
new file mode 100644
index 00000000..9d2ac0ae
Binary files /dev/null and b/images/sword.tga differ
diff --git a/images/verticalline.tga b/images/verticalline.tga
new file mode 100644
index 00000000..5519e1b3
Binary files /dev/null and b/images/verticalline.tga differ
diff --git a/locales/Details-enUS.lua b/locales/Details-enUS.lua
new file mode 100644
index 00000000..25f38d06
--- /dev/null
+++ b/locales/Details-enUS.lua
@@ -0,0 +1,292 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details", "enUS", true)
+if not Loc then return end
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+ Loc ["STRING_DETAILS1"] = "|cffffaeaeDetails:|r " --> color and details name
+
+ Loc ["STRING_AUTO"] = "auto"
+ Loc ["STRING_LEFT"] = "left"
+ Loc ["STRING_CENTER"] = "center"
+ Loc ["STRING_RIGHT"] = "right"
+ Loc ["STRING_TOOOLD"] = "could not be installed because your Details! version is too old."
+
+--> Slash
+ Loc ["STRING_COMMAND_LIST"] = "command list"
+
+ Loc ["STRING_SLASH_DISABLE"] = "disable"
+ Loc ["STRING_SLASH_DISABLE_DESC"] = "turn off all captures of data."
+ Loc ["STRING_SLASH_CAPTUREOFF"] = "all captures has been turned off."
+
+ Loc ["STRING_SLASH_ENABLE"] = "enable"
+ Loc ["STRING_SLASH_ENABLE_DESC"] = "turn on all captures of data."
+ Loc ["STRING_SLASH_CAPTUREON"] = "all captures has been turned on."
+
+ Loc ["STRING_SLASH_OPTIONS"] = "options"
+ Loc ["STRING_SLASH_OPTIONS_DESC"] = "open the options panel."
+
+ Loc ["STRING_SLASH_NEW"] = "new"
+ Loc ["STRING_SLASH_NEW_DESC"] = "open or reopen a instance."
+
+
+
+--> StatusBar Plugins
+ Loc ["STRING_STATUSBAR_NOOPTIONS"] = "This widget doesn't have options."
+
+--> Fights and Segments
+
+ Loc ["STRING_SEGMENT"] = "Segment"
+ Loc ["STRING_TOTAL"] = "Total"
+ Loc ["STRING_OVERALL"] = "Overall"
+ Loc ["STRING_CURRENT"] = "Current"
+ Loc ["STRING_CURRENTFIGHT"] = "Current Fight"
+ Loc ["STRING_FIGHTNUMBER"] = "Fight #"
+ Loc ["STRING_UNKNOW"] = "Unknow"
+ Loc ["STRING_AGAINST"] = "against"
+
+--> Custom Window
+
+ Loc ["STRING_CUSTOM_REMOVE"] = "Remove"
+ Loc ["STRING_CUSTOM_BROADCAST"] = "Shout"
+ Loc ["STRING_CUSTOM_NAME"] = "Custom Name"
+ Loc ["STRING_CUSTOM_SPELLID"] = "Spell Id"
+ Loc ["STRING_CUSTOM_SOURCE"] = "Source"
+ Loc ["STRING_CUSTOM_TARGET"] = "Target"
+ Loc ["STRING_CUSTOM_TOOLTIPNAME"] = "Insert here the name of your custom display.\nAllow letters and numbers, minimum of 5 characters and 32 max."
+ Loc ["STRING_CUSTOM_TOOLTIPSPELL"] = "Select a boss ability from the menu on the right\nor type the spell name to filter."
+ Loc ["STRING_CUSTOM_TOOLTIPSOURCE"] = "Spell source allow (with brackets):\n|cFF00FF00[all]|r: Search for spell in all Actors.\n|cFFFF9900[raid]|r: Search only in your raid or party members.\n|cFF33CCFF[player]|r: Check only you\nAny other text will be considered an spesific Actor name."
+ Loc ["STRING_CUSTOM_TOOLTIPTARGET"] = "Insert the ability (player, monster, boss) target name."
+ Loc ["STRING_CUSTOM_TOOLTIPNOTWORKING"] = "Ouch, some gnome engineer touched this and broke it =("
+ Loc ["STRING_CUSTOM_BROADCASTSENT"] = "Sent"
+ Loc ["STRING_CUSTOM_CREATED"] = "The new display has been created."
+ Loc ["STRING_CUSTOM_ICON"] = "Icon"
+ Loc ["STRING_CUSTOM_CREATE"] = "Create"
+ Loc ["STRING_CUSTOM_INCOMBAT"] = "You are in combat."
+ Loc ["STRING_CUSTOM_NOATTRIBUTO"] = "No attribute has been selected."
+ Loc ["STRING_CUSTOM_SHORTNAME"] = "Name need at least 5 characters."
+ Loc ["STRING_CUSTOM_LONGNAME"] = "Name too long, maximum allowed 32 characters."
+ Loc ["STRING_CUSTOM_NOSPELL"] = "Spell field cannot be empty."
+ Loc ["STRING_CUSTOM_HELP1"] = "When you mouse over the Remove button, a menu is shown asking which one of previously created customs you want to erase.\n\nThe send button shows up a menu for broadcast your custom to your raid group."
+ Loc ["STRING_CUSTOM_HELP2"] = "Choose here the attribute type of the spell, if your spell is a Healing spell, you may click on Heal."
+ Loc ["STRING_CUSTOM_HELP3"] = "Custom name will be used on Details attribute menu, and also, shown when reporting.\n\nOn spell id field, type some letters to filter spell names, you can also choose a spell from encounter menu on the right.\n\nOver source field, type where Details will serach for the spell, more info at his tooltip."
+ Loc ["STRING_CUSTOM_HELP4"] = "You can choose a spell from a raid encounter, mouse over this button and the options will be shown to you."
+ Loc ["STRING_CUSTOM_"] = ""
+
+--> Switch Window
+
+ Loc ["STRING_SWITCH_CLICKME"] = "left click me"
+
+--> Mode Names
+
+ Loc ["STRING_MODE_SELF"] = "Self"
+ Loc ["STRING_MODE_GROUP"] = "Group"
+ Loc ["STRING_MODE_ALL"] = "Everything"
+ Loc ["STRING_MODE_RAID"] = "Raid"
+
+--> Wait Messages
+
+ Loc ["STRING_NEWROW"] = "waiting refresh..."
+ Loc ["STRING_WAITPLUGIN"] = "waiting for\nplugins"
+
+--> Cooltip
+
+ Loc ["STRING_COOLTIP_NOOPTIONS"] = "no options"
+
+--> Attributes
+
+ Loc ["STRING_ATTRIBUTE_DAMAGE"] = "Damage"
+ Loc ["STRING_ATTRIBUTE_DAMAGE_DONE"] = "Damage Done"
+ Loc ["STRING_ATTRIBUTE_DAMAGE_DPS"] = "Damage Per Second"
+ Loc ["STRING_ATTRIBUTE_DAMAGE_TAKEN"] = "Damage Taken"
+ Loc ["STRING_ATTRIBUTE_DAMAGE_FRIENDLYFIRE"] = "Friendly Fire"
+
+
+ Loc ["STRING_ATTRIBUTE_HEAL"] = "Heal"
+ Loc ["STRING_ATTRIBUTE_HEAL_DONE"] = "Healing Done"
+ Loc ["STRING_ATTRIBUTE_HEAL_HPS"] = "Healing Per Second"
+ Loc ["STRING_ATTRIBUTE_HEAL_OVERHEAL"] = "Overhealing"
+ Loc ["STRING_ATTRIBUTE_HEAL_TAKEN"] = "Healing Taken"
+
+ Loc ["STRING_ATTRIBUTE_ENERGY"] = "Energy"
+ Loc ["STRING_ATTRIBUTE_ENERGY_MANA"] = "Mana Restored"
+ Loc ["STRING_ATTRIBUTE_ENERGY_RAGE"] = "Rage Generated"
+ Loc ["STRING_ATTRIBUTE_ENERGY_ENERGY"] = "Energy Generated"
+ Loc ["STRING_ATTRIBUTE_ENERGY_RUNEPOWER"] = "Runic Power Generated"
+
+ Loc ["STRING_ATTRIBUTE_MISC"] = "Miscellaneous"
+ Loc ["STRING_ATTRIBUTE_MISC_CCBREAK"] = "CC Breaks"
+ Loc ["STRING_ATTRIBUTE_MISC_RESS"] = "Ress"
+ Loc ["STRING_ATTRIBUTE_MISC_INTERRUPT"] = "Interrupts"
+ Loc ["STRING_ATTRIBUTE_MISC_DISPELL"] = "Dispells"
+ Loc ["STRING_ATTRIBUTE_MISC_DEAD"] = "Deaths"
+
+ Loc ["STRING_ATTRIBUTE_CUSTOM"] = "Custom"
+
+--> Tooltips & Info Box
+
+ Loc ["STRING_SPELLS"] = "Spells"
+ Loc ["STRING_NO_SPELL"] = "no spell has been used"
+ Loc ["STRING_TARGET"] = "Target"
+ Loc ["STRING_TARGETS"] = "Targets"
+ Loc ["STRING_PET"] = "Pet"
+ Loc ["STRING_DPS"] = "Dps"
+ Loc ["STRING_SEE_BELOW"] = "see below"
+ Loc ["STRING_GERAL"] = "Geral"
+ Loc ["STRING_PERCENTAGE"] = "Percentage"
+ Loc ["STRING_MEDIA"] = "Media"
+ Loc ["STRING_HITS"] = "Hits"
+ Loc ["STRING_DAMAGE"] = "Damage"
+ Loc ["STRING_NORMAL_HITS"] = "Normal Hits"
+ Loc ["STRING_CRITICAL_HITS"] = "Critical Hits"
+ Loc ["STRING_MINIMUM"] = "Minimum"
+ Loc ["STRING_MAXIMUM"] = "Maximum"
+ Loc ["STRING_DEFENSES"] = "Defenses"
+ Loc ["STRING_GLANCING"] = "Glancing"
+ Loc ["STRING_RESISTED"] = "Resisted"
+ Loc ["STRING_ABSORBED"] = "Absorbed"
+ Loc ["STRING_BLOCKED"] = "Blocked"
+ Loc ["STRING_FAIL_ATTACKS"] = "Attack Failures"
+ Loc ["STRING_MISS"] = "Miss"
+ Loc ["STRING_PARRY"] = "Parry"
+ Loc ["STRING_DODGE"] = "Dodge"
+ Loc ["STRING_DAMAGE_FROM"] = "Took damage from"
+ Loc ["STRING_HEALING_FROM"] = "Healing received from"
+ Loc ["STRING_PLAYERS"] = "Players"
+
+ Loc ["STRING_HPS"] = "Hps"
+ Loc ["STRING_HEAL"] = "Heal"
+ Loc ["STRING_HEAL_ABSORBED"] = "Heal absorbed"
+ Loc ["STRING_OVERHEAL"] = "Overheal"
+ Loc ["STRING_"] = ""
+
+----------------
+--> BuiltIn Plugins
+
+ Loc ["STRING_PLUGIN_MINSEC"] = "Minutes & Seconds"
+ Loc ["STRING_PLUGIN_SECONLY"] = "Seconds Only"
+ Loc ["STRING_PLUGIN_TIMEDIFF"] = "Last Combat Difference"
+
+ Loc ["STRING_PLUGIN_TOOLTIP_LEFTBUTTON"] = "Config current plugin"
+ Loc ["STRING_PLUGIN_TOOLTIP_RIGHTBUTTON"] = "Choose another plugin"
+
+ Loc ["STRING_PLUGIN_CLOCKTYPE"] = "Clock Type"
+
+ Loc ["STRING_PLUGIN_CLOCKNAME"] = "Encounter Time"
+ Loc ["STRING_PLUGIN_PSEGMENTNAME"] = "Instance Segment"
+ Loc ["STRING_PLUGIN_PDPSNAME"] = "Raid Dps"
+ Loc ["STRING_PLUGIN_THREATNAME"] = "My Threat"
+ Loc ["STRING_PLUGIN_PATTRIBUTENAME"] = "Attribute"
+
+ Loc ["STRING_PLUGINOPTIONS_COMMA"] = "Comma"
+ Loc ["STRING_PLUGINOPTIONS_ABBREVIATE"] = "Abbreviate"
+ Loc ["STRING_PLUGINOPTIONS_NOFORMAT"] = "None"
+
+ Loc ["STRING_PLUGINOPTIONS_TEXTSTYLE"] = "Text Style"
+ Loc ["STRING_PLUGINOPTIONS_TEXTCOLOR"] = "Text Color"
+ Loc ["STRING_PLUGINOPTIONS_TEXTSIZE"] = "Font Size"
+ Loc ["STRING_PLUGINOPTIONS_TEXTALIGN"] = "Text Align"
+
+ Loc ["STRING_PLUGINOPTIONS_FONTFACE"] = "Select Font Style"
+ Loc ["STRING_PLUGINOPTIONS_TEXTALIGN_X"] = "Text Align X"
+ Loc ["STRING_PLUGINOPTIONS_TEXTALIGN_Y"] = "Text Align Y"
+
+ Loc ["STRING_OPTIONS_COLOR"] = "Color"
+ Loc ["STRING_OPTIONS_SIZE"] = "Size"
+ Loc ["STRING_OPTIONS_ANCHOR"] = "Side"
+
+
+ Loc ["ABILITY_ID"] = "ability id"
+
+--> Details Instances
+
+ Loc ["STRING_SOLO_SWITCHINCOMBAT"] = "Cannot switch while in combat"
+ Loc ["STRING_CUSTOM_NEW"] = "Create New"
+ Loc ["STRING_CUSTOM_REPORT"] = "Report for (custom)"
+ Loc ["STRING_REPORT"] = "Report for"
+ Loc ["STRING_REPORT_FIGHT"] = "fight"
+ Loc ["STRING_REPORT_LAST"] = "Last" -- >last< 3 fights
+ Loc ["STRING_REPORT_FIGHTS"] = "fights" -- last 3 >fights<
+ Loc ["STRING_REPORT_LASTFIGHT"] = "last fight"
+ Loc ["STRING_REPORT_PREVIOUSFIGHTS"] = "previous fights"
+ Loc ["STRING_REPORT_INVALIDTARGET"] = "Whisper target not found"
+
+--> report frame
+
+ Loc ["STRING_REPORTFRAME_PARTY"] = "Party"
+ Loc ["STRING_REPORTFRAME_RAID"] = "Raid"
+ Loc ["STRING_REPORTFRAME_GUILD"] = "Guild"
+ Loc ["STRING_REPORTFRAME_OFFICERS"] = "Officer Channel"
+ Loc ["STRING_REPORTFRAME_WHISPER"] = "Whisper"
+ Loc ["STRING_REPORTFRAME_WHISPERTARGET"] = "Whisper Target"
+ Loc ["STRING_REPORTFRAME_SAY"] = "Say"
+ Loc ["STRING_REPORTFRAME_LINES"] = "Lines"
+ Loc ["STRING_REPORTFRAME_INSERTNAME"] = "insert player name"
+ Loc ["STRING_REPORTFRAME_CURRENT"] = "Current"
+ Loc ["STRING_REPORTFRAME_REVERT"] = "Reverse"
+ Loc ["STRING_REPORTFRAME_REVERTED"] = "reversed"
+ Loc ["STRING_REPORTFRAME_CURRENTINFO"] = "Display only data which are current being shown (if supported)."
+ Loc ["STRING_REPORTFRAME_REVERTINFO"] = "Reverse result, showing in ascending order (if supported)."
+ Loc ["STRING_REPORTFRAME_WINDOW_TITLE"] = "Create Report"
+ Loc ["STRING_REPORTFRAME_SEND"] = "Send"
+
+--> player details frame
+
+ Loc ["STRING_ACTORFRAME_NOTHING"] = "nothing to report"
+ Loc ["STRING_ACTORFRAME_REPORTTO"] = "report for"
+ Loc ["STRING_ACTORFRAME_REPORTTARGETS"] = "report for targets of"
+ Loc ["STRING_ACTORFRAME_REPORTOF"] = "of"
+ Loc ["STRING_ACTORFRAME_REPORTAT"] = "at"
+ Loc ["STRING_ACTORFRAME_SPELLUSED"] = "All spells used"
+ Loc ["STRING_ACTORFRAME_SPELLDETAILS"] = "Spell details"
+ Loc ["STRING_MASTERY"] = "Mastery"
+
+--> Main Window
+
+ Loc ["STRING_OPTIONS_WINDOW"] = "options"
+ Loc ["STRING_LOCK_WINDOW"] = "lock"
+ Loc ["STRING_UNLOCK_WINDOW"] = "unlock"
+ Loc ["STRING_ERASE"] = "delete"
+ Loc ["STRING_UNLOCK"] = "Spread out instances\n in this button"
+ Loc ["STRING_PLUGIN_NAMEALREADYTAKEN"] = "Details! can't install plugin because his name already has been taken"
+ Loc ["STRING_RESIZE_COMMON"] = "Resize\n"
+ Loc ["STRING_RESIZE_HORIZONTAL"] = "Resize the width off all\n windows in the cluster"
+ Loc ["STRING_RESIZE_VERTICAL"] = "Resize the heigth off all\n windows in the cluster"
+ Loc ["STRING_RESIZE_ALL"] = "Freely resize all windows"
+ Loc ["STRING_FREEZE"] = "This segment is not available at the moment"
+ Loc ["STRING_CLOSEALL"] = "All Details windows are close, Type '/details new' to re-open."
+
+ Loc ["STRING_HELP_MENUS"] = "Gear Menu: changes the game mode.\nSolo: tools where you can play by your self.\nGroup: display only actors which make part of your group.\nAll: show everything.\nRaid: assistance tools for raid or pvp groups.\n\nBook Menu: Change the segment, in Details! segments are dynamic and the instances change the displaying encounter data when a fight finishes.\n\nSword Menu: Change the attribute which this instance shown."
+ Loc ["STRING_HELP_ERASE"] = "Remove all segments stored."
+ Loc ["STRING_HELP_INSTANCE"] = "Click: open a new instance (window).\n\nMouse over: display a menu with all closed instances, you can reopen anyone at any time."
+ Loc ["STRING_HELP_STATUSBAR"] = "Statusbar can hold three plugins: one in left, another in the center and right side.\n\nRight click: select another plugin to show.\n\nLeft click: open the options window."
+ Loc ["STRING_HELP_SWITCH"] = "Right click: shows up the fast switch panel.\n\nLeft click on a switch option: change the instance (window) attribute.\nRight click: closes switch.\n\nYou can right click over icons to choose another attribute."
+ Loc ["STRING_HELP_RESIZE"] = "Resize and lock buttons."
+ Loc ["STRING_HELP_STRETCH"] = "Click, hold and pull to stretch the window."
+
+ Loc ["STRING_HELP_MODESELF"] = "The self mode plugins are intended to focus only on you. Use the sword menu to choose which plugin you want to use."
+ Loc ["STRING_HELP_MODEGROUP"] = "Use this option to display only you or players which are in your group or raid."
+ Loc ["STRING_HELP_MODEALL"] = "This mode will show every player, npc, boss with data captured by Details!."
+ Loc ["STRING_HELP_MODERAID"] = "The raid mode is the opposite of self mode, this plugins are intended to work with data captured from your group. You can change the plugin on sword menu."
+
+
+
+--O modo sozinho possui plugins que irão trabalhar apenas em cima dos dados capturados do seu personagem, como o dano que ele causa, os buffs e debuffs que ele possui, entre outros.
+
+--> misc
+
+ Loc ["STRING_PLAYER_DETAILS"] = "Player Details"
+ Loc ["STRING_MELEE"] = "Melee"
+ Loc ["STRING_AUTOSHOT"] = "Auto Shot"
+ Loc ["STRING_DOT"] = " (DoT)"
+ Loc ["STRING_UNKNOWSPELL"] = "Unknow Spell"
+
+ Loc ["STRING_CCBROKE"] = "Crowd Control Removed"
+ Loc ["STRING_DISPELLED"] = "Buffs/Debuffs Removed"
+ Loc ["STRING_SPELL_INTERRUPTED"] = "Spells interrupted"
+
+
+
+
+
+
+
diff --git a/locales/Details-ptBR.lua b/locales/Details-ptBR.lua
new file mode 100644
index 00000000..bb7f9a7b
--- /dev/null
+++ b/locales/Details-ptBR.lua
@@ -0,0 +1,272 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details", "ptBR")
+if not Loc then return end
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+
+ Loc ["STRING_DETAILS1"] = "|cffffaeaeDetalhes:|r " --> color and details name
+
+ Loc ["STRING_AUTO"] = "auto"
+ Loc ["STRING_LEFT"] = "esquerda"
+ Loc ["STRING_CENTER"] = "centro"
+ Loc ["STRING_RIGHT"] = "direita"
+ Loc ["STRING_TOOOLD"] = "nao pode ser instalado pois sua versao do Details! e muito antiga."
+
+--> Slash
+ Loc ["STRING_COMMAND_LIST"] = "lista de comandos"
+
+ Loc ["STRING_SLASH_DISABLE"] = "desativar"
+ Loc ["STRING_SLASH_DISABLE_DESC"] = "desliga todas as capturas de dados."
+ Loc ["STRING_SLASH_CAPTUREOFF"] = "todas as capturas foram desligadas."
+
+ Loc ["STRING_SLASH_ENABLE"] = "ativa"
+ Loc ["STRING_SLASH_ENABLE_DESC"] = "liga todas as capturas de dados."
+ Loc ["STRING_SLASH_CAPTUREON"] = "todas as capturas foram ligadas."
+
+ Loc ["STRING_SLASH_OPTIONS"] = "opcoes"
+ Loc ["STRING_SLASH_OPTIONS_DESC"] = "abre o painel de opcoes."
+
+ Loc ["STRING_SLASH_NEW"] = "novo"
+ Loc ["STRING_SLASH_NEW_DESC"] = "abre ou reabre uma instancia."
+
+--> StatusBar Plugins
+ Loc ["STRING_STATUSBAR_NOOPTIONS"] = "Nao ha opcoes para esta ferramenta."
+
+--> Fights and Segments
+
+ Loc ["STRING_SEGMENT"] = "Segmento"
+ Loc ["STRING_TOTAL"] = "Total"
+ Loc ["STRING_OVERALL"] = "Dados Gerais"
+ Loc ["STRING_CURRENT"] = "Atual"
+ Loc ["STRING_CURRENTFIGHT"] = "Luta Atual"
+ Loc ["STRING_FIGHTNUMBER"] = "Luta #"
+ Loc ["STRING_UNKNOW"] = "Desconhecido"
+ Loc ["STRING_AGAINST"] = "contra"
+
+--> Custom Window -- traduzir
+
+ Loc ["STRING_CUSTOM_REMOVE"] = "Remover"
+ Loc ["STRING_CUSTOM_BROADCAST"] = "Enviar"
+ Loc ["STRING_CUSTOM_NAME"] = "Nome"
+ Loc ["STRING_CUSTOM_SPELLID"] = "Id da Magia"
+ Loc ["STRING_CUSTOM_SOURCE"] = "Fonte"
+ Loc ["STRING_CUSTOM_TARGET"] = "Alvo"
+ Loc ["STRING_CUSTOM_TOOLTIPNAME"] = "Insira aqui o nome da sua customizacao.\nPermitido letras e numeros, minimo de 5 caracteres e no maximo 32."
+ Loc ["STRING_CUSTOM_TOOLTIPSPELL"] = "Selecione uma habilidade de um chefe no botao a direita ou digite o nome para filtrar todas as habilidades."
+ Loc ["STRING_CUSTOM_TOOLTIPSOURCE"] = "Fonte da magia (com os colchetes):\n|cFF00FF00[all]|r: Procura pela magia em todos os atores.\n|cFFFF9900[raid]|r: Busca apenas na raide ou no grupo.\n|cFF33CCFF[player]|r: Procura apenas em voce.\nQualquer outro texto sera considerado um nome de um ator."
+ Loc ["STRING_CUSTOM_TOOLTIPTARGET"] = "Insert the ability (player, monster, boss) target name."
+ Loc ["STRING_CUSTOM_TOOLTIPNOTWORKING"] = "Ouch, algum gnomo tocou nisso e acabou quebrando =("
+ Loc ["STRING_CUSTOM_BROADCASTSENT"] = "Enviar"
+ Loc ["STRING_CUSTOM_CREATED"] = "Sua customizacao foi criada."
+ Loc ["STRING_CUSTOM_ICON"] = "Icone"
+ Loc ["STRING_CUSTOM_CREATE"] = "Criar"
+ Loc ["STRING_CUSTOM_INCOMBAT"] = "Voce esta em combate."
+ Loc ["STRING_CUSTOM_NOATTRIBUTO"] = "Nenhum atributo foi selecionado."
+ Loc ["STRING_CUSTOM_SHORTNAME"] = "O nome precisa de pelo menos 5 caracteres."
+ Loc ["STRING_CUSTOM_LONGNAME"] = "O nome esta fora do permitido, use ate 32 caracteres."
+ Loc ["STRING_CUSTOM_NOSPELL"] = "O campo do Id da magia nao pode ser ignorado."
+ Loc ["STRING_CUSTOM_HELP1"] = "Remove a previously created custom\nSend this custom to all raid members."
+ Loc ["STRING_CUSTOM_HELP2"] = "Escolha aqui o atributo, se a sua magia for de curar, voce deve escolher cura."
+ Loc ["STRING_CUSTOM_HELP3"] = "O nome da customizacao e usado no menu de atributos do Detalhes, e tambem mostrado no relatorio ao reportar."
+ Loc ["STRING_CUSTOM_HELP4"] = "Voce pode escolher uma magia de algum encontro de uma raide, basta deixar o ponteiro do mouse sobre o botao para que o menu seja mostrado."
+ Loc ["STRING_CUSTOM_"] = ""
+
+--> Switch Window
+
+ Loc ["STRING_SWITCH_CLICKME"] = "clique-me"
+
+--> Mode Names
+
+ Loc ["STRING_MODE_SELF"] = "Sozinho"
+ Loc ["STRING_MODE_GROUP"] = "Grupo"
+ Loc ["STRING_MODE_ALL"] = "Tudo"
+ Loc ["STRING_MODE_RAID"] = "Raid"
+
+-->
+
+ Loc ["STRING_NEWROW"] = "esperando atualizar..."
+ Loc ["STRING_WAITPLUGIN"] = "esperando por\nplugins"
+
+--> Cooltip
+
+ Loc ["STRING_COOLTIP_NOOPTIONS"] = "Nao ha opcoes"
+
+--> Attributes
+
+ Loc ["STRING_ATTRIBUTE_DAMAGE"] = "Dano"
+ Loc ["STRING_ATTRIBUTE_DAMAGE_DONE"] = "Dano Feito"
+ Loc ["STRING_ATTRIBUTE_DAMAGE_DPS"] = "Dano por Segundo"
+ Loc ["STRING_ATTRIBUTE_DAMAGE_TAKEN"] = "Dano Recebido"
+ Loc ["STRING_ATTRIBUTE_DAMAGE_FRIENDLYFIRE"] = "Fogo Amigo"
+
+ Loc ["STRING_ATTRIBUTE_HEAL"] = "Cura"
+ Loc ["STRING_ATTRIBUTE_HEAL_DONE"] = "Cura Feita"
+ Loc ["STRING_ATTRIBUTE_HEAL_HPS"] = "Cura Por Segundo"
+ Loc ["STRING_ATTRIBUTE_HEAL_OVERHEAL"] = "Sobrecura"
+ Loc ["STRING_ATTRIBUTE_HEAL_TAKEN"] = "Cura Recebida"
+
+ Loc ["STRING_ATTRIBUTE_ENERGY"] = "Energia"
+ Loc ["STRING_ATTRIBUTE_ENERGY_MANA"] = "Mana Restaurada"
+ Loc ["STRING_ATTRIBUTE_ENERGY_RAGE"] = "e_rage Gerada"
+ Loc ["STRING_ATTRIBUTE_ENERGY_ENERGY"] = "Energia Gerada"
+ Loc ["STRING_ATTRIBUTE_ENERGY_RUNEPOWER"] = "Power Runico Gerado"
+
+ Loc ["STRING_ATTRIBUTE_MISC"] = "Miscelanea"
+ Loc ["STRING_ATTRIBUTE_MISC_CCBREAK"] = "Quebras de CC"
+ Loc ["STRING_ATTRIBUTE_MISC_RESS"] = "Revividos"
+ Loc ["STRING_ATTRIBUTE_MISC_INTERRUPT"] = "Interrupcoes"
+ Loc ["STRING_ATTRIBUTE_MISC_DISPELL"] = "Dissipados"
+ Loc ["STRING_ATTRIBUTE_MISC_DEAD"] = "Mortes"
+
+ Loc ["STRING_ATTRIBUTE_CUSTOM"] = "Customizados"
+
+--> Tooltips & Info Box
+
+ Loc ["STRING_SPELLS"] = "Habilidades"
+ Loc ["STRING_NO_SPELL"] = "Nenhuma habilidade foi usada"
+ Loc ["STRING_TARGET"] = "Alvo"
+ Loc ["STRING_TARGETS"] = "Alvos"
+ Loc ["STRING_PET"] = "Ajudante"
+ Loc ["STRING_DPS"] = "Dps"
+ Loc ["STRING_SEE_BELOW"] = "veja abaixo"
+ Loc ["STRING_GERAL"] = "Geral"
+ Loc ["STRING_PERCENTAGE"] = "Porcentagem"
+ Loc ["STRING_MEDIA"] = "Media"
+ Loc ["STRING_HITS"] = "Golpes"
+ Loc ["STRING_DAMAGE"] = "Dano"
+ Loc ["STRING_NORMAL_HITS"] = "Golpes Normais"
+ Loc ["STRING_CRITICAL_HITS"] = "Golpes Criticos"
+ Loc ["STRING_MINIMUM"] = "Minimo"
+ Loc ["STRING_MAXIMUM"] = "Maximo"
+ Loc ["STRING_DEFENSES"] = "Defensas"
+ Loc ["STRING_GLANCING"] = "Glancing"
+ Loc ["STRING_RESISTED"] = "Resistido"
+ Loc ["STRING_ABSORBED"] = "Absorvido"
+ Loc ["STRING_BLOCKED"] = "Bloqueado"
+ Loc ["STRING_FAIL_ATTACKS"] = "Falhas de Ataque"
+ Loc ["STRING_MISS"] = "Errou"
+ Loc ["STRING_PARRY"] = "Aparo"
+ Loc ["STRING_DODGE"] = "Desvio"
+ Loc ["STRING_DAMAGE_FROM"] = "Recebeu dano de"
+ Loc ["STRING_HEALING_FROM"] = "Cura recebida de"
+ Loc ["STRING_PLAYERS"] = "Jogadores"
+
+ Loc ["STRING_HPS"] = "Hps"
+ Loc ["STRING_HEAL"] = "Cura"
+ Loc ["STRING_HEAL_ABSORBED"] = "Cura absorvida"
+ Loc ["STRING_OVERHEAL"] = "Sobrecura"
+----------------
+ Loc ["ABILITY_ID"] = "id da habilidade"
+
+--> BuiltIn Plugins
+
+ Loc ["STRING_PLUGIN_MINSEC"] = "Minutos & Segundos"
+ Loc ["STRING_PLUGIN_SECONLY"] = "Somentte Segundos"
+ Loc ["STRING_PLUGIN_TIMEDIFF"] = "Diferenca do Ultimo Combate"
+
+ Loc ["STRING_PLUGIN_TOOLTIP_LEFTBUTTON"] = "Configura a ferramenta atual"
+ Loc ["STRING_PLUGIN_TOOLTIP_RIGHTBUTTON"] = "Escolher uma outra ferramenta"
+
+ Loc ["STRING_PLUGIN_CLOCKTYPE"] = "Tipo do Tempo"
+
+ Loc ["STRING_PLUGIN_CLOCKNAME"] = "Tempo de Luta"
+ Loc ["STRING_PLUGIN_PSEGMENTNAME"] = "Segmento Mostrado"
+ Loc ["STRING_PLUGIN_PDPSNAME"] = "Dps da Raide"
+ Loc ["STRING_PLUGIN_THREATNAME"] = "Minha Ameaça"
+ Loc ["STRING_PLUGIN_PATTRIBUTENAME"] = "Atributo"
+
+ Loc ["STRING_PLUGINOPTIONS_COMMA"] = "Virgula"
+ Loc ["STRING_PLUGINOPTIONS_ABBREVIATE"] = "Abreviar"
+ Loc ["STRING_PLUGINOPTIONS_NOFORMAT"] = "Nenhum"
+
+ Loc ["STRING_PLUGINOPTIONS_TEXTSTYLE"] = "Estilo do Texto"
+ Loc ["STRING_PLUGINOPTIONS_TEXTCOLOR"] = "Cor do Texto"
+ Loc ["STRING_PLUGINOPTIONS_TEXTSIZE"] = "Tamanho"
+ Loc ["STRING_PLUGINOPTIONS_TEXTALIGN"] = "Alinhamento"
+
+ Loc ["STRING_PLUGINOPTIONS_FONTFACE"] = "Fonte"
+ Loc ["STRING_PLUGINOPTIONS_TEXTALIGN_X"] = "Alinhamento X"
+ Loc ["STRING_PLUGINOPTIONS_TEXTALIGN_Y"] = "Alinhamento Y"
+
+ Loc ["STRING_OPTIONS_COLOR"] = "Cor"
+ Loc ["STRING_OPTIONS_SIZE"] = "Tamanho"
+ Loc ["STRING_OPTIONS_ANCHOR"] = "Lado"
+
+--> Details Instances
+
+ Loc ["STRING_SOLO_SWITCHINCOMBAT"] = "Voce esta em combate"
+ Loc ["STRING_CUSTOM_NEW"] = "Criar Novo"
+ Loc ["STRING_CUSTOM_REPORT"] = "Relatorio para (custom)"
+ Loc ["STRING_REPORT"] = "Relatorio para"
+ Loc ["STRING_REPORT_FIGHT"] = "luta"
+ Loc ["STRING_REPORT_LAST"] = "Ultimas"
+ Loc ["STRING_REPORT_FIGHTS"] = "lutas"
+ Loc ["STRING_REPORT_LASTFIGHT"] = "ultima luta"
+ Loc ["STRING_REPORT_PREVIOUSFIGHTS"] = "lutas anteriores"
+ Loc ["STRING_REPORT_INVALIDTARGET"] = "O alvo nao pode ser encontrado"
+
+--> report frame
+
+ Loc ["STRING_REPORTFRAME_PARTY"] = "Grupo"
+ Loc ["STRING_REPORTFRAME_RAID"] = "Raide"
+ Loc ["STRING_REPORTFRAME_GUILD"] = "Guilda"
+ Loc ["STRING_REPORTFRAME_OFFICERS"] = "Canal dos Oficiais"
+ Loc ["STRING_REPORTFRAME_WHISPER"] = "Sussurrar"
+ Loc ["STRING_REPORTFRAME_WHISPERTARGET"] = "Sussurar o Alvo"
+ Loc ["STRING_REPORTFRAME_SAY"] = "Dizer"
+ Loc ["STRING_REPORTFRAME_LINES"] = "Linhas"
+ Loc ["STRING_REPORTFRAME_INSERTNAME"] = "entre com um nome"
+ Loc ["STRING_REPORTFRAME_CURRENT"] = "Mostrando"
+ Loc ["STRING_REPORTFRAME_REVERT"] = "Inverter"
+ Loc ["STRING_REPORTFRAME_REVERTED"] = "invertido"
+ Loc ["STRING_REPORTFRAME_CURRENTINFO"] = "Reporta apenas as informacoes que estao sendo mostradas no momento."
+ Loc ["STRING_REPORTFRAME_REVERTINFO"] = "Inverte as posicoes colocando em ordem crescente."
+ Loc ["STRING_REPORTFRAME_WINDOW_TITLE"] = "Emitir Relatorio"
+ Loc ["STRING_REPORTFRAME_SEND"] = "Enviar"
+
+--> player details frame
+
+ Loc ["STRING_ACTORFRAME_NOTHING"] = "nao ha nada para reportar"
+ Loc ["STRING_ACTORFRAME_REPORTTO"] = "relatorio para"
+ Loc ["STRING_ACTORFRAME_REPORTTARGETS"] = "relatorio para os alvos de"
+ Loc ["STRING_ACTORFRAME_REPORTOF"] = "de"
+ Loc ["STRING_ACTORFRAME_REPORTAT"] = "em"
+ Loc ["STRING_ACTORFRAME_SPELLUSED"] = "Todas as habilidades usadas"
+ Loc ["STRING_ACTORFRAME_SPELLDETAILS"] = "detalhes da habilidade"
+ Loc ["STRING_MASTERY"] = "Maestria"
+
+--> Main Window
+
+ Loc ["STRING_OPTIONS_WINDOW"] = "opcoes"
+ Loc ["STRING_LOCK_WINDOW"] = "travar"
+ Loc ["STRING_UNLOCK_WINDOW"] = "destravar"
+ Loc ["STRING_ERASE"] = "apagar"
+ Loc ["STRING_UNLOCK"] = "Separe as janelas\n neste botao"
+ Loc ["STRING_PLUGIN_NAMEALREADYTAKEN"] = "Details! nao pode instalar um plugin pois o nome dele ja esta em uso"
+ Loc ["STRING_RESIZE_COMMON"] = "Redimensiona livremente\n"
+ Loc ["STRING_RESIZE_HORIZONTAL"] = "Redimenciona a largura\n de todas as janelas na linha horizontal"
+ Loc ["STRING_RESIZE_VERTICAL"] = "Redimenciona a altura\n de todas as janelas na linha horizontal"
+ Loc ["STRING_RESIZE_ALL"] = "Redimenciona livremente\n e reajusta todas as janelas"
+ Loc ["STRING_FREEZE"] = "Este segmento não está disponível no momento"
+ Loc ["STRING_CLOSEALL"] = "Todas as janelas do Details estao fechadas, digite '/details new' para reabri-las."
+
+ Loc ["STRING_HELP_MENUS"] = "Menu da Engrenagem: altera o modo de jogo.\nSolo: ferramentas para voce jogar sozinho.\nGroup: mostra apenas os atores que pertencem ao seu grupo de raide.\nAll: mostra tudo.\nRaid: ferramentas para auxiliar em grupos de raide.\n\nMenu do Livro: altera o segmento que esta sendo mostrado na janela.\n\nMenu da Espada: muda o atributo que esta janela esta mostrando."
+ Loc ["STRING_HELP_ERASE"] = "Apaga todo o historico de lutas."
+ Loc ["STRING_HELP_INSTANCE"] = "Clique: abre uma nova janela.\n\nMouse em cima: mostra um menu com todas as janelas fechadas, voce pode reabrilas quando quiser."
+ Loc ["STRING_HELP_STATUSBAR"] = "A barra de status armazena 3 plugins: um na esquerda, outro no centro e na direita.\n\nBotao direito: seleciona outro plugin para mostrar.\n\nBotao esquerdo: mostra as opcoes do plugin."
+ Loc ["STRING_HELP_SWITCH"] = "Botao direito: mostra o painel de mudanca rapida.\n\nBotao esquerdo em uma opcao do painel de mudanca rapida: muda o atributo que a janela esta mostrando.\nbotao direito: fecha o painel.\n\nVoce pode clicar nos icones para escolher outro atributo."
+ Loc ["STRING_HELP_RESIZE"] = "Botoes de redimencionar e travar a janela."
+ Loc ["STRING_HELP_STRETCH"] = "Clique, segure e puxe para esticar a janela."
+
+------------------------------------------------------------------------------------------------------------------------------------
+--> MISC
+
+ Loc ["STRING_PLAYER_DETAILS"] = "Detalhes do Jogador"
+ Loc ["STRING_MELEE"] = "Corpo-a-Corpo"
+ Loc ["STRING_AUTOSHOT"] = "Tiro Automatico"
+ Loc ["STRING_UNKNOWSPELL"] = "Magia Desconhecida"
+
+ Loc ["STRING_CCBROKE"] = "CC Quebrados"
+ Loc ["STRING_DISPELLED"] = "Auras Removidas"
+ Loc ["STRING_SPELL_INTERRUPTED"] = "Magias Interrompidas"
+
+ Loc ["STRING_DOT"] = " (DoT)"
diff --git a/plugins/Details_DmgRank/Details_DmgRank.lua b/plugins/Details_DmgRank/Details_DmgRank.lua
new file mode 100644
index 00000000..e7eff9a7
--- /dev/null
+++ b/plugins/Details_DmgRank/Details_DmgRank.lua
@@ -0,0 +1,559 @@
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ("DetailsDmgRank")
+
+--> Needed locals
+local _GetTime = GetTime --> wow api local
+local _UFC = UnitAffectingCombat --> wow api local
+local _IsInRaid = IsInRaid --> wow api local
+local _IsInGroup = IsInGroup --> wow api local
+local _UnitAura = UnitAura --> wow api local
+local _math_floor = math.floor --> lua library local
+local _cstr = string.format --> lua library local
+
+--> Create the plugin Object
+local DmgRank = _detalhes:NewPluginObject ("Details_DmgRank")
+--> Main Frame
+local DmgRankFrame = DmgRank.Frame
+
+
+--> this function will run when the plugin receives the Addon_Loaded event, ["data"] = previus saved player rank
+local function CreatePluginFrames (data)
+
+ --> catch Details! main object
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+ --local
+
+ --> default rank table
+ DmgRank.rank = data or {level = 1, dps = 0, dpshistory = {}, lasttry = {}, annouce = true}
+ --DmgRank.rank.level = 20
+
+ --> OnEvent Table
+ function DmgRank:OnDetailsEvent (event, ...)
+ if (event == "HIDE") then --> plugin hidded, disabled
+ DmgRankFrame:SetScript ("OnUpdate", nil)
+ DmgRank:Cancel()
+
+ elseif (event == "SHOW") then
+
+ elseif (event == "REFRESH") then --> requested a refresh window
+ DmgRank:Refresh()
+
+ elseif (event == "COMBAT_PLAYER_TIMESTARTED") then --> combat started
+ --print ("recebeu event start")
+ local combat = select (1, ...)
+ --print (combat)
+ DmgRank:Start()
+
+ end
+ end
+
+------------- Build Ranking ----------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> damage goal table
+ DmgRank.TimeGoal = {
+
+ --> The 30 seconds Trial
+ {time = 30, damage = 1500000, name = Loc ["CHALLENGENAME_1"]}, -- Ready to Raid -- rank 2 --> -- Patrulha --> 50K DPS required
+ {time = 30, damage = 1800000, name = Loc ["CHALLENGENAME_2"]}, -- Damage Practice --rank 3 --> -- Soldier --> 60K DPS required
+ {time = 30, damage = 2100000, name = Loc ["CHALLENGENAME_3"]}, -- The Training Continue... -- rank 4 --> -- Corporal --> 70K DPS required
+
+ --> 90 seconds bracket
+ {time = 90, damage = 5080000, name = Loc ["CHALLENGENAME_4"]}, -- You Just Need a Little More Time -- rank 5 --> -- Sergeant --> 56K DPS required
+ {time = 90, damage = 5814800, name = Loc ["CHALLENGENAME_5"]}, -- Became a Knight -- rank 6 --> -- Sergeant --> 64K DPS required
+
+ --> middle bracket
+ {time = 120, damage = 7901760, name = Loc ["CHALLENGENAME_6"]}, -- Two Minutes -- rank 7 --> Iron Knight --> 65K DPS required
+ {time = 120, damage = 8442112, name = Loc ["CHALLENGENAME_7"]}, --rank 8 --> Steel Knight --> 70K DPS required
+ {time = 180, damage = 13452000, name = Loc ["CHALLENGENAME_8"]}, --rank 9 --> --> The High Knight --> 74K DPS required
+ {time = 180, damage = 14152100, name = Loc ["CHALLENGENAME_9"]}, --rank 10 --> Yes Sir! -- Thorium Knight --> 78K DPS required
+ {time = 180, damage = 15052100, name = Loc ["CHALLENGENAME_10"]}, --rank 11 --> Salute -- Silver Lieutenant --> 83K DPS required
+
+ --> burst bracket
+ {time = 40, damage = 5000000, name = Loc ["CHALLENGENAME_11"]}, --rank 12 --> In Burst We Trust -- Gold Lieutenant --> 125K DPS required
+ {time = 40, damage = 5700000, name = Loc ["CHALLENGENAME_12"]}, --rank 13 --> Watch me Explode -- Stone Guardian --> 142K DPS required
+ {time = 40, damage = 6300000, name = Loc ["CHALLENGENAME_13"]}, --rank 14 --> T.N.T-- Fel Guardian --> 157K DPS required
+
+ --> long run bracket
+ {time = 300, damage = 35052100, name = Loc ["CHALLENGENAME_14"]}, --rank 15 --> Time is Damage My Friend -- Titan Guardian --> 116K DPS required
+ {time = 330, damage = 41151120, name = Loc ["CHALLENGENAME_15"]}, --rank 16 - Just a Little Patience --> Bronze Centurion --> 124K DPS required
+ {time = 360, damage = 47395100, name = Loc ["CHALLENGENAME_16"]}, --rank 17 --> Silver Centurion --> 131K DPS required
+
+ {time = 300, damage = 56911000, name = Loc ["CHALLENGENAME_17"]}, --rank 18 --> Flame Centurion --> ?K DPS required
+ {time = 360, damage = 71821980, name = Loc ["CHALLENGENAME_18"]}, --rank 19 --> Lower Vanquisher --> ?K DPS required
+ {time = 180, damage = 45910990, name = Loc ["CHALLENGENAME_19"]}, --rank 20 --> Middle Vanquisher --> ?K DPS required
+
+ --> end
+ {time = nil, damage = nil, name = ""}, --rank 21 --> none
+ }
+
+ --> tiles and badges
+ DmgRank.Titles = {
+
+ Loc ["RANKNAME_1"], --> rank 1 --> -- recruit -- Recruta -- Farmer
+ Loc ["RANKNAME_2"], --> rank 2 --> soldier
+ Loc ["RANKNAME_3"], --> rank 3 --> corporal
+
+ Loc ["RANKNAME_4"], --> rank 4 --> -- Gold Sergeant
+ Loc ["RANKNAME_5"], --> rank 5 --> -- Star Sergeant
+
+ Loc ["RANKNAME_6"], --> rank 6 - Iron Knight
+ Loc ["RANKNAME_7"], --> rank 7 - Steel Knight
+ Loc ["RANKNAME_8"], --> rank 8 - Mithril Knight
+ Loc ["RANKNAME_9"], --> rank 9 - Thorium Knight
+
+ Loc ["RANKNAME_10"], --> rank 10 - Silver Lieutenant
+ Loc ["RANKNAME_11"], --> rank 11 - Gold Lieutenant
+
+ Loc ["RANKNAME_12"], --> rank 12 - Stone Guardian
+ Loc ["RANKNAME_13"], --> rank 13 - Fel Guardian
+ Loc ["RANKNAME_14"], --> rank 14 - Titan Guardian
+
+ Loc ["RANKNAME_15"], --> rank 15 - Bronze Centurion
+ Loc ["RANKNAME_16"], --> rank 16 - Silver Centurion
+ Loc ["RANKNAME_17"], --> rank 17 - Flame Centurion
+
+ Loc ["RANKNAME_18"], --> rank 18 - "Lower Vanquisher"
+ Loc ["RANKNAME_19"], --> rank 19 - "Middle Vanquisher"
+ Loc ["RANKNAME_20"], --> rank 20 - "High Vanquisher"
+
+ --[[
+ legionary
+ Commander
+ General
+ marshal
+ Champion -- campeoao
+ Conqueror -- conquistador
+ --]]
+
+ }
+ DmgRank.Badges = {}
+ DmgRank.Badges.TexCoords = {
+ {0.7734375, 0.89453125, 0.060546875, 0.181640625}, --> rank 1
+ {0.1640625, 0.259765625, 0.083984375, 0.185546875}, --> rank 2 - soldier
+ {0.31640625, 0.412109375, 0.06640625, 0.18359375}, --> rank 3 --> Corporal
+ {0.45703125, 0.55078125, 0.05859375, 0.177734375}, --> rank 4 --> Gold Sergeant
+ {0.607421875, 0.701171875, 0.044921875, 0.177734375}, --> rank 5 --> star Sergeant
+
+ {0.017578125, 0.169921875, 0.236328125, 0.3984375}, --> rank 6 - Iron Knight
+ {0.201171875, 0.357421875, 0.234375, 0.3984375}, --> rank 7 - Steel Knight
+ {0.38671875, 0.541015625, 0.234375, 0.3984375}, --> rank 8 - Mithril Knight
+ {0.572265625, 0.7265625, 0.234375, 0.3984375}, --> rank 9 - Thorium Knight
+
+ {0.16015625, 0.2734375, 0.44921875, 0.583984375}, --> rank 10 - Silver Lieutenant
+ {0.0234375, 0.130859375, 0.44921875, 0.583984375}, --> rank 11 - Gold Lieutenant
+
+ {0.30078125, 0.4375, 0.44140625, 0.5859375}, --> rank 12 - Stone Guardian
+ {0.45703125, 0.59375, 0.44140625, 0.5859375}, --> rank 13 - Fel Guardian
+ {0.61328125, 0.75, 0.44140625, 0.5859375}, --> rank 14 - Titan Guardian
+
+ {0.017578125, 0.173828125, 0.625, 0.78125}, --> rank 15 - Bronze Centurion
+ {0.212890625, 0.369140625, 0.625, 0.78125}, --> rank 16 - Silver Centurion
+ {0.408203125, 0.56640625, 0.625, 0.78125}, --> rank 17 - Flame Centurion
+
+ {0.00390625, 0.208984375, 0.810546875, 0.9765625}, --> rank 18 - Lower Vanquisher
+ {0.21875, 0.42578125, 0.810546875, 0.9765625}, --> rank 19 - Middle Vanquisher
+ {0.43359375, 0.638671875, 0.810546875, 0.9765625}, --> rank 20 - High Vanquisher
+
+ }
+ DmgRank.Badges.Sizes = {
+ {50, 50}, --> rank 1
+ {50, 52}, --> rank 2 - soldier
+ {50, 60}, --> rank 3 - Corporal
+ {49, 59}, --> rank 4 - Gold Sergeant
+ {48, 61}, ---> rank 5 - star Sergeant
+ {56, 63}, --> rank 6 - Iron Knight
+ {56, 63}, -->rank 7 - Steel Knight
+ {56, 63}, --> rank 8 - Mithril Knight
+ {56, 63}, --> rank 9 - Thorium Knight
+
+ {61, 59}, --> rank 10 - Silver Lieutenant
+ {55, 67}, --> rank 11 - Gold Lieutenant
+
+ {70, 74}, --> rank 12 - Stone Guardian
+ {70, 74}, --> rank 13 - Fel Guardian
+ {70, 74}, --> rank 14 - Titan Guardian
+
+ {70, 70}, --> rank 15 - Bronze Centurion
+ {70, 70}, --> rank 16 - Silver Centurion
+ {70, 70}, --> rank 17 - Flame Centurion
+
+ {80, 65}, --> rank 18 - Lower Vanquisher
+ {80, 65}, --> rank 19 - Middle Vanquisher
+ {80, 65}, --> rank 20 - High Vanquisher
+ }
+ DmgRank.Badges.SetPointMod = {
+ {0, 6}, --> rank 1
+ {0, 5}, --> rank 2 - soldier
+ {0, 10}, --> rank 3 - Corporal
+ {0, 10}, --> rank 4 - Gold Sergeant
+ {0, 16}, --> rank 5 - star Sergeant
+ {0, 12}, --> rank 6 - Iron Knight
+ {0, 12}, --> rank 7 - Steel Knight
+ {0, 12}, --> rank 8 - Mithril Knight
+ {0, 12}, --> rank 9 - Thorium Knight
+
+ {0, 12}, --> rank 10 - Silver Lieutenant
+ {0, 17}, --> rank 11 - Gold Lieutenant
+
+ {0, 20}, --> rank 12 - Stone Guardian
+ {0, 20}, --> rank 13 - Fel Guardian
+ {0, 20}, --> rank 14 - Titan Guardian
+
+ {0, 20}, --> rank 15 - Bronze Centurion
+ {0, 20}, --> rank 16 - Silver Centurion
+ {0, 20}, --> rank 17 - Flame Centurion
+
+ {-3, 16}, --> rank 18 - Lower Vanquisher
+ {-3, 16}, --> rank 19 - Middle Vanquisher
+ {-3, 16}, --> rank 20 - High Vanquisher
+
+ }
+
+ --> main frame and background texture
+
+ DmgRankFrame:SetPoint ("topleft", UIParent)
+ DmgRankFrame:SetResizable (false) --> cant resize, this is a fixed size
+ DmgRankFrame:SetWidth (300) --> need to be 300x300 to fit details window
+ DmgRankFrame:SetHeight (300) --> need to be 300x300 to fit details window
+ DmgRank.Frame = DmgRankFrame
+ DmgRankFrame:Hide()
+
+ --> default background picture
+ local background = DmgRankFrame:CreateTexture (nil, "background")
+ background:SetTexture ("Interface\\ACHIEVEMENTFRAME\\UI-Achievement-StatsBackground")
+ background:SetPoint ("topleft", DmgRankFrame, "topleft", 2, 0)
+ background:SetPoint ("bottomright", DmgRankFrame, "bottomright", -2, 0)
+ background:SetVertexColor (.7, .7, .7, 1)
+ background:SetDrawLayer ("background", 1)
+ DmgRank.BackgroundTex = background
+
+ local AnimeFrame = CreateFrame ("frame", nil, DmgRankFrame)
+ AnimeFrame:SetAllPoints (DmgRankFrame)
+
+ local background2 = AnimeFrame:CreateTexture (nil, "background")
+ background2:SetTexture ("Interface\\AddOns\\Details_DmgRank\\solo_bgtimeattack")
+ background2:SetPoint ("topleft", DmgRankFrame, "topleft", 2, 0)
+ background2:SetPoint ("bottomright", DmgRankFrame, "bottomright", -2, 0)
+ DmgRank.BackgroundTex2 = background2
+ background2:SetDrawLayer ("background", 2)
+
+ local RotateAnimGroup = AnimeFrame:CreateAnimationGroup()
+ local rotate = RotateAnimGroup:CreateAnimation ("Rotation")
+ rotate:SetDegrees (360)
+ rotate:SetDuration (120)
+ RotateAnimGroup:SetLooping ("repeat")
+ RotateAnimGroup:Play()
+
+ --> next rank at display
+ local challengeName = DetailsFrameWork:NewLabel (DmgRankFrame, DmgRankFrame, nil, "challengeName", "", "QuestFont_Shadow_Huge")
+ challengeName:SetPoint ("center", DmgRankFrame, "center")
+ challengeName:SetPoint ("top", DmgRankFrame, "top", 0, -98)
+ DmgRank.challengeName = challengeName
+
+ local challengeGoal = DetailsFrameWork:NewLabel (DmgRankFrame, DmgRankFrame, nil, "challengeGoal", "", "GameFontHighlightSmall")
+ challengeGoal:SetPoint ("center", DmgRankFrame, "center")
+ challengeGoal:SetPoint ("top", DmgRankFrame, "top", 0, -118)
+ DmgRank.challengeGoal = challengeGoal
+
+ --> main time display
+ local showTimeMinutes = DetailsFrameWork:NewLabel (DmgRankFrame, DmgRankFrame, nil, "showTimeMinutes", "00:", "GameFontHighlightLarge")
+ showTimeMinutes:SetPoint ("center", DmgRankFrame, "center")
+ showTimeMinutes:SetPoint ("top", DmgRankFrame, "top", -25, -150)
+ showTimeMinutes:SetJustifyH ("RIGHT")
+ DmgRank.TimeMinutes = showTimeMinutes
+
+ local showTimeSeconds = DetailsFrameWork:NewLabel (DmgRankFrame, DmgRankFrame, nil, "showTimeSeconds", "00:", "GameFontHighlightLarge")
+ showTimeSeconds:SetPoint ("center", DmgRankFrame, "center")
+ showTimeSeconds:SetPoint ("top", DmgRankFrame, "top", 0, -150)
+ DmgRank.TimeSeconds = showTimeSeconds
+
+ local showTimeMiliSeconds = DetailsFrameWork:NewLabel (DmgRankFrame, DmgRankFrame, nil, "showTimeMiliSeconds", "00", "GameFontHighlightLarge")
+ showTimeMiliSeconds:SetPoint ("center", DmgRankFrame, "center")
+ showTimeMiliSeconds:SetPoint ("top", DmgRankFrame, "top", 23, -150)
+ DmgRank.TimeMiliSeconds = showTimeMiliSeconds
+
+ --> main damage display
+ local damage = DetailsFrameWork:NewLabel (DmgRankFrame, DmgRankFrame, "showdamage", nil, "00.000.000", "GameFontHighlightLarge")
+ damage:SetPoint ("center", DmgRankFrame, "center")
+ damage:SetPoint ("top", DmgRankFrame, "top", 0, -170)
+ DmgRank.MainDamageDisplay = damage
+
+ --> background da badge e titulo
+ local bg1 = DetailsFrameWork:NewPanel (DmgRankFrame, _, "DetailsDmgRankBadgeBackground", _, 280, 75)
+ bg1:SetPoint ("topleft", DmgRankFrame, 10, -10)
+ bg1:DisableGradient()
+
+ local GlowFrame = CreateFrame ("frame", "DetailsRankUpGlowFrame", bg1.widget, "DetailsAlertRankUpTemplate")
+ GlowFrame:SetPoint ("topleft", bg1.widget)
+ GlowFrame:SetWidth (280)
+ GlowFrame:SetHeight (60)
+ GlowFrame:Hide()
+
+ --> badge icon display
+ local titleIcon = bg1:CreateTexture (nil, "overlay")
+ titleIcon:SetTexture ("Interface\\AddOns\\Details_DmgRank\\images\\badges")
+ titleIcon:SetTexCoord (unpack (DmgRank.Badges.TexCoords [DmgRank.rank.level]))
+ titleIcon:SetWidth (DmgRank.Badges.Sizes [DmgRank.rank.level] [1]*1.33)
+ titleIcon:SetHeight (DmgRank.Badges.Sizes [DmgRank.rank.level] [2]*1.33)
+ titleIcon:SetPoint ("topleft", DmgRankFrame, "topleft", 20, -20)
+ DmgRank.TitleIcon = titleIcon
+
+ --> title
+ local pretitle = DetailsFrameWork:NewLabel (bg1, bg1, nil, "pretitle", Loc ["STRING_CURRENTRANK"], "GameFontHighlightSmall")
+ pretitle:SetPoint ("left", titleIcon, "right", 20, 9)
+ DmgRank.PreTitle = pretitle
+
+ local title = DetailsFrameWork:NewLabel (bg1, bg1, nil, "title", DmgRank.Titles [DmgRank.rank.level], "GameFontHighlightLarge")
+ title:SetPoint ("left", titleIcon, "right", 20, -9)
+ DmgRank.Title = title
+
+ --> help button
+ --> after 10 logins on the character this help button will not be show any more
+ if (_detalhes.tutorial.main_help_button < 10) then
+ local help = DetailsFrameWork:NewHelp (DmgRankFrame, 280, 280, 0, -20, 40, 40)
+ help:SetPoint ("topright", DmgRankFrame, "topright", 8, 9)
+ help:AddHelp (300, 300, 0, 0, 138, -138, Loc ["STRING_HELP"])
+ help:SetFrameLevel (DmgRankFrame:GetFrameLevel()+2)
+ end
+
+ --> announce switch
+ local announce = DetailsFrameWork:NewSwitch (bg1, _, "DetailsDmgRankAnnouce", "announceSwitch", 60, 20, _, _, DmgRank.rank.annouce)
+ bg1.announceSwitch:SetPoint ("topleft", DmgRankFrame, 12, -184)
+ bg1.announceSwitch.OnSwitch = function (self, _, value)
+ DmgRank.rank.annouce = value
+ end
+ DetailsFrameWork:NewLabel (bg1, _, nil, "announceLabel", Loc ["STRING_ANNOUNCE"], "GameFontHighlightSmall")
+ bg1.announceLabel:SetPoint ("bottom", bg1.announceSwitch, "top", -5, -2)
+
+ --> background dos tempos das ultimas tries
+ local lasttrylabel = DetailsFrameWork:NewLabel (bg1, bg1, nil, "lasttrylabel", Loc ["STRING_LASTTRIES"], "GameFontHighlightSmall") -->
+ lasttrylabel:SetPoint ("topleft", DmgRankFrame, 12, -204)
+ local lastranklabel = DetailsFrameWork:NewLabel (bg1, bg1, nil, "lastranklabel", Loc ["STRING_LASTRANKS"], "GameFontHighlightSmall") -->
+ lastranklabel:SetPoint ("topleft", DmgRankFrame, 162, -204)
+
+ local bg_esq = DetailsFrameWork:NewPanel (DmgRankFrame, _, "DetailsDmgRankLeftBackground", _, 130, 85, _, {.9, .9, .9, .7})
+ bg_esq:SetPoint ("topleft", DmgRankFrame, 10, -215)
+ local bg_dir = DetailsFrameWork:NewPanel (DmgRankFrame, _, "DetailsDmgRankRightBackground", _, 130, 85, _, {.9, .9, .9, .7})
+ bg_dir:SetPoint ("topleft", DmgRankFrame, 160, -215)
+
+ --> try dps dos 5 ultimos ranks
+ DmgRank.Try = {}
+ for i = 1, 5 do
+ DetailsFrameWork:NewLabel (bg_esq, bg_esq, nil, "try"..i, "0", "GameFontHighlightSmall")
+ bg_esq ["try"..i]:SetPoint ("bottomleft", DmgRankFrame, "bottomleft", 20, math.abs (i*15-83))
+ DmgRank.Try [i] = bg_esq ["try"..i]
+ end
+
+ --> dps dos 5 ultimos ranks
+ DmgRank.Dps = {}
+ for i = 1, 5 do
+ DetailsFrameWork:NewLabel (bg_dir, bg_dir, nil, "dps"..i, "0", "GameFontHighlightSmall")
+ bg_dir ["dps"..i]:SetPoint ("bottomleft", DmgRankFrame, "bottomleft", 170, math.abs (i*15-83))
+ DmgRank.Dps [i] = bg_dir ["dps"..i]
+ end
+
+ --> refresh all window components
+ function DmgRank:Refresh()
+ --> update badge icon and text
+
+ if (not self) then
+ self = DmgRank
+ end
+
+ self.challengeName:SetText (self.TimeGoal[DmgRank.rank.level].name)
+ if (self.TimeGoal[DmgRank.rank.level].damage) then
+ self.challengeGoal:SetText (_detalhes:comma_value (self.TimeGoal[DmgRank.rank.level].damage) .. " ".. Loc ["STRING_DAMAGEIN"] .." " .. self.TimeGoal[DmgRank.rank.level].time .. " " ..Loc ["STRING_SECONDS"])
+ else
+ self.challengeGoal:SetText ("")
+ end
+ self.Title:SetText (self.Titles [DmgRank.rank.level])
+
+ self.TitleIcon:SetTexCoord (unpack (self.Badges.TexCoords [DmgRank.rank.level]))
+ self.TitleIcon:SetWidth (self.Badges.Sizes [DmgRank.rank.level] [1]*1.33)
+ self.TitleIcon:SetHeight (self.Badges.Sizes [DmgRank.rank.level] [2]*1.33)
+ self.TitleIcon:SetPoint ("topleft", DmgRankFrame, 20+self.Badges.SetPointMod[DmgRank.rank.level][1], -20+self.Badges.SetPointMod[DmgRank.rank.level][2])
+
+ --> update last try atempts
+ for i = 1, 5 do
+ if (DmgRank.rank.lasttry [i]) then
+ self.Try [i]:SetText ("#"..i..": ".. _detalhes:comma_value (DmgRank.rank.lasttry [i]))
+ else
+ self.Try [i]:SetText ("-")
+ end
+ end
+
+ --> update last levels ups
+ for i = 1, 5 do
+ if (DmgRank.rank.dpshistory [i]) then
+ self.Dps [i]:SetText (Loc ["STRING_RANK"] .. " ".. DmgRank.rank.dpshistory [i])
+ else
+ self.Dps [i]:SetText ("-")
+ end
+ end
+ end
+
+ --> Refresh on Addon Load
+ DmgRank:Refresh()
+
+ local update = 0
+ local player --> short cut for Player Actor Object
+
+ --> Cancel function
+ function DmgRank:Cancel()
+ if (DmgRank.Time and DmgRank.Time.Working) then
+ print (Loc ["STRING_CANCELLED"])
+ DmgRank.Time.Working = false
+ DmgRank.Time.Done = true
+ DmgRank.Frame:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ --> Exec function
+ local DoDmgRank = function (self, elapsed)
+
+ DmgRank.Time.Elapsed = DmgRank.Time.Elapsed + elapsed
+ update = update + elapsed
+
+ if (_GetTime() > DmgRank.Time.EndTime) then --> reached the end time
+ if (DmgRank.Time.Working and not DmgRank.Time.Done) then
+ DmgRank:Cancel()
+ DmgRank:Finish()
+ end
+ else
+ --> aqui vem as funções que verificam se o jogador esta em grupo ou se tem algum buff proibido
+ DmgRank.Time.Tick = DmgRank.Time.Tick + elapsed
+ if (DmgRank.Time.Tick > 1) then
+ DmgRank.Time.Tick = 0
+ if (not _UFC ("player")) then --> isn't in combat
+ print (Loc ["STRING_CANCELLED_NOT_COMBAT"])
+ DmgRank:Cancel()
+ elseif (_IsInRaid() or _IsInGroup()) then
+ print (Loc ["STRING_CANCELLED_IN_GROUP"])
+ DmgRank:Cancel()
+ else
+ --> check for not allowed buffs:
+ for i = 1, 41 do
+ local auraName, _, _, _, _, _, _, _, _, _, spellId = _UnitAura ("player", i)
+ if (spellId and (spellId == 2825 or spellId == 80353 or spellId == 90355)) then --> bloodlust//timewarp//ancient hysteria
+ print (Loc ["STRING_CANCELLED_AURA"] .. auraName)
+ DmgRank:Cancel()
+ end
+ end
+ end
+ else
+ if (update > 0.050) then
+
+ local minutos, segundos = _math_floor (DmgRank.Time.Elapsed/60), _math_floor (DmgRank.Time.Elapsed%60)
+ if (segundos < 10) then
+ segundos = "0"..segundos
+ end
+ local mili = _cstr ("%.2f", DmgRank.Time.Elapsed - _math_floor (DmgRank.Time.Elapsed))*100
+ if (mili < 10) then
+ mili = "0"..mili
+ end
+ DmgRank.TimeMinutes:SetText ("0".. minutos .. ":")
+ DmgRank.TimeSeconds:SetText (segundos ..":")
+ DmgRank.TimeMiliSeconds:SetText (mili)
+
+ DmgRank.MainDamageDisplay:SetText (_detalhes:comma_value (player.total))
+ update = 0
+ end
+ end
+ end
+
+ end
+
+ --> add failed attempt to falied records
+ function DmgRank:FailedLevelUpRank()
+ table.insert (DmgRank.rank.lasttry, 1, player.total)
+ table.remove (DmgRank.rank.lasttry, 6)
+ DmgRank:Refresh()
+ end
+
+ --> Levelup
+ function DmgRank:LevelUpRank()
+ _detalhes:PlayGlow (GlowFrame)
+ DmgRank.rank.level = DmgRank.rank.level + 1
+
+ if (DmgRank.rank.annouce) then
+ SendChatMessage (UnitName ("player") .. " " .. Loc ["STRING_ANNOUNCE_STRING"] .. " " .. DmgRank.rank.level .. " (" .. self.Titles [DmgRank.rank.level] .. ") " .. Loc ["STRING_ANNOUNCE_ON"] .. " Details! " .. Loc ["STRING_PLUGIN_NAME"] .. ".", "GUILD")
+ end
+
+ DmgRank.rank.dps = player.total
+ table.insert (DmgRank.rank.dpshistory, 1, DmgRank.rank.level..": ".._detalhes:comma_value (player.total))
+ table.remove (DmgRank.rank.dpshistory, 6)
+ DmgRank:Refresh()
+ end
+
+ --> When the time is gone
+ function DmgRank:Finish()
+ local DamageGoal = DmgRank.TimeGoal [DmgRank.rank.level].damage --> damage
+ if (player.total > DamageGoal) then --> yeah, you didit
+ DmgRank:LevelUpRank()
+ else
+ DmgRank:FailedLevelUpRank()
+ end
+ end
+
+ --> When a new combat is received by the PlugIn
+ function DmgRank:Start()
+
+ if (DmgRank.Time and DmgRank.Time.Working) then
+ return
+ end
+
+ if (not DmgRank.TimeGoal[DmgRank.rank.level].damage) then
+ return
+ end
+
+ --> reset
+ DmgRank.TimeMinutes:SetText ("00:")
+ DmgRank.TimeSeconds:SetText ("00:")
+ DmgRank.TimeMiliSeconds:SetText ("00")
+ DmgRank.MainDamageDisplay:SetText ("00.000.000")
+
+ DmgRank.Time = {}
+ DmgRank.Time.StartTime = _GetTime()
+ DmgRank.Time.EndTime = DmgRank.Time.StartTime + DmgRank.TimeGoal[DmgRank.rank.level].time
+ DmgRank.Time.Elapsed = 0
+ DmgRank.Time.Done = nil
+ DmgRank.Time.Working = true
+ DmgRank.Time.Tick = 0
+ player = _detalhes:GetActor() --> param 1 = combat | param 2 = attribute | param 3 = player name
+ update = 0
+ DmgRank.Frame:SetScript ("OnUpdate", DoDmgRank)
+
+ end
+
+end
+
+function DmgRank:OnEvent (_, event, ...)
+
+ if (event == "ADDON_LOADED") then
+ local AddonName = select (1, ...)
+ if (AddonName == "Details_DmgRank") then
+
+ if (_G._detalhes) then
+
+ --> create widgets
+ CreatePluginFrames (_detalhes_databaseDmgRank)
+
+ local MINIMAL_DETAILS_VERSION_REQUIRED = 1
+
+ --> Install plugin inside details
+ local install = _G._detalhes:InstallPlugin ("SOLO", Loc ["STRING_PLUGIN_NAME"], "Interface\\Icons\\ACHIEVEMENT_GUILDPERK_HONORABLEMENTION_RANK2", DmgRank, "DETAILS_PLUGIN_DAMAGE_RANK", MINIMAL_DETAILS_VERSION_REQUIRED)
+ if (type (install) == "table" and install.error) then
+ print (install.error)
+ end
+
+ --> Register needed events
+ _G._detalhes:RegisterEvent (DmgRank, "COMBAT_PLAYER_TIMESTARTED")
+
+ end
+ end
+
+ elseif (event == "PLAYER_LOGOUT") then
+ _detalhes_databaseDmgRank = DmgRank.rank
+ end
+end
\ No newline at end of file
diff --git a/plugins/Details_DmgRank/Details_DmgRank.toc b/plugins/Details_DmgRank/Details_DmgRank.toc
new file mode 100644
index 00000000..99e69e39
--- /dev/null
+++ b/plugins/Details_DmgRank/Details_DmgRank.toc
@@ -0,0 +1,15 @@
+## Interface: 50300
+## Title: Details DamageRank (plugin)
+## Notes: Plugin for Details
+## SavedVariablesPerCharacter: _detalhes_databaseDmgRank
+## RequiredDeps: Details
+## OptionalDeps: Ace3, LibSharedMedia-3.0, LibBossIDs-1.0, LibGraph-2.0, !ClassColors
+
+#@no-lib-strip@
+embeds.xml
+#@end-no-lib-strip@
+
+enUS.lua
+ptBR.lua
+
+Details_DmgRank.lua
\ No newline at end of file
diff --git a/plugins/Details_DmgRank/Libs/AceLocale-3.0/AceLocale-3.0.lua b/plugins/Details_DmgRank/Libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 00000000..2ecc0cb8
--- /dev/null
+++ b/plugins/Details_DmgRank/Libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/plugins/Details_DmgRank/Libs/AceLocale-3.0/AceLocale-3.0.xml b/plugins/Details_DmgRank/Libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 00000000..d69dbb13
--- /dev/null
+++ b/plugins/Details_DmgRank/Libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/Details_DmgRank/Libs/LibStub/LibStub.lua b/plugins/Details_DmgRank/Libs/LibStub/LibStub.lua
new file mode 100644
index 00000000..f5fc9192
--- /dev/null
+++ b/plugins/Details_DmgRank/Libs/LibStub/LibStub.lua
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ -- LibStub:NewLibrary(major, minor)
+ -- major (string) - the major version of the library
+ -- minor (string or number ) - the minor version of the library
+ --
+ -- returns nil if a newer or same version of the lib is already present
+ -- returns empty library object or old library object if upgrade is needed
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ -- LibStub:GetLibrary(major, [silent])
+ -- major (string) - the major version of the library
+ -- silent (boolean) - if true, library is optional, silently return nil if its not found
+ --
+ -- throws an error if the library can not be found (except silent is set)
+ -- returns the library object if found
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ -- LibStub:IterateLibraries()
+ --
+ -- Returns an iterator for the currently registered libraries
+ function LibStub:IterateLibraries()
+ return pairs(self.libs)
+ end
+
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/plugins/Details_DmgRank/Libs/LibStub/LibStub.toc b/plugins/Details_DmgRank/Libs/LibStub/LibStub.toc
new file mode 100644
index 00000000..c3dc3656
--- /dev/null
+++ b/plugins/Details_DmgRank/Libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 40200
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: r95
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/plugins/Details_DmgRank/Libs/LibStub/tests/test.lua b/plugins/Details_DmgRank/Libs/LibStub/tests/test.lua
new file mode 100644
index 00000000..645a08b1
--- /dev/null
+++ b/plugins/Details_DmgRank/Libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/plugins/Details_DmgRank/Libs/LibStub/tests/test2.lua b/plugins/Details_DmgRank/Libs/LibStub/tests/test2.lua
new file mode 100644
index 00000000..af431dd3
--- /dev/null
+++ b/plugins/Details_DmgRank/Libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib doesn't exist yet, by iterating through all the libraries
+ assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+ if major == "MyLib" then -- we found it!
+ count = count +1
+ assert(rawequal(library, lib)) -- verify that the references are equal
+ end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/plugins/Details_DmgRank/Libs/LibStub/tests/test3.lua b/plugins/Details_DmgRank/Libs/LibStub/tests/test3.lua
new file mode 100644
index 00000000..01aabb8d
--- /dev/null
+++ b/plugins/Details_DmgRank/Libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/plugins/Details_DmgRank/Libs/LibStub/tests/test4.lua b/plugins/Details_DmgRank/Libs/LibStub/tests/test4.lua
new file mode 100644
index 00000000..15a9c9cd
--- /dev/null
+++ b/plugins/Details_DmgRank/Libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/plugins/Details_DmgRank/embeds.xml b/plugins/Details_DmgRank/embeds.xml
new file mode 100644
index 00000000..9cd274d8
--- /dev/null
+++ b/plugins/Details_DmgRank/embeds.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/plugins/Details_DmgRank/enUS.lua b/plugins/Details_DmgRank/enUS.lua
new file mode 100644
index 00000000..ab764a59
--- /dev/null
+++ b/plugins/Details_DmgRank/enUS.lua
@@ -0,0 +1,65 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("DetailsDmgRank", "enUS", true)
+
+if (not Loc) then
+ return
+end
+
+--> Labels:
+Loc ["STRING_PLUGIN_NAME"] = "Damage Rank"
+Loc ["STRING_CURRENTRANK"] = "Your current rank is:"
+Loc ["STRING_ANNOUNCE"] = "announce"
+Loc ["STRING_ANNOUNCE_STRING"] = "has reached the level"
+Loc ["STRING_ANNOUNCE_ON"] = "on"
+Loc ["STRING_LASTTRIES"] = "Recent Attempts"
+Loc ["STRING_LASTRANKS"] = "Last Ranks:"
+Loc ["STRING_DAMAGEIN"] = "damage over"
+Loc ["STRING_SECONDS"] = "seconds"
+Loc ["STRING_RANK"] = "rank"
+Loc ["STRING_CANCELLED"] = "This attempt has been cancelled."
+Loc ["STRING_CANCELLED_NOT_COMBAT"] = "This attempt has been cancelled: you aren't in combat."
+Loc ["STRING_CANCELLED_IN_GROUP"] = "This attempt has been cancelled: you are in a group."
+Loc ["STRING_CANCELLED_AURA"] = "This attempt has been cancelled: prohibited aura: "
+Loc ["STRING_HELP"] = "Damage Rank is a fun tool where your goal is reach the requested damage within the given time. Completing the mission, your rank increases and the challenge becomes harder and harder."
+
+--> Challenge Names:
+Loc ["CHALLENGENAME_1"] = "Ready to Raid"
+Loc ["CHALLENGENAME_2"] = "Damage Practice"
+Loc ["CHALLENGENAME_3"] = "The Training Continue"
+Loc ["CHALLENGENAME_4"] = "You Just Need a Little More Time"
+Loc ["CHALLENGENAME_5"] = "Became a Knight"
+Loc ["CHALLENGENAME_6"] = "60*2 Seconds"
+Loc ["CHALLENGENAME_7"] = "Hand of Mithril"
+Loc ["CHALLENGENAME_8"] = "The High Knight"
+Loc ["CHALLENGENAME_9"] = "Yes Sir!"
+Loc ["CHALLENGENAME_10"] = "Salute"
+Loc ["CHALLENGENAME_11"] = "In Burst We Trust"
+Loc ["CHALLENGENAME_12"] = "Watch me Explode"
+Loc ["CHALLENGENAME_13"] = "T.N.T"
+Loc ["CHALLENGENAME_14"] = "Time is Damage My Friend"
+Loc ["CHALLENGENAME_15"] = "Just a Little Patience"
+Loc ["CHALLENGENAME_16"] = "I'm D.P.S And I Know It"
+Loc ["CHALLENGENAME_17"] = "Gear Check"
+Loc ["CHALLENGENAME_18"] = "Just Do It..."
+Loc ["CHALLENGENAME_19"] = "I Remember You... In The Details!"
+
+--> Rank Names:
+Loc ["RANKNAME_1"] = "Farmer"
+Loc ["RANKNAME_2"] = "Soldier"
+Loc ["RANKNAME_3"] = "Corporal"
+Loc ["RANKNAME_4"] = "Gold Sergeant"
+Loc ["RANKNAME_5"] = "Star Sergeant"
+Loc ["RANKNAME_6"] = "Iron Knight"
+Loc ["RANKNAME_7"] = "Steel Knight"
+Loc ["RANKNAME_8"] = "Mithril Knight"
+Loc ["RANKNAME_9"] = "Thorium Knight"
+Loc ["RANKNAME_10"] = "Silver Lieutenant"
+Loc ["RANKNAME_11"] = "Gold Lieutenant"
+Loc ["RANKNAME_12"] = "Stone Guardian"
+Loc ["RANKNAME_13"] = "Fel Guardian"
+Loc ["RANKNAME_14"] = "Titan Guardian"
+Loc ["RANKNAME_15"] = "Bronze Centurion"
+Loc ["RANKNAME_16"] = "Silver Centurion"
+Loc ["RANKNAME_17"] = "Flame Centurion"
+Loc ["RANKNAME_18"] = "Lower Vanquisher"
+Loc ["RANKNAME_19"] = "Middle Vanquisher"
+Loc ["RANKNAME_20"] = "High Vanquisher"
\ No newline at end of file
diff --git a/plugins/Details_DmgRank/images/badges.tga b/plugins/Details_DmgRank/images/badges.tga
new file mode 100644
index 00000000..86c43d02
Binary files /dev/null and b/plugins/Details_DmgRank/images/badges.tga differ
diff --git a/plugins/Details_DmgRank/ptBR.lua b/plugins/Details_DmgRank/ptBR.lua
new file mode 100644
index 00000000..82835739
--- /dev/null
+++ b/plugins/Details_DmgRank/ptBR.lua
@@ -0,0 +1,65 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("DetailsDmgRank", "ptBR")
+
+if (not Loc) then
+ return
+end
+
+--> Labels:
+Loc ["STRING_PLUGIN_NAME"] = "Rank de Dano"
+Loc ["STRING_CURRENTRANK"] = "Seu rank atual:"
+Loc ["STRING_LASTTRIES"] = "Ultimas tentativas:"
+Loc ["STRING_ANNOUNCE"] = "anunciar"
+Loc ["STRING_ANNOUNCE_STRING"] = "alcancou o nivel"
+Loc ["STRING_ANNOUNCE_ON"] = "no"
+Loc ["STRING_LASTRANKS"] = "Ultimos ranks:"
+Loc ["STRING_DAMAGEIN"] = "de dano em"
+Loc ["STRING_SECONDS"] = "segundos"
+Loc ["STRING_RANK"] = "rank"
+Loc ["STRING_CANCELLED"] = "Esta tentativa foi cancelada."
+Loc ["STRING_CANCELLED_NOT_COMBAT"] = "Esta tentativa foi cancelada: você não esta mais em combate."
+Loc ["STRING_CANCELLED_IN_GROUP"] = "Esta tentativa foi cancelada: você está em grupo."
+Loc ["STRING_CANCELLED_AURA"] = "Esta tentativa foi cancelada: buff proibido: "
+Loc ["STRING_HELP"] = "Rank de Dano eh uma ferramenta interativa cujo o objetivo eh conseguir alcancar a margem de dano pedida dentro do tempo estabelecido. Cada vez que voce alcanca-lo, seu nivel aumenta e o desafio torna-se maior."
+
+--> Challenge Names:
+Loc ["CHALLENGENAME_1"] = "Pronto Para Raidar"
+Loc ["CHALLENGENAME_2"] = "Pratique, pratique, pratique"
+Loc ["CHALLENGENAME_3"] = "Continue a treinar"
+Loc ["CHALLENGENAME_4"] = "Um Pouco Mais de Tempo"
+Loc ["CHALLENGENAME_5"] = "Tornando-se um Cavalheiro"
+Loc ["CHALLENGENAME_6"] = "2 minutos"
+Loc ["CHALLENGENAME_7"] = "Maos de Mithril"
+Loc ["CHALLENGENAME_8"] = "A Alta Cavalaria"
+Loc ["CHALLENGENAME_9"] = "Sim Senhor!"
+Loc ["CHALLENGENAME_10"] = "Continencia"
+Loc ["CHALLENGENAME_11"] = "Na Explosão Nós Confiamos"
+Loc ["CHALLENGENAME_12"] = "Me Veja Explodir"
+Loc ["CHALLENGENAME_13"] = "T.N.T"
+Loc ["CHALLENGENAME_14"] = "Tempo é Dano Meu Amigo"
+Loc ["CHALLENGENAME_15"] = "Apenas um Pouco de Paciência"
+Loc ["CHALLENGENAME_16"] = "Meu Dano Calcula-se Em Milésimos"
+Loc ["CHALLENGENAME_17"] = "Prova Do Equipamento"
+Loc ["CHALLENGENAME_18"] = "Apenas Faça..."
+Loc ["CHALLENGENAME_19"] = "Eu Lembro de Você... no Detalhes!"
+
+--> Rank Names:
+Loc ["RANKNAME_1"] = "Fazendeiro"
+Loc ["RANKNAME_2"] = "Soldado"
+Loc ["RANKNAME_3"] = "Cabo"
+Loc ["RANKNAME_4"] = "Sargento de Ouro"
+Loc ["RANKNAME_5"] = "Sargento Estrela"
+Loc ["RANKNAME_6"] = "Cavaleiro de Ferro"
+Loc ["RANKNAME_7"] = "Cavaleiro de Aço"
+Loc ["RANKNAME_8"] = "Cavaleiro de Mithril"
+Loc ["RANKNAME_9"] = "Cavaleiro de Thorium"
+Loc ["RANKNAME_10"] = "Tenente de Prata"
+Loc ["RANKNAME_11"] = "Tenente de Ouro"
+Loc ["RANKNAME_12"] = "Guardião de Pedra"
+Loc ["RANKNAME_13"] = "Guardião Vil"
+Loc ["RANKNAME_14"] = "Guardião Titânico"
+Loc ["RANKNAME_15"] = "Centurião de Bronze"
+Loc ["RANKNAME_16"] = "Centurião de Prata"
+Loc ["RANKNAME_17"] = "Centurião das Chamas"
+Loc ["RANKNAME_18"] = "Vencedor Menor"
+Loc ["RANKNAME_19"] = "Vencedor"
+Loc ["RANKNAME_20"] = "Vencedor Maior"
\ No newline at end of file
diff --git a/plugins/Details_DmgRank/solo_bgtimeattack.tga b/plugins/Details_DmgRank/solo_bgtimeattack.tga
new file mode 100644
index 00000000..a8601224
Binary files /dev/null and b/plugins/Details_DmgRank/solo_bgtimeattack.tga differ
diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails.lua b/plugins/Details_EncounterDetails/Details_EncounterDetails.lua
new file mode 100644
index 00000000..0ef60a4e
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Details_EncounterDetails.lua
@@ -0,0 +1,1297 @@
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ("Details_EncounterDetails")
+local Graphics = LibStub:GetLibrary("LibGraph-2.0")
+
+--> Needed locals
+local _GetTime = GetTime --> wow api local
+local _UFC = UnitAffectingCombat --> wow api local
+local _IsInRaid = IsInRaid --> wow api local
+local _IsInGroup = IsInGroup --> wow api local
+local _UnitAura = UnitAura --> wow api local
+local _GetSpellInfo = _detalhes.getspellinfo --> wow api local
+local _CreateFrame = CreateFrame --> wow api local
+local _GetTime = GetTime --> wow api local
+local _GetCursorPosition = GetCursorPosition --> wow api local
+local _GameTooltip = GameTooltip --> wow api local
+
+local _math_floor = math.floor --> lua library local
+local _cstr = string.format --> lua library local
+local _ipairs = ipairs --> lua library local
+local _pairs = pairs --> lua library local
+local _table_sort = table.sort --> lua library local
+local _table_insert = table.insert --> lua library local
+local _unpack = unpack --> lua library local
+
+
+--> Create the plugin Object
+local EncounterDetails = _detalhes:NewPluginObject ("Details_EncounterDetails", DETAILSPLUGIN_ALWAYSENABLED)
+tinsert (UISpecialFrames, "Details_EncounterDetails")
+--> Main Frame
+local EncounterDetailsFrame = EncounterDetails.Frame
+
+--> container types
+local class_type_damage = _detalhes.atributos.dano --> damage
+local class_type_misc = _detalhes.atributos.misc --> misc
+--> main combat object
+local _combat_object
+
+local CLASS_ICON_TCOORDS = _G.CLASS_ICON_TCOORDS
+
+EncounterDetails.name = "Encounter Details"
+
+local ability_type_table = {
+ [0x1] = "|cFF00FF00"..Loc ["STRING_HEAL"].."|r",
+ [0x2] = "|cFF710000"..Loc ["STRING_LOWDPS"].."|r",
+ [0x4] = "|cFF057100"..Loc ["STRING_LOWHEAL"].."|r",
+ [0x8] = "|cFFd3acff"..Loc ["STRING_VOIDZONE"].."|r",
+ [0x10] = "|cFFbce3ff"..Loc ["STRING_DISPELL"].."|r",
+ [0x20] = "|cFFffdc72"..Loc ["STRING_INTERRUPT"].."|r",
+ [0x40] = "|cFFd9b77c"..Loc ["STRING_POSITIONING"].."|r",
+ [0x80] = "|cFFd7ff36"..Loc ["STRING_RUNAWAY"].."|r",
+ [0x100] = "|cFF9a7540"..Loc ["STRING_TANKSWITCH"] .."|r",
+ [0x200] = "|cFFff7800"..Loc ["STRING_MECHANIC"].."|r",
+ [0x400] = "|cFFbebebe"..Loc ["STRING_CROWDCONTROL"].."|r",
+ [0x800] = "|cFF6e4d13"..Loc ["STRING_TANKCOOLDOWN"].."|r",
+ [0x1000] = "|cFFffff00"..Loc ["STRING_KILLADD"].."|r",
+ [0x2000] = "|cFFff9999"..Loc ["STRING_SPREADOUT"].."|r",
+ [0x3000] = "|cFFffff99"..Loc ["STRING_STOPCAST"].."|r"
+}
+
+local debugmode = false
+
+--> main object frame functions
+local function CreatePluginFrames (data)
+
+ --> catch Details! main object
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+
+ --> saved data if any
+ EncounterDetails.data = data or {}
+ --> record if button is shown
+ EncounterDetails.showing = false
+ --> record if boss window is open or not
+ EncounterDetails.window_open = false
+ EncounterDetails.combat_boss_found = false
+
+ --> OnEvent Table
+ function EncounterDetails:OnDetailsEvent (event, ...)
+
+ --> when main frame became hide
+ if (event == "HIDE") then --> plugin hidded, disabled
+ self.open = false
+
+ --> when main frame is shown on screen
+ elseif (event == "SHOW") then --> plugin hidded, disabled
+ self.open = true
+
+ --> when details finish his startup and are ready to work
+ elseif (event == "DETAILS_STARTED") then
+ --> check if details are in combat, if not check if the last fight was a boss fight
+ if (not EncounterDetails:IsInCombat()) then
+ --> get the current combat table
+ _combat_object = EncounterDetails:GetCombat()
+ --> check if was a boss fight
+ EncounterDetails:WasEncounter()
+ end
+ _detalhes:RegisterTimeCapture (1)
+
+ elseif (event == "COMBAT_PLAYER_ENTER") then --> combat started
+ if (EncounterDetails.showing) then
+ EncounterDetails:HideIcon()
+ EncounterDetails:CloseWindow()
+ end
+
+ elseif (event == "COMBAT_PLAYER_LEAVE") then
+ --> combat leave and enter always send current combat table
+ _combat_object = select (1, ...)
+ --> check if was a boss fight
+ EncounterDetails:WasEncounter()
+ if (EncounterDetails.combat_boss_found) then
+ EncounterDetails.combat_boss_found = false
+ end
+
+ elseif (event == "COMBAT_BOSS_FOUND") then
+ EncounterDetails.combat_boss_found = true
+
+ elseif (event == "DETAILS_DATA_RESET") then
+ if (_G.DetailsRaidDpsGraph) then
+ _G.DetailsRaidDpsGraph:ResetData()
+ end
+ EncounterDetails:HideIcon()
+ EncounterDetails:CloseWindow()
+ end
+ end
+
+ function EncounterDetails:WasEncounter()
+
+ --> check if last combat was a boss encounter fight
+ if (not debugmode) then
+ if (not _combat_object.is_boss) then
+ _combat_object.is_boss = EncounterDetails:FindBoss()
+ if (not _combat_object.is_boss) then
+ return
+ end
+ elseif (_combat_object.is_boss.encounter == "pvp") then
+ return
+ end
+ end
+
+ --> boss found, we need to show the icon
+ EncounterDetails:ShowIcon()
+ end
+
+ --> show icon on toolbar
+ function EncounterDetails:ShowIcon()
+ EncounterDetails.showing = true
+ --> [1] button to show [2] button animation: "star", "blink" or true (blink)
+ EncounterDetails:ShowToolbarIcon (EncounterDetails.ToolbarButton, "star")
+ end
+
+ --> hide icon on toolbar
+ function EncounterDetails:HideIcon()
+ EncounterDetails.showing = false
+ EncounterDetails:HideToolbarIcon (EncounterDetails.ToolbarButton)
+ end
+
+ --> user clicked on button, need open or close window
+ function EncounterDetails:OpenWindow()
+ if (EncounterDetails.open) then
+ return EncounterDetails:CloseWindow()
+ end
+
+ --> build all window data
+ EncounterDetails:OpenAndRefresh()
+ --> show
+ EncounterDetailsFrame:Show()
+ if (EncounterDetailsFrame.ShowType == "graph") then
+ EncounterDetails:BuildDpsGraphic()
+ end
+ return true
+ end
+
+ function EncounterDetails:CloseWindow()
+ EncounterDetailsFrame:Hide()
+ return true
+ end
+
+ --> create the button to show on toolbar [1] function OnClick [2] texture [3] tooltip [4] width or 14 [5] height or 14 [6] frame name or nil
+ EncounterDetails.ToolbarButton = _detalhes.ToolBar:NewPluginToolbarButton (EncounterDetails.OpenWindow, "Interface\\Scenarios\\ScenarioIcon-Boss", Loc ["STRING_TOOLTIP"], 12, 12, "ENCOUNTERDETAILS_BUTTON") --"Interface\\COMMON\\help-i"
+ --> setpoint anchors mod if needed
+ EncounterDetails.ToolbarButton.y = 0.5
+ EncounterDetails.ToolbarButton.x = 5
+
+ --> build all frames ans widgets
+ _detalhes.EncounterDetailsTempWindow (EncounterDetails)
+ _detalhes.EncounterDetailsTempWindow = nil
+
+end
+
+--> custom tooltip for dead details ---------------------------------------------------------------------------------------------------------
+
+ local function KillInfo (deathTable, row)
+
+ local lastEvents = deathTable [1]
+ local timeOfDeath = deathTable [2]
+ local hp_max = deathTable [5]
+
+ local lines = {}
+
+ local battleress = false
+ local skillTable = row.extra
+
+ local GameCooltip = GameCooltip
+
+ GameCooltip:Reset()
+ GameCooltip:SetType ("tooltipbar")
+ GameCooltip:SetOwner (row)
+
+ for index, event in _ipairs (lastEvents) do
+
+ --max hp percent (in case of hp cooldowns)
+ local hp = _math_floor (event[5]/hp_max*100)
+ if (hp > 100) then
+ hp = 100
+ end
+
+ if (event [1]) then --> DAMAGE
+ local nome_magia, _, icone_magia = _GetSpellInfo (event [2])
+
+ if (not event[3] and not battleress) then --> battle ress
+
+ GameCooltip:AddLine ("+".._cstr ("%.1f", event[4] - timeOfDeath) .."s "..nome_magia.." ("..event[6]..")", "-- -- -- ", 1, "white")
+ GameCooltip:AddIcon ("Interface\\Glues\\CharacterSelect\\Glues-AddOn-Icons", 1, 1, nil, nil, .75, 1, 0, 1)
+ GameCooltip:AddStatusBar (100, 1, "silver", false)
+ battleress = true
+
+ elseif (event[3]) then
+
+ local habilidade_school = skillTable [event [2]] --> pegou a tabela com os hex --> aqui 4
+ local _school = ""
+
+ if (habilidade_school) then
+ for _, hex in _ipairs (habilidade_school) do
+ _school = _school .. " " .. ability_type_table [hex]
+ end
+ end
+
+ _school = _detalhes:trim (_school)
+ local texto_esquerdo = "".._cstr ("%.1f", event[4] - timeOfDeath) .."s "..nome_magia.." (".. _school ..")"
+ texto_esquerdo = texto_esquerdo:gsub ("(%()%)", "")
+
+ GameCooltip:AddLine (texto_esquerdo, "-".._detalhes:ToK (event[3]).." (".. hp .."%)", 1, "white", "white")
+ GameCooltip:AddIcon (icone_magia)
+ GameCooltip:AddStatusBar (hp, 1, "red", true)
+
+ end
+ else
+ local nome_magia, _, icone_magia = _GetSpellInfo (event [2])
+ GameCooltip:AddLine ("".._cstr ("%.1f", event[4] - timeOfDeath) .."s "..nome_magia.." ("..event[6]..")", "+".._detalhes:ToK (event[3]).." (".. hp .."%)", 1, "white", "white")
+ GameCooltip:AddIcon (icone_magia, 1, 1)
+ GameCooltip:AddStatusBar (hp, 1, "green", true)
+ end
+ end
+
+ if (battleress) then
+ GameCooltip:AddSpecial ("line", 2, nil, deathTable [6] .. " "..Loc ["STRING_DIED"], "-- -- -- ", 1, "white")
+ GameCooltip:AddSpecial ("icon", 2, nil, "Interface\\AddOns\\Details\\images\\small_icons", 1, 1, nil, nil, .75, 1, 0, 1)
+ GameCooltip:AddSpecial ("statusbar", 2, nil, 100, 1, "darkgray", false)
+ else
+ GameCooltip:AddSpecial ("line", 1, nil, deathTable [6] .. " "..Loc ["STRING_DIED"], "-- -- -- ", 1, "white")
+ GameCooltip:AddSpecial ("icon", 1, nil, "Interface\\AddOns\\Details\\images\\small_icons", 1, 1, nil, nil, .75, 1, 0, 1)
+ GameCooltip:AddSpecial ("statusbar", 1, nil, 100, 1, "darkgray", false)
+
+ end
+
+ GameCooltip:SetOption ("StatusBarHeightMod", -6)
+ GameCooltip:SetOption ("FixedWidth", 400)
+ GameCooltip:SetOption ("TextSize", 9.5)
+ GameCooltip:ShowCooltip()
+
+ end
+
+--> custom tooltip for dispells details ---------------------------------------------------------------------------------------------------------
+local function DispellInfo (dispell, barra)
+
+ local jogadores = dispell [1] --> [nome od jogador] = total
+ local tabela_jogadores = {}
+
+ for nome, tabela in _pairs (jogadores) do --> tabela = [1] total tomado [2] classe
+ tabela_jogadores [#tabela_jogadores + 1] = {nome, tabela [1], tabela [2]}
+ end
+
+ _table_sort (tabela_jogadores, function (a, b) return a[2] > b[2] end)
+
+ _GameTooltip:ClearLines()
+ _GameTooltip:AddLine (barra.texto_esquerdo:GetText())
+
+ for index, tabela in _ipairs (tabela_jogadores) do
+ local coords = CLASS_ICON_TCOORDS [tabela[3]]
+ if (not coords) then
+ GameTooltip:AddDoubleLine ("|TInterface\\GossipFrame\\DailyActiveQuestIcon:14:14:0:0:16:16:0:1:0:1".."|t "..tabela[1]..": ", tabela[2], 1, 1, 1, 1, 1, 1)
+ else
+ GameTooltip:AddDoubleLine ("|TInterface\\AddOns\\Details\\images\\classes_small:14:14:0:0:128:128:"..(coords[1]*128)..":"..(coords[2]*128)..":"..(coords[3]*128)..":"..(coords[4]*128).."|t "..tabela[1]..": ", tabela[2], 1, 1, 1, 1, 1, 1)
+ end
+ end
+end
+
+--> custom tooltip for kick details ---------------------------------------------------------------------------------------------------------
+
+local function KickBy (magia, barra)
+
+ local jogadores = magia [1] --> [nome od jogador] = total
+ local tabela_jogadores = {}
+
+ for nome, tabela in _pairs (jogadores) do --> tabela = [1] total tomado [2] classe
+ tabela_jogadores [#tabela_jogadores + 1] = {nome, tabela [1], tabela [2]}
+ end
+
+ _table_sort (tabela_jogadores, function (a, b) return a[2] > b[2] end)
+
+ _GameTooltip:ClearLines()
+ _GameTooltip:AddLine (barra.texto_esquerdo:GetText())
+
+ for index, tabela in _ipairs (tabela_jogadores) do
+ local coords = CLASS_ICON_TCOORDS [tabela[3]]
+ GameTooltip:AddDoubleLine ("|TInterface\\AddOns\\Details\\images\\classes_small:14:14:0:0:128:128:"..(coords[1]*128)..":"..(coords[2]*128)..":"..(coords[3]*128)..":"..(coords[4]*128).."|t "..tabela[1]..": ", tabela[2], 1, 1, 1, 1, 1, 1)
+ end
+end
+
+--> custom tooltip for enemy abilities details ---------------------------------------------------------------------------------------------------------
+
+local function EnemySkills (habilidade, barra)
+ --> barra.jogador agora tem a tabela com --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia
+
+ local total = habilidade [1]
+ local jogadores = habilidade [2] --> [nome od jogador] = total
+
+ local tabela_jogadores = {}
+
+ for nome, tabela in _pairs (jogadores) do --> tabela = [1] total tomado [2] classe
+ tabela_jogadores [#tabela_jogadores + 1] = {nome, tabela[1], tabela[2]}
+ end
+
+ _table_sort (tabela_jogadores, function (a, b) return a[2] > b[2] end)
+
+ _GameTooltip:ClearLines()
+ _GameTooltip:AddLine (barra.texto_esquerdo:GetText())
+
+ for index, tabela in _ipairs (tabela_jogadores) do
+ local coords = CLASS_ICON_TCOORDS [tabela[3]]
+ --GameTooltip:AddDoubleLine ("|TInterface\\AddOns\\Details\\images\\classes_small:14:14:0:0:128:128:"..coords[1]..":"..coords[2]..":"..coords[3]..":"..coords[4].."|t "..tabela[1]..": ", _detalhes:comma_value(tabela[2]).." (".._cstr("%.1f", (tabela[2]/total) * 100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddDoubleLine ("|TInterface\\AddOns\\Details\\images\\classes_small:14:14:0:0:128:128:"..(coords[1]*128)..":"..(coords[2]*128)..":"..(coords[3]*128)..":"..(coords[4]*128).."|t "..tabela[1]..": ", _detalhes:comma_value(tabela[2]).." (".._cstr("%.1f", (tabela[2]/total) * 100).."%)", 1, 1, 1, 1, 1, 1)
+ end
+
+end
+
+--> custom tooltip for damage taken details ---------------------------------------------------------------------------------------------------------
+
+local function DamageTakenDetails (jogador, barra)
+
+ local agressores = jogador.damage_from
+ local damage_taken = jogador.damage_taken
+
+ local showing = _combat_object [class_type_damage] --> o que esta sendo mostrado -> [1] - dano [2] - cura --> pega o container com ._NameIndexTable ._ActorTable
+
+ local meus_agressores = {}
+
+ for nome, _ in _pairs (agressores) do --> agressores seria a lista de nomes
+ local este_agressor = showing._ActorTable[showing._NameIndexTable[nome]]
+ if (este_agressor) then --> checagem por causa do total e do garbage collector que não limpa os nomes que deram dano
+
+ local habilidades = este_agressor.spell_tables._ActorTable
+ for id, habilidade in _pairs (habilidades) do
+ --print ("oi - " .. este_agressor.nome)
+ local alvos = habilidade.targets
+ for index, alvo in _ipairs (alvos._ActorTable) do
+ --print ("hello -> "..alvo.nome)
+ if (alvo.nome == jogador.nome) then
+ meus_agressores [#meus_agressores+1] = {id, alvo.total, este_agressor.nome}
+ end
+ end
+ end
+ end
+ end
+
+ _table_sort (meus_agressores, function (a, b) return a[2] > b[2] end)
+
+ _GameTooltip:ClearLines()
+ _GameTooltip:AddLine (barra.texto_esquerdo:GetText())
+
+ local max = #meus_agressores
+ if (max > 20) then
+ max = 20
+ end
+
+ local teve_melee = false
+
+ for i = 1, max do
+
+ local nome_magia, _, icone_magia = _GetSpellInfo (meus_agressores[i][1])
+
+ if (meus_agressores[i][1] == 1) then
+ nome_magia = "*"..meus_agressores[i][3]
+ teve_melee = true
+ end
+
+ GameTooltip:AddDoubleLine (nome_magia..": ", _detalhes:comma_value(meus_agressores[i][2]).." (".._cstr("%.1f", (meus_agressores[i][2]/damage_taken) * 100).."%)", 1, 1, 1, 1, 1, 1)
+ GameTooltip:AddTexture (icone_magia)
+ end
+
+ if (teve_melee) then
+ GameTooltip:AddLine ("* "..Loc ["STRING_MELEE_DAMAGE"], 0, 1, 0)
+ end
+end
+
+--> custom tooltip clicks on any bar ---------------------------------------------------------------------------------------------------------
+function _detalhes:BossInfoRowClick (barra, param1)
+
+ if (type (self) == "table") then
+ barra, param1 = self, barra
+ end
+
+ if (type (param1) == "table") then
+ barra = param1
+ end
+
+ if (barra._no_report) then
+ return
+ end
+
+ local reportar
+
+ if (barra.TTT == "morte") then --> deaths
+ reportar = {barra.report_text .. " " .. barra.texto_esquerdo:GetText()}
+ for i = 1, _detalhes.popup.NumLines, 1 do
+
+ local texto_left = _detalhes.popup.frame1.linhas[i].left_text:GetText()
+ local texto_right = _detalhes.popup.frame1.linhas[i].right_text:GetText()
+
+ if (texto_left and texto_right) then
+ texto_left = texto_left:gsub (("|T(.*)|t "), "")
+ reportar [#reportar+1] = ""..texto_left.." "..texto_right..""
+ end
+ end
+ else
+
+ barra.report_text = barra.report_text or ""
+ reportar = {barra.report_text .. " " .. _G.GameTooltipTextLeft1:GetText()}
+ local numLines = _GameTooltip:NumLines()
+
+ for i = 1, numLines, 1 do
+ local nome_left = "GameTooltipTextLeft"..i
+ local texto_left = _G[nome_left]
+ texto_left = texto_left:GetText()
+
+ local nome_right = "GameTooltipTextRight"..i
+ local texto_right = _G[nome_right]
+ texto_right = texto_right:GetText()
+
+ if (texto_left and texto_right) then
+ texto_left = texto_left:gsub (("|T(.*)|t "), "")
+ reportar [#reportar+1] = ""..texto_left.." "..texto_right..""
+ end
+ end
+ end
+
+ return _detalhes:Reportar (reportar, {_no_current = true, _no_inverse = true, _custom = true})
+
+end
+
+--> custom tooltip that handle mouse enter and leave on customized rows ---------------------------------------------------------------------------------------------------------
+
+function EncounterDetails:SetRowScripts (barra, index, container)
+
+ barra:SetScript ("OnMouseDown", function (self)
+ if (self.fading_in) then
+ return
+ end
+
+ self.mouse_down = _GetTime()
+ local x, y = _GetCursorPosition()
+ self.x = _math_floor (x)
+ self.y = _math_floor (y)
+
+ EncounterDetailsFrame:StartMoving()
+ EncounterDetailsFrame.isMoving = true
+
+ end)
+
+ barra:SetScript ("OnMouseUp", function (self)
+
+ if (self.fading_in) then
+ return
+ end
+
+ if (EncounterDetailsFrame.isMoving) then
+ EncounterDetailsFrame:StopMovingOrSizing()
+ EncounterDetailsFrame.isMoving = false
+ --instancia:SaveMainWindowPosition() --> precisa fazer algo pra salvar o trem
+ end
+
+ local x, y = _GetCursorPosition()
+ x = _math_floor (x)
+ y = _math_floor (y)
+ if ((self.mouse_down+0.4 > _GetTime() and (x == self.x and y == self.y)) or (x == self.x and y == self.y)) then
+ _detalhes:BossInfoRowClick (self)
+ end
+ end)
+
+ barra:SetScript ("OnEnter", --> MOUSE OVER
+ function (self)
+ --> aqui 1
+ if (container.fading_in or container.faded) then
+ return
+ end
+
+ self.mouse_over = true
+
+ self:SetHeight (17)
+ self:SetAlpha(1)
+
+ self:SetBackdrop({edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", tile = true, tileSize = 16, edgeSize = 10,insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ self:SetBackdropBorderColor (170/255, 170/255, 170/255)
+ self:SetBackdropColor (24/255, 24/255, 24/255)
+
+ GameTooltip:SetOwner (self, "ANCHOR_TOPRIGHT")
+
+ if (not self.TTT) then --> tool tip type
+ return
+ end
+
+ if (self.TTT == "damage_taken") then --> damage taken
+ DamageTakenDetails (self.jogador, barra)
+ elseif (self.TTT == "habilidades_inimigas") then --> enemy abilytes
+ EnemySkills (self.jogador, self)
+ elseif (self.TTT == "total_interrupt") then
+ KickBy (self.jogador, self)
+ elseif (self.TTT == "dispell") then
+ DispellInfo (self.jogador, self)
+ elseif (self.TTT == "morte") then --> deaths
+ KillInfo (self.jogador, self) --> aqui 2
+ end
+
+ GameTooltip:Show()
+ end)
+
+ barra:SetScript ("OnLeave", --> MOUSE OUT
+ function (self)
+
+ if (self.fading_in or self.faded or not self:IsShown() or self.hidden) then
+ return
+ end
+
+ self:SetHeight (16)
+ self:SetAlpha(0.9)
+
+ self:SetBackdrop({bgFile = "", edgeFile = "", tile = true, tileSize = 16, edgeSize = 32, insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ self:SetBackdropBorderColor (0, 0, 0, 0)
+ self:SetBackdropColor (0, 0, 0, 0)
+
+ GameTooltip:Hide()
+ _detalhes.popup:ShowMe (false, "tooltip")
+
+ end)
+end
+
+--> Here start the data mine ---------------------------------------------------------------------------------------------------------
+function EncounterDetails:OpenAndRefresh()
+
+ --> small alias
+ local frame = EncounterDetailsFrame
+
+ --[
+ if (frame.ShowType == "main") then
+ --frame.buttonSwitchNormal:Disable()
+
+ --if (_combat_object.DpsGraphic[1]) then
+ --frame.buttonSwitchGraphic:Enable()
+ --else
+ -- frame.buttonSwitchGraphic:Disable()
+ --end
+ elseif (frame.ShowType == "graph") then
+ --frame.buttonSwitchNormal:Enable()
+ --frame.buttonSwitchGraphic:Disable()
+ end
+ --]]
+
+ local boss_id
+ local map_id
+ local boss_info
+
+ if (debugmode and not _combat_object.is_boss) then
+ _combat_object.is_boss = {
+ index = 1,
+ name = _detalhes:GetBossName (1098, 1),
+ zone = "Throne of Thunder",
+ mapid = 1098,
+ encounter = "Jin'Rohk the Breaker"
+ }
+ end
+
+ boss_id = _combat_object.is_boss.index
+ map_id = _combat_object.is_boss.mapid
+ boss_info = _detalhes:GetBossDetails (_combat_object.is_boss.mapid, _combat_object.is_boss.index)
+
+-------------- set boss name and zone name --------------
+ EncounterDetailsFrame.boss_name:SetText (_combat_object.is_boss.encounter)
+ EncounterDetailsFrame.raid_name:SetText (_combat_object.is_boss.zone)
+
+-------------- set portrait and background image --------------
+ local L, R, T, B, Texture = EncounterDetails:GetBossIcon (_combat_object.is_boss.mapid, _combat_object.is_boss.index)
+ EncounterDetailsFrame.boss_icone:SetTexture (Texture)
+ EncounterDetailsFrame.boss_icone:SetTexCoord (L, R, T, B)
+ EncounterDetailsFrame.raidbackground:SetTexture (EncounterDetails:GetRaidBackground (_combat_object.is_boss.mapid))
+
+-------------- set totals on down frame --------------
+--[[ data mine:
+ _combat_object ["totals_grupo"] hold the total [1] damage // [2] heal // [3] [energy_name] energies // [4] [misc_name] miscs --]]
+
+ EncounterDetailsFrame.StatusBar_totaldamage:SetText (Loc ["STRING_TOTAL_DAMAGE"]..": ".. _detalhes:comma_value (_combat_object.totals_grupo[1])) --> [1] total damage
+ EncounterDetailsFrame.StatusBar_totalheal:SetText (Loc ["STRING_TOTAL_HEAL"]..": ".. _detalhes:comma_value (_combat_object.totals_grupo[2])) --> [2] total heal
+
+ --> Container Overall Damage Taken
+ --[[ data mine:
+ combat tables have 4 containers [1] damage [2] heal [3] energy [4] misc each container have 2 tables: ._NameIndexTable and ._ActorTable --]]
+ local DamageContainer = _combat_object [class_type_damage]
+
+ local damage_taken = _detalhes.atributo_damage:RefreshWindow ({}, _combat_object, _, { key = "damage_taken", modo = _detalhes.modos.group })
+
+ local container = frame.overall_damagetaken.gump
+
+ local quantidade = 0
+ local dano_do_primeiro = 0
+
+ for index, jogador in _ipairs (DamageContainer._ActorTable) do
+ --> ta em ordem de quem tomou mais dano.
+
+ if (not jogador.grupo) then --> só aparecer nego da raid
+ break
+ end
+
+ if (jogador.classe and jogador.classe ~= "UNGROUPPLAYER") then
+ local barra = container.barras [index]
+ if (not barra) then
+ barra = EncounterDetails:CreateRow (index, container)
+ barra.TTT = "damage_taken" -- tool tip type --> damage taken
+ barra.report_text = Loc ["STRING_PLUGIN_NAME"].."! "..Loc ["STRING_DAMAGE_TAKEN_REPORT"]
+ end
+
+ barra.texto_esquerdo:SetText (jogador.nome)
+ barra.texto_direita:SetText (_detalhes:comma_value (jogador.damage_taken))
+
+ _detalhes:name_space (barra)
+
+ barra.jogador = jogador
+
+ barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [jogador.classe]))
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ dano_do_primeiro = jogador.damage_taken
+ else
+ barra.textura:SetValue (jogador.damage_taken/dano_do_primeiro *100)
+ end
+
+ barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+ barra.icone:SetTexCoord (_unpack (CLASS_ICON_TCOORDS [jogador.classe]))
+
+ barra:Show()
+ quantidade = quantidade + 1
+ end
+ end
+
+ EncounterDetails:JB_AtualizaContainer (container, quantidade)
+
+ if (quantidade < #container.barras) then
+ for i = quantidade+1, #container.barras, 1 do
+
+ if (barra) then
+ barra:Hide()
+ end
+ end
+ end
+
+ --> Fim do container Overall Damage Taken
+
+ --> Container Overall Habilidades Inimigas
+ local habilidades_poll = {}
+
+ --> pega as magias contínuas presentes em todas as fases
+ if (boss_info.continuo) then
+ for index, spellid in _ipairs (boss_info.continuo) do
+ habilidades_poll [spellid] = true
+ end
+ end
+
+ --> pega as habilidades que pertence especificamente a cada fase
+ local fases = boss_info.phases
+ for fase_id, fase in _ipairs (fases) do
+ if (fase.spells) then
+ for index, spellid in _ipairs (fase.spells) do
+ habilidades_poll [spellid] = true
+ end
+ end
+ end
+
+ local habilidades_usadas = {}
+
+ for index, jogador in _ipairs (DamageContainer._ActorTable) do
+ local habilidades = jogador.spell_tables._ActorTable
+ for id, habilidade in _pairs (habilidades) do
+ if (habilidades_poll [id]) then
+ --> esse jogador usou uma habilidade do boss
+ local esta_habilidade = habilidades_usadas [id] --> tabela não numerica, pq diferentes monstros podem castar a mesma magia
+ if (not esta_habilidade) then
+ esta_habilidade = {0, {}, {}, id} --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia
+ habilidades_usadas [id] = esta_habilidade
+ end
+
+ --> adiciona ao [1] total de dano que esta habilidade causou
+ esta_habilidade[1] = esta_habilidade[1] + habilidade.total
+
+ --> adiciona ao [3] total do jogador que castou
+ if (not esta_habilidade[3][jogador.nome]) then
+ esta_habilidade[3][jogador.nome] = 0
+ end
+
+ esta_habilidade[3][jogador.nome] = esta_habilidade[3][jogador.nome] + habilidade.total
+
+ --> pega os alvos e adiciona ao [2]
+ local alvos = habilidade.targets
+ for index, jogador in _ipairs (alvos._ActorTable) do
+
+ --> ele tem o nome do jogador, vamos ver se este alvo é realmente um jogador verificando na tabela do combate
+ local tabela_dano_do_jogador = DamageContainer._ActorTable [DamageContainer._NameIndexTable [jogador.nome]]
+ if (tabela_dano_do_jogador and tabela_dano_do_jogador.grupo) then
+ if (not esta_habilidade[2] [jogador.nome]) then
+ esta_habilidade[2] [jogador.nome] = {0, tabela_dano_do_jogador.classe}
+ end
+ esta_habilidade[2] [jogador.nome] [1] = esta_habilidade[2] [jogador.nome] [1] + jogador.total
+ end
+ end
+ end
+ end
+ end
+
+ --> por em ordem
+ local tabela_em_ordem = {}
+ for id, tabela in _pairs (habilidades_usadas) do
+ tabela_em_ordem [#tabela_em_ordem+1] = tabela
+ end
+
+ _table_sort (tabela_em_ordem, function (a, b) return a[1] > b[1] end)
+
+ container = frame.overall_habilidades.gump
+ quantidade = 0
+ dano_do_primeiro = 0
+
+ --> mostra o resultado nas barras
+ for index, habilidade in _ipairs (tabela_em_ordem) do
+ --> ta em ordem das habilidades que deram mais dano
+
+ if (habilidade[1] > 0) then
+
+ local barra = container.barras [index]
+ if (not barra) then
+ barra = EncounterDetails:CreateRow (index, container)
+ barra.TTT = "habilidades_inimigas" -- tool tip type --enemy abilities
+ barra.report_text = Loc ["STRING_PLUGIN_NAME"].."! " .. Loc ["STRING_ABILITY_DAMAGE"]
+ end
+
+ local nome_magia, _, icone_magia = _GetSpellInfo (habilidade[4])
+
+ barra.texto_esquerdo:SetText (nome_magia)
+ barra.texto_direita:SetText (_detalhes:comma_value (habilidade[1]))
+
+ _detalhes:name_space (barra)
+
+ barra.jogador = habilidade --> barra.jogador agora tem a tabela com --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia
+
+ --barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [jogador.classe]))
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> a cor pode ser a spell school da magia
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ dano_do_primeiro = habilidade[1]
+ else
+ barra.textura:SetValue (habilidade[1]/dano_do_primeiro *100)
+ end
+
+ barra.icone:SetTexture (icone_magia)
+ --barra.icone:SetTexCoord (_unpack (CLASS_ICON_TCOORDS [jogador.classe]))
+
+ barra:Show()
+ quantidade = quantidade + 1
+
+ end
+ end
+
+ --print (quantidade)
+ EncounterDetails:JB_AtualizaContainer (container, quantidade)
+
+ if (quantidade < #container.barras) then
+ for i = quantidade+1, #container.barras, 1 do
+ container.barras [i]:Hide()
+ end
+ end
+
+ --> Fim do container Over Habilidades Inimigas
+
+ --> Identificar os ADDs da luta:
+
+ --> declara a pool onde serão armazenados os adds existentas na luta
+ local adds_pool = {}
+
+ --> pega as habilidades que pertence especificamente a cada fase
+ for fase_id, fase in _ipairs (boss_info.phases) do
+ if (fase.adds) then
+ for index, addId in _ipairs (fase.adds) do
+ adds_pool [addId] = true
+ end
+ end
+ end
+
+ --> agora ja tenho a lista de todos os adds da luta
+ -- vasculhar o container de dano e achar os adds:
+
+ local adds = {}
+
+ for index, jogador in _ipairs (DamageContainer._ActorTable) do
+
+ --> só estou interessado nos adds, conferir pelo nome
+ if (adds_pool [tonumber (jogador.serial:sub(6, 10), 16)]) then
+
+ local nome = jogador.nome
+ local tabela = {total = 0, dano_em = {}, dano_em_total = 0, damage_from = {}, damage_from_total = 0}
+
+ --> total de dano que ele causou
+ tabela.total = jogador.total
+
+ --> em quem ele deu dano
+ for _, alvo in _ipairs (jogador.targets._ActorTable) do
+ --local este_jogador = DamageContainer._ActorTable [DamageContainer._NameIndexTable [alvo.nome]]
+ local este_jogador = _combat_object (1, alvo.nome)
+ if (este_jogador) then
+ if (este_jogador.classe ~= "PET" and este_jogador.classe ~= "UNGROUPPLAYER" and este_jogador.classe ~= "UNKNOW") then
+ tabela.dano_em [#tabela.dano_em +1] = {alvo.nome, alvo.total, este_jogador.classe}
+ tabela.dano_em_total = tabela.dano_em_total + alvo.total
+ end
+ else
+ print ("actor not found: " ..alvo.nome )
+ end
+ end
+ _table_sort (tabela.dano_em, function(a, b) return a[2] > b[2] end)
+
+ --> quem deu dano nele
+ for agressor, _ in _pairs (jogador.damage_from) do
+ --local este_jogador = DamageContainer._ActorTable [DamageContainer._NameIndexTable [agressor]]
+ local este_jogador = _combat_object (1, agressor)
+ if (este_jogador and este_jogador:IsPlayer()) then
+ for _, alvo in _ipairs (este_jogador.targets._ActorTable) do
+ if (alvo.nome == nome) then
+ tabela.damage_from [#tabela.damage_from+1] = {agressor, alvo.total, este_jogador.classe}
+ tabela.damage_from_total = tabela.damage_from_total + alvo.total
+ end
+ end
+ end
+ end
+ _table_sort (tabela.damage_from,
+ function (a, b)
+ if (a[3] ~= "PET" and b[3] ~= "PET") then
+ return a[2] > b[2]
+ elseif (a[3] == "PET" and b[3] ~= "PET") then
+ return false
+ elseif (a[3] ~= "PET" and b[3] == "PET") then
+ return true
+ else
+ return a[2] > b[2]
+ end
+ end)
+
+ adds [nome] = tabela
+
+ end
+
+ end
+
+ --> montou a tabela, agora precisa mostrar no painel
+
+ local function _DanoFeito (barra)
+ barra = barra:GetParent()
+ local tabela = barra.jogador
+ local dano_em = tabela.dano_em
+
+ GameTooltip:SetOwner (barra, "ANCHOR_TOPRIGHT")
+
+ _GameTooltip:ClearLines()
+ _GameTooltip:AddLine (barra.texto_esquerdo:GetText().." ".. Loc ["STRING_INFLICTED"])
+
+ local dano_em_total = tabela.dano_em_total
+ for _, esta_tabela in _pairs (dano_em) do
+ local coords = CLASS_ICON_TCOORDS [esta_tabela[3]]
+ GameTooltip:AddDoubleLine ("|TInterface\\AddOns\\Details\\images\\classes_small:14:14:0:0:128:128:"..(coords[1]*128)..":"..(coords[2]*128)..":"..(coords[3]*128)..":"..(coords[4]*128).."|t "..esta_tabela[1]..": ", _detalhes:comma_value(esta_tabela[2]).." (".. _cstr ("%.1f", esta_tabela[2]/dano_em_total*100) .."%)", 1, 1, 1, 1, 1, 1)
+ end
+
+ GameTooltip:Show()
+ end
+
+ local function _DanoRecebido (barra)
+ barra = barra:GetParent()
+ local tabela = barra.jogador
+ local damage_from = tabela.damage_from
+
+ GameTooltip:SetOwner (barra, "ANCHOR_TOPRIGHT")
+
+ GameTooltip:ClearLines()
+ GameTooltip:AddLine (barra.texto_esquerdo:GetText().." "..Loc ["STRING_DAMAGE_TAKEN"])
+
+ local damage_from_total = tabela.damage_from_total
+
+ for _, esta_tabela in _pairs (damage_from) do
+
+ local coords = CLASS_ICON_TCOORDS [esta_tabela[3]]
+ if (coords) then
+ GameTooltip:AddDoubleLine ("|TInterface\\AddOns\\Details\\images\\classes_small:14:14:0:0:128:128:"..(coords[1]*128)..":"..(coords[2]*128)..":"..(coords[3]*128)..":"..(coords[4]*128).."|t "..esta_tabela[1]..": ", _detalhes:comma_value(esta_tabela[2]).." (".. _cstr ("%.1f", esta_tabela[2]/damage_from_total*100) .."%)", 1, 1, 1, 1, 1, 1)
+ else
+ GameTooltip:AddDoubleLine (esta_tabela[1], _detalhes:comma_value(esta_tabela[2]).." (".. _cstr ("%.1f", esta_tabela[2]/damage_from_total*100) .."%)", 1, 1, 1, 1, 1, 1)
+ end
+ end
+
+ GameTooltip:Show()
+ end
+
+ local y = 10
+ local frame_adds = EncounterDetailsFrame.overall_adds
+ container = frame_adds.gump
+ local index = 1
+ quantidade = 0
+
+ for addName, esta_tabela in _pairs (adds) do
+
+ local barra = container.barras [index]
+ if (not barra) then
+ barra = EncounterDetails:CreateRow (index, container)
+ barra:SetWidth (160)
+ barra._no_report = true
+
+ --> criar 2 botão: um para o dano que add deu e outro para o dano que o add tomou
+ local add_damage_taken = _CreateFrame ("Button", nil, barra)
+ add_damage_taken.report_text = "Details! "
+ add_damage_taken.barra = barra
+ add_damage_taken:SetWidth (16)
+ add_damage_taken:SetHeight (16)
+ add_damage_taken:EnableMouse (true)
+ add_damage_taken:SetResizable (false)
+ add_damage_taken:SetPoint ("left", barra, "left", 0, 0)
+
+ add_damage_taken:SetBackdrop (gump_fundo_backdrop)
+ add_damage_taken:SetBackdropColor (.3, .7, .7, 0.8)
+
+ add_damage_taken:SetScript ("OnEnter", _DanoRecebido)
+ add_damage_taken:SetScript ("OnLeave", function() GameTooltip:Hide() end)
+ add_damage_taken:SetScript ("OnClick", EncounterDetails.BossInfoRowClick)
+
+ add_damage_taken.textura = add_damage_taken:CreateTexture (nil, "overlay")
+ add_damage_taken.textura:SetTexture ("Interface\\Buttons\\UI-MicroStream-Green")
+ add_damage_taken.textura:SetWidth (16)
+ add_damage_taken.textura:SetHeight (16)
+ add_damage_taken.textura:SetTexCoord (0, 1, 1, 0)
+ add_damage_taken.textura:SetPoint ("center", add_damage_taken, "center")
+
+ local add_damage_done = _CreateFrame ("Button", nil, barra)
+ add_damage_done.report_text = "Details! "
+ add_damage_done.barra = barra
+ add_damage_done:SetWidth (16)
+ add_damage_done:SetHeight (16)
+ add_damage_done:EnableMouse (true)
+ add_damage_done:SetResizable (false)
+ add_damage_done:SetPoint ("left", add_damage_taken, "right", 0, 0)
+
+ add_damage_done:SetBackdrop (gump_fundo_backdrop)
+ add_damage_done:SetBackdropColor (.9, .9, .3, 0.8)
+
+ add_damage_done.textura = add_damage_done:CreateTexture (nil, "overlay")
+ add_damage_done.textura:SetTexture ("Interface\\Buttons\\UI-MicroStream-Red")
+ add_damage_done.textura:SetWidth (16)
+ add_damage_done.textura:SetHeight (16)
+ add_damage_done.textura:SetPoint ("topleft", add_damage_done, "topleft")
+
+ add_damage_done:SetScript ("OnEnter", _DanoFeito)
+ add_damage_done:SetScript ("OnLeave", function() GameTooltip:Hide() end)
+ add_damage_done:SetScript ("OnClick", EncounterDetails.BossInfoRowClick)
+
+ barra.texto_esquerdo:SetPoint ("left", add_damage_done, "right")
+ barra.textura:SetStatusBarTexture (nil)
+ _detalhes:SetFontSize (barra.texto_esquerdo, 9)
+ _detalhes:SetFontSize (barra.texto_direita, 9)
+
+ --barra.TTT = "habilidades_inimigas" -- tool tip type
+ end
+
+ barra.texto_esquerdo:SetText (addName)
+ barra.texto_direita:SetText (_detalhes:comma_value (esta_tabela.total))
+
+ _detalhes:name_space (barra)
+
+ barra.jogador = esta_tabela --> barra.jogador agora tem a tabela com --> [1] total dano causado [2] jogadores que foram alvos [3] jogadores que castaram essa magia [4] ID da magia
+
+ --barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [jogador.classe]))
+ barra.textura:SetStatusBarColor (1, 1, 1, 1) --> a cor pode ser a spell school da magia
+ barra.textura:SetValue (100)
+
+ --barra.icone:SetTexture (icone_magia)
+ --barra.icone:SetTexCoord (_unpack (CLASS_ICON_TCOORDS [jogador.classe]))
+
+ barra:Show()
+ quantidade = quantidade + 1
+ index = index +1
+ end
+
+ EncounterDetails:JB_AtualizaContainer (container, quantidade, 4)
+
+ if (quantidade < #container.barras) then
+ for i = quantidade+1, #container.barras, 1 do
+ container.barras [i]:Hide()
+ end
+ end
+
+ --> Fim do container Over ADDS
+
+ --> Inicio do Container de Interrupts:
+
+ local misc = _combat_object [class_type_misc]
+
+ local total_interrompido = _detalhes.atributo_misc:RefreshWindow ({}, _combat_object, _, { key = "interrupt", modo = _detalhes.modos.group })
+
+ local frame_interrupts = EncounterDetailsFrame.overall_interrupt
+ container = frame_interrupts.gump
+
+ quantidade = 0
+ local interrupt_do_primeiro = 0
+
+ local habilidades_interrompidas = {}
+
+ for index, jogador in _ipairs (misc._ActorTable) do
+ if (not jogador.grupo) then --> só aparecer nego da raid
+ break
+ end
+
+ if (jogador.classe and jogador.classe ~= "UNGROUPPLAYER") then
+ local interrupts = jogador.interrupt
+ if (interrupts and interrupts > 0) then
+ local oque_interrompi = jogador.interrompeu_oque
+ --> vai ter [spellid] = quantidade
+
+ for spellid, amt in _pairs (oque_interrompi) do
+ if (not habilidades_interrompidas [spellid]) then --> se a spell não tiver na pool, cria a tabela dela
+ habilidades_interrompidas [spellid] = {{}, 0, spellid} --> tabela com quem interrompeu e o total de vezes que a habilidade foi interrompida
+ end
+
+ if (not habilidades_interrompidas [spellid] [1] [jogador.nome]) then --> se o jogador não tiver na pool dessa habilidade interrompida, cria um indice pra ele.
+ habilidades_interrompidas [spellid] [1] [jogador.nome] = {0, jogador.classe}
+ end
+
+ habilidades_interrompidas [spellid] [2] = habilidades_interrompidas [spellid] [2] + amt
+ habilidades_interrompidas [spellid] [1] [jogador.nome] [1] = habilidades_interrompidas [spellid] [1] [jogador.nome] [1] + amt
+ end
+ end
+ end
+ end
+
+ --> por em ordem
+ tabela_em_ordem = {}
+ for spellid, tabela in _pairs (habilidades_interrompidas) do
+ tabela_em_ordem [#tabela_em_ordem+1] = tabela
+ end
+ _table_sort (tabela_em_ordem, function (a, b) return a[2] > b[2] end)
+
+ index = 1
+
+ for _, tabela in _ipairs (tabela_em_ordem) do
+
+ local barra = container.barras [index]
+ if (not barra) then
+ barra = EncounterDetails:CreateRow (index, container, 3, 3, -6)
+ barra.TTT = "total_interrupt" -- tool tip type
+ barra.report_text = "Details! ".. Loc ["STRING_INTERRUPT_BY"]
+ end
+
+ local nome_magia, _, icone_magia = _GetSpellInfo (tabela [3])
+
+ barra.texto_esquerdo:SetText (nome_magia)
+ barra.texto_direita:SetText (tabela [2])
+
+ _detalhes:name_space (barra)
+
+ barra.jogador = tabela
+
+ --barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [jogador.classe]))
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ dano_do_primeiro = tabela [2]
+ else
+ barra.textura:SetValue (tabela [2]/dano_do_primeiro *100)
+ end
+
+ barra.icone:SetTexture (icone_magia)
+ --barra.icone:SetTexCoord (_unpack (CLASS_ICON_TCOORDS [jogador.classe]))
+
+ barra:Show()
+
+ quantidade = quantidade + 1
+ index = index + 1
+ end
+
+ EncounterDetails:JB_AtualizaContainer (container, quantidade, 4)
+
+ if (quantidade < #container.barras) then
+ for i = quantidade+1, #container.barras, 1 do
+ container.barras[i]:Hide()
+ end
+ end
+
+ --> Fim do container dos Interrupts
+
+ --> Inicio do Container dos Dispells:
+
+ --> force refresh window behavior
+ local total_dispelado = _detalhes.atributo_misc:RefreshWindow ({}, _combat_object, _, { key = "dispell", modo = _detalhes.modos.group })
+
+ local frame_dispell = EncounterDetailsFrame.overall_dispell
+ container = frame_dispell.gump
+
+ quantidade = 0
+ local dispell_do_primeiro = 0
+
+ local habilidades_dispeladas = {}
+
+ for index, jogador in _ipairs (misc._ActorTable) do
+ if (not jogador.grupo) then --> só aparecer nego da raid
+ break
+ end
+
+ if (jogador.classe and jogador.classe ~= "UNGROUPPLAYER") then
+
+ local dispells = jogador.dispell
+ if (dispells and dispells > 0) then
+ local oque_dispelei = jogador.dispell_oque
+ --> vai ter [spellid] = quantidade
+
+ --print ("dispell: " .. jogador.classe .. " nome: " .. jogador.nome)
+
+ for spellid, amt in _pairs (oque_dispelei) do
+ if (not habilidades_dispeladas [spellid]) then --> se a spell não tiver na pool, cria a tabela dela
+ habilidades_dispeladas [spellid] = {{}, 0, spellid} --> tabela com quem dispolou e o total de vezes que a habilidade foi dispelada
+ end
+
+ if (not habilidades_dispeladas [spellid] [1] [jogador.nome]) then --> se o jogador não tiver na pool dessa habilidade interrompida, cria um indice pra ele.
+ habilidades_dispeladas [spellid] [1] [jogador.nome] = {0, jogador.classe}
+ --print (jogador.nome)
+ --print (jogador.classe)
+ end
+
+ habilidades_dispeladas [spellid] [2] = habilidades_dispeladas [spellid] [2] + amt
+ habilidades_dispeladas [spellid] [1] [jogador.nome] [1] = habilidades_dispeladas [spellid] [1] [jogador.nome] [1] + amt
+ end
+ end
+ end
+ end
+
+ --> por em ordem
+ tabela_em_ordem = {}
+ for spellid, tabela in _pairs (habilidades_dispeladas) do
+ tabela_em_ordem [#tabela_em_ordem+1] = tabela
+ end
+ _table_sort (tabela_em_ordem, function (a, b) return a[2] > b[2] end)
+
+ index = 1
+
+ for _, tabela in _ipairs (tabela_em_ordem) do
+
+ local barra = container.barras [index]
+ if (not barra) then
+ barra = EncounterDetails:CreateRow (index, container, 3, 3, -6)
+ barra.TTT = "dispell" -- tool tip type
+ barra.report_text = "Details! ".. Loc ["STRING_DISPELLED_BY"]
+ end
+
+ local nome_magia, _, icone_magia = _GetSpellInfo (tabela [3])
+
+ barra.texto_esquerdo:SetText (nome_magia)
+ barra.texto_direita:SetText (tabela [2])
+
+ _detalhes:name_space (barra)
+
+ barra.jogador = tabela
+
+ --barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [jogador.classe]))
+
+ if (index == 1) then
+ barra.textura:SetValue (100)
+ dano_do_primeiro = tabela [2]
+ else
+ barra.textura:SetValue (tabela [2]/dano_do_primeiro *100)
+ end
+
+ barra.icone:SetTexture (icone_magia)
+ --barra.icone:SetTexCoord (_unpack (CLASS_ICON_TCOORDS [jogador.classe]))
+
+ barra:Show()
+
+ quantidade = quantidade + 1
+ index = index + 1
+ end
+
+ EncounterDetails:JB_AtualizaContainer (container, quantidade, 4)
+
+ if (quantidade < #container.barras) then
+ for i = quantidade+1, #container.barras, 1 do
+ container.barras [i]:Hide()
+ end
+ end
+
+ --> Fim do container dos Dispells
+
+ --> Inicio do Container das Mortes:
+ local frame_mortes = EncounterDetailsFrame.overall_dead
+ container = frame_mortes.gump
+
+ quantidade = 0
+
+ -- boss_info.spell_tables_info o erro de lua do boss é a habilidade dele que não foi declarada ainda
+
+ local mortes = _combat_object.last_events_tables
+ local habilidades_info = boss_info.spell_mechanics --barra.extra pega esse cara aqui --> então esse erro é das habilidades que não tao
+
+ for index, tabela in _ipairs (mortes) do
+ --> {esta_morte, time, este_jogador.nome, este_jogador.classe, _UnitHealthMax (alvo_name), minutos.."m "..segundos.."s", ["dead"] = true}
+ local barra = container.barras [index]
+ if (not barra) then
+ barra = EncounterDetails:CreateRow (index, container, 3, 3, -4)
+ barra.TTT = "morte" -- tool tip type
+ barra.report_text = "Details! " .. Loc ["STRING_DEAD_LOG"]
+ end
+
+ barra.texto_esquerdo:SetText (index..". "..tabela [3])
+ barra.texto_direita:SetText (tabela [6])
+
+ _detalhes:name_space (barra)
+
+ barra.jogador = tabela
+ barra.extra = habilidades_info
+
+ barra.textura:SetStatusBarColor (_unpack (_detalhes.class_colors [tabela [4]]))
+ barra.textura:SetValue (100)
+
+ barra.icone:SetTexture ("Interface\\AddOns\\Details\\images\\classes_small")
+ barra.icone:SetTexCoord (_unpack (CLASS_ICON_TCOORDS [tabela [4]]))
+
+ barra:Show()
+
+ quantidade = quantidade + 1
+
+ end
+
+ EncounterDetails:JB_AtualizaContainer (container, quantidade, 4)
+
+ if (quantidade < #container.barras) then
+ for i = quantidade+1, #container.barras, 1 do
+ container.barras [i]:Hide()
+ end
+ end
+end
+
+function EncounterDetails:OnEvent (_, event, ...)
+
+ if (event == "ADDON_LOADED") then
+ local AddonName = select (1, ...)
+ if (AddonName == "Details_EncounterDetails") then
+
+ if (_G._detalhes) then
+
+ --> create widgets
+ CreatePluginFrames (data)
+
+ local MINIMAL_DETAILS_VERSION_REQUIRED = 1
+
+ --> Install
+ local install = _G._detalhes:InstallPlugin ("TOOLBAR", Loc ["STRING_PLUGIN_NAME"], "placeholder string", EncounterDetails, "DETAILS_PLUGIN_ENCOUNTER_DETAILS", MINIMAL_DETAILS_VERSION_REQUIRED)
+ if (type (install) == "table" and install.error) then
+ print (install.error)
+ end
+
+ --> Register needed events
+ _G._detalhes:RegisterEvent (EncounterDetails, "COMBAT_PLAYER_ENTER")
+ _G._detalhes:RegisterEvent (EncounterDetails, "COMBAT_PLAYER_LEAVE")
+ _G._detalhes:RegisterEvent (EncounterDetails, "COMBAT_BOSS_FOUND")
+ _G._detalhes:RegisterEvent (EncounterDetails, "DETAILS_DATA_RESET")
+
+ end
+ end
+
+ elseif (event == "PLAYER_LOGOUT") then
+ _detalhes_databaseEncounterDetails = EncounterDetails.data
+ end
+end
diff --git a/plugins/Details_EncounterDetails/Details_EncounterDetails.toc b/plugins/Details_EncounterDetails/Details_EncounterDetails.toc
new file mode 100644
index 00000000..a28ad87b
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Details_EncounterDetails.toc
@@ -0,0 +1,16 @@
+## Interface: 50300
+## Title: Details Encounter (plugin)
+## Notes: Plugin for Details
+## SavedVariablesPerCharacter: _detalhes_databaseEncounterDetails
+## RequiredDeps: Details
+## OptionalDeps: Ace3
+
+#@no-lib-strip@
+embeds.xml
+#@end-no-lib-strip@
+
+enUS.lua
+ptBR.lua
+frames.lua
+
+Details_EncounterDetails.lua
\ No newline at end of file
diff --git a/plugins/Details_EncounterDetails/Libs/AceLocale-3.0/AceLocale-3.0.lua b/plugins/Details_EncounterDetails/Libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 00000000..2ecc0cb8
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/plugins/Details_EncounterDetails/Libs/AceLocale-3.0/AceLocale-3.0.xml b/plugins/Details_EncounterDetails/Libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 00000000..d69dbb13
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/Details_EncounterDetails/Libs/LibStub/LibStub.lua b/plugins/Details_EncounterDetails/Libs/LibStub/LibStub.lua
new file mode 100644
index 00000000..f5fc9192
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Libs/LibStub/LibStub.lua
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ -- LibStub:NewLibrary(major, minor)
+ -- major (string) - the major version of the library
+ -- minor (string or number ) - the minor version of the library
+ --
+ -- returns nil if a newer or same version of the lib is already present
+ -- returns empty library object or old library object if upgrade is needed
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ -- LibStub:GetLibrary(major, [silent])
+ -- major (string) - the major version of the library
+ -- silent (boolean) - if true, library is optional, silently return nil if its not found
+ --
+ -- throws an error if the library can not be found (except silent is set)
+ -- returns the library object if found
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ -- LibStub:IterateLibraries()
+ --
+ -- Returns an iterator for the currently registered libraries
+ function LibStub:IterateLibraries()
+ return pairs(self.libs)
+ end
+
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/plugins/Details_EncounterDetails/Libs/LibStub/LibStub.toc b/plugins/Details_EncounterDetails/Libs/LibStub/LibStub.toc
new file mode 100644
index 00000000..c3dc3656
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 40200
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: r95
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/plugins/Details_EncounterDetails/Libs/LibStub/tests/test.lua b/plugins/Details_EncounterDetails/Libs/LibStub/tests/test.lua
new file mode 100644
index 00000000..645a08b1
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/plugins/Details_EncounterDetails/Libs/LibStub/tests/test2.lua b/plugins/Details_EncounterDetails/Libs/LibStub/tests/test2.lua
new file mode 100644
index 00000000..af431dd3
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib doesn't exist yet, by iterating through all the libraries
+ assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+ if major == "MyLib" then -- we found it!
+ count = count +1
+ assert(rawequal(library, lib)) -- verify that the references are equal
+ end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/plugins/Details_EncounterDetails/Libs/LibStub/tests/test3.lua b/plugins/Details_EncounterDetails/Libs/LibStub/tests/test3.lua
new file mode 100644
index 00000000..01aabb8d
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/plugins/Details_EncounterDetails/Libs/LibStub/tests/test4.lua b/plugins/Details_EncounterDetails/Libs/LibStub/tests/test4.lua
new file mode 100644
index 00000000..15a9c9cd
--- /dev/null
+++ b/plugins/Details_EncounterDetails/Libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/plugins/Details_EncounterDetails/embeds.xml b/plugins/Details_EncounterDetails/embeds.xml
new file mode 100644
index 00000000..a5cb37d2
--- /dev/null
+++ b/plugins/Details_EncounterDetails/embeds.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/plugins/Details_EncounterDetails/enUS.lua b/plugins/Details_EncounterDetails/enUS.lua
new file mode 100644
index 00000000..f7d16b93
--- /dev/null
+++ b/plugins/Details_EncounterDetails/enUS.lua
@@ -0,0 +1,52 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_EncounterDetails", "enUS", true)
+
+if (not Loc) then
+ return
+end
+
+Loc ["STRING_PLUGIN_NAME"] = "Encounter Details"
+Loc ["STRING_WINDOW_TITLE"] = "Encounter Details"
+Loc ["STRING_TOTAL_DAMAGE"] = "Total Damage"
+Loc ["STRING_TOTAL_HEAL"] = "Total Heal"
+Loc ["STRING_SHOW_ALL_DATA"] = "Show overall data"
+Loc ["STRING_SHOW_PHASE_DATA"] = "Show details for this phase"
+Loc ["STRING_NOT IMPLEMENTED"] = "Not implemented yet"
+Loc ["STRING_DIED"] = "died"
+Loc ["STRING_MELEE_DAMAGE"] = "melee damage"
+Loc ["STRING_DAMAGE_TAKEN_REPORT"] = "Damage taken by ability"
+Loc ["STRING_ABILITY_DAMAGE"] = "Ability damage"
+Loc ["STRING_DAMAGE_TAKEN"] = "Damage Taken"
+Loc ["STRING_TOOK_DAMAGE_FROM"] = "Took damage from"
+Loc ["STRING_INTERRUPT_BY"] = "interrupted by"
+Loc ["STRING_DISPELLED_BY"] = "dispelled by"
+Loc ["STRING_DEAD_LOG"] = "last seconds of"
+Loc ["STRING_CURRENT"] = "Current"
+Loc ["STRING_TRY"] = "Fight"
+Loc ["STRING_DAMAGE_AT"] = "Damage Taken"
+Loc ["STRING_INFLICTED_BY"] = "Damage inflicted by"
+Loc ["STRING_INFLICTED"] = "Damage inflicted"
+Loc ["STRING_ADDS"] = "Adds"
+Loc ["STRING_INTERRUPTS"] = "Interrupts"
+Loc ["STRING_DISPELLS"] = "Dispells"
+Loc ["STRING_DEATH_LOG"] = "Death Log"
+Loc ["STRING_FIGHT_SUMMARY"] = "fight details"
+Loc ["STRING_FIGHT_GRAPHIC"] = "performance charts"
+Loc ["STRING_TOOLTIP"] = "Show Encounter Details Window"
+Loc ["STRING_"] = ""
+
+--> mechanic types
+Loc ["STRING_HEAL"] = "heal"
+Loc ["STRING_LOWDPS"] = "lowdps"
+Loc ["STRING_LOWHEAL"] = "lowheal"
+Loc ["STRING_VOIDZONE"] = "voidzone"
+Loc ["STRING_DISPELL"] = "dispell"
+Loc ["STRING_INTERRUPT"] = "interrupt"
+Loc ["STRING_POSITIONING"] = "positioning"
+Loc ["STRING_RUNAWAY"] = "runaway"
+Loc ["STRING_TANKSWITCH"] = "tankswitch"
+Loc ["STRING_MECHANIC"] = "mechanic"
+Loc ["STRING_CROWDCONTROL"] = "cc"
+Loc ["STRING_TANKCOOLDOWN"] = "tankcooldown"
+Loc ["STRING_KILLADD"] = "killadd"
+Loc ["STRING_SPREADOUT"] = "spreadout"
+Loc ["STRING_STOPCAST"] = "stopcast"
\ No newline at end of file
diff --git a/plugins/Details_EncounterDetails/frames.lua b/plugins/Details_EncounterDetails/frames.lua
new file mode 100644
index 00000000..992e62c9
--- /dev/null
+++ b/plugins/Details_EncounterDetails/frames.lua
@@ -0,0 +1,1205 @@
+do
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+ local AceLocale = LibStub ("AceLocale-3.0")
+ local Loc = AceLocale:GetLocale ("Details_EncounterDetails")
+ local Graphics = LibStub:GetLibrary("LibGraph-2.0")
+ local _ipairs = ipairs
+ local _math_floor = math.floor
+ local _GetSpellInfo = _detalhes.getspellinfo
+
+ _detalhes.EncounterDetailsTempWindow = function (EncounterDetails)
+
+ function EncounterDetails:CreateRowTexture (row)
+ row.textura = CreateFrame ("StatusBar", nil, row)
+ row.textura:SetAllPoints (row)
+ row.textura:SetStatusBarTexture ("Interface\\AddOns\\Details\\images\\bar4")
+ row.textura:SetStatusBarColor(.5, .5, .5, 0)
+ row.textura:SetMinMaxValues(0,100)
+
+ row.texto_esquerdo = row.textura:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ row.texto_esquerdo:SetPoint ("LEFT", row.textura, "LEFT", 22, 0)
+ row.texto_esquerdo:SetJustifyH ("LEFT")
+ row.texto_esquerdo:SetTextColor (1,1,1,1)
+
+ row.texto_direita = row.textura:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ row.texto_direita:SetPoint ("RIGHT", row.textura, "RIGHT", -2, 0)
+ row.texto_direita:SetJustifyH ("RIGHT")
+ row.texto_direita:SetTextColor (1,1,1,1)
+
+ row.textura:Show()
+ end
+
+ function EncounterDetails:CreateRow (index, container, x_mod, y_mod, width_mod)
+
+ local barra = CreateFrame ("Button", "Details_"..container:GetName().."_barra_"..index, container)
+
+ x_mod = x_mod or 0
+ width_mod = width_mod or 0
+
+ barra:SetWidth (200+width_mod) --> tamanho da barra de acordo com o tamanho da janela
+ barra:SetHeight (16) --> altura determinada pela instância
+
+ local y = (index-1)*17 --> 17 é a altura da barra
+ y_mod = y_mod or 0
+ y = y + y_mod
+ y = y*-1 --> baixo
+
+ barra:SetPoint ("LEFT", container, "LEFT", x_mod, 0)
+ barra:SetPoint ("RIGHT", container, "RIGHT", width_mod, 0)
+ barra:SetPoint ("TOP", container, "TOP", 0, y)
+ barra:SetFrameLevel (container:GetFrameLevel() + 1)
+
+ barra:EnableMouse (true)
+ barra:RegisterForClicks ("LeftButtonDown","RightButtonUp")
+
+ EncounterDetails:CreateRowTexture (barra)
+
+ --> icone
+ barra.icone = barra.textura:CreateTexture (nil, "OVERLAY")
+ barra.icone:SetWidth (14)
+ barra.icone:SetHeight (14)
+ barra.icone:SetPoint ("RIGHT", barra.textura, "LEFT", 0+20, 0)
+
+ barra:SetAlpha(0.9)
+ barra.icone:SetAlpha (0.8)
+
+ EncounterDetails:SetRowScripts (barra, index, container)
+
+ container.barras [index] = barra
+
+ return barra
+ end
+
+ function EncounterDetails:JB_AtualizaContainer (container, amt, barras_total)
+ barras_total = barras_total or 6
+ if (amt >= barras_total and container.ultimo ~= amt) then
+ local tamanho = 17*amt
+ container:SetHeight (tamanho)
+ container.window.slider:Update()
+ container.window.ultimo = amt
+ elseif (amt <= barras_total-1 and container.slider.ativo) then
+ container.window.slider:Update (true)
+ container:SetHeight (140)
+ container.window.scroll_ativo = false
+ container.window.ultimo = 0
+ end
+ end
+
+ local grafico_cores = {{1, 1, 1, 1}, {1, 0.5, 0.3, 1}, {0.75, 0.7, 0.1, 1}, {0.2, 0.9, 0.2, 1}, {0.2, 0.5, 0.9, 1}} --, {0.9, 0.2, 0.35, 1}, {0.85, 0.55, 0.45, 1}, {0.4, 0.98, 0.29, 1}
+
+ local lastBoss = nil
+ function EncounterDetails:BuildDpsGraphic()
+
+ EncounterDetails.LastGraphicDrew = EncounterDetails.LastGraphicDrew or {}
+ local graphicData = _detalhes.tabela_vigente:GetTimeData()
+
+ if (not graphicData or not _detalhes.tabela_vigente.start_time or not _detalhes.tabela_vigente.end_time) then
+ return
+ elseif (graphicData == EncounterDetails.LastGraphicDrew) then
+ return
+ else
+ EncounterDetails.LastGraphicDrew = graphicData
+ end
+
+ if (graphicData.damageMax == 0 or not graphicData.damage) then
+ return
+ end
+
+ --> battle time
+ if (_detalhes.tabela_vigente.end_time - _detalhes.tabela_vigente.start_time < 12) then
+ return
+ end
+
+ local g
+
+ EncounterDetails.Frame.linhas = EncounterDetails.Frame.linhas or 0
+ EncounterDetails.Frame.linhas = EncounterDetails.Frame.linhas + 1
+
+ if (EncounterDetails.Frame.linhas > 5) then
+ EncounterDetails.Frame.linhas = 1
+ end
+
+ if (not _G.DetailsRaidDpsGraph) then
+ g = Graphics:CreateGraphLine ("DetailsRaidDpsGraph", EncounterDetails.Frame, "topleft","topleft",20,-76,670,238)
+ g:SetXAxis (-1,1)
+ g:SetYAxis (-1,1)
+ g:SetGridSpacing (false, false)
+ g:SetGridColor ({0.5,0.5,0.5,0.3})
+ g:SetAxisDrawing (false,false)
+ g:SetAxisColor({1.0,1.0,1.0,1.0})
+ g:SetAutoScale (true)
+ g:SetLineTexture ("smallline")
+ g:SetBorderSize ("right", 0.001)
+ g.VerticalLines = {}
+ g.TryIndicator = {}
+
+ function g:ChangeColorOnDataSeries (index, color)
+ self.Data [index].Color = color
+ self.NeedsUpdate=true
+ end
+
+ function g:AddDataSeriesOnFirstIndex (points, color, n2)
+ local data
+ --Make sure there is data points
+ if not points then
+ return
+ end
+
+ data=points
+ if n2==nil then
+ n2=false
+ end
+ if n2 or (table.getn(points)==2 and table.getn(points[1])~=2) then
+ data={}
+ for k,v in ipairs(points[1]) do
+ tinsert(data,{v,points[2][k]})
+ end
+ end
+
+ table.insert (self.Data, 1, {Points=data;Color=color})
+
+ self.NeedsUpdate=true
+ end
+
+ DetailsFrameWork:NewLabel (EncounterDetails.Frame, EncounterDetails.Frame, nil, "timeamt0", "00:00", "GameFontHighlightSmall")
+ EncounterDetails.Frame["timeamt0"]:SetPoint ("TOPLEFT", EncounterDetails.Frame, "TOPLEFT", 85, -300)
+
+ for i = 1, 8, 1 do
+
+ local line = g:CreateTexture (nil, "overlay")
+ line:SetTexture (.5, .5, .5, .7)
+ line:SetWidth (670)
+ line:SetHeight (1)
+ line:SetVertexColor (.4, .4, .4, .8)
+
+ DetailsFrameWork:NewLabel (EncounterDetails.Frame, EncounterDetails.Frame, nil, "dpsamt"..i, "", "GameFontHighlightSmall")
+ EncounterDetails.Frame["dpsamt"..i]:SetPoint ("TOPLEFT", EncounterDetails.Frame, "TOPLEFT", 27, -61 + (-(24.6*i)))
+ line:SetPoint ("topleft", EncounterDetails.Frame["dpsamt"..i].widget, "bottom", -27, 0)
+
+ DetailsFrameWork:NewLabel (EncounterDetails.Frame, EncounterDetails.Frame, nil, "timeamt"..i, "", "GameFontHighlightSmall")
+ EncounterDetails.Frame["timeamt"..i].widget:SetPoint ("TOPLEFT", EncounterDetails.Frame, "TOPLEFT", 75+(73*i), -300)
+ end
+
+ g.max_time = 0
+ g.max_damage = 0
+
+ EncounterDetails.MaxGraphics = EncounterDetails.MaxGraphics or 5
+
+ for i = 1, EncounterDetails.MaxGraphics do
+ local texture = g:CreateTexture (nil, "overlay")
+ texture:SetWidth (9)
+ texture:SetHeight (9)
+ texture:SetPoint ("TOPLEFT", EncounterDetails.Frame, "TOPLEFT", (i*65) + 299, -81)
+ texture:SetTexture (unpack (grafico_cores[i]))
+ local text = g:CreateFontString (nil, "OVERLAY", "GameFontHighlightSmall")
+ text:SetPoint ("LEFT", texture, "right", 2, 0)
+ text:SetJustifyH ("LEFT")
+ if (i == 1) then
+ text:SetText (Loc ["STRING_CURRENT"])
+ else
+ text:SetText (Loc ["STRING_TRY"] .. " #" .. i)
+ end
+ --texture:Hide()
+ g.TryIndicator [#g.TryIndicator+1] = {texture = texture, text = text}
+ end
+
+ local v = g:CreateTexture (nil, "overlay")
+ v:SetWidth (1)
+ v:SetHeight (238)
+ v:SetPoint ("top", g, "top", 0, 1)
+ v:SetPoint ("left", g, "left", 55, 0)
+ v:SetTexture (1, 1, 1, 1)
+
+ local h = g:CreateTexture (nil, "overlay")
+ h:SetWidth (668)
+ h:SetHeight (2)
+ h:SetPoint ("top", g, "top", 0, -217)
+ h:SetPoint ("left", g, "left")
+ h:SetTexture (1, 1, 1, 1)
+
+ else
+ g = _G.DetailsRaidDpsGraph
+
+ if (not _detalhes.tabela_vigente.is_boss or not lastBoss or _detalhes.tabela_vigente.is_boss.index ~= lastBoss) then
+ g:ResetData()
+ g.max_damage = 0
+ end
+ end
+
+ lastBoss = _detalhes.tabela_vigente.is_boss and _detalhes.tabela_vigente.is_boss.index
+
+ local _data = {}
+ local dps_max = graphicData.damageMax
+ local amount = #graphicData.damage
+
+ local scaleW = 1/670
+
+ local content = graphicData.damage
+ table.insert (content, 1, 0)
+ table.insert (content, 1, 0)
+ table.insert (content, #content+1, 0)
+ table.insert (content, #content+1, 0)
+ local _i = 3
+
+ local graphMaxDps = math.max (g.max_damage, dps_max)
+ while (_i <= #content-2) do
+ local v = (content[_i-2]+content[_i-1]+content[_i]+content[_i+1]+content[_i+2])/5 --> normalize
+ _data [#_data+1] = {scaleW*(_i-2), v/graphMaxDps} --> x and y coords
+ _i = _i + 1
+ end
+
+--[[ precisa de uma proteção contra troca de tabela, no inicio dos trash
+Message: ..\AddOns\Details_EncounterDetails\frames.lua line 156:
+ attempt to perform arithmetic on field 'end_time' (a nil value)--]]
+
+ local tempo = _detalhes.tabela_vigente.end_time - _detalhes.tabela_vigente.start_time
+ if (g.max_time < tempo) then
+ g.max_time = tempo
+
+ local tempo_divisao = g.max_time / 8
+
+ for i = 1, 8, 1 do
+ local t = tempo_divisao*i
+ local minutos, segundos = _math_floor (t/60), _math_floor (t%60)
+ if (segundos < 10) then
+ segundos = "0"..segundos
+ end
+ if (minutos < 10) then
+ minutos = "0"..minutos
+ end
+ EncounterDetails.Frame["timeamt"..i]:SetText (minutos..":"..segundos)
+ end
+ end
+
+ print ("DPSMAX: " .. dps_max .. " > " .. g.max_damage)
+
+ if (dps_max > g.max_damage) then
+
+ --> normalize previous data
+
+ --table.insert (self.Data, 1, {Points=data;Color=color})
+
+ if (g.max_damage > 0) then
+ local normalizePercent = g.max_damage / dps_max
+ print ("Normalizing: " .. normalizePercent)
+ for dataIndex, Data in ipairs (g.Data) do
+ local Points = Data.Points
+ for i = 1, #Points do
+ --print (Points[i][1], Points[i][2])
+ Points[i][2] = Points[i][2]*normalizePercent
+ end
+ end
+ end
+
+ g.max_damage = dps_max
+
+ local dano_divisao = g.max_damage/8
+
+ local o = 1
+ for i = 8, 1, -1 do
+ local d = _detalhes:ToK (dano_divisao*i)
+ EncounterDetails.Frame["dpsamt"..o]:SetText (d)
+ o = o + 1
+ end
+
+ end
+
+ if (#g.Data == 5) then
+ table.remove (g.Data, 5)
+ end
+
+ g:AddDataSeriesOnFirstIndex (_data, grafico_cores [1])
+
+ for i = 2, #g.Data do
+ g:ChangeColorOnDataSeries (i, grafico_cores [i])
+ end
+
+ local mortes = _detalhes.tabela_vigente.last_events_tables
+ local scaleG = 650/_detalhes.tabela_vigente:GetCombatTime()
+
+ for _, row in _ipairs (g.VerticalLines) do
+ row:Hide()
+ end
+
+ for i = 1, math.min (3, #mortes) do
+
+ local vRowFrame = g.VerticalLines [i]
+ local deadTime = mortes [i][2] - _detalhes.tabela_vigente.start_time
+
+ if (not vRowFrame) then
+
+ vRowFrame = CreateFrame ("frame", "DetailsEncountersVerticalLine"..i, g)
+ vRowFrame:SetWidth (20)
+ vRowFrame:SetHeight (43)
+ vRowFrame:SetFrameLevel (g:GetFrameLevel()+2)
+
+ vRowFrame:SetScript ("OnEnter", function (frame)
+
+ if (vRowFrame.dead[1] and vRowFrame.dead[1][3] and vRowFrame.dead[1][3][2]) then
+ local nome_magia3, _, icone_magia3 = _GetSpellInfo (vRowFrame.dead[1][3][2])
+ if (type (vRowFrame.dead[1][3][3]) == "number") then
+ nome_magia3 = _detalhes:comma_value (vRowFrame.dead[1][3][3]).." "..nome_magia3
+ end
+
+ local nome_magia2, _, icone_magia2 = _GetSpellInfo (vRowFrame.dead[1][2][2])
+ if (type (vRowFrame.dead[1][2][3]) == "number") then
+ nome_magia2 = _detalhes:comma_value (vRowFrame.dead[1][2][3]).." "..nome_magia2
+ end
+
+ local nome_magia1, _, icone_magia1 = _GetSpellInfo (vRowFrame.dead[1][1][2])
+ if (type (vRowFrame.dead[1][1][3]) == "number") then
+ nome_magia1 = _detalhes:comma_value (vRowFrame.dead[1][1][3]).." "..nome_magia1
+ else --bress
+ local decorrido = vRowFrame.dead[1][1][4] - _detalhes.tabela_vigente.start_time
+ local minutos, segundos = _math_floor (decorrido/60), _math_floor (decorrido%60)
+ nome_magia1 = minutos..":"..segundos.." "..nome_magia1
+ end
+
+ GameCooltip:Reset()
+
+ GameCooltip:AddLine (vRowFrame.dead[6].." "..vRowFrame.dead[3])
+ GameCooltip:AddIcon ("Interface\\AddOns\\Details_EncounterDetails\\images\\small_icons", _,_,_,_, .75, 1, 0, 1)
+
+ GameCooltip:AddLine (nome_magia3)
+ GameCooltip:AddIcon (icone_magia3)
+
+ GameCooltip:AddLine (nome_magia2)
+ GameCooltip:AddIcon (icone_magia1)
+
+ GameCooltip:AddLine (nome_magia1)
+ GameCooltip:AddIcon (icone_magia1)
+
+ GameCooltip:SetOption ("TextSize", 9.5)
+ GameCooltip:SetOption ("IconSize", 12)
+ GameCooltip:SetOption ("HeightAnchorMod", -15)
+ GameCooltip:SetOption ("TextHeightMod", -2)
+
+ GameCooltip:ShowCooltip (frame, "tooltip")
+ end
+ end)
+
+ vRowFrame:SetScript ("OnLeave", function (frame)
+ _detalhes.popup:ShowMe (false)
+ end)
+
+ vRowFrame.texture = vRowFrame:CreateTexture (nil, "overlay")
+ vRowFrame.texture:SetTexture ("Interface\\AddOns\\Details\\images\\verticalline")
+ vRowFrame.texture:SetWidth (3)
+ vRowFrame.texture:SetHeight (20)
+ vRowFrame.texture:SetPoint ("center", "DetailsEncountersVerticalLine"..i, "center")
+ vRowFrame.texture:SetPoint ("bottom", "DetailsEncountersVerticalLine"..i, "bottom", 0, 0)
+ vRowFrame.texture:SetVertexColor (1, 1, 1, .5)
+
+ vRowFrame.icon = vRowFrame:CreateTexture (nil, "overlay")
+ vRowFrame.icon:SetTexture ("Interface\\WorldStateFrame\\SkullBones")
+ vRowFrame.icon:SetTexCoord (0.046875, 0.453125, 0.046875, 0.46875)
+ vRowFrame.icon:SetWidth (16)
+ vRowFrame.icon:SetHeight (16)
+ vRowFrame.icon:SetPoint ("center", "DetailsEncountersVerticalLine"..i, "center")
+ vRowFrame.icon:SetPoint ("bottom", "DetailsEncountersVerticalLine"..i, "bottom", 0, 20)
+
+ g.VerticalLines [i] = vRowFrame
+ end
+
+ vRowFrame:SetPoint ("topleft", EncounterDetails.Frame, "topleft", (deadTime*scaleG), -268)
+ vRowFrame.dead = mortes [i]
+ vRowFrame:Show()
+
+ end
+
+ _G.DetailsRaidDpsGraph:Show()
+
+ end
+
+ local BossFrame = EncounterDetails.Frame
+
+ local DetailsFrameWork = _detalhes.gump
+
+ BossFrame:SetFrameStrata ("MEDIUM")
+ if (_detalhes.janela_info) then
+ BossFrame:SetFrameLevel (_detalhes.janela_info:GetFrameLevel()+3)
+ end
+
+ BossFrame:SetWidth (698)
+ BossFrame:SetHeight (354)
+ BossFrame:EnableMouse (true)
+ BossFrame:SetResizable (false)
+ BossFrame:SetMovable (true)
+
+ function BossFrame:ToFront()
+ if (_detalhes.janela_info) then
+ if (BossFrame:GetFrameLevel() < _detalhes.janela_info:GetFrameLevel()) then
+ BossFrame:SetFrameLevel (BossFrame:GetFrameLevel()+3)
+ _detalhes.janela_info:SetFrameLevel (_detalhes.janela_info:GetFrameLevel()-3)
+ end
+ end
+ end
+
+ BossFrame.grab = DetailsFrameWork:NewDetailsButton (BossFrame, BossFrame, _, BossFrame.ToFront, nil, nil, 698, 73, "", "", "", "", {OnGrab = "PassClick"})
+ BossFrame.grab:SetPoint ("topleft", BossFrame, "topleft")
+ BossFrame.grab:SetFrameLevel (BossFrame:GetFrameLevel()+1)
+
+ BossFrame:SetScript ("OnMouseDown",
+ function (self, botao)
+ if (botao == "LeftButton") then
+ self:StartMoving()
+ self.isMoving = true
+ end
+ end)
+
+ BossFrame:SetScript ("OnMouseUp",
+ function (self)
+ if (self.isMoving) then
+ self:StopMovingOrSizing()
+ self.isMoving = false
+ end
+ end)
+
+ --> fix para dar fadein ao apertar esc
+ --[[
+ BossFrame:SetScript ("OnHide", function (self)
+ if (not BossFrame.hidden) then --> significa que foi fechado com ESC
+ BossFrame:Show()
+ DetailsFrameWork:Fade (BossFrame, "in")
+ end
+ end)
+ --]]
+
+ --BossFrame:SetBackdrop (gump_fundo_backdrop)
+ --BossFrame:SetBackdropColor (0, 0, 0, 0.3)
+
+ BossFrame:SetPoint ("CENTER", UIParent)
+ --EncounterDetails.Frame = BossFrame
+
+ --> icone da classe no canto esquerdo superior
+ BossFrame.boss_icone = BossFrame:CreateTexture (nil, "BACKGROUND")
+ BossFrame.boss_icone:SetPoint ("TOPLEFT", BossFrame, "TOPLEFT", 4, 0)
+ BossFrame.boss_icone:SetWidth (64)
+ BossFrame.boss_icone:SetHeight (64)
+
+ --> imagem de fundo
+ BossFrame.raidbackground = BossFrame:CreateTexture (nil, "BACKGROUND")
+ BossFrame.raidbackground:SetPoint ("TOPLEFT", BossFrame, "TOPLEFT", 244, -74)
+
+ BossFrame.raidbackground:SetWidth (512)
+ BossFrame.raidbackground:SetHeight (256)
+
+ --> background completo
+ BossFrame.bg = BossFrame:CreateTexture (nil, "BORDER")
+ BossFrame.bg:SetPoint ("TOPLEFT", BossFrame, "TOPLEFT", 0, 0)
+ BossFrame.bg:SetWidth (1024)
+ BossFrame.bg:SetHeight (512)
+ BossFrame.bg:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_bg")
+
+ BossFrame.Widgets = {}
+
+ BossFrame.ShowType = "main"
+
+ --> revisar
+ BossFrame.Reset = function()
+ BossFrame.switch ("main")
+ if (_G.DetailsRaidDpsGraph) then
+ _G.DetailsRaidDpsGraph:ResetData()
+ end
+ if (BossFrame.aberta) then
+ _detalhes:FecharEncounterWindows()
+ end
+ BossFrame.linhas = nil
+ end
+
+ local selected
+ local u
+
+ BossFrame.switch = function (to)
+ if (to == "main") then
+ BossFrame.bg:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_bg")
+ for _, frame in _ipairs (BossFrame.Widgets) do
+ frame:Show()
+ end
+
+ --BossFrame.buttonSwitchNormal:Disable()
+ --BossFrame.buttonSwitchGraphic:Enable()
+
+ selected:SetPoint ("center", BossFrame.buttonSwitchNormal, "center", 0, 1)
+ u:SetAllPoints (BossFrame.buttonSwitchNormal)
+
+ if (_G.DetailsRaidDpsGraph) then
+ _G.DetailsRaidDpsGraph:Hide()
+ for i = 1, 8, 1 do
+ BossFrame["dpsamt"..i]:Hide()
+ BossFrame["timeamt"..i]:Hide()
+
+ end
+ BossFrame["timeamt0"]:Hide()
+ end
+
+ BossFrame.StatusBar_damageicon:Show()
+ BossFrame.StatusBar_healicon:Show()
+ BossFrame.StatusBar_totaldamage:Show()
+ BossFrame.StatusBar_totalheal:Show()
+
+ BossFrame.ShowType = "main"
+
+ elseif (to == "graph") then
+
+ EncounterDetails:BuildDpsGraphic()
+ if (not _G.DetailsRaidDpsGraph) then
+ return
+ end
+
+ BossFrame.bg:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_bg_graphic")
+ for _, frame in _ipairs (BossFrame.Widgets) do
+ frame:Hide()
+ end
+
+ selected:SetPoint ("center", BossFrame.buttonSwitchGraphic, "center", 0, 1)
+ u:SetAllPoints (BossFrame.buttonSwitchGraphic)
+
+ --BossFrame.buttonSwitchNormal:Enable()
+ --BossFrame.buttonSwitchGraphic:Disable()
+
+ _G.DetailsRaidDpsGraph:Show()
+
+ BossFrame.StatusBar_damageicon:Hide()
+ BossFrame.StatusBar_healicon:Hide()
+ BossFrame.StatusBar_totaldamage:Hide()
+ BossFrame.StatusBar_totalheal:Hide()
+
+ for i = 1, 8, 1 do
+ BossFrame["dpsamt"..i].widget:Show()
+ BossFrame["timeamt"..i].widget:Show()
+ end
+ BossFrame["timeamt0"].widget:Show()
+
+ BossFrame.ShowType = "graph"
+ end
+ end
+
+ BossFrame.buttonSwitchNormal = DetailsFrameWork:NewDetailsButton (BossFrame, BossFrame, _, BossFrame.switch, "main", nil, 26, 33)
+ BossFrame.buttonSwitchNormal:SetPoint ("bottomright", BossFrame, "bottomright", -10, 5)
+ local t = BossFrame.buttonSwitchNormal:CreateTexture (nil, "artwork")
+ t:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons")
+ t:SetTexCoord (0, 0.1015625, 0, 0.515625)
+ t:SetWidth (26)
+ t:SetHeight (33)
+ t:SetAllPoints (BossFrame.buttonSwitchNormal)
+
+ BossFrame.buttonSwitchGraphic = DetailsFrameWork:NewDetailsButton (BossFrame, BossFrame, _, BossFrame.switch, "graph", nil, 26, 33)
+ BossFrame.buttonSwitchGraphic:SetPoint ("right", BossFrame.buttonSwitchNormal, "left", 0, 0)
+ local g = BossFrame.buttonSwitchGraphic:CreateTexture (nil, "artwork")
+ g:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons")
+ g:SetTexCoord (0.1171875, 0.21875, 0, 0.515625)
+ g:SetWidth (26)
+ g:SetHeight (33)
+ g:SetAllPoints (BossFrame.buttonSwitchGraphic)
+
+ u = BossFrame.buttonSwitchGraphic:CreateTexture (nil, "overlay")
+ u:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_buttons")
+ u:SetTexCoord (0.8984375, 1, 0, 0.515625)
+ u:SetWidth (26)
+ u:SetHeight (33)
+ u:SetAllPoints (BossFrame.buttonSwitchNormal)
+
+ selected = BossFrame.buttonSwitchGraphic:CreateTexture (nil, "overlay")
+ selected:SetTexture (1, 1, 1, .1)
+ selected:SetWidth (22)
+ selected:SetHeight (28)
+ selected:SetPoint ("center", BossFrame.buttonSwitchNormal, "center", 0, 0)
+
+ BossFrame.buttonSwitchNormal.MouseOnEnterHook = function()
+ GameCooltip:Reset()
+ GameCooltip:AddLine (Loc ["STRING_FIGHT_SUMMARY"])
+ GameCooltip:ShowCooltip (BossFrame.buttonSwitchNormal, "tooltip")
+ end
+ BossFrame.buttonSwitchNormal.MouseOnLeaveHook = function() _detalhes.popup:ShowMe (false) end
+
+ BossFrame.buttonSwitchGraphic.MouseOnEnterHook = function()
+ GameCooltip:Reset()
+ GameCooltip:AddLine (Loc ["STRING_FIGHT_GRAPHIC"])
+ GameCooltip:ShowCooltip (BossFrame.buttonSwitchGraphic, "tooltip")
+ end
+ BossFrame.buttonSwitchGraphic.MouseOnLeaveHook = function() _detalhes.popup:ShowMe (false) end
+
+ DetailsFrameWork:NewLabel (BossFrame, BossFrame, nil, "titulo", Loc ["STRING_WINDOW_TITLE"], "GameFontHighlightLeft", 12, {227/255, 186/255, 4/255})
+ BossFrame.titulo:SetPoint ("center", BossFrame, "center")
+ BossFrame.titulo:SetPoint ("top", BossFrame, "top", 0, -18)
+
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ local frame = BossFrame
+
+ local mouse_down = function()
+ frame:StartMoving()
+ frame.isMoving = true
+ end
+
+ local mouse_up = function()
+ if (frame.isMoving) then
+ frame:StopMovingOrSizing()
+ frame.isMoving = false
+ end
+ end
+
+
+
+ local backdrop = {edgeFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeSize = 1, insets = {left = 1, right = 1, top = 0, bottom = 1}}
+
+ --> Nome do Encontro
+ DetailsFrameWork:NewLabel (frame, frame, nil, "boss_name", "Nome do Boss Aqui", "QuestFont_Large")
+ frame.boss_name:SetPoint ("TOPLEFT", frame, "TOPLEFT", 100, -51)
+
+ --> Nome da Raid
+ DetailsFrameWork:NewLabel (frame, frame, nil, "raid_name", "Throne of Thunder", "GameFontHighlightSmall")
+ frame.raid_name:SetPoint ("CENTER", frame.boss_name, "CENTER", 0, 14)
+
+ --> Barra de Status:
+
+ frame.StatusBar_damageicon = frame:CreateTexture (nil, "overlay")
+ frame.StatusBar_damageicon:SetPoint ("bottomleft", frame, "bottomleft", 20, 21)
+ frame.StatusBar_damageicon:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_icones")
+ frame.StatusBar_damageicon:SetWidth (16)
+ frame.StatusBar_damageicon:SetHeight (16)
+ frame.StatusBar_damageicon:SetTexCoord (0, 0.0625, 0, 1) -- 256x16
+
+ DetailsFrameWork:NewLabel (frame, frame, nil, "StatusBar_totaldamage", Loc ["STRING_TOTAL_DAMAGE"], "GameFontHighlightSmall")
+ frame.StatusBar_totaldamage:SetPoint ("left", frame.StatusBar_damageicon, "right", 2, 0)
+
+ frame.StatusBar_healicon = frame:CreateTexture (nil, "overlay")
+ frame.StatusBar_healicon:SetPoint ("bottomleft", frame, "bottomleft", 20, 5)
+ frame.StatusBar_healicon:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_icones")
+ frame.StatusBar_healicon:SetWidth (16)
+ frame.StatusBar_healicon:SetHeight (16)
+ frame.StatusBar_healicon:SetTexCoord (0.0625, 0.125, 0, 1) -- 256x16
+
+ DetailsFrameWork:NewLabel (frame, frame, nil, "StatusBar_totalheal", Loc ["STRING_TOTAL_HEAL"], "GameFontHighlightSmall")
+ frame.StatusBar_totalheal:SetPoint ("left", frame.StatusBar_healicon, "right", 2, 0)
+
+ --> Caixa do Dano total tomado pela Raid
+
+ local container_damagetaken_window = CreateFrame ("ScrollFrame", "Details_Boss_ContainerDamageTaken", frame)
+ local container_damagetaken_frame = CreateFrame ("Frame", "Details_Boss_FrameDamageTaken", container_damagetaken_window)
+
+ frame.Widgets [#frame.Widgets+1] = container_damagetaken_window
+
+ container_damagetaken_frame:SetScript ("OnMouseDown", mouse_down)
+ container_damagetaken_frame:SetScript ("OnMouseUp", mouse_up)
+
+ container_damagetaken_frame.barras = {}
+
+ --label titulo & background
+ local dano_recebido_bg = CreateFrame ("Frame", nil, frame)
+ dano_recebido_bg:SetWidth (200)
+ dano_recebido_bg:SetHeight (16)
+ dano_recebido_bg:EnableMouse (true)
+ dano_recebido_bg:SetResizable (false)
+ dano_recebido_bg:SetPoint ("topleft", frame, "topleft", 20, -76)
+
+ frame.Widgets [#frame.Widgets+1] = dano_recebido_bg
+
+ dano_recebido_bg.textura = dano_recebido_bg:CreateTexture (nil, "overlay")
+ dano_recebido_bg.textura:SetPoint ("topleft", dano_recebido_bg, "topleft")
+ dano_recebido_bg.textura:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\dano_recebido_bg")
+ dano_recebido_bg.textura:Hide()
+
+ dano_recebido_bg:SetScript ("OnEnter", function(self) self.textura:Show() end)
+ dano_recebido_bg:SetScript ("OnLeave", function(self) self.textura:Hide() end)
+
+ DetailsFrameWork:NewLabel (dano_recebido_bg, dano_recebido_bg, nil, "damagetaken_title", Loc ["STRING_DAMAGE_AT"], "GameFontHighlightSmall")
+ dano_recebido_bg.damagetaken_title:SetPoint ("BOTTOMLEFT", container_damagetaken_window, "TOPLEFT", 5, 3)
+
+ --container_damagetaken_window:SetBackdrop({edgeFile = "Interface\\DialogFrame\\UI-DialogBox-gold-Border", tile = true, tileSize = 16, edgeSize = 5, insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ --container_damagetaken_window:SetBackdropBorderColor (0,0,0,0)
+
+ container_damagetaken_frame:SetBackdrop (backdrop)
+ container_damagetaken_frame:SetBackdropBorderColor (0,0,0,0)
+ container_damagetaken_frame:SetBackdropColor (0, 0, 0, 0.6)
+
+ container_damagetaken_frame:SetAllPoints (container_damagetaken_window)
+ container_damagetaken_frame:SetWidth (200)
+ container_damagetaken_frame:SetHeight (100)
+ container_damagetaken_frame:EnableMouse (true)
+ container_damagetaken_frame:SetResizable (false)
+ container_damagetaken_frame:SetMovable (true)
+
+ container_damagetaken_window:SetWidth (200)
+ container_damagetaken_window:SetHeight (100)
+ container_damagetaken_window:SetScrollChild (container_damagetaken_frame)
+ container_damagetaken_window:SetPoint ("TOPLEFT", frame, "TOPLEFT", 20, -90)
+
+ DetailsFrameWork:NewScrollBar (container_damagetaken_window, container_damagetaken_frame, 4, -2)
+ container_damagetaken_window.slider:Altura (89)
+ container_damagetaken_window.slider:cimaPoint (0, 1)
+ container_damagetaken_window.slider:baixoPoint (0, -1)
+ container_damagetaken_frame.slider = container_damagetaken_window.slider
+
+ container_damagetaken_window.gump = container_damagetaken_frame
+ container_damagetaken_frame.window = container_damagetaken_window
+ container_damagetaken_window.ultimo = 0
+ frame.overall_damagetaken = container_damagetaken_window
+
+ --> Caixa das Habilidades do boss
+
+ local container_habilidades_window = CreateFrame ("ScrollFrame", "Details_Boss_ContainerHabilidades", frame)
+ local container_habilidades_frame = CreateFrame ("Frame", "Details_Boss_FrameHabilidades", container_habilidades_window)
+
+ container_habilidades_frame:SetScript ("OnMouseDown", mouse_down)
+ container_habilidades_frame:SetScript ("OnMouseUp", mouse_up)
+
+ container_habilidades_frame.barras = {}
+
+ --label titulo % background
+
+ local habilidades_inimigas_bg = CreateFrame ("Frame", nil, frame)
+ habilidades_inimigas_bg:SetWidth (200)
+ habilidades_inimigas_bg:SetHeight (16)
+ habilidades_inimigas_bg:EnableMouse (true)
+ habilidades_inimigas_bg:SetResizable (false)
+ habilidades_inimigas_bg:SetPoint ("topleft", frame, "topleft", 20, -196)
+
+ frame.Widgets [#frame.Widgets+1] = habilidades_inimigas_bg
+ frame.Widgets [#frame.Widgets+1] = container_habilidades_window
+ frame.Widgets [#frame.Widgets+1] = container_habilidades_frame
+
+ habilidades_inimigas_bg.textura = habilidades_inimigas_bg:CreateTexture (nil, "overlay")
+ habilidades_inimigas_bg.textura:SetPoint ("topleft", habilidades_inimigas_bg, "topleft")
+ --habilidades_inimigas_bg.textura:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\habilidades_inimigas_bg")
+ habilidades_inimigas_bg.textura:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\habilidades_inimigas_bg")
+ habilidades_inimigas_bg.textura:Hide()
+
+ habilidades_inimigas_bg:SetScript ("OnEnter", function(self) self.textura:Show() end)
+ habilidades_inimigas_bg:SetScript ("OnLeave", function(self) self.textura:Hide() end)
+
+ DetailsFrameWork:NewLabel (habilidades_inimigas_bg, habilidades_inimigas_bg, nil, "habilidades_title", Loc ["STRING_INFLICTED_BY"], "GameFontHighlightSmall")
+ habilidades_inimigas_bg.habilidades_title:SetPoint ("BOTTOMLEFT", container_habilidades_window, "TOPLEFT", 5, 3)
+
+ --> container background
+ --container_habilidades_window:SetBackdrop({edgeFile = "Interface\\DialogFrame\\UI-DialogBox-gold-Border", tile = true, tileSize = 16, edgeSize = 5, insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ --container_habilidades_window:SetBackdropBorderColor (0,0,0,0)
+
+ container_habilidades_frame:SetBackdrop (backdrop)
+ container_habilidades_frame:SetBackdropBorderColor (0,0,0,0)
+ container_habilidades_frame:SetBackdropColor (0, 0, 0, 0.6)
+
+ container_habilidades_frame:SetAllPoints (container_habilidades_window)
+ container_habilidades_frame:SetWidth (200)
+ container_habilidades_frame:SetHeight (100)
+ container_habilidades_frame:EnableMouse (true)
+ container_habilidades_frame:SetResizable (false)
+ container_habilidades_frame:SetMovable (true)
+
+ container_habilidades_window:SetWidth (200)
+ container_habilidades_window:SetHeight (100)
+ container_habilidades_window:SetScrollChild (container_habilidades_frame)
+ container_habilidades_window:SetPoint ("TOPLEFT", frame, "TOPLEFT", 20, -211)
+
+ DetailsFrameWork:NewScrollBar (container_habilidades_window, container_habilidades_frame, 4, -2)
+ container_habilidades_window.slider:Altura (89)
+ container_habilidades_window.slider:cimaPoint (0, 1)
+ container_habilidades_window.slider:baixoPoint (0, -1)
+ container_habilidades_frame.slider = container_habilidades_window.slider
+
+ container_habilidades_window.gump = container_habilidades_frame
+ container_habilidades_frame.window = container_habilidades_window
+ container_habilidades_window.ultimo = 0
+ frame.overall_habilidades = container_habilidades_window
+
+
+ --> Caixa dos Adds
+
+ local container_adds_window = CreateFrame ("ScrollFrame", "Details_Boss_ContainerAdds", frame)
+ local container_adds_frame = CreateFrame ("Frame", "Details_Boss_FrameAdds", container_adds_window)
+ local mouseOver_adds_frame = CreateFrame ("Frame", "MouseOverDetails_Boss_FrameAdds", frame)
+
+ frame.Widgets [#frame.Widgets+1] = mouseOver_adds_frame
+ frame.Widgets [#frame.Widgets+1] = container_adds_frame
+ frame.Widgets [#frame.Widgets+1] = container_adds_window
+
+ mouseOver_adds_frame:SetPoint ("bottom", container_adds_window, "top")
+ mouseOver_adds_frame:SetPoint ("bottomleft", container_adds_window, "topleft", 0, 5)
+ mouseOver_adds_frame:SetPoint ("bottomright", container_adds_window, "topright", 20, 5)
+ mouseOver_adds_frame:SetHeight (50)
+
+ mouseOver_adds_frame.imagem = mouseOver_adds_frame:CreateTexture (nil, "overlay")
+ mouseOver_adds_frame.imagem:SetPoint ("topright", mouseOver_adds_frame, "topright", -7, -9)
+
+ mouseOver_adds_frame.imagem:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_icons")
+ mouseOver_adds_frame.imagem:SetTexCoord (0.52734375, 0.7421875, 0.03125, 0.3671875)
+ mouseOver_adds_frame.imagem:SetWidth (57)
+ mouseOver_adds_frame.imagem:SetHeight (44)
+
+ mouseOver_adds_frame:SetScript ("OnEnter",
+ function()
+ mouseOver_adds_frame.imagem:SetTexCoord (0.7734375, 0.99609375, 0.03125, 0.3671875)
+ end)
+ mouseOver_adds_frame:SetScript ("OnLeave",
+ function()
+ mouseOver_adds_frame.imagem:SetTexCoord (0.52734375, 0.7421875, 0.03125, 0.3671875)
+ end)
+
+ mouseOver_adds_frame:SetScript ("OnMouseDown", mouse_down)
+ mouseOver_adds_frame:SetScript ("OnMouseUp", mouse_up)
+ container_adds_frame:SetScript ("OnMouseDown", mouse_down)
+ container_adds_frame:SetScript ("OnMouseUp", mouse_up)
+
+ container_adds_frame.barras = {}
+
+ --container_adds_window:SetBackdrop({edgeFile = "Interface\\DialogFrame\\UI-DialogBox-gold-Border", tile = true, tileSize = 16, edgeSize = 5, insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ --container_adds_window:SetBackdropBorderColor (0,0,0,0)
+
+ --container_adds_window:SetBackdrop (gump_fundo_backdrop)
+ --container_adds_window:SetBackdropBorderColor (1, 1, 1, 1)
+ --container_adds_window:SetBackdropColor (0, 0, 0, 0.1)
+
+ container_adds_frame:SetAllPoints (container_adds_window)
+ container_adds_frame:SetWidth (170)
+ container_adds_frame:SetHeight (67)
+ container_adds_frame:EnableMouse (true)
+ container_adds_frame:SetResizable (false)
+ container_adds_frame:SetMovable (true)
+
+ container_adds_window:SetWidth (170)
+ container_adds_window:SetHeight (67)
+ container_adds_window:SetScrollChild (container_adds_frame)
+ container_adds_window:SetPoint ("TOPLEFT", frame, "TOPLEFT", 260, -117)
+
+ DetailsFrameWork:NewLabel (container_adds_window, container_adds_window, nil, "titulo", Loc ["STRING_ADDS"], "QuestFont_Large", 16, {1, 1, 1})
+ container_adds_window.titulo:SetPoint ("bottomleft", container_adds_window, "topleft", 0, 4)
+
+ DetailsFrameWork:NewScrollBar (container_adds_window, container_adds_frame, 4, -9)
+ container_adds_window.slider:Altura (45)
+ container_adds_window.slider:cimaPoint (0, 1)
+ container_adds_window.slider:baixoPoint (0, -1)
+ container_adds_frame.slider = container_adds_window.slider
+
+ container_adds_window.gump = container_adds_frame
+ container_adds_frame.window = container_adds_window
+ container_adds_window.ultimo = 0
+ frame.overall_adds = container_adds_window
+
+ --> Caixa dos interrupts (kicks)
+
+ local container_interrupt_window = CreateFrame ("ScrollFrame", "Details_Boss_Containerinterrupt", frame)
+ local container_interrupt_frame = CreateFrame ("Frame", "Details_Boss_Frameinterrupt", container_interrupt_window)
+ local mouseOver_interrupt_frame = CreateFrame ("Frame", "MouseOverDetails_Boss_FrameInterrupt", frame)
+
+ frame.Widgets [#frame.Widgets+1] = container_interrupt_window
+ frame.Widgets [#frame.Widgets+1] = container_interrupt_frame
+ frame.Widgets [#frame.Widgets+1] = mouseOver_interrupt_frame
+
+ mouseOver_interrupt_frame:SetPoint ("bottom", container_interrupt_window, "top")
+ mouseOver_interrupt_frame:SetPoint ("bottomleft", container_interrupt_window, "topleft", 0, 5)
+ mouseOver_interrupt_frame:SetPoint ("bottomright", container_interrupt_window, "topright", 20, 5)
+ mouseOver_interrupt_frame:SetHeight (50)
+
+ mouseOver_interrupt_frame.imagem = mouseOver_interrupt_frame:CreateTexture (nil, "overlay")
+ mouseOver_interrupt_frame.imagem:SetPoint ("topright", mouseOver_interrupt_frame, "topright", 12, -16)
+
+ mouseOver_interrupt_frame.imagem:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_icons")
+ mouseOver_interrupt_frame.imagem:SetTexCoord (0.6015625, 1, 0.734375, 0.9765625)
+ mouseOver_interrupt_frame.imagem:SetWidth (103)
+ mouseOver_interrupt_frame.imagem:SetHeight (34)
+
+ mouseOver_interrupt_frame:SetScript ("OnEnter",
+ function()
+ mouseOver_interrupt_frame.imagem:SetTexCoord (0.6015625, 1, 0.4296875, 0.6953125)
+ end)
+ mouseOver_interrupt_frame:SetScript ("OnLeave",
+ function()
+ mouseOver_interrupt_frame.imagem:SetTexCoord (0.6015625, 1, 0.734375, 0.9765625)
+ end)
+
+ container_interrupt_frame:SetScript ("OnMouseDown", mouse_down)
+ container_interrupt_frame:SetScript ("OnMouseUp", mouse_up)
+ mouseOver_interrupt_frame:SetScript ("OnMouseDown", mouse_down)
+ mouseOver_interrupt_frame:SetScript ("OnMouseUp", mouse_up)
+
+ container_interrupt_frame.barras = {}
+
+ --container_interrupt_window:SetBackdrop({edgeFile = "Interface\\DialogFrame\\UI-DialogBox-gold-Border", tile = true, tileSize = 16, edgeSize = 5, insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ --container_interrupt_window:SetBackdropBorderColor (0,0,0,0)
+
+ --container_interrupt_window:SetBackdrop (gump_fundo_backdrop)
+ --container_interrupt_window:SetBackdropBorderColor (1, 1, 1, 1)
+ --container_interrupt_window:SetBackdropColor (0, 0, 0, 0.1)
+
+ container_interrupt_frame:SetAllPoints (container_interrupt_window)
+ container_interrupt_frame:SetWidth (170)
+ container_interrupt_frame:SetHeight (67)
+ container_interrupt_frame:EnableMouse (true)
+ container_interrupt_frame:SetResizable (false)
+ container_interrupt_frame:SetMovable (true)
+
+ container_interrupt_window:SetWidth (170)
+ container_interrupt_window:SetHeight (67)
+ container_interrupt_window:SetScrollChild (container_interrupt_frame)
+ container_interrupt_window:SetPoint ("TOPLEFT", frame, "TOPLEFT", 480, -117)
+
+ DetailsFrameWork:NewLabel (container_interrupt_window, container_interrupt_window, nil, "titulo", Loc ["STRING_INTERRUPTS"], "QuestFont_Large", 16, {1, 1, 1})
+ container_interrupt_window.titulo:SetPoint ("bottomleft", container_interrupt_window, "topleft", 0, 4)
+
+ DetailsFrameWork:NewScrollBar (container_interrupt_window, container_interrupt_frame, 4, -9)
+ container_interrupt_window.slider:Altura (45)
+ container_interrupt_window.slider:cimaPoint (0, 1)
+ container_interrupt_window.slider:baixoPoint (0, -1)
+ container_interrupt_frame.slider = container_interrupt_window.slider
+
+ container_interrupt_window.gump = container_interrupt_frame
+ container_interrupt_frame.window = container_interrupt_window
+ container_interrupt_window.ultimo = 0
+ frame.overall_interrupt = container_interrupt_window
+
+ --> Caixa dos Dispells
+
+ local container_dispell_window = CreateFrame ("ScrollFrame", "Details_Boss_Containerdispell", frame)
+ local container_dispell_frame = CreateFrame ("Frame", "Details_Boss_Framedispell", container_dispell_window)
+ local mouseOver_dispell_frame = CreateFrame ("Frame", "MouseOverDetails_Boss_FrameDispell", frame)
+
+ frame.Widgets [#frame.Widgets+1] = container_dispell_window
+ frame.Widgets [#frame.Widgets+1] = container_dispell_frame
+ frame.Widgets [#frame.Widgets+1] = mouseOver_dispell_frame
+
+ mouseOver_dispell_frame:SetPoint ("bottom", container_dispell_window, "top")
+ mouseOver_dispell_frame:SetPoint ("bottomleft", container_dispell_window, "topleft", 0, 5)
+ mouseOver_dispell_frame:SetPoint ("bottomright", container_dispell_window, "topright", 20, 5)
+ mouseOver_dispell_frame:SetHeight (50)
+
+ mouseOver_dispell_frame.imagem = mouseOver_dispell_frame:CreateTexture (nil, "overlay")
+ mouseOver_dispell_frame.imagem:SetPoint ("topright", mouseOver_dispell_frame, "topright", -8, -17)
+
+ mouseOver_dispell_frame.imagem:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_icons")
+ mouseOver_dispell_frame.imagem:SetTexCoord (0, 0.15625, 0.4140625, 0.71875)
+ mouseOver_dispell_frame.imagem:SetWidth (40)
+ mouseOver_dispell_frame.imagem:SetHeight (39)
+
+ mouseOver_dispell_frame:SetScript ("OnEnter",
+ function()
+ mouseOver_dispell_frame.imagem:SetTexCoord (0.1796875, 0.3359375, 0.4140625, 0.71875)
+ end)
+ mouseOver_dispell_frame:SetScript ("OnLeave",
+ function()
+ mouseOver_dispell_frame.imagem:SetTexCoord (0, 0.15625, 0.4140625, 0.71875)
+ end)
+
+ container_dispell_frame:SetScript ("OnMouseDown", mouse_down)
+ container_dispell_frame:SetScript ("OnMouseUp", mouse_up)
+ mouseOver_dispell_frame:SetScript ("OnMouseDown", mouse_down)
+ mouseOver_dispell_frame:SetScript ("OnMouseUp", mouse_up)
+
+ container_dispell_frame.barras = {}
+
+ --container_dispell_window:SetBackdrop (backdrop)
+ --container_dispell_window:SetBackdropBorderColor (0,0,0,0)
+
+ --container_dispell_window:SetBackdrop (gump_fundo_backdrop)
+ --container_dispell_window:SetBackdropBorderColor (1, 1, 1, 1)
+ --container_dispell_window:SetBackdropColor (0, 0, 0, 0.1)
+
+ container_dispell_frame:SetAllPoints (container_dispell_window)
+ container_dispell_frame:SetWidth (170)
+ container_dispell_frame:SetHeight (67)
+ container_dispell_frame:EnableMouse (true)
+ container_dispell_frame:SetResizable (false)
+ container_dispell_frame:SetMovable (true)
+
+ container_dispell_window:SetWidth (170)
+ container_dispell_window:SetHeight (70)
+ container_dispell_window:SetScrollChild (container_dispell_frame)
+ container_dispell_window:SetPoint ("TOPLEFT", frame, "TOPLEFT", 260, -235)
+
+ DetailsFrameWork:NewLabel (container_dispell_window, container_dispell_window, nil, "titulo", Loc ["STRING_DISPELLS"], "QuestFont_Large", 16, {1, 1, 1})
+ container_dispell_window.titulo:SetPoint ("bottomleft", container_dispell_window, "topleft", 0, 4)
+
+ DetailsFrameWork:NewScrollBar (container_dispell_window, container_dispell_frame, 4, -9)
+ container_dispell_window.slider:Altura (45)
+ container_dispell_window.slider:cimaPoint (0, 1)
+ container_dispell_window.slider:baixoPoint (0, -1)
+ container_dispell_frame.slider = container_dispell_window.slider
+
+ container_dispell_window.gump = container_dispell_frame
+ container_dispell_frame.window = container_dispell_window
+ container_dispell_window.ultimo = 0
+ frame.overall_dispell = container_dispell_window
+
+
+ --> Caixa das mortes
+
+ local container_dead_window = CreateFrame ("ScrollFrame", "Details_Boss_ContainerDead", frame)
+ local container_dead_frame = CreateFrame ("Frame", "Details_Boss_FrameDead", container_dead_window)
+ local mouseOver_dead_frame = CreateFrame ("Frame", "MouseOverDetails_Boss_FrameDead", frame)
+
+ frame.Widgets [#frame.Widgets+1] = container_dead_window
+ frame.Widgets [#frame.Widgets+1] = container_dead_frame
+ frame.Widgets [#frame.Widgets+1] = mouseOver_dead_frame
+
+ mouseOver_dead_frame:SetPoint ("bottom", container_dead_window, "top")
+ mouseOver_dead_frame:SetPoint ("bottomleft", container_dead_window, "topleft", 0, 5)
+ mouseOver_dead_frame:SetPoint ("bottomright", container_dead_window, "topright", 20, 5)
+ mouseOver_dead_frame:SetHeight (50)
+
+ mouseOver_dead_frame.imagem = mouseOver_dead_frame:CreateTexture (nil, "overlay")
+ mouseOver_dead_frame.imagem:SetPoint ("topright", mouseOver_dead_frame, "topright", -14, -10)
+
+ mouseOver_dead_frame.imagem:SetTexture ("Interface\\AddOns\\Details_EncounterDetails\\images\\boss_icons")
+ mouseOver_dead_frame.imagem:SetTexCoord (0, 0.1640625, 0.03125, 0.34375)
+ mouseOver_dead_frame.imagem:SetWidth (42)
+ mouseOver_dead_frame.imagem:SetHeight (41)
+
+ mouseOver_dead_frame:SetScript ("OnEnter",
+ function()
+ mouseOver_dead_frame.imagem:SetTexCoord (0.171875, 0.3359375, 0.03125, 0.34375)
+ end)
+ mouseOver_dead_frame:SetScript ("OnLeave",
+ function()
+ mouseOver_dead_frame.imagem:SetTexCoord (0, 0.1640625, 0.03125, 0.34375)
+ end)
+
+ container_dead_frame:SetScript ("OnMouseDown", mouse_down)
+ container_dead_frame:SetScript ("OnMouseUp", mouse_up)
+ mouseOver_dead_frame:SetScript ("OnMouseDown", mouse_down)
+ mouseOver_dead_frame:SetScript ("OnMouseUp", mouse_up)
+
+ container_dead_frame.barras = {}
+
+ --container_dead_window:SetBackdrop({edgeFile = "Interface\\DialogFrame\\UI-DialogBox-gold-Border", tile = true, tileSize = 16, edgeSize = 5, insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ --container_dead_window:SetBackdropBorderColor (0,0,0,0)
+
+ --container_dead_window:SetBackdrop (gump_fundo_backdrop)
+ --container_dead_window:SetBackdropBorderColor (1, 1, 1, 1)
+ --container_dead_window:SetBackdropColor (0, 0, 0, 0.1)
+
+ --container_dead_frame:SetAllPoints (container_dead_window)
+ container_dead_frame:SetPoint ("left", container_dead_window, "left")
+ container_dead_frame:SetPoint ("right", container_dead_window, "right")
+ container_dead_frame:SetPoint ("top", container_dead_window, "top")
+ container_dead_frame:SetPoint ("bottom", container_dead_window, "bottom", 0, 10)
+
+ container_dead_frame:SetWidth (170)
+ container_dead_frame:SetHeight (60)
+
+ container_dead_frame:EnableMouse (true)
+ container_dead_frame:SetResizable (false)
+ container_dead_frame:SetMovable (true)
+
+ container_dead_window:SetWidth (170)
+ container_dead_window:SetHeight (70)
+ container_dead_window:SetScrollChild (container_dead_frame)
+ container_dead_window:SetPoint ("TOPLEFT", frame, "TOPLEFT", 480, -235)
+
+ DetailsFrameWork:NewLabel (container_dead_window, container_dead_window, nil, "titulo", Loc ["STRING_DEATH_LOG"], "QuestFont_Large", 16, {1, 1, 1})
+ container_dead_window.titulo:SetPoint ("bottomleft", container_dead_window, "topleft", 0, 3)
+
+ DetailsFrameWork:NewScrollBar (container_dead_window, container_dead_frame, 4, -9)
+ container_dead_window.slider:Altura (45)
+ container_dead_window.slider:cimaPoint (0, 1)
+ container_dead_window.slider:baixoPoint (0, -1)
+ container_dead_frame.slider = container_dead_window.slider
+
+ container_dead_window.gump = container_dead_frame
+ container_dead_frame.window = container_dead_window
+ container_dead_window.ultimo = 0
+ frame.overall_dead = container_dead_window
+
+
+ --> funções dos botões das fases
+ local disable_func = function (self) self.texto:SetTextColor (.4, .4, .4) end
+ local enable_func = function (self) self.texto:SetTextColor (.7, .7, .7) end
+
+ function frame.ShowOverall()
+ return true
+ end
+ function frame.ShowFase (fase)
+ return true
+ end
+
+ --> Botão Overall
+ local botao_overall = DetailsFrameWork:NewDetailsButton (frame, frame, _, frame.ShowOverall, _, nil, 32, 16,
+ "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button_disabled", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button")
+ botao_overall:SetPoint ("topleft", frame, "topleft", 480, -50)
+ DetailsFrameWork:NewLabel (botao_overall, botao_overall, nil, "texto", "A", "QuestFont_Large", 12, {.7, .7, .7})
+ botao_overall.texto:SetPoint ("center", botao_overall, "center", 0, 1)
+ botao_overall:SetScript ("OnEnable", enable_func)
+ botao_overall:SetScript ("OnDisable", disable_func)
+ botao_overall.tooltip = Loc ["STRING_SHOW_ALL_DATA"].."\n|cFFFF0000"..Loc ["STRING_NOT IMPLEMENTED"]
+
+
+ --> Botão Fase 1
+ local botao_fase1 = DetailsFrameWork:NewDetailsButton (frame, frame, _, frame.ShowFase, 1, nil, 32, 16,
+ "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button_disabled", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button")
+ botao_fase1:SetPoint ("left", botao_overall, "right", 2, 0)
+ DetailsFrameWork:NewLabel (botao_fase1, botao_fase1, nil, "texto", "F1", "QuestFont_Large", 12, {.7, .7, .7})
+ botao_fase1.texto:SetPoint ("center", botao_fase1, "center", 0, 1)
+ botao_fase1:SetScript ("OnEnable", enable_func)
+ botao_fase1:SetScript ("OnDisable", disable_func)
+ botao_fase1.tooltip = Loc ["STRING_SHOW_PHASE_DATA"].."\n|cFFFF0000"..Loc ["STRING_NOT IMPLEMENTED"]
+
+ --> Botão Fase 2
+ local botao_fase2 = DetailsFrameWork:NewDetailsButton (frame, frame, _, frame.ShowFase, 2, nil, 32, 16,
+ "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button_disabled", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button")
+ botao_fase2:SetPoint ("left", botao_fase1, "right", 2, 0)
+ DetailsFrameWork:NewLabel (botao_fase2, botao_fase2, nil, "texto", "F2", "QuestFont_Large", 12, {.7, .7, .7})
+ botao_fase2.texto:SetPoint ("center", botao_fase2, "center", 0, 1)
+ botao_fase2:SetScript ("OnEnable", enable_func)
+ botao_fase2:SetScript ("OnDisable", disable_func)
+ botao_fase2.tooltip = Loc ["STRING_SHOW_PHASE_DATA"].."\n|cFFFF0000"..Loc ["STRING_NOT IMPLEMENTED"]
+
+ --> Botão Fase 3
+ local botao_fase3 = DetailsFrameWork:NewDetailsButton (frame, frame, _, frame.ShowFase, 3, nil, 32, 16,
+ "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button_disabled", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button")
+ botao_fase3:SetPoint ("left", botao_fase2, "right", 2, 0)
+ DetailsFrameWork:NewLabel (botao_fase3, botao_fase3, nil, "texto", "F3", "QuestFont_Large", 12, {.7, .7, .7})
+ botao_fase3.texto:SetPoint ("center", botao_fase3, "center", 0, 1)
+ botao_fase3:SetScript ("OnEnable", enable_func)
+ botao_fase3:SetScript ("OnDisable", disable_func)
+ botao_fase3.tooltip = Loc ["STRING_SHOW_PHASE_DATA"].."\n|cFFFF0000"..Loc ["STRING_NOT IMPLEMENTED"]
+
+ --> Botão Fase 4
+ local botao_fase4 = DetailsFrameWork:NewDetailsButton (frame, frame, _, frame.ShowFase, 4, nil, 32, 16,
+ "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button_disabled", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button")
+ botao_fase4:SetPoint ("left", botao_fase3, "right", 2, 0)
+ DetailsFrameWork:NewLabel (botao_fase4, botao_fase4, nil, "texto", "F4", "QuestFont_Large", 12, {.7, .7, .7})
+ botao_fase4.texto:SetPoint ("center", botao_fase4, "center", 0, 1)
+ botao_fase4:SetScript ("OnEnable", enable_func)
+ botao_fase4:SetScript ("OnDisable", disable_func)
+ botao_fase4.tooltip = Loc ["STRING_SHOW_PHASE_DATA"].."\n|cFFFF0000"..Loc ["STRING_NOT IMPLEMENTED"]
+
+ --> Botão Fase 5
+ local botao_fase5 = DetailsFrameWork:NewDetailsButton (frame, frame, _, frame.ShowFase, 5, nil, 32, 16,
+ "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button_disabled", "Interface\\AddOns\\Details_EncounterDetails\\images\\boss_frame_button")
+ botao_fase5:SetPoint ("left", botao_fase4, "right", 2, 0)
+ DetailsFrameWork:NewLabel (botao_fase5, botao_fase5, nil, "texto", "F5", "QuestFont_Large", 12, {.7, .7, .7})
+ botao_fase5.texto:SetPoint ("center", botao_fase5, "center", 0, 1)
+ botao_fase5:SetScript ("OnEnable", enable_func)
+ botao_fase5:SetScript ("OnDisable", disable_func)
+ botao_fase5.tooltip = Loc ["STRING_SHOW_PHASE_DATA"].."\n|cFFFF0000"..Loc ["STRING_NOT IMPLEMENTED"]
+
+
+ botao_overall:SetFrameLevel (frame:GetFrameLevel()+2)
+ botao_fase1:SetFrameLevel (frame:GetFrameLevel()+2)
+ botao_fase2:SetFrameLevel (frame:GetFrameLevel()+2)
+ botao_fase3:SetFrameLevel (frame:GetFrameLevel()+2)
+ botao_fase4:SetFrameLevel (frame:GetFrameLevel()+2)
+ botao_fase5:SetFrameLevel (frame:GetFrameLevel()+2)
+
+ --> os botões das fases estão desativados pois não foram implementados ainda
+ --[[
+ botao_overall:Disable()
+ botao_fase1:Disable()
+ botao_fase2:Disable()
+ botao_fase3:Disable()
+ botao_fase4:Disable()
+ botao_fase5:Disable()
+ --]]
+
+ --> botão fechar
+ frame.fechar = CreateFrame ("Button", nil, frame, "UIPanelCloseButton")
+ frame.fechar:SetWidth (32)
+ frame.fechar:SetHeight (32)
+ frame.fechar:SetPoint ("TOPRIGHT", frame, "TOPRIGHT", 5, -8)
+ frame.fechar:SetText ("X")
+ frame.fechar:SetScript ("OnClick", function(self)
+ EncounterDetails:CloseWindow()
+ end)
+ frame.fechar:SetFrameLevel (frame:GetFrameLevel()+2)
+
+end
+end
diff --git a/plugins/Details_EncounterDetails/images/boss_bg.tga b/plugins/Details_EncounterDetails/images/boss_bg.tga
new file mode 100644
index 00000000..c1697c49
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_bg.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_bg_graphic.tga b/plugins/Details_EncounterDetails/images/boss_bg_graphic.tga
new file mode 100644
index 00000000..5f578987
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_bg_graphic.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_button_statistic.tga b/plugins/Details_EncounterDetails/images/boss_button_statistic.tga
new file mode 100644
index 00000000..4afa97c9
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_button_statistic.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_dispell.tga b/plugins/Details_EncounterDetails/images/boss_dispell.tga
new file mode 100644
index 00000000..2494113c
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_dispell.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_frame1.tga b/plugins/Details_EncounterDetails/images/boss_frame1.tga
new file mode 100644
index 00000000..7d20786f
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_frame1.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_frame2.tga b/plugins/Details_EncounterDetails/images/boss_frame2.tga
new file mode 100644
index 00000000..9e20bd92
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_frame2.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_frame3.tga b/plugins/Details_EncounterDetails/images/boss_frame3.tga
new file mode 100644
index 00000000..c3bf0871
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_frame3.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_frame4.tga b/plugins/Details_EncounterDetails/images/boss_frame4.tga
new file mode 100644
index 00000000..6c4fe273
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_frame4.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_frame_button.tga b/plugins/Details_EncounterDetails/images/boss_frame_button.tga
new file mode 100644
index 00000000..5081635f
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_frame_button.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_frame_button_disabled.tga b/plugins/Details_EncounterDetails/images/boss_frame_button_disabled.tga
new file mode 100644
index 00000000..31158c06
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_frame_button_disabled.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_frame_buttons.tga b/plugins/Details_EncounterDetails/images/boss_frame_buttons.tga
new file mode 100644
index 00000000..72c7430a
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_frame_buttons.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_icones.tga b/plugins/Details_EncounterDetails/images/boss_icones.tga
new file mode 100644
index 00000000..457c9ad2
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_icones.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_icons.tga b/plugins/Details_EncounterDetails/images/boss_icons.tga
new file mode 100644
index 00000000..568f1375
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_icons.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_interrupt.tga b/plugins/Details_EncounterDetails/images/boss_interrupt.tga
new file mode 100644
index 00000000..65cea74d
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_interrupt.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_minisha.tga b/plugins/Details_EncounterDetails/images/boss_minisha.tga
new file mode 100644
index 00000000..2d77fd49
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_minisha.tga differ
diff --git a/plugins/Details_EncounterDetails/images/boss_stone.tga b/plugins/Details_EncounterDetails/images/boss_stone.tga
new file mode 100644
index 00000000..854dabb5
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/boss_stone.tga differ
diff --git a/plugins/Details_EncounterDetails/images/dano_recebido_bg.tga b/plugins/Details_EncounterDetails/images/dano_recebido_bg.tga
new file mode 100644
index 00000000..b699626f
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/dano_recebido_bg.tga differ
diff --git a/plugins/Details_EncounterDetails/images/habilidades_inimigas_bg.tga b/plugins/Details_EncounterDetails/images/habilidades_inimigas_bg.tga
new file mode 100644
index 00000000..78465656
Binary files /dev/null and b/plugins/Details_EncounterDetails/images/habilidades_inimigas_bg.tga differ
diff --git a/plugins/Details_EncounterDetails/ptBR.lua b/plugins/Details_EncounterDetails/ptBR.lua
new file mode 100644
index 00000000..918baeb8
--- /dev/null
+++ b/plugins/Details_EncounterDetails/ptBR.lua
@@ -0,0 +1,51 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_EncounterDetails", "ptBR")
+
+if (not Loc) then
+ return
+end
+
+Loc ["STRING_PLUGIN_NAME"] = "Detalhes do Combate"
+Loc ["STRING_WINDOW_TITLE"] = "Detalhes do Combate"
+Loc ["STRING_TOTAL_DAMAGE"] = "Total de Dano"
+Loc ["STRING_TOTAL_HEAL"] = "Total de Cura"
+Loc ["STRING_SHOW_ALL_DATA"] = "Mostrar dados totais"
+Loc ["STRING_SHOW_PHASE_DATA"] = "Mostrar dados apenas para esta fase"
+Loc ["STRING_NOT IMPLEMENTED"] = "Nao esta implementado ainda"
+Loc ["STRING_DIED"] = "morreu"
+Loc ["STRING_MELEE_DAMAGE"] = "dano corpo-a-corpo"
+Loc ["STRING_DAMAGE_TAKEN_REPORT"] = "Dano recebido por habilidade"
+Loc ["STRING_ABILITY_DAMAGE"] = "Dano da habilidade"
+Loc ["STRING_DAMAGE_TAKEN"] = "Dano recebido"
+Loc ["STRING_TOOK_DAMAGE_FROM"] = "Recebeu dano de"
+Loc ["STRING_INTERRUPT_BY"] = "interrompido por"
+Loc ["STRING_DISPELLED_BY"] = "removido por"
+Loc ["STRING_DEAD_LOG"] = "ultimos segundos de"
+Loc ["STRING_CURRENT"] = "Atual"
+Loc ["STRING_TRY"] = "Luta"
+Loc ["STRING_DAMAGE_AT"] = "Dano causado em"
+Loc ["STRING_INFLICTED_BY"] = "Dano causado por"
+Loc ["STRING_ADDS"] = "Adds"
+Loc ["STRING_INTERRUPTS"] = "Cortes"
+Loc ["STRING_DISPELLS"] = "Dissipados"
+Loc ["STRING_DEATH_LOG"] = "Ultimos Segundos"
+Loc ["STRING_FIGHT_SUMMARY"] = "detalhes da luta"
+Loc ["STRING_FIGHT_GRAPHIC"] = "graficos da performance"
+Loc ["STRING_TOOLTIP"] = "Mostrar os detalhes do combate"
+Loc ["STRING_"] = ""
+
+--> mechanic types
+Loc ["STRING_HEAL"] = "cura"
+Loc ["STRING_LOWDPS"] = "dpsbaixo"
+Loc ["STRING_LOWHEAL"] = "curabaixa"
+Loc ["STRING_VOIDZONE"] = "voidzone"
+Loc ["STRING_DISPELL"] = "dispell"
+Loc ["STRING_INTERRUPT"] = "interromper"
+Loc ["STRING_POSITIONING"] = "posicao"
+Loc ["STRING_RUNAWAY"] = "correr"
+Loc ["STRING_TANKSWITCH"] = "trocadetank"
+Loc ["STRING_MECHANIC"] = "mecanica"
+Loc ["STRING_CROWDCONTROL"] = "cc"
+Loc ["STRING_TANKCOOLDOWN"] = "tankcooldown"
+Loc ["STRING_KILLADD"] = "mataradd"
+Loc ["STRING_SPREADOUT"] = "separar"
+Loc ["STRING_STOPCAST"] = "pararcast"
\ No newline at end of file
diff --git a/plugins/Details_ErrorReport/Details_ErrorReport.lua b/plugins/Details_ErrorReport/Details_ErrorReport.lua
new file mode 100644
index 00000000..afec86b0
--- /dev/null
+++ b/plugins/Details_ErrorReport/Details_ErrorReport.lua
@@ -0,0 +1,228 @@
+--localization
+ --> english
+ do
+ local Loc = LibStub("AceLocale-3.0"):NewLocale("DetailsErrorReport", "enUS", true)
+ Loc ["STRING_PLUGIN_NAME"] = "Error Report"
+ Loc ["STRING_TOOLTIP"] = "Did you found a bug? Report here!"
+ Loc ["STRING_REPORT"] = "Details Report"
+ Loc ["STRING_PROBLEM"] = "problem"
+ Loc ["STRING_SUGESTION"] = "sugestion"
+ Loc ["STRING_LUAERROR_DESC"] = "send a report about occurrence of lua errors"
+ Loc ["STRING_ACCURACY_DESC"] = "you found something which isn't the amount that should be\nfor instance, some healing or damage spell doesn't have the correct amount calculated."
+ Loc ["STRING_NOTWORK_DESC"] = "anything which should be doing something and actually isn't"
+ Loc ["STRING_OTHER_DESC"] = "any other problem or perhaps a suggesting not involving the subjects above, can be reported here"
+ Loc ["STRING_LUA_ERROR"] = "Lua Error"
+ Loc ["STRING_ACCURACY_ERROR"] = "Instable Accuracy"
+ Loc ["STRING_NOTWORK_ERROR"] = "Isn't Working"
+ Loc ["STRING_OTHER_ERROR"] = "Other"
+
+ Loc ["STRING_DEFAULT_TEXT_LUA"] = "You can copy and paste here the first 20 lines from the lua error window, also, is important a small description about the error, when it occurs and with what frequency it occurs."
+ Loc ["STRING_DEFAULT_TEXT_ACCURACY"] = "A miss accuracy is normal and happen all the time, but when the problem happen with frequency it's important tell to us. A good way to report is analyzing when the instability occurs, if is caused by a spell or if is a untracked pet."
+ Loc ["STRING_DEFAULT_TEXT_NOTWORK"] = "When you click in something and the result isn't the expected, could be a bug. If thing like this occurs more then once, report the problem to us, dont forget to mention which button is and the frequency."
+ Loc ["STRING_DEFAULT_TEXT_OTHER"] = "Any other problem not mentioned in the other 3 options should be reported here."
+
+ Loc ["STRING_WELCOME_TEXT"] = "Details are in early alpha stages and many errors can occur,\nto try make this report process faster, we'll use this small plug in,\nat least on alpha stage."
+ Loc ["STRING_SEND"] = "Send"
+ Loc ["STRING_CANCELLED"] = "Cancelled."
+ Loc ["STRING_EMPTY"] = "Text field is empty"
+ Loc ["STRING_TOOBIG"] = "1024 Text characters limit reached"
+ end
+
+
+
+ --> português
+ do
+ --[[
+ local Loc = LibStub("AceLocale-3.0"):NewLocale("DetailsErrorReport", "ptBR")
+ Loc ["STRING_PLUGIN_NAME"] = "Relatorio de Erros"
+ Loc ["STRING_TOOLTIP"] = "Encontrou um bug? reporte aqui"
+ Loc ["STRING_REPORT"] = "Details Relatorio de Erros"
+ Loc ["STRING_PROBLEM"] = "problema"
+ Loc ["STRING_SUGESTION"] = "sugestao"
+ Loc ["STRING_LUAERROR_DESC"] = "envia um relatorio sobre erros de lua que estao ocorrendo"
+ Loc ["STRING_ACCURACY_DESC"] = "caso voce encontre problemas na quantidade de dano ou healing que esta mais baixo do que deveria ser"
+ Loc ["STRING_NOTWORK_DESC"] = "qualquer coisa que voce clique e deveria efetuar uma funcao mas que nao esta"
+ Loc ["STRING_OTHER_DESC"] = "outros problemas e por que nao, sugestoes, podem ser enviadas usando este assunto"
+ Loc ["STRING_LUA_ERROR"] = "Erro de Lua"
+ Loc ["STRING_ACCURACY_ERROR"] = "Precisao dos Dados"
+ Loc ["STRING_NOTWORK_ERROR"] = "Algo Nao Funciona"
+ Loc ["STRING_OTHER_ERROR"] = "Outro"
+ Loc ["STRING_WELCOME_TEXT"] = "Detalhes esta apenas comecando a caminhar e muitos erros podem surgir, para que o erros chegem a nos mais rapidamente estaremos usando este plugin pelo menos na etapa Alfa do projeto."
+ Loc ["STRING_SEND"] = "Enviar"
+ --]]
+ end
+
+
+--plugin object
+ local ErrorReport = _G._detalhes:NewPluginObject ("Details_ErrorReport")
+ tinsert (UISpecialFrames, "Details_ErrorReport")
+ local Loc = LibStub ("AceLocale-3.0"):GetLocale ("DetailsErrorReport")
+
+--plugin panel
+ local BuildReportPanel = function()
+
+ function ErrorReport:OnDetailsEvent (event, ...)
+ return
+ end
+
+ --> catch Details! main object
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+
+ --> create the button to show on toolbar [1] function OnClick [2] texture [3] tooltip [4] width or 14 [5] height or 14 [6] frame name or nil
+ function ErrorReport:OpenWindow()
+ ErrorReport.Frame:SetPoint ("center", UIParent, "center")
+ ErrorReport.Frame:Show()
+ end
+ ErrorReport.ToolbarButton = _detalhes.ToolBar:NewPluginToolbarButton (ErrorReport.OpenWindow, "Interface\\HELPFRAME\\HelpIcon-Bug", Loc ["STRING_TOOLTIP"], 20, 20, "DETAILS_ERRORREPORT_BUTTON")
+ --> setpoint anchors mod if needed
+ ErrorReport.ToolbarButton.y = 0
+ ErrorReport.ToolbarButton.x = 1
+
+ ErrorReport:ShowToolbarIcon (ErrorReport.ToolbarButton)
+
+ local mainFrame = ErrorReport.Frame
+ mainFrame:SetWidth (400)
+ mainFrame:SetHeight (400)
+
+ --[[
+ o que falta fazer:
+ - fazer toda parte externa do report com .php talvez e mandando email? acho que sim
+ --]]
+
+ --> build widgets
+
+ --background
+ DetailsFrameWork:NewPanel (mainFrame, _, "DetailsErrorReportBackground", "background", 400, 400)
+ local bg = mainFrame.background
+ bg:SetPoint()
+
+ bg.close_with_right = true
+
+ bg:SetHook ("OnHide", function()
+ mainFrame:Hide()
+ end)
+ mainFrame:SetScript ("OnShow", function()
+ bg:Show()
+ end)
+
+ --title
+ DetailsFrameWork:NewLabel (bg, _, _, "titlelabel", Loc ["STRING_REPORT"], "GameFontHighlightSmall", 11)
+ bg.titlelabel:SetPoint (10, -10)
+
+ --welcome
+ DetailsFrameWork:NewLabel (bg, _, _, "welcomelabel", Loc ["STRING_WELCOME_TEXT"], "GameFontHighlightSmall", 9)
+ bg.welcomelabel:SetPoint (10, -25)
+
+ local textArray = {Loc ["STRING_DEFAULT_TEXT_LUA"], Loc ["STRING_DEFAULT_TEXT_ACCURACY"], Loc ["STRING_DEFAULT_TEXT_NOTWORK"], Loc ["STRING_DEFAULT_TEXT_OTHER"]}
+
+ --text field background
+ DetailsFrameWork:NewPanel (bg, _, "DetailsErrorReportTextFieldBackground", "textfieldBackground", 390, 260)
+ bg.textfieldBackground:SetPoint (5, -85)
+
+ local lastValue = 1
+
+ --text field
+ DetailsFrameWork:NewTextEntry (bg, _, "DetailsErrorReportText", "textfield", 380, 260)
+ bg.textfield:SetBackdrop (nil)
+ bg.textfield:SetPoint (10, -90) -- topleft anchor and parent will be use in this case
+ bg.textfield:SetFrameLevel (1, bg.textfieldBackground) -- +1 relative to other frame
+ bg.textfield.text = Loc ["STRING_DEFAULT_TEXT_LUA"]
+ bg.textfield.multiline = true
+ bg.textfield.align = "left"
+
+ bg.textfield:SetHook ("OnEditFocusGained", function()
+ if (bg.textfield.text == textArray [lastValue]) then
+ bg.textfield.text = ""
+ end
+ end)
+
+ bg.textfield:SetHook ("OnEditFocusLost", function()
+ if (bg.textfield.text == "") then
+ bg.textfield.text = textArray [lastValue]
+ end
+ end)
+
+ --type dropdown
+ local selected = function (self, _, index)
+ if (bg.textfield.text == textArray [self.lastValue]) then
+ bg.textfield.text = textArray [index]
+ end
+ self.lastValue = index
+ lastValue = index
+ end
+
+ local options = {
+ {onclick = selected, desc = Loc ["STRING_LUAERROR_DESC"], value = 1, icon = "Interface\\ICONS\\INV_Pet_Cockroach", label = Loc ["STRING_LUA_ERROR"], color = "yellow", selected = true },
+ {onclick = selected, desc = Loc ["STRING_ACCURACY_DESC"], value = 2, icon = "Interface\\ICONS\\Ability_Hunter_FocusedAim", label = Loc ["STRING_ACCURACY_ERROR"], color = "skyblue" },
+ {onclick = selected, desc = Loc ["STRING_NOTWORK_DESC"], value = 3, icon = "Interface\\ICONS\\INV_Misc_ScrewDriver_01", label = Loc ["STRING_NOTWORK_ERROR"], color = "pink" },
+ {onclick = selected, desc = Loc ["STRING_OTHER_DESC"], value = 4, icon = "Interface\\ICONS\\Achievement_Reputation_01", label = Loc ["STRING_OTHER_ERROR"], color = "white" },
+ }
+ local buildMenu = function()
+ return options
+ end
+ DetailsFrameWork:NewDropDown (bg, _, "DetailsErrorReportType", "type", 250, 20, buildMenu, 1) -- func, default
+ bg.type:SetPoint (10, -60)
+ bg.type:SetFrameLevel (2, bg)
+ bg.type.lastValue = 1
+
+
+
+ --send button
+ local sendFunc = function()
+
+ if (string.len (bg.textfield.text) < 2) then
+ print (Loc ["STRING_EMPTY"])
+ return
+ end
+
+ if (string.len (bg.textfield.text) > 1024) then
+ print (Loc ["STRING_TOOBIG"])
+ return
+ end
+
+ if (bg.textfield.text == textArray [lastValue]) then
+ print (Loc ["STRING_CANCELLED"])
+ mainFrame:Hide()
+ return
+ end
+
+ local subject = {
+ "LuaError", "InstableAccuracy", "IsntWorking", "Other"
+ }
+
+ local url = "http://reporttodevs.hol.es/sendtodev.php?dev=detailsaddon&subject=" .. subject [bg.type.value] .. "&text=" .. bg.textfield.text:gsub (" ", "%%20")
+
+ ErrorReport:CopyPaste (url)
+ mainFrame:Hide()
+ end
+
+ DetailsFrameWork:NewButton (bg, _, "DetailsErrorReportButton", "send", 100, 20, sendFunc, _, _, _, Loc ["STRING_SEND"])
+ bg.send:InstallCustomTexture()
+ bg.send:SetPoint (10, -370)
+
+
+ end
+
+--events
+ function ErrorReport:OnEvent (_, event, ...)
+
+ if (event == "ADDON_LOADED") then
+ local AddonName = select (1, ...)
+ if (AddonName == "Details_ErrorReport") then
+
+ if (_G._detalhes) then
+
+ --> create widgets
+ BuildReportPanel (data)
+
+ --> Install
+ local install = _G._detalhes:InstallPlugin ("TOOLBAR", Loc ["STRING_PLUGIN_NAME"], "placeholder string", ErrorReport, "DETAILS_PLUGIN_REPORT_ERRORS")
+ if (type (install) == "table" and install.error) then
+ print (install.error)
+ end
+
+ end
+ end
+ end
+ end
\ No newline at end of file
diff --git a/plugins/Details_ErrorReport/Details_ErrorReport.toc b/plugins/Details_ErrorReport/Details_ErrorReport.toc
new file mode 100644
index 00000000..081ffbc1
--- /dev/null
+++ b/plugins/Details_ErrorReport/Details_ErrorReport.toc
@@ -0,0 +1,6 @@
+## Interface: 50300
+## Title: Details Error Report
+## Notes: This plugin adds a button to Details tooltip where you can report bugs directly to Details Developers.
+## RequiredDeps: Details
+
+Details_ErrorReport.lua
\ No newline at end of file
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Details_RaidInfo-ThroneOfThunder.toc b/plugins/Details_RaidInfo-ThroneOfThunder/Details_RaidInfo-ThroneOfThunder.toc
new file mode 100644
index 00000000..725a6717
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Details_RaidInfo-ThroneOfThunder.toc
@@ -0,0 +1,9 @@
+## Interface: 50300
+## Title: Details: Throne of Thunder
+## Notes: Plugin for Details
+## RequiredDeps: Details
+
+enUS.lua
+ptBR.lua
+
+ThroneOfThunder.lua
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Libs/AceLocale-3.0/AceLocale-3.0.lua b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 00000000..2ecc0cb8
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Libs/AceLocale-3.0/AceLocale-3.0.xml b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 00000000..d69dbb13
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/LibStub.lua b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/LibStub.lua
new file mode 100644
index 00000000..f5fc9192
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/LibStub.lua
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ -- LibStub:NewLibrary(major, minor)
+ -- major (string) - the major version of the library
+ -- minor (string or number ) - the minor version of the library
+ --
+ -- returns nil if a newer or same version of the lib is already present
+ -- returns empty library object or old library object if upgrade is needed
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ -- LibStub:GetLibrary(major, [silent])
+ -- major (string) - the major version of the library
+ -- silent (boolean) - if true, library is optional, silently return nil if its not found
+ --
+ -- throws an error if the library can not be found (except silent is set)
+ -- returns the library object if found
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ -- LibStub:IterateLibraries()
+ --
+ -- Returns an iterator for the currently registered libraries
+ function LibStub:IterateLibraries()
+ return pairs(self.libs)
+ end
+
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/LibStub.toc b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/LibStub.toc
new file mode 100644
index 00000000..c3dc3656
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 40200
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: r95
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test.lua b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test.lua
new file mode 100644
index 00000000..645a08b1
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test2.lua b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test2.lua
new file mode 100644
index 00000000..af431dd3
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib doesn't exist yet, by iterating through all the libraries
+ assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+ if major == "MyLib" then -- we found it!
+ count = count +1
+ assert(rawequal(library, lib)) -- verify that the references are equal
+ end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test3.lua b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test3.lua
new file mode 100644
index 00000000..01aabb8d
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test4.lua b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test4.lua
new file mode 100644
index 00000000..15a9c9cd
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/Libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/ThroneOfThunder.lua b/plugins/Details_RaidInfo-ThroneOfThunder/ThroneOfThunder.lua
new file mode 100644
index 00000000..b4d1ed3e
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/ThroneOfThunder.lua
@@ -0,0 +1,946 @@
+--[[
+=====================================================================================================
+ Throne of Thunder Mobs and Spells Ids for Details
+=====================================================================================================
+]]--
+
+local Loc = LibStub ("AceLocale-3.0"):GetLocale ("Details_RaidInfo-ThroneOfThunder")
+
+local _detalhes = _G._detalhes
+
+local throne_of_thunder = {
+ id = 1098,
+
+ name = Loc ["STRING_RAID_NAME"],
+
+ icons = "Interface\\AddOns\\Details_RaidInfo-ThroneOfThunder\\images\\tot",
+
+ icon = "Interface\\AddOns\\Details_RaidInfo-ThroneOfThunder\\images\\icon256x128",
+
+ background = "Interface\\AddOns\\Details_RaidInfo-ThroneOfThunder\\images\\raid_tot",
+
+ boss_names = {
+ "Jin'rokh the Breaker",
+ "Horridon",
+ "Frost King Malakk",
+ "Tortos",
+ "Magaera",
+ "Ji-Kun",
+ "Durumu the Forgotten",
+ "Primordius",
+ "Dark Animus",
+ "Iron Qon",
+ "Lu'lin",
+ "Lei Shen",
+ "Ra-den"
+ },
+
+ boss_ids = {
+ -- Last Stand of the Zandalari
+ [69465] = 1, -- Jin'rokh the Breaker
+ [68476] = 2, -- Horridon
+ [69134] = 3, -- Kazra'jin, Council of Elders
+ [69078] = 3, -- Sul the Sandcrawler, Council of Elders
+ [69131] = 3, -- Frost King Malakk, Council of Elders
+ [69132] = 3, -- High Priestess Mar'li, Council of Elders
+ -- Forgotten Depths
+ [67977] = 4, -- Tortos
+ [70229] = 5, -- Flaming Head
+ [70250] = 5, -- Frozen Head
+ [70251] = 5, -- Venomous Head
+ [70247] = 5, -- Venomous Head
+ [69712] = 6, -- Ji-Kun
+ -- Halls of Flesh-Shaping
+ [68036] = 7, -- Durumu the Forgotten
+ [69017] = 8, -- Primordius
+ [69427] = 9, -- Dark Animus
+ -- Pinnacle of Storms
+ [68078] = 10, -- Iron Qon
+ [68905] = 11, -- Lu'lin , Twin Consorts
+ [68904] = 11, -- Suen , Twin Consorts
+ [68397] = 12 -- Lei Shen
+ },
+
+ encounters = {
+
+------------> Jin'rokh the Breaker ------------------------------------------------------------------------------
+ [1] = {
+
+ boss = "Jin'rokh the Breaker",
+
+ spell_mechanics = {
+ [137261] = {0x1, 0x40}, --> Lightning Storm
+ [137162] = {0x1, 0x100}, --> Static Burst
+ [138389] = {0x100}, --> Static Wound
+ [137423] = {0x80}, --> Focused Lightning
+ [137374] = {0x40}, --> Focused Lightning Detonation
+ [138133] = {0x40}, --> Lightning Fissure Conduction
+ [137485] = {0x40}, --> Lightning Fissure
+ [137370] = {0x200, 0x1}, --> Thundering Throw
+ [137167] = {0x200, 0x1}, --> Thundering Throw
+ [137905] = {0x40}, --> Lightning Diffusion
+ [138733] = {0x10, 0x40}, --> Ionization
+ [137647] = {0x40}, --> Lightning Strike
+ },
+
+ phases = {
+ --> fase 1
+ {
+ spells = {
+ 137261, --> Lightning Storm
+ 137162, --> Static Burst
+ 138389, --> Static Wound
+ 137423, --> Focused Lightning
+ 137374, --> Focused Lightning Detonation
+ 138133, --> Lightning Fissure Conduction
+ 137370, --> Thundering Throw
+ 137167 --> Thundering Throw
+ },
+
+ adds = {
+ 69465, -- Jin'rokh the Breaker
+ }
+ }
+ }
+ },
+------------> Horridon ------------------------------------------------------------------------------
+ [2] = {
+
+ boss = "Horridon",
+
+ spell_mechanics = {
+ [136719] = {0x10}, --> Blazing Sunlight (Wastewalker)
+ [136723] = {0x8}, --> Sand Trap (Voidzone)
+ [136725] = {0x8}, --> Sand Trap Heroic (Voidzone)
+ [136654] = {0x1}, --> Rending Charge (Bloodlord)
+ [136653] = {0x1}, --> Rending Charge (Bloodlord)
+ [136587] = {0x20, 0x10, 0x1}, --> Venom Bolt Volley (Venom Priest & Venomous Effusions)
+ [136646] = {0x8}, --> Living Poison (Voidzone)
+ [136710] = {0x400, 0x10}, --> Deadly Plague (Drakkari Champions & Drakkari Warriors)
+ [136670] = {0x800, 0x1}, --> Mortal Strike (Frozen Warlords)
+ [136573] = {0x8}, --> Frozen Bolt (Voidzone)
+ [136465] = {0x1, 0x20}, --> Fireball (Amani'shi Flame Casters)
+ [136480] = {0x20, 0x40, 0x1}, --> Chain Lightning (Amani'shi Beast Shaman)
+ [136513] = {0x10, 0x1}, --> Hex of Confusion (Amani'shi Beast Shaman)
+ [136489] = {0x8}, --> Lightning Nova (Voidzone)
+ [136490] = {0x8}, --> Lightning Nova (Voidzone)
+ [136817] = {0x200, 0x2, 0x1}, --> Bestial Cry (dpsrun)
+ [136740] = {0x40}, --> Double Swipe (frontal)
+ [136739] = {0x40}, --> Double Swipe (trazeiro)
+ [137458] = {0x1}, --> Dire Call (heroic)
+ [136767] = {0x1, 0x100}, --> Triple Puncture
+ [136463] = {0x40} --> Swipe (Amani Warbear)
+ },
+
+ continuo = {
+ 136767, --> Triple Puncture 10m normal (Horridon)
+ 136740, -- Double Swipe (frontal)
+ 136739, -- Double Swipe (trazeiro)
+ 137458 --> Dire Call (heroic)
+ },
+
+ phases = {
+ {
+ --> fase 1 - The Farraki
+ spells = {
+ 136719, --> Blazing Sunlight 10m normal (Wastewalker)
+ 136723, --> Sand Trap 10m normal (Voidzone)
+ 136725 --> Sand Trap 10m heroic (Voidzone)
+ },
+ adds = {
+ 69175, --> Farraki Wastewalker
+ 69172, --> Sul'lithuz Stonegazers
+ 69173 --> Farraki Skirmishers
+ }
+ },
+ {
+ --> fase 2 - The Gurubashi
+ spells = {
+ 136654, --> Rending Charge 10m normal (Bloodlord)
+ 136587, --> Venom Bolt Volley 10m normal (Venom Priest & Venomous Effusions)
+ 136646 --> Living Poison 10m normal (Voidzone)
+ },
+ adds = {
+ 69167, -- Gurubashi Bloodlord
+ 69164, -- Gurubashi Venom Priest
+ 69314, -- Venomous Effusion
+ 68476 -- Horridon
+ }
+ },
+ {
+ --> fase 3 - The Drakkari
+ spells = {
+ 136710, --> Deadly Plague (Drakkari Champions & Drakkari Warriors)
+ 136670, --> Mortal Strike (Frozen Warlords)
+ 139573 --> Frozen Bolt (Voidzone)
+ },
+ adds = {
+ 69178,-- "Drakkari Frozen Warlord",
+ 69184,-- "Risen Drakkari Warriors",
+ 69185, --"Risen Drakkari Champions"
+ 68476 -- Horridon
+ }
+ },
+ {
+ --> fase 4 - The Amani
+ spells = {
+ 136465, --> Fireball (Amani'shi Flame Casters)
+ 136480, --> Chain Lightning (Amani'shi Beast Shaman)
+ 136513, --> Hex of Confusion (Amani'shi Beast Shaman)
+ 136489, --> Lightning Nova (Voidzone)
+ 136463 --> Swipe (Warbears)
+ },
+ adds = {
+ 69169, -- "Amani'shi Protector",
+ 69168, -- "Amani'shi Flame Caster",
+ 69177, -- "Amani Warbear",
+ 69176, -- "Amani'shi Beast Shaman"
+ 68476 -- Horridon
+ }
+ },
+ {
+ --> fase 5 - War-God Jalak's
+ spells = {
+ 136817 --> Bestial Cry
+ },
+ adds = {
+ 69374, --"War-God Jalak"
+ 68476 -- Horridon
+ }
+ }
+
+ } --> fim das fasses do segundo boss
+
+ }, --> fim do segundo boss
+
+------------> Concil of Elders ------------------------------------------------------------------------------
+ [3] = {
+ boss = "Council of Elders",
+
+ --> this is a fix for twisted fate spell, due Mar'li adds comes with exactly the same name as the player name, the add spell are assigned to the player
+ func = function()
+ local combat = _detalhes:GetCombat ("current")
+ local actorList = combat:GetActorList (DETAILS_ATTRIBUTE_DAMAGE)
+
+ for _, actor in ipairs (actorList) do
+ local TwistedFate = actor.spell_tables:GetSpell (137972) --> twisted fate adds spell
+ if (TwistedFate) then
+ if (not actor.lastTwistedFate) then
+ actor.lastTwistedFate = 0
+ end
+ actor.total = actor.total - (TwistedFate.total - actor.lastTwistedFate)
+ actor.lastTwistedFate = TwistedFate.total
+ end
+ end
+ end,
+
+ funcType = 0x3, -- 0x1 + 0x2 --> realtime + end of combat
+
+ spell_mechanics = {
+ [136507] = {0x2}, --> Dark Power (Todos)
+
+ [136190] = {0x20, 0x1}, --> Sandbold (Sul the Sandcrawler)
+ [138740] = {0x20, 0x1}, --> Sandbolt (Sul the Sandcrawler)
+ [136899] = {0x1}, --> Sandstorm (Sul the Sandcrawler)
+ [136860] = {0x10, 0x8}, --> Quicksand (Sul the Sandcrawler)
+
+ [137344] = {0x20, 0x1}, --> Wrath of the Loa (High Priestess Mar'li)
+ [137347] = {0x20, 0x1}, --> Wrath of the Loa (High Priestess Mar'li)
+ [137390] = {0x80, 0x1000}, --> Shadowed Gift (High Priestess Mar'li)
+ [137407] = {0x80, 0x1000}, --> Shadowed Gift (High Priestess Mar'li)
+ [137972] = {0x200, 0x40}, --> Twisted Fate (High Priestess Mar'li)
+
+ [136937] = {0x40, 0x1}, --> Frostbite (Frost King Malakk)
+ [136990] = {0x40, 0x1}, --> Frostbite (Frost King Malakk)
+ [136911] = {0x1}, --> Frigid Assault (Frost King Malakk)
+ [136991] = {0x40}, --> Biting Cold (Frost King Malakk)
+ [136917] = {0x40}, --> Biting Cold (Frost King Malakk)
+
+ [137151] = {0x1}, --> Overload (Kazra'jin)
+ [136935] = {0x1}, --> Discharge (Kazra'jin)
+ [137122] = {0x8}, --> Reckless Charge (Kazra'jin)
+ [137133] = {0x8}, --> Reckless Charge (Kazra'jin)
+
+ [137641] = {0x200, 0x1} --> Soul Fragment
+ },
+
+ continuo = {
+ 136507, --> Dark Power (Todos)
+ 137641, --> Soul Fragment
+
+ 136190, --> Sandbold (Sul the Sandcrawler)
+ 138740, --> Sandbolt (Sul the Sandcrawler)
+ 136899, --> Sandstorm (Sul the Sandcrawler)
+ 136860, --> Quicksand (Sul the Sandcrawler)
+
+ 137344, --> Wrath of the Loa (High Priestess Mar'li)
+ 137390, --> Shadowed Gift (High Priestess Mar'li)
+ 137407, --> Shadowed Gift (High Priestess Mar'li)
+ 137347, --> Wrath of the Loa (High Priestess Mar'li)
+ 137972, --> Twisted Fate (High Priestess Mar'li)
+
+ 136937, --> Frostbite (Frost King Malakk)
+ 136990, --> Frostbite (Frost King Malakk)
+ 136911, --> Frigid Assault (Frost King Malakk)
+ 136991, --> Biting Cold (Frost King Malakk)
+ 136917, --> Biting Cold (Frost King Malakk)
+
+ 137151, --> Overload (Kazra'jin)
+ 137122, --> Reckless Charge (Kazra'jin)
+ 137133, --> Reckless Charge (Kazra'jin)
+ 136935 --> Discharge (Kazra'jin)
+ },
+
+ phases = {
+ {
+ adds = {
+ 69548, -- "Shadowed Loa Spirit"
+ 69491, -- "Blessed Loa Spirit"
+ 69480, -- "Living Sand"
+ 69131, -- Frost King Malakk
+ 69134, -- Kazra'jin
+ 69078, -- Sul the Sandcrawler
+ 69132 -- High Priestess Mar'li
+
+ }
+ }
+ }
+
+ },
+
+------------> Tortos ------------------------------------------------------------------------------
+ [4] = {
+ boss = "Tortos",
+
+ spell_mechanics = {
+ [134476] = {0x1}, --> "Rockfall",
+ [134920] = {0x1}, --> "Quake Stomp",
+ [134011] = {0x1, 0x40}, --> "Spinning Shell",
+ [135251] = {0x1}, --> "Snapping Bite",
+ [134539] = {0x8, 0x40}, --> "Rockfall",
+ [135101] = {0x4, 0x200, 0x800} --> "Drain the Weak",
+
+ },
+
+ continuo = {
+ 134476, --> "Rockfall",
+ 134920, --> "Quake Stomp",
+ 134011, --> "Spinning Shell",
+ 135251, --> "Snapping Bite",
+ 134539, --> "Rockfall",
+ 135101 --> "Drain the Weak",
+ },
+
+ phases = {
+ {
+ adds = {
+ 67966, --"Whirl Turtle",
+ 68497, -- "Vampiric Cave Bat"
+ 67977 -- Tortos
+ }
+ }
+ }
+ },
+
+------------> Megaera ------------------------------------------------------------------------------
+ [5] = {
+ boss = "Megaera",
+
+ spell_mechanics = {
+ [139549] = {0x1}, --Rampage blue
+ [139548] = {0x1}, --rampage red
+ [139551] = {0x1}, --rampage green
+ [139552] = {0x1}, --rampage arcane
+
+ [139842] = {0x100}, --Arctic Freeze
+ [137731] = {0x100}, --Ignite Flesh
+ [137730] = {0x100}, --Ignite Flesh
+ [139839] = {0x100}, --Rot Armor
+
+ [139850] = {0x80, 0x40}, -- Acid Rain
+ [139836] = {0x10}, --Cinders
+ [139822] = {0x10}, --Cinders
+ [139836] = {0x8},--Cinders voidzone
+ [139909] = {0x8}, -- Icy Ground
+ [139889] = {0x80}, -- Torrent of Ice
+ [139992] = {0x100}, -- Diffusion
+ [140178] = {0x20} --Nether Spike
+ },
+
+ continuo = {
+ 139549, --Rampage blue
+ 139548, --rampage red
+ 139551, --rampage green
+ 139552, --rampage arcane
+
+ 139842, --Arctic Freeze
+ 137731, --Ignite Flesh
+ 137730, --Ignite Flesh
+ 139839, --Rot Armor
+
+ 139850, -- Acid Rain
+ 139822, --Cinders
+ 139836,--Cinders voidzone
+ 139909, -- Icy Ground
+ 139889, -- Torrent of Ice
+ 140178, --Nether Spike
+ 139992 --Diffusion
+ },
+
+ phases = {
+ {
+ adds = {
+ 70235, --"Frozen Head",
+ 70247, --"Venomous Head",
+ 70212, --"Flaming Head"
+ 70248, --"Arcane Head"
+ 70507 -- Nether Wyrm (heroic)
+ }
+ }
+ }
+ },
+
+------------> Ji-Kun ------------------------------------------------------------------------------
+ [6] = {
+ boss = "Ji'kun",
+
+ spell_mechanics = {
+ [134381] = {0x1}, --Quills
+ [140092] = {0x100}, -- Infected Talons
+ [134366] = {0x100}, -- Talon Rake
+ [139100] = {0x100}, -- Talon Strike
+ [134256] = {0x200, 0x1, 0x8}, -- Slimed
+ [134375] = {0x1, 0x40}, -- Caw
+ [138319] = {0x200, 0x1}, -- Feed Pool
+ [140129] = {0x1}, -- Cheep
+ [139296] = {0x1}, -- Cheep
+ [140570] = {0x1}, -- Cheep
+ [139298] = {0x1} -- Cheep
+ },
+
+ continuo = {
+ 134381, --Quills
+ 140092, -- Infected Talons
+ 134256, -- Slimed
+ 134366, -- Talon Rake
+ 139100, -- Talon Strike
+ 134375, -- Caw
+ 138319, -- Feed Pool
+ 140129, -- Cheep
+ 139296, -- Cheep
+ 140570, -- Cheep
+ 139298 -- Cheep
+ },
+
+ phases = {
+ {
+ adds = {
+ 68192, --Hatchling
+ 69628, --Mature Egg of Ji-Kun
+ 68192, --Fledgling
+ 69836, --Juvenile
+ 70134 --Nest Guardian
+ }
+ }
+ }
+ },
+
+------------> Durumu the forgotten ------------------------------------------------------------------------------
+ [7] = {
+ boss = "Durumu the Forgotten",
+ spell_mechanics = {
+ [133732] = {0x1, 0x200}, --> Infrared Light
+ [133738] = {0x1, 0x200}, --> Bright Light
+ [133677] = {0x1, 0x200}, --> Blue Rays
+ [139107] = {0x1}, --> Mind Daggers
+ [133597] = {0x10, 0x200}, --> Dark Parasite
+ [134755] = {0x40}, --> Eye Sore
+ [133765] = {0x100}, --> Hard Stare
+ [133768] = {0x1, 0x100}, --> Arterial Cut
+ [133793] = {0x8}, --> Lingering Gaze
+ [134044] = {0x8}, --> Lingering Gaze
+ [140495] = {0x8}, --> Lingering Gaze
+ [133798] = {0x200}, --> Life Drain
+ [134005] = {0x1}, --> Devour
+ [134010] = {0x1}, --> Devour
+ [136154] = {0x1}, --> Caustic Spike
+ [136123] = {0x200}, --> Burst of Amber
+ [136175] = {0x1}, --> Amber Retaliation
+ [134029] = {0x40}, --> Gaze
+ [136413] = {0x40}, --> Force of Will
+ [134169] = {0x80} --> Disintegration Beam
+ },
+
+ continuo = {},
+
+ phases = {
+ {
+ spells = {
+ 139107, --> Mind Daggers
+ 133732, --> Infrared Light
+ 133738, --> Bright Light
+ 133597, --> Dark Parasite
+ 133677, --> Blue Rays
+ 133765, --> Hard Stare
+ 133793, --> Lingering Gaze
+ 133798, --> Life Drain
+ 134044, --> Lingering Gaze
+ 134005, --> Devour
+ 136154, --> Caustic Spike
+ 134010, --> Devour
+ 140495, --> Lingering Gaze
+ 133768, --> Arterial Cut
+ 136123, --> Burst of Amber
+ 136175, --> Amber Retaliation
+ 134029, --> Gaze
+ 136413 --> Force of Will
+ },
+ adds = {
+ 68036, --> Durumu the Forgotten
+ 69050, --> Crimson Fogs
+ 69052, --> Azure Fog
+ 69051, --> Amber Fog
+ 67859, --> Hungry Eye
+ 68024, --> Wandering Eye
+ 68291 --> Ice Wall
+ }
+ },
+ {
+ spells = {
+ 139107, --> Mind Daggers
+ 133597, --> Dark Parasite
+ 134755, --> Eye Sore
+ 133793, --> Lingering Gaze
+ 134044, --> Lingering Gaze
+ 134005, --> Devour
+ 134010, --> Devour
+ 140495, --> Lingering Gaze
+ 134169 --> Disintegration Beam
+ },
+ adds = {
+ 68036, --> Durumu the Forgotten
+ 67859, --> Hungry Eye
+ 68024, --> Wandering Eye
+ 68291 --> Ice Wall
+ }
+ }
+
+ }
+ },
+
+------------> Primordius ------------------------------------------------------------------------------
+ [8] = {
+ boss = "Primordius",
+ spell_mechanics = {
+ [136220] = {0x1, 0x2000}, --> Acidic Explosion
+ [136216] = {0x1, 0x40}, --> Caustic Gas
+ [136178] = {0x1}, --> Mutation
+ [136211] = {0x1}, --> Ventral Sacs
+ [137000] = {0x100, 0x1}, --> Black Blood
+ [136247] = {0x40}, --> Pustule Eruption
+ [136050] = {0x100, 0x1}, --> Malformed Blood
+ [136231] = {0x1}, --> Volatile Pathogen
+ [136037] = {0x800, 0x1}, --> Primordial Strike
+ [140508] = {0x1} --> Volatile Mutation
+ },
+ continuo = {
+ 136220, --> Acidic Explosion
+ 136216, --> Caustic Gas
+ 136178, --> Mutation
+ 136211, --> Ventral Sacs
+ 137000, --> Black Blood
+ 136247, --> Pustule Eruption
+ 136050, --> Malformed Blood
+ 136231, --> Volatile Pathogen
+ 136037, --> Primordial Strike
+ 140508 --> Volatile Mutation
+ },
+ phases = {
+ {
+ spells = {},
+ adds = {
+ 69069, --> living-fluid
+ 69017, --> Primordius
+ 69070 --> Viscous Horror
+ }
+ }
+ }
+ },
+
+------------> Dark Animus ------------------------------------------------------------------------------
+
+ [9] = {
+ boss = "Dark Animus",
+ spell_mechanics = {
+ [139867] = {0x1, 0x3000}, --> Interrupting Jolt
+ [138659] = {0x1}, --> Touch of the Animus
+ [138707] = {0x2000, 0x1}, --> Anima Font
+ [138618] = {0x200, 0x10}, --> Matter Swap
+ [138569] = {0x40, 0x100}, --> Explosive Slam
+ [136962] = {0x100}, --> Anima Ring
+ [138480] = {0x8, 0x80} --> Crimson Wake
+ },
+ continuo = {
+ 139867, --> Interrupting Jolt
+ 138659, --> Touch of the Animus
+ 138707, --> Anima Font
+ 138618, --> Matter Swap
+ 138569, --> Explosive Slam
+ 136962, --> Anima Ring
+ 138480 --> Crimson Wake
+ },
+ phases = {
+ {
+ spells = {
+ },
+ adds = {
+ 69427, --> Dark Animus
+ 69701, --> Anima Golem
+ 69699, --> Massive Anima Golem
+ 69700 --> Large Anima Golem
+ }
+ }
+ }
+ },
+
+------------> Iron Qon ------------------------------------------------------------------------------
+ [10] = {
+ boss = "Iron Qon",
+ spell_mechanics = {
+ [136925] = {0x40}, --> Burning Blast
+ [134628] = {0x200, 0x1}, --> Unleashed Flame
+ [134664] = {0x200}, --> Molten Inferno
+
+ [136193] = {0x2000}, --> Arcing Lightning
+ [137669] = {0x8}, --> Storm Cloud
+ [136577] = {0x80}, --> Wind Storm
+ [139167] = {0x40}, --> Whirling Winds
+ [136192] = {0x200}, --> Lightning Storm
+ [136498] = {0x1}, --> Storm Surge
+ [137654] = {0x80}, --> Rushing Winds
+
+ [137709] = {0x1}, --> Shatter
+ [135146] = {0x1}, --> Shatter
+ [137664] = {0x8}, --> Frozen Blood
+ [136520] = {0x8}, --> Frozen Blood
+ [135142] = {0x1}, --> Frozen Resilience
+ [139180] = {0x40}, --> Frost Spike
+ [134759] = {0x8}, --> Ground Rupture
+
+ [136147] = {0x2, 0x1}, --> Fist Smash
+ [134691] = {0x100}, --> Impale
+ [134926] = {0x40} --> Throw Spear
+ },
+
+ continuo = {
+ 134691 --> Impale
+ },
+
+ phases = {
+ --> phase 1 Ro'shak
+ {
+ spells = {
+ 136925, --> Burning Blast
+ 134664, --> Molten Inferno
+ 134628, --> Unleashed Flame
+ 139167, --> Whirling Winds
+ 136192, --> Lightning Storm
+ 139167, --> Whirling Winds
+ 136498 --> Storm Surge
+ },
+ adds = {
+ 68079 --> Ro'shak
+ }
+ },
+
+ --> phase 2 Quet'zal
+ {
+ spells = {
+ 136193, --> Arcing Lightning
+ 137669, --> Storm Cloud
+ 136577, --> Wind Storm
+ 139167, --> Whirling Winds
+ 136192, --> Lightning Storm
+ 136498, --> Storm Surge
+ 137654, --> Rushing Winds
+ 139180 --> Frost Spike
+ },
+ adds = {
+ 68080 --> Quet'zal
+ }
+ },
+
+ --> phase 3 Dam'ren
+ {
+ spells = {
+ 137709, --> Shatter
+ 135146, --> Shatter
+ 137664, --> Frozen Blood
+ 136520, --> Frozen Blood
+ 135142, --> Frozen Resilience
+ 139180, --> Frost Spike
+ 134759, --> Ground Rupture
+ 134664, --> Molten Inferno
+ 134628 --> Unleashed Flame
+ },
+ adds = {
+ 68081 --> Dam'ren
+ }
+ },
+
+ --> phase 4 Iron Qon
+ {
+ spells = {
+ 139167, --> Whirling Winds
+ 136147, --> Fist Smash
+ 134691, --> Impale
+ 134664, --> Molten Inferno
+ 134628, --> Unleashed Flame
+ 139180, --> Frost Spike
+ 139167, --> Whirling Winds
+ 136498 --> Storm Surge
+ },
+ adds = {
+ 68078 --> Iron Qon
+ }
+ }
+ }
+ },
+
+------------> Twin Consorts ------------------------------------------------------------------------------
+ [11] = {
+ boss = "Twin Consorts",
+
+ spell_mechanics = {
+ [137410] = {0x200, 0x1}, --> Blazing Radiance
+ [137492] = {0x1}, --> Nuclear Inferno
+ [137382] = {0x1}, --> Darkness
+ [138682] = {0x1}, --> Darkness
+ [137129] = {0x1, 0x2000}, --> Crashing Star
+ [137405] = {0x1}, --> Tears of the Sun
+ [138746] = {0x1}, --> Tears of the Sun
+ [137494] = {0x1, 0x2000}, --> Light of Day
+ [137403] = {0x1, 0x2000}, --> Light of Day
+ [138804] = {0x1, 0x2000}, --> Light of Day
+ [137360] = {0x200}, --> Corrupted Healing
+ [137408] = {0x100}, --> Fan of Flames
+ [136722] = {0x40}, --> Slumber Spores
+ [137417] = {0x8}, --> Flames of Passion
+ [137414] = {0x8}, --> Flames of Passion
+ [138688] = {0x1}, --> Tidal Force
+ [137716] = {0x1}, --> Tidal Force
+ [137419] = {0x1, 0x2000} --> Ice Comet
+ },
+
+ continuo = {
+ },
+
+ phases = {
+ --> phase 1 (night)
+ {
+ spells = {
+ 137382, --> Darkness
+ 138682, --> Darkness
+ 137405, --> Tears of the Sun
+ 138746, --> Tears of the Sun
+ 137494, --> Light of Day
+ 137403, --> Light of Day
+ 138804, --> Light of Day
+ 137360, --> Corrupted Healing
+ 136722, --> Slumber Spores
+ 137129 --> Crashing Star
+
+ },
+ adds = {
+ 69591, -- Lurker in the Night
+ 69479, -- Beast of Nightmares
+ 68905, --> Lu'lin
+ 68904 --> Suen
+ }
+ },
+ --> phase 2 (day)
+ {
+ spells = {
+ 137492, --> Nuclear Inferno
+ 137410, --> Blazing Radiance
+ 137408, --> Fan of Flames
+ 137417, --> Flames of Passion
+ 137419, --> Ice Comet
+ 137129 --> Crashing Star
+ },
+ adds = {
+ 68904 --> Suen
+ }
+ },
+ --> phase 3 (dusk)
+ {
+ spells = {
+ 137492, --> Nuclear Inferno
+ 137410, --> Blazing Radiance
+ 138688, --> Tidal Force
+ 137419, --> Ice Comet
+ 137494, --> Light of Day
+ 137403, --> Light of Day
+ 138804, --> Light of Day
+ 137410 --> Blazing Radiance
+ },
+ adds = {
+ 68905, --> Lu'lin
+ 68904 --> Suen
+ }
+ },
+ --> phase 4
+ {
+ spells = {
+ 137492, --> Nuclear Inferno
+ 137410, --> Blazing Radiance
+ 137382, --> Darkness
+ 138682, --> Darkness
+ 137360, --> Corrupted Healing
+ 137408, --> Fan of Flames
+ 136722, --> Slumber Spores
+ 137417, --> Flames of Passion
+ 137129 --> Crashing Star
+ },
+ adds = {
+ 69591, --Lurker in the Night
+ 69479, --Beast of Nightmares
+ 68905, --> Lu'lin
+ 68904 --> Suen
+ }
+ }
+ }
+ },
+
+------------> Lei Shen ------------------------------------------------------------------------------
+ [12] = {
+ boss = "Lei Shen",
+
+ spell_mechanics = {
+ [136889] = {0x2, 0x1}, --> Violent Gale Winds
+ [135096] = {0x40}, --> Thunderstruck
+ [135703] = {0x200}, --> Static Shock
+ [134821] = {0x200}, --> Discharged Energy
+ [136366] = {0x1}, --> Bouncing Bolt
+ [136620] = {0x1}, --> Ball Lightning
+ [136543] = {0x1}, --> Summon Ball Lightning
+ [136021] = {0x40}, --> Chain Lightning
+ [135150] = {0x8}, --> Crashing Thunder
+ [135153] = {0x8}, --> Crashing Thunder
+ [136914] = {0x1}, --> Electrical Shock
+ [136019] = {0x40}, --> Chain Lightning
+ [136018] = {0x40}, --> Chain Lightning
+ [139011] = {0x1}, --> Helm of Command
+ [134916] = {0x80, 0x100}, --> Decapitate
+ [136326] = {0x40}, --> Overcharge
+ [136478] = {0x100}, --> Fusion Slash
+ [135991] = {0x40}, --> Diffusion Chain
+ [136853] = {0x8}, --> Lightning Bolt
+ [137176] = {0x8}, --> Overloaded Circuits
+ [136850] = {0x8, 0x40} --> Lightning Whip
+ },
+ continuo = {
+ 135703, --> Static Shock
+ 136366, --> Bouncing Bolt
+ 136021, --> Chain Lightning
+ 136019, --> Chain Lightning
+ 136018, --> Chain Lightning
+ 136326, --> Overcharge
+ 135991 --> Diffusion Chain
+ },
+ phases = {
+
+ --> phase 1
+ {
+ spells = {
+ 135096, --> Thunderstruck
+ 134821, --> Discharged Energy
+ 135150, --> Crashing Thunder
+ 135153, --> Crashing Thunder
+ 134916 --> Decapitate
+ },
+ adds = {
+ 69013, --> Diffused Lightning
+ 69133, --> Unharnessed Power
+ 68397 --> Lei Shen
+ }
+ },
+
+ --> phase 2
+ {
+ spells = {
+
+ },
+ adds = {
+ 69013, --> Diffused Lightning
+ 69133 --> Unharnessed Power
+ }
+ },
+
+ --> phase 3
+ {
+ spells = {
+ 134821, --> Discharged Energy
+ 136620, --> Ball Lightning
+ 136543, --> Summon Ball Lightning
+ 139011, --> Helm of Command
+ 136478, --> Fusion Slash
+ 136853, --> Lightning Bolt
+ 137176, --> Overloaded Circuits
+ 136850 --> Lightning Whip
+ },
+ adds = {
+ 69013, --> Diffused Lightning
+ 69133, --> Unharnessed Power
+ 69232, --> Ball Lightning
+ 68397 --> Lei Shen
+ }
+ },
+
+ --> phase 4
+ {
+ spells = {
+ 137176 --> Overloaded Circuits
+ },
+ adds = {
+ 69013, --> Diffused Lightning
+ 69133 --> Unharnessed Power
+ }
+ },
+
+ --> phase 5
+ {
+ spells = {
+ 136889, --> Violent Gale Winds
+ 135096, --> Thunderstruck
+ 134821, --> Discharged Energy
+ 136620, --> Ball Lightning
+ 136543, --> Summon Ball Lightning
+ 136914, --> Electrical Shock
+ 139011, --> Helm of Command
+ 136478, --> Fusion Slash
+ 136853, --> Lightning Bolt
+ 137176, --> Overloaded Circuits
+ 136850 --> Lightning Whip
+ },
+ adds = {
+ 69013, --> Diffused Lightning
+ 69133, --> Unharnessed Power
+ 69232, --> Ball Lightning
+ 68397 --> Lei Shen
+ }
+ }
+ }
+ },
+
+------------> Ra-den ------------------------------------------------------------------------------
+ [13] = {
+ boss = "Ra-Den",
+ phases = {}
+ }
+
+ } --> Fim da lista dos Bosses de Throne of Thunder
+}
+
+
+_detalhes:InstallEncounter (throne_of_thunder)
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/embeds.xml b/plugins/Details_RaidInfo-ThroneOfThunder/embeds.xml
new file mode 100644
index 00000000..a5cb37d2
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/embeds.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/enUS.lua b/plugins/Details_RaidInfo-ThroneOfThunder/enUS.lua
new file mode 100644
index 00000000..ef913e03
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/enUS.lua
@@ -0,0 +1,24 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_RaidInfo-ThroneOfThunder", "enUS", true)
+
+if (not Loc) then
+ return
+end
+
+Loc ["PLUGIN_NAME"] = "Raid Info Throne of Thunder"
+Loc ["STRING_RAID_NAME"] = "Throne of Thunder"
+
+---------------------------------------------------------------------------------------------------
+
+Loc ["STRING_JINROKH"] = "Jin'rokh the Breaker"
+Loc ["STRING_HORRIDON"] = "Horridon"
+Loc ["STRING_CONCIL"] = "Council of Elders"
+Loc ["STRING_TORTOS"] = "Tortos"
+Loc ["STRING_MEGAERA"] = "Megaera"
+Loc ["STRING_JIKUN"] = "Ji'kun"
+Loc ["STRING_DURUMU"] = "Durumu the Forgotten"
+Loc ["STRING_PRIMORDIUS"] = "Primordius"
+Loc ["STRING_DARKANIMUS"] = "Dark Animus"
+Loc ["STRING_IRONQON"] = "Iron Qon"
+Loc ["STRING_TWINS"] = "Twin Consorts"
+Loc ["STRING_LEISHEN"] = "Lei Shen"
+Loc ["STRING_RADEN"] = "Ra-Den"
\ No newline at end of file
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/images/icon256x128.tga b/plugins/Details_RaidInfo-ThroneOfThunder/images/icon256x128.tga
new file mode 100644
index 00000000..eb6a0070
Binary files /dev/null and b/plugins/Details_RaidInfo-ThroneOfThunder/images/icon256x128.tga differ
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/images/raid_tot.tga b/plugins/Details_RaidInfo-ThroneOfThunder/images/raid_tot.tga
new file mode 100644
index 00000000..74681589
Binary files /dev/null and b/plugins/Details_RaidInfo-ThroneOfThunder/images/raid_tot.tga differ
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/images/tot.tga b/plugins/Details_RaidInfo-ThroneOfThunder/images/tot.tga
new file mode 100644
index 00000000..dec31e8a
Binary files /dev/null and b/plugins/Details_RaidInfo-ThroneOfThunder/images/tot.tga differ
diff --git a/plugins/Details_RaidInfo-ThroneOfThunder/ptBR.lua b/plugins/Details_RaidInfo-ThroneOfThunder/ptBR.lua
new file mode 100644
index 00000000..fe9c9e85
--- /dev/null
+++ b/plugins/Details_RaidInfo-ThroneOfThunder/ptBR.lua
@@ -0,0 +1,11 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_RaidInfo-ThroneOfThunder", "ptBR")
+
+if (not Loc) then
+ return
+end
+
+Loc ["PLUGIN_NAME"] = "Info da Raide Trono do Trovao"
+Loc ["STRING_RAID_NAME"] = "Trono do Trovao"
+
+---------------------------------------------------------------------------------------------------
+
diff --git a/plugins/Details_SaveData/Details_SaveData.toc b/plugins/Details_SaveData/Details_SaveData.toc
new file mode 100644
index 00000000..c02b416e
--- /dev/null
+++ b/plugins/Details_SaveData/Details_SaveData.toc
@@ -0,0 +1,6 @@
+## Interface: 50300
+## Title: Details Save Data
+## Notes: Save Details database
+## RequiredDeps: Details
+
+Details_SaveData.xml
\ No newline at end of file
diff --git a/plugins/Details_SaveData/Details_SaveData.xml b/plugins/Details_SaveData/Details_SaveData.xml
new file mode 100644
index 00000000..e09ee163
--- /dev/null
+++ b/plugins/Details_SaveData/Details_SaveData.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ self:RegisterEvent ("ADDON_LOADED")
+ self:RegisterEvent ("PLAYER_LOGOUT")
+
+
+
+ if (event == "ADDON_LOADED") then
+ _G._detalhes_saver = true
+
+ elseif (event == "PLAYER_LOGOUT") then
+ _G._detalhes:SaveDataOnLogout()
+
+ end
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/Details_SpellDetails/Details_SpellDetails.lua b/plugins/Details_SpellDetails/Details_SpellDetails.lua
new file mode 100644
index 00000000..1fd3412f
--- /dev/null
+++ b/plugins/Details_SpellDetails/Details_SpellDetails.lua
@@ -0,0 +1,1288 @@
+local Loc = LibStub ("AceLocale-3.0"):GetLocale ("Details_SpellDetails")
+local Graphics = LibStub:GetLibrary("LibGraph-2.0")
+
+--> Main Plugin Object
+local SpellDetails = _detalhes:NewPluginObject ("Details_SpellDetails")
+--> Main Frame
+local SpellDetailsFrame = SpellDetails.Frame
+
+--> Needed locals
+local _GetTime = GetTime --> wow api local
+local _UFC = UnitAffectingCombat --> wow api local
+local _IsInRaid = IsInRaid --> wow api local
+local _IsInGroup = IsInGroup --> wow api local
+local _UnitAura = UnitAura --> wow api local
+local _CreateFrame = CreateFrame --> wow api local
+local _ipairs = ipairs --> lua library local
+local _pairs = pairs --> lua library local
+local _string_len = string.len --> lua library local
+local _math_floor = math.floor --> lua library local
+local _cstr = string.format --> lua library local
+local _string_format = string.format
+local _table_sort = table.sort
+local _tostring = tostring
+local _GetSpellInfo =_detalhes.getspellinfo --> details spell cache
+local _string_lower = string.lower
+local _string_sub = string.sub
+
+--> this function will run when the plugin receives the Addon_Loaded event, ["data"] = previus saved player rank
+local function CreatePluginFrames (data)
+
+ --> catch Details! main object
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+
+ if (not _detalhes) then
+ --> details isn't active
+ return
+ end
+
+ --> Saved Data
+ SpellDetails.data = data or {}
+ SpellDetails.updating = false
+
+ local timeCaptureFunction = function (second, myTimeTable, myAttributesTable)
+ --> second: number of the tick
+ --> myTimeTable: is the table wich will contain the data
+ --> myAttributesTable: table wich your custom parameters
+
+ if (SpellDetails.playerActor) then
+ --> get player total damage
+ local actorTotalDamage = SpellDetails.playerActor.total
+ --> calculate the diferente between last tick
+ local currentDamage = actorTotalDamage - myAttributesTable.lastDamage
+ --> record damage
+ myTimeTable [second] = currentDamage
+ --> check if this tick was greater then before
+ if (currentDamage > myAttributesTable.maxDamage) then
+ myAttributesTable.maxDamage = currentDamage
+ end
+ --> record tick total damage
+ myAttributesTable.lastDamage = actorTotalDamage
+ end
+ end
+
+ function SpellDetails:OnDetailsEvent (event, ...)
+ if (event == "SHOW") then --> plugin shown on screen, actived
+
+ --> register a custom time capture // time capture is a custom function wich will run every second and grab any kind of data.
+ --> here we want to capture the damage of "player".
+ --> _detalhes:RegisterTimeCapture ( function, give a name, parameters table )
+
+ _detalhes:RegisterTimeCapture (timeCaptureFunction, "SpellDetails_PlayerDamage", {lastDamage = 0, maxDamage = 0})
+
+ elseif (event == "HIDE") then --> plugin hidded, disabled
+ SpellDetailsFrame:SetScript ("OnUpdate", nil)
+ _detalhes:UnregisterTimeCapture ("SpellDetails_PlayerDamage")
+ SpellDetails.playerActor = nil
+
+ elseif (event == "REFRESH") then --> requested a refresh window
+ SpellDetails:Refresh()
+
+ elseif (event == "COMBAT_PLAYER_TIMESTARTED") then --> combat started
+ if (not SpellDetailsFrame:GetScript ("OnUpdate")) then
+ _detalhes:RegisterEvent (SpellDetails, "BUFF_UPDATE") --> register buffs on player
+ _detalhes:RegisterEvent (SpellDetails, "BUFF_UPDATE_DEBUFFPOWER") --> register debuffs wich player cast on oponents
+ SpellDetails:RefreshBuffs()
+ SpellDetails:JanelaSoloUpdate (1)
+ SpellDetails.playerActor = select (2, ...)
+ end
+
+ elseif (event == "BUFF_UPDATE") then
+ --> trigger when a buff is applyed on player
+ SpellDetails:RefreshBuffs()
+
+ end
+ end
+
+ function SpellDetails:CombatEnd()
+ _detalhes:UnregisterEvent (SpellDetails, "BUFF_UPDATE")
+ _detalhes:UnregisterEvent (SpellDetails, "BUFF_UPDATE_DEBUFFPOWER")
+ SpellDetailsFrame:SetScript ("OnUpdate", nil)
+ SpellDetails:RefreshBuffs()
+ end
+
+--------> Build Frame and Widgets ---------------------------------------------------------------------------------------------------------------------------
+ SpellDetailsFrame:SetResizable (false)
+ SpellDetailsFrame:SetPoint ("TOPLEFT", UIParent, "TOPLEFT")
+ SpellDetailsFrame:SetWidth (1)
+ SpellDetailsFrame:SetHeight (1)
+
+ --> Widgets Container
+ SpellDetails.SummaryLine = {}
+ SpellDetails.SpellButtons = {}
+ SpellDetails.SpellInfoLabels = {}
+ SpellDetails.BuffTextEntry = {}
+
+ --> reset all labels
+ function SpellDetails:ResetWindow()
+ SpellDetails.SummaryLine:Reset()
+ SpellDetails.SpellButtons:Reset()
+ SpellDetails.SpellInfoLabels:Reset()
+ SpellDetails:ClearBuffTexts()
+ end
+
+--------> Build head displays -----------------------------------------------------------------------------------------
+ local y = -5
+ local x = {
+ 25, 55, --> total de feito
+ 120, 158, --> media
+ 200, 240 --> tempo decorrido
+ }
+
+ --> background
+ SpellDetailsFrame.bg_status = SpellDetailsFrame:CreateTexture (nil, "BACKGROUND")
+ SpellDetailsFrame.bg_status:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", -35, y+5)
+ SpellDetailsFrame.bg_status:SetWidth (370)
+ SpellDetailsFrame.bg_status:SetHeight (30)
+ SpellDetailsFrame.bg_status:SetTexture ("Interface\\UNITPOWERBARALT\\WowUI_Horizontal_Frame")
+
+ local TotalLabel = DetailsFrameWork:NewLabel (SpellDetailsFrame, SpellDetailsFrame, nil, "SummaryDmg", Loc ["STRING_DAMAGE"]..": ".." 0", "GameFontHighlightSmall")
+ TotalLabel:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", x[1]-5, y-5)
+
+ local TotalDpsLabel = DetailsFrameWork:NewLabel (SpellDetailsFrame, SpellDetailsFrame, nil, "SummaryDps", Loc ["STRING_DPS"]..":".." 0", "GameFontHighlightSmall")
+ TotalDpsLabel:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", x[3], y-5)
+
+ local TotalTimeLabel = DetailsFrameWork:NewLabel (SpellDetailsFrame, SpellDetailsFrame, nil, "SummaryTime", Loc ["STRING_TEMPO"]..":".." 0.0", "GameFontHighlightSmall")
+ TotalTimeLabel:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", x[5]+10, y-5)
+
+ SpellDetails.SummaryLine.total = TotalLabel
+ SpellDetails.SummaryLine.dps = TotalDpsLabel
+ SpellDetails.SummaryLine.time = TotalTimeLabel
+
+ function SpellDetails.SummaryLine:Reset()
+ SpellDetails.SummaryLine.total:SetText (Loc ["STRING_DAMAGE"]..": 0")
+ SpellDetails.SummaryLine.dps:SetText (Loc ["STRING_DPS"]..":".." 0")
+ SpellDetails.SummaryLine.time:SetText (Loc ["STRING_TEMPO"]..":".." 0")
+ end
+
+--------> Build 9 spells boxes -----------------------------------------------------------------------------------------
+
+ function SpellDetails:ChangeSpellBox (id, spellid, icon, line1, line2, tooltip)
+ local BoxTable = SpellDetails.SpellButtons [id]
+
+ if (BoxTable) then
+ if (icon) then
+ BoxTable.icon:SetTexture (icon)
+ end
+
+ if (line1) then
+ BoxTable.label1:SetText (line1)
+ end
+
+ if (line2) then
+ BoxTable.label2:SetText (line2)
+ end
+
+ if (tooltip) then
+ BoxTable.button.tooltip = tooltip
+ end
+
+ BoxTable.spellid = spellid
+ end
+ end
+
+ function SpellDetails.ShowSpellDetails (id)
+ if (SpellDetails.CurrentSpellSlot) then
+ SpellDetails.SpellButtons [SpellDetails.CurrentSpellSlot].background:Hide()
+ end
+ return SpellDetails:DetalhesDaMagia (id)
+ end
+
+ local CreateSpellBox = function (x, y, w, h, id, framelevel)
+
+ local button = DetailsFrameWork:NewDetailsButton (SpellDetailsFrame, SpellDetailsFrame, _, SpellDetails.ShowSpellDetails, id, _, w, h+10, "Interface\\BUTTONS\\UI-DialogBox-Button-Disabled.blp")
+ button:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", x, y)
+ button:SetFrameLevel (framelevel)
+
+ local icon = button:CreateTexture (nil, "OVERLAY")
+ icon:SetPoint ("TOPLEFT", button, "TOPLEFT", 6, -5)
+ icon:SetWidth (18)
+ icon:SetHeight (18)
+
+ local label2 = DetailsFrameWork:NewLabel (button, button, nil, "text2", "", "GameFontHighlightSmall", 9.2)
+ label2:SetPoint ("LEFT", icon, "RIGHT", 5, 4)
+ local label1 = DetailsFrameWork:NewLabel (button, button, nil, "text1", "", "GameFontHighlightSmall", 9.2)
+ label1:SetPoint ("LEFT", icon, "RIGHT", 5, -5)
+
+ local box = button:CreateTexture (nil, "artwork")
+ box:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", x, y)
+ box:SetWidth (w)
+ box:SetHeight (h+10)
+ box:SetTexture ("Interface\\BUTTONS\\UI-DialogBox-Button-Disabled.blp")
+ box:SetBlendMode ("ADD")
+ box:Hide()
+
+ SpellDetails.SpellButtons [id] = {background = box, button = button, icon = icon, label1 = label1, label2 = label2, selected = false}
+ end
+
+ SpellDetails.SpellButtons.LastSelected = nil
+ SpellDetails.SpellButtons.selected = SpellDetailsFrame:CreateTexture (nil, "background")
+ SpellDetails.SpellButtons.selected:SetDrawLayer ("background", 1)
+ SpellDetails.SpellButtons.selected:SetWidth (98)
+ SpellDetails.SpellButtons.selected:SetHeight (36)
+
+ function SpellDetails:ClearSpellBox (id)
+ local BoxTable = SpellDetails.SpellButtons [id]
+ if (BoxTable) then
+ BoxTable.icon:SetTexture (nil)
+ BoxTable.label1:SetText ("")
+ BoxTable.label2:SetText ("")
+ BoxTable.button.tooltip = nil
+ BoxTable.selected = false
+ end
+ end
+
+ function SpellDetails.SpellButtons:Reset()
+ for i = 1, 9 do
+ SpellDetails:ClearSpellBox (i)
+ SpellDetails.SpellButtons.LastSelected = nil
+ SpellDetails.SpellButtons.selected:ClearAllPoints()
+ end
+ end
+
+ --> Call the build function for the 9 spell boxes
+ local ROWX = {6, 106, 206} --> up
+
+ for i = 1, 3 do
+ CreateSpellBox (ROWX[i], -32, 90, 30, i, 5)
+ end
+ for i = 4, 6 do
+ CreateSpellBox (ROWX[i-3], -62, 90, 30, i, 6)
+ end
+ for i = 7, 9 do
+ CreateSpellBox (ROWX[i-6], -92, 90, 30, i, 7)
+ end
+
+--------> Cria o background da esquerda
+ SpellDetails.graphic = {}
+
+ SpellDetails.graphic.fundo = _CreateFrame ("frame", nil, SpellDetailsFrame)
+ SpellDetails.graphic.fundo:SetPoint ("topleft", SpellDetailsFrame, "topleft", 5, -133)
+ SpellDetails.graphic.fundo:SetWidth (288)
+ SpellDetails.graphic.fundo:SetHeight (160)
+ SpellDetails.graphic.fundo:SetBackdrop ({
+ --edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ tile = true, tileSize = 16, edgeSize = 10, insets = {left = 1, right = 1, top = 0, bottom = 1},
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
+
+ SpellDetails.graphic.fundo:SetScript ("OnEnter", function()
+ local _r, _g, _b, _a =SpellDetails.graphic.fundo:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (SpellDetails.graphic.fundo, "frame", _r, _g, _b, _a, .3, .3, .3, .5, 0.9)
+ end)
+
+ SpellDetails.graphic.fundo:SetScript ("OnLeave", function()
+ local _r, _g, _b, _a = SpellDetails.graphic.fundo:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (SpellDetails.graphic.fundo, "frame", _r, _g, _b, _a, .9, .7, .7, 1, 0.9)
+ end)
+
+
+ --> Cria a janela do gráfico
+ if (not _G.DetailsSoloDpsGraph) then
+ local g = Graphics:CreateGraphLine ("DetailsSoloDpsGraph", SpellDetails.graphic.fundo, "topleft", "topleft", 0, 0, 288, 140)
+ g:SetXAxis (-1,1)
+ g:SetYAxis (-1,1)
+ g:SetGridSpacing (false, 0.105)
+ g:SetGridColor ({0.5, 0.5, 0.5, 0.5})
+ g:SetAxisDrawing (true, true)
+ g:SetAxisColor({1.0, 1.0, 1.0, 1.0})
+ g:SetAutoScale (true)
+ g.CustomRightBorder = 0.001
+ g.max_time = 0
+ g.max_damage = 0
+ g.BuffLines = {}
+ g.LinesContainer = {}
+ g.CustomLine = "smallline"
+ --g.LockOnXMax = true
+
+ for i = 1, 8, 1 do
+ DetailsFrameWork:NewLabel (SpellDetails.graphic.fundo, SpellDetails.graphic.fundo, nil, "dpsamt"..i, "", "GameFontHighlightSmall")
+ SpellDetails.graphic.fundo["dpsamt"..i]:SetPoint ("TOPLEFT", SpellDetails.graphic.fundo, "TOPLEFT", -1, -(14.4*i))
+ _detalhes:SetFontSize (SpellDetails.graphic.fundo["dpsamt"..i], 9)
+ end
+
+ end
+
+ function SpellDetails:UpdateDamageGraphic()
+
+ local GraphicObject = _G.DetailsSoloDpsGraph
+
+ if (not GraphicObject) then
+ print ("Nao ha um grafico criado.")
+ return
+ end
+
+ SpellDetails.LastGraphicDrew = SpellDetails.LastGraphicDrew or {}
+ local graphicData = _detalhes.tabela_vigente:GetTimeData()
+
+ if (graphicData == SpellDetails.LastGraphicDrew) then
+ return
+ else
+ SpellDetails.LastGraphicDrew = SpellDetails.LastGraphicDrew
+ end
+
+ if (not graphicData ["SpellDetails_PlayerDamageAttributes"]) then
+ return
+ elseif (graphicData ["SpellDetails_PlayerDamageAttributes"].maxDamage == 0) then
+ return
+ end
+
+ if (#graphicData ["SpellDetails_PlayerDamageData"] < 2) then
+ local timetooshort = SpellDetails.graphic.fundo.timetooshot or DetailsFrameWork:NewLabel (SpellDetails.graphic.fundo, SpellDetails.graphic.fundo, nil, "timetooshort", Loc ["STRING_TOOSHORT"], "GameFontHighlightSmall")
+ timetooshort:SetPoint ("TOPLEFT", SpellDetails.graphic.fundo, "TOPLEFT", 40, -55)
+ _detalhes:SetFontSize (timetooshort, 10)
+ timetooshort:SetJustifyH ("center")
+ timetooshort:Show()
+ return
+ elseif (SpellDetails.graphic.fundo.timetooshort) then
+ SpellDetails.graphic.fundo.timetooshort:Hide()
+ end
+
+ GraphicObject:ResetData()
+
+ local _data = {}
+ local dps_max = graphicData ["SpellDetails_PlayerDamageAttributes"].maxDamage
+ local amount = #graphicData ["SpellDetails_PlayerDamageData"]
+
+ local scaleW = 1/288
+
+ local content = graphicData ["SpellDetails_PlayerDamageData"]
+ table.insert (content, 1, 0)
+ table.insert (content, 1, 0)
+ table.insert (content, #content+1, 0)
+ table.insert (content, #content+1, 0)
+ local _i = 3
+ while (_i <= #content-2) do
+ local v = (content[_i-2]+content[_i-1]+content[_i]+content[_i+1]+content[_i+2])/5
+ _data [#_data+1] = {scaleW*(_i-2), v/dps_max} -->
+ _i = _i + 1
+ end
+
+ local BuffTable = _detalhes.Buffs.BuffsTable
+ local iconIndex = 1
+
+ if (BuffTable) then
+
+ local geralLineIndex = 1
+ local scaleG = 277/_detalhes.tabela_vigente:GetCombatTime() --288
+
+ for spellName, spellTable in _pairs (BuffTable) do
+
+ local timeTable = {}
+ for index, appliedAt in _ipairs (spellTable.appliedAt) do
+ timeTable [#timeTable+1] = {appliedAt, spellTable.tableIndex}
+ end
+
+ for index, appliedAt in _ipairs (timeTable) do
+ local thisLine = GraphicObject.BuffLines [geralLineIndex]
+ if (not thisLine) then
+ thisLine = GraphicObject:CreateTexture (nil, "overlay")
+ thisLine:SetTexture ("Interface\\AddOns\\Details\\images\\verticalline")
+ thisLine:SetWidth (3)
+ thisLine:SetHeight (160)
+ thisLine:SetPoint ("topleft", SpellDetails.graphic.fundo, "topleft", (appliedAt[1]*scaleG)+25, 0)
+ thisLine:SetVertexColor (.4, .4, .4, .8)
+
+ thisLine.icon = GraphicObject:CreateTexture (nil, "overlay")
+ local _, _, icon = GetSpellInfo (spellName)
+ --print (spellName, icon)
+ thisLine.icon:SetTexture (icon)
+ thisLine.icon:SetWidth (12)
+ thisLine.icon:SetHeight (12)
+
+ if (iconIndex == 1) then
+ thisLine.icon:SetPoint ("left", thisLine, "right", -2, 0)
+ thisLine.icon:SetPoint ("top", thisLine, "bottom", 0, 25)
+ elseif (iconIndex == 2) then
+ thisLine.icon:SetPoint ("right", thisLine, "left", 2, 0)
+ thisLine.icon:SetPoint ("top", thisLine, "bottom", 0, 25)
+ elseif (iconIndex == 3) then
+ thisLine.icon:SetPoint ("right", thisLine, "left", 2, 0)
+ thisLine.icon:SetPoint ("top", thisLine, "bottom", 0, 12)
+ elseif (iconIndex == 4) then
+ thisLine.icon:SetPoint ("left", thisLine, "right", -2, 0)
+ thisLine.icon:SetPoint ("top", thisLine, "bottom", 0, 12)
+ end
+
+ GraphicObject.BuffLines [geralLineIndex] = thisLine
+ else
+ thisLine:SetPoint ("topleft", SpellDetails.graphic.fundo, "topleft", (appliedAt[1]*scaleG)+28, 0)
+ local _, _, icon = GetSpellInfo (spellName)
+ thisLine.icon:SetTexture (icon)
+ end
+
+ geralLineIndex = geralLineIndex + 1
+ end
+
+ iconIndex = iconIndex + 1
+ if (iconIndex == 5) then
+ iconIndex = 1
+ end
+
+ end
+ end
+
+ local dano_divisao = dps_max/8
+ local o = 1
+ for i = 8, 1, -1 do
+ local d = _detalhes:ToK0 (dano_divisao*i)
+ SpellDetails.graphic.fundo["dpsamt"..o]:SetText (d)
+ o = o + 1
+ end
+
+ GraphicObject:AddDataSeries (_data, {1, 1, 1, 1})
+
+ end
+
+ --> Hida
+ SpellDetails.graphic.fundo:Hide()
+
+--------> Cria o background
+ SpellDetailsFrame.fundo = SpellDetailsFrame:CreateTexture (nil, "background")
+ SpellDetailsFrame.fundo:SetTexture ("Interface\\AddOns\\Details_SpellDetails\\images\\solo_bg")
+ SpellDetailsFrame.fundo:SetPoint ("topleft", SpellDetailsFrame, "topleft", 0, -125)
+ SpellDetailsFrame.fundo:SetWidth (298)
+ SpellDetailsFrame.fundo:SetHeight (175)
+ SpellDetailsFrame.fundo:SetTexCoord (0, 0.615234375, 0, 0.6640625)
+ SpellDetailsFrame.fundo:SetDrawLayer ("background", 1)
+
+--------> Cria o background da esquerda
+ SpellDetailsFrame.fundoEsq = _CreateFrame ("frame", nil, SpellDetailsFrame)
+ --SpellDetailsFrame.fundoEsq:SetTexture ("Interface\\Tooltips\\UI-Tooltip-Background")
+ SpellDetailsFrame.fundoEsq:SetPoint ("topleft", SpellDetailsFrame, "topleft", 5, -133)
+ SpellDetailsFrame.fundoEsq:SetWidth (120)
+ SpellDetailsFrame.fundoEsq:SetHeight (160)
+ SpellDetailsFrame.fundoEsq:SetBackdrop ({
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ tile = true, tileSize = 16, edgeSize = 10, insets = {left = 1, right = 1, top = 0, bottom = 1},
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
+
+ SpellDetailsFrame.fundoEsq:SetScript ("OnEnter", function()
+ local _r, _g, _b, _a =SpellDetailsFrame.fundoEsq:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (SpellDetailsFrame.fundoEsq, "frame", _r, _g, _b, _a, .3, .3, .3, .5, .9)
+
+ end)
+
+ SpellDetailsFrame.fundoEsq:SetScript ("OnLeave", function()
+ local _r, _g, _b, _a = SpellDetailsFrame.fundoEsq:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (SpellDetailsFrame.fundoEsq, "frame", _r, _g, _b, _a, .9, .7, .7, 1, .9)
+ end)
+
+--------> Cria o background da direita
+ SpellDetailsFrame.fundoDir = _CreateFrame ("frame", nil, SpellDetailsFrame)
+ SpellDetailsFrame.fundoDir:SetPoint ("topleft", SpellDetailsFrame, "topright", 127, -138+5)
+ SpellDetailsFrame.fundoDir:SetWidth (166)
+ SpellDetailsFrame.fundoDir:SetHeight (160)
+ SpellDetailsFrame.fundoDir:SetBackdrop ({
+ edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
+ tile = true, tileSize = 16, edgeSize = 10, insets = {left = 1, right = 1, top = 0, bottom = 1},
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
+ SpellDetailsFrame.fundoDir:SetScript ("OnEnter", function()
+ local _r, _g, _b, _a =SpellDetailsFrame.fundoDir:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (SpellDetailsFrame.fundoDir, "frame", _r, _g, _b, _a, .3, .3, .3, .5, .9)
+ end)
+ SpellDetailsFrame.fundoDir:SetScript ("OnLeave", function()
+ local _r, _g, _b, _a = SpellDetailsFrame.fundoDir:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (SpellDetailsFrame.fundoDir, "frame", _r, _g, _b, _a, .9, .7, .7, 1, .9)
+ end)
+
+-----------------------------------------------------------------------------------------------------------------------------------------------
+--> botão switch
+
+ SpellDetails.Detalhes = 1 --> normal
+ function SpellDetails:ShowGraphic()
+ --> hidar os 2 blocos em baixo:
+
+ if (SpellDetails.Detalhes == 1) then --> show graphic
+
+ if (InCombatLockdown()) then
+ print ("|cffFF2222"..Loc ["STRING_INCOMBAT"])
+ return
+ end
+
+ SpellDetailsFrame.fundoEsq:Hide()
+ SpellDetailsFrame.fundoDir:Hide()
+ SpellDetails.Detalhes = 2
+ SpellDetails.SwitchButton.text:SetText ("X") --> localize-me
+ SpellDetails.SwitchButton:SetWidth (15)
+ SpellDetails.graphic.fundo:Show()
+ SpellDetails:UpdateDamageGraphic (SpellDetailsFrame)
+ SpellDetails.SwitchButton:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", 275, -136)
+
+ elseif (SpellDetails.Detalhes == 2) then --> show normal details
+ SpellDetailsFrame.fundoEsq:Show()
+ SpellDetailsFrame.fundoDir:Show()
+ SpellDetails.Detalhes = 1
+ SpellDetails.SwitchButton.text:SetText ("Graphic") --> localize-me
+ SpellDetails.SwitchButton:SetWidth (110)
+ SpellDetails.graphic.fundo:Hide()
+ SpellDetails.SwitchButton:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", 10, -274)
+
+ end
+ end
+
+ --> botão para o gráfico:
+ local SwitchButton = DetailsFrameWork:NewDetailsButton (SpellDetailsFrame, SpellDetailsFrame, _, SpellDetails.ShowGraphic, _, _, 110, 15)
+ SwitchButton:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", 10, -274)
+ SwitchButton:SetFrameLevel (6)
+ SwitchButton:InstallCustomTexture()
+ SwitchButton.text:SetText ("Graphic") --> localize-me
+
+ SpellDetails.SwitchButton = SwitchButton
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+ --> painel da esquerda inferior (informações da magia)
+
+ local loc_y = {-140, -150, -160, -170, -180, -190, -200, -210, -220, -230, -240}
+ local xStart = 10
+
+ local total = DetailsFrameWork:NewLabel (SpellDetailsFrame.fundoEsq, SpellDetailsFrame.fundoEsq, nil, "total", Loc ["STRING_DAMAGE"]..":", "GameFontHighlightSmall")
+ SpellDetailsFrame.fundoEsq.total:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", xStart, loc_y[1])
+ SpellDetails.SpellInfoLabels.total = total
+
+ local dps = DetailsFrameWork:NewLabel (SpellDetailsFrame.fundoEsq, SpellDetailsFrame.fundoEsq, nil, "dps", Loc ["STRING_DPS"]..":", "GameFontHighlightSmall")
+ SpellDetailsFrame.fundoEsq.dps:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", xStart, loc_y[2])
+ SpellDetails.SpellInfoLabels.dps = dps
+
+ local media = DetailsFrameWork:NewLabel (SpellDetailsFrame.fundoEsq, SpellDetailsFrame.fundoEsq, nil, "porcento", Loc ["STRING_PERCENT"]..":", "GameFontHighlightSmall")
+ SpellDetailsFrame.fundoEsq.porcento:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", xStart, loc_y[3])
+ SpellDetails.SpellInfoLabels.porcento = media
+
+ local uptime = DetailsFrameWork:NewLabel (SpellDetailsFrame.fundoEsq, SpellDetailsFrame.fundoEsq, nil, "tempo_em_uso", Loc ["STRING_UPTIME"]..":", "GameFontHighlightSmall")
+ SpellDetailsFrame.fundoEsq.tempo_em_uso:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", xStart, loc_y[4])
+ SpellDetails.SpellInfoLabels.uptime = uptime
+
+ local critical = DetailsFrameWork:NewLabel (SpellDetailsFrame.fundoEsq, SpellDetailsFrame.fundoEsq, nil, "critico", Loc ["STRING_CRIT"]..":", "GameFontHighlightSmall")
+ SpellDetailsFrame.fundoEsq.critico:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", xStart, loc_y[5])
+ SpellDetails.SpellInfoLabels.critical = critical
+
+ local miss = DetailsFrameWork:NewLabel (SpellDetailsFrame.fundoEsq, SpellDetailsFrame.fundoEsq, nil, "miss", Loc ["STRING_MISS"]..":", "GameFontHighlightSmall")
+ SpellDetailsFrame.fundoEsq.miss:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", xStart, loc_y[6])
+ SpellDetails.SpellInfoLabels.miss = miss
+
+ local block = DetailsFrameWork:NewLabel (SpellDetailsFrame.fundoEsq, SpellDetailsFrame.fundoEsq, nil, "blocked", Loc ["STRING_BLOCKED"]..":", "GameFontHighlightSmall")
+ SpellDetailsFrame.fundoEsq.blocked:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", xStart, loc_y[7])
+ SpellDetails.SpellInfoLabels.block = block
+
+ local glancing = DetailsFrameWork:NewLabel (SpellDetailsFrame.fundoEsq, SpellDetailsFrame.fundoEsq, nil, "glancing", "Glancing: ", "GameFontHighlightSmall")
+ SpellDetailsFrame.fundoEsq.glancing:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPLEFT", xStart, loc_y[8])
+ SpellDetails.SpellInfoLabels.glancing = glancing
+
+ function SpellDetails.SpellInfoLabels:Reset()
+ SpellDetails.SpellInfoLabels.total:SetText (Loc ["STRING_DAMAGE"]..": 0")
+ SpellDetails.SpellInfoLabels.dps:SetText (Loc ["STRING_DPS"]..":".." 0")
+ SpellDetails.SpellInfoLabels.porcento:SetText (Loc ["STRING_PERCENT"]..":".." 0")
+ SpellDetails.SpellInfoLabels.uptime:SetText (Loc ["STRING_UPTIME"]..":".." 0")
+ SpellDetails.SpellInfoLabels.critical:SetText (Loc ["STRING_CRIT"]..":".." 0")
+ SpellDetails.SpellInfoLabels.miss:SetText (Loc ["STRING_MISS"]..":".." 0")
+ SpellDetails.SpellInfoLabels.block:SetText (Loc ["STRING_BLOCKED"]..":".." 0")
+ SpellDetails.SpellInfoLabels.glancing:SetText (Loc ["STRING_GLANCING"]..":".." 0")
+ end
+
+
+
+--------------------------------------------------------------------------------------------------------------------------------------------
+ --> painel da direita inferior (detalhes dos buffs do jogador)
+
+ --_detalhes.SoloTables.BuffsTable.BuffIds = _detalhes.SoloTables.BuffsTable.BuffIds or {0, 0, 0, 0}
+ --_detalhes.SoloTables.BuffsTableNameCache = _detalhes.SoloTables.BuffsTableNameCache or {"", "", "", ""}
+
+ local BuffIndex = {}
+
+ function SpellDetails:ClearBuffTexts()
+ for _, BuffInput in _ipairs (SpellDetails.BuffTextEntry) do
+ BuffInput.amtdone:SetText ("")
+ BuffInput.dps:SetText ("")
+ BuffInput.uptime:SetText ("")
+ end
+ end
+
+ function SpellDetails:SetBuffTexts (id, damage, dps)
+ local BuffInput = SpellDetails.BuffTextEntry [id]
+ BuffInput.amtdone:SetText (Loc ["STRING_DAMAGE"]..": "..damage)
+ BuffInput.dps:SetText (Loc ["STRING_DPS"]..":".." "..dps)
+ end
+
+ local Clear = function (BuffEntryTable)
+ --> clicked on X to clear the buff
+ _detalhes.Buffs:RemoveBuff (BuffEntryTable.name:GetText())
+
+ --_detalhes.SoloTables.BuffsTable.BuffIds [BuffEntryTable.id] = 0
+ BuffIndex [BuffEntryTable.name:GetText()] = nil
+
+ BuffEntryTable.icon:SetTexture (nil)
+ BuffEntryTable.name:SetText ("")
+ BuffEntryTable.amtdone:SetText ("")
+ BuffEntryTable.dps:SetText ("")
+ BuffEntryTable.editbox:SetText (Loc ["STRING_DEBUFFNAME"])
+ BuffEntryTable.editbox:Show()
+ BuffEntryTable.background:Hide()
+ BuffEntryTable.backgroundFrame:Hide()
+ BuffEntryTable.button:Hide()
+ end
+
+ local SetBuff = function (BuffEntryTable, spellid, id)
+
+ local spellname, _, spellicon = GetSpellInfo (spellid)
+
+ if (not _detalhes.Buffs:IsRegistred (spellid)) then
+ _detalhes.Buffs:NewBuff (spellname, spellid)
+ end
+
+ BuffIndex [spellname] = BuffEntryTable
+
+ BuffEntryTable.icon:SetTexture (spellicon)
+ BuffEntryTable.name:SetText (spellname)
+ BuffEntryTable.amtdone:SetText (Loc ["STRING_DAMAGE"]..": 0")
+ BuffEntryTable.dps:SetText (Loc ["STRING_DPS"]..":".." 0")
+ BuffEntryTable.editbox:Hide()
+ BuffEntryTable.background:Show()
+ BuffEntryTable.backgroundFrame:Show()
+ BuffEntryTable.button:Show()
+ --print (debugstack())
+ end
+
+ local OnEnter = function (_, id, texto, editbox, by)
+
+ if (_string_len (texto) > 0 and texto ~= Loc ["STRING_DEBUFFNAME"]) then
+ if (by == editbox) then --> By Enter
+ if (_detalhes.popup.NumLines > 0) then
+ local texto2 = _detalhes.popup:GetText(1):match ("(.-):")
+ texto = texto2
+ end
+ end
+ if (not tonumber (texto)) then
+ editbox:SetText (Loc ["STRING_DEBUFFNAME"])
+ return
+ end
+ SetBuff (SpellDetails.BuffTextEntry [id], tonumber (texto), id)
+ else
+ editbox:SetText (Loc ["STRING_DEBUFFNAME"])
+ end
+
+ if (_detalhes.popup.active) then
+ _detalhes.popup:ShowMe (false)
+ end
+ end
+
+ local CreateBuffInput = function (y, id)
+
+ local backgroundFrame = _CreateFrame ("frame", "SoloBuffEditBox"..id.."Background", SpellDetailsFrame.fundoDir)
+ backgroundFrame:SetWidth (166)
+ backgroundFrame:SetHeight (40)
+ backgroundFrame:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPRIGHT", 127, y+5+8)
+ backgroundFrame:SetBackdrop ({edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", tile = true, tileSize = 16, edgeSize = 10, insets = {left = 1, right = 1, top = 0, bottom = 1},
+ bgFile = "Interface\\DialogFrame\\UI-DialogBox-Gold-Background"})
+ backgroundFrame:SetBackdropColor (.3, .3, .3, .5)
+ --backgroundFrame:SetBackdropBorderColor (1, 0, 0, 1)
+ backgroundFrame:Hide()
+
+ backgroundFrame:SetScript ("OnEnter", function()
+ if (not backgroundFrame.Actived) then
+ local _r, _g, _b, _a = backgroundFrame:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (backgroundFrame, "frame", _r, _g, _b, _a, .9, .7, .7, 1, .9)
+ else
+ local _r, _g, _b, _a = backgroundFrame:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (backgroundFrame, "frame", _r, _g, _b, _a, 75/255, 246/255, 78/255, 1, .9)
+ end
+ end)
+
+ backgroundFrame:SetScript ("OnLeave", function()
+ if (not backgroundFrame.Actived) then
+ local _r, _g, _b, _a = backgroundFrame:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (backgroundFrame, "frame", _r, _g, _b, _a, .3, .3, .3, .5, .9)
+ else
+ local _r, _g, _b, _a = backgroundFrame:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (backgroundFrame, "frame", _r, _g, _b, _a, 22/255, 155/255, 29/255, .9, .9)
+ end
+ end)
+
+ function backgroundFrame:Active()
+ local _r, _g, _b, _a = backgroundFrame:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (backgroundFrame, "frame", _r, _g, _b, _a, 22/255, 155/255, 29/255, .9, .9)
+ backgroundFrame.Actived = true
+ end
+
+ function backgroundFrame:Desactive()
+ local _r, _g, _b, _a = backgroundFrame:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (backgroundFrame, "frame", _r, _g, _b, _a, .3, .3, .3, .5, .9)
+ backgroundFrame.Actived = false
+ end
+
+ local background = SpellDetailsFrame.fundoDir:CreateTexture (nil, "background")
+ --background:SetTexture ("Interface\\DialogFrame\\UI-DialogBox-Background")
+ background:SetWidth (166)
+ background:SetHeight (36)
+ background:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPRIGHT", 127, y+3+8)
+ background:SetDrawLayer ("background", 2)
+ background:Hide()
+
+ --> editbox
+ --local editbox = DetailsFrameWork:NewTextBox (SpellDetailsFrame.fundoDir, SpellDetailsFrame.fundoDir, "SoloBuffEditBox"..id, OnEnter, "param_1", id, 120, 14)
+
+ local editbox = DetailsFrameWork:NewTextEntry (SpellDetailsFrame.fundoDir, nil, "DetailsSpellDetailsBox"..id, "SoloBuffEditBox"..id, 120, 14, OnEnter, "param_1", id)
+
+ editbox:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPRIGHT", 150, y)
+ editbox.text = Loc ["STRING_DEBUFFNAME"]
+
+ local imageLeft = editbox:CreateTexture (nil, "overlay")
+ imageLeft:SetPoint ("right", "DetailsSpellDetailsBox"..id, "left", 0.5, -2)
+ imageLeft:SetTexture ("Interface\\ARCHEOLOGY\\ArchaeologyParts")
+ imageLeft:SetTexCoord (0.119140625, 0.1875, 0.8046875, 0.87890625)
+ imageLeft:SetWidth (19)
+ imageLeft:SetHeight (10)
+ local imageRight = editbox:CreateTexture (nil, "overlay")
+ imageRight:SetPoint ("left", "DetailsSpellDetailsBox"..id, "right", -0.5, -2)
+ imageRight:SetTexture ("Interface\\ARCHEOLOGY\\ArchaeologyParts")
+ imageRight:SetTexCoord (0.0078125, 0.078125, 0.859375, 0.93359375)
+ imageRight:SetWidth (19)
+ imageRight:SetHeight (10)
+
+ editbox.HaveMenu = false
+
+ local OnClickMenu = function (_, _, SpellID)
+ editbox:SetText (SpellID)
+ editbox:PressEnter (true)
+ editbox.HaveMenu = false
+ _detalhes.popup:ShowMe (false)
+ end
+
+ editbox.OnTextChangedHook = function (frame, userChanged)
+
+ if (not userChanged) then
+ return
+ end
+
+ local texto = editbox:GetText()
+ texto = _detalhes:trim (texto)
+ texto = _string_lower (texto)
+ texto = texto:gsub ("%(", "")
+ texto = texto:gsub ("%[", "")
+
+ local index = _string_sub (texto, 1, 1)
+ local cached = _detalhes.spellcachefull [index]
+
+ if (cached) then
+
+ local CoolTip = _G.GameCooltip
+
+ CoolTip:Reset()
+ CoolTip:SetType ("menu")
+ CoolTip:SetOwner (_G ["DetailsSpellDetailsBox"..id])
+ CoolTip:SetOption ("NoLastSelectedBar", true)
+ CoolTip:SetOption ("HeightAnchorMod", -8)
+ CoolTip:SetOption ("TextSize", 9.5)
+
+ local CoolTipTable = {}
+ local texcoord = {0,1,0,1}
+ local i = 1
+
+ for SpellID, SpellTable in _pairs (cached) do
+
+ if (_string_lower (SpellTable[1]):find (texto)) then
+ local rank = SpellTable[3]
+ if (not rank or rank == "") then
+ rank = ""
+ else
+ rank = " ("..rank..")"
+ end
+
+ CoolTip:AddMenu (1, OnClickMenu, SpellID, nil, nil, SpellID..": "..SpellTable[1]..rank, SpellTable[2], true)
+
+ if (i > 20) then
+ break
+ else
+ i = i + 1
+ end
+ end
+
+ end
+
+ _detalhes.popup.buttonOver = true
+ editbox.HaveMenu = true
+ CoolTip:ShowCooltip()
+ end
+ end
+
+ local icon = backgroundFrame:CreateTexture (nil, "OVERLAY")
+ icon:SetWidth (16)
+ icon:SetHeight (16)
+ icon:SetPoint ("TOPLEFT", SpellDetailsFrame, "TOPRIGHT", 133, y+8)
+
+ local name = DetailsFrameWork:NewLabel (backgroundFrame, backgroundFrame, nil, "BuffName"..id, "", "GameFontHighlightSmall")
+ name:SetPoint ("LEFT", icon, "RIGHT", 3, 4)
+
+ local amtdone = DetailsFrameWork:NewLabel (backgroundFrame, backgroundFrame, nil, "BuffDone"..id, "", "GameFontHighlightSmall")
+ amtdone:SetPoint ("LEFT", icon, "RIGHT", 3, -6)
+ local uptime = DetailsFrameWork:NewLabel (backgroundFrame, backgroundFrame, nil, "BuffUptime"..id, "", "GameFontHighlightSmall")
+ uptime:SetPoint ("LEFT", icon, "RIGHT", 55, -6)
+
+ local dps = DetailsFrameWork:NewLabel (backgroundFrame, backgroundFrame, nil, "BuffDps"..id, "", "GameFontHighlightSmall")
+ dps:SetPoint ("LEFT", icon, "RIGHT", 3, -16)
+
+ local clearbutton = _CreateFrame ("Button", nil, backgroundFrame, "UIPanelCloseButton")
+ clearbutton:SetWidth (20)
+ clearbutton:SetHeight (20)
+ clearbutton:SetPoint ("TOPLEFT", icon, "TOPRIGHT", -18, -15)
+
+ SpellDetails.BuffTextEntry [id] = {id = id, editbox = editbox, icon = icon, name = name, amtdone = amtdone, dps = dps, uptime = uptime, button = clearbutton, background = background, backgroundFrame = backgroundFrame}
+
+ --clearbutton:SetText ("x")
+
+ clearbutton:SetScript ("OnClick", function() Clear (SpellDetails.BuffTextEntry [id]) end)
+ clearbutton:Hide()
+
+ editbox.OnEscapePressedHook = function()
+ editbox:SetText (Loc ["STRING_DEBUFFNAME"])
+ _detalhes.popup:ShowMe (false)
+ end
+
+ editbox.OnEnterPressedHook = function()
+ if (editbox:GetText() == Loc ["STRING_DEBUFFNAME"]) then
+ editbox:SetText ("")
+ elseif (_string_len (editbox:GetText()) > 0) then
+ if (not _detalhes.popup.active) then
+ editbox.OnTextChangedHook (true)
+ end
+ end
+ end
+
+ editbox.OnLeaveHook = function()
+ if (not editbox:HasFocus()) then
+ if (editbox:GetText() == "") then
+ editbox:SetText (Loc ["STRING_DEBUFFNAME"])
+ end
+ end
+
+ _detalhes.popup.buttonOver = false
+ if (_detalhes.popup.active) then
+ local passou = 0
+ editbox:SetScript ("OnUpdate", function (self, elapsed)
+ passou = passou+elapsed
+ if (passou > 0.3) then
+ if (not _detalhes.popup.mouseOver and not _detalhes.popup.buttonOver) then
+ _detalhes.popup:ShowMe (false)
+ end
+ editbox:SetScript ("OnUpdate", nil)
+ end
+ end)
+ elseif (_detalhes.popup.tooltip) then
+ _detalhes.popup:ShowMe (false)
+ else
+ editbox:SetScript ("OnUpdate", nil)
+ end
+
+ end
+
+ editbox.OnEditFocusGainedHook = function()
+ if (InCombatLockdown()) then
+
+ GameCooltip:Reset()
+ GameCooltip:AddLine ("|cffFF2222"..Loc ["STRING_INCOMBAT"])
+ GameCooltip:AddIcon ("Interface\\Buttons\\LockButton-Locked-Up",_,_, 25, 25)
+ GameCooltip:ShowCooltip (_G ["DetailsSpellDetailsBox"..id], "tooltip")
+
+ editbox:PressEnter()
+ else
+ editbox:SetText ("")
+ _detalhes:BuildSpellList()
+ end
+ end
+
+ editbox.OnEditFocusLostHook = function()
+ editbox.HaveMenu = false
+ local texto = editbox:GetText()
+ if (_string_len (texto) > 0 and texto ~= Loc ["STRING_DEBUFFNAME"]) then
+ SetBuff (SpellDetails.BuffTextEntry [id], tonumber (texto), id)
+ else
+ editbox:SetText (Loc ["STRING_DEBUFFNAME"])
+ end
+ _detalhes:ClearSpellList()
+ end
+
+ end
+
+ --> Crias as caixas dos buffs
+ local y = {-146, -186, -226, -266} -- +8
+ for i = 1, 4 do
+ CreateBuffInput (y [i], i)
+ end
+
+ --> fill with buff information:
+ --> inject inside details for ace3 delay
+ function _detalhes:SpellDetailsStartupBuffs()
+ local buffmax = 4
+ local BuffList = _detalhes.Buffs:GetBuffListIds()
+ for i = 1, #BuffList do
+ if (i >= 5) then
+ break
+ end
+ SetBuff (SpellDetails.BuffTextEntry [i], BuffList [i], i)
+ end
+ end
+
+ _detalhes:ScheduleTimer ("SpellDetailsStartupBuffs", 5)
+ --_detalhes:SpellDetailsStartupBuffs()
+
+ function SpellDetails:RefreshBuffs()
+ for BuffName, BuffTable in _pairs (_detalhes.Buffs.BuffsTable) do
+ if (BuffTable.active and SpellDetails:IsInCombat()) then
+ if (BuffIndex [BuffName]) then
+ BuffIndex [BuffName].backgroundFrame:Active()
+ end
+ else
+ if (BuffIndex [BuffName]) then
+ BuffIndex [BuffName].backgroundFrame:Desactive()
+ end
+ end
+ end
+ end
+
+ function SpellDetails:Refresh()
+ SpellDetails:AtualizaSoloMode()
+ SpellDetails:DetalhesDaMagia (SpellDetails.CurrentSpellSlot)
+ SpellDetails:ForceUpdateUpDisplay()
+ end
+
+ function SpellDetails:JanelaSoloUpdate (OnOff)
+
+ local janela_solo = SpellDetailsFrame
+ if (OnOff > 0) then
+
+ if (not _detalhes.SoloTables.CombatID) then
+ return
+ end
+
+ local MySelf
+ if (_detalhes.SoloTables.CombatID == _detalhes:NumeroCombate()) then
+ MySelf = _detalhes.tabela_vigente (_detalhes.SoloTables.Attribute, _detalhes.playername)
+ else
+ local vigente = _detalhes.tabela_historico.tabelas[_detalhes:NumeroCombate() - _detalhes.SoloTables.CombatID]
+ MySelf = vigente (_detalhes.SoloTables.Attribute, _detalhes.playername)
+ end
+
+ if (MySelf) then
+ janela_solo.SoloInicioCombate = MySelf.start_time
+ janela_solo.SoloInicioTimer = _GetTime()
+ janela_solo.SoloTimer = 0
+ janela_solo.SoloDps = 0
+ janela_solo.AtualizarJanelaDetalhes = 0
+ janela_solo.MySelf = MySelf
+ janela_solo.Instancia = self
+ janela_solo:SetScript ("OnUpdate", SpellDetails.SoloUpdater)
+ end
+ else
+ janela_solo.SoloInicioCombate = nil
+ janela_solo.SoloTimer = nil
+ janela_solo.SoloDps = nil
+ janela_solo.AtualizarJanelaDetalhes = nil
+ janela_solo.MySelf = nil
+ janela_solo.Instancia = nil
+ janela_solo:SetScript ("OnUpdate", nil)
+ end
+ end
+
+ function SpellDetails:ForceUpdateUpDisplay()
+ local MySelf = _detalhes.tabela_vigente (_detalhes.SoloTables.Attribute, _detalhes.playername)
+ if (MySelf and MySelf.end_time and MySelf.start_time) then
+ local tempo_in_combat = MySelf.end_time - MySelf.start_time
+ SpellDetails.SummaryLine.time:SetText (Loc ["STRING_TEMPO"]..":".." ".._string_format ("%.1f", tempo_in_combat))
+ SpellDetails.SummaryLine.dps:SetText (Loc ["STRING_DPS"]..":".." ".._cstr ("%.1f", MySelf.total/tempo_in_combat))
+ SpellDetails.SummaryLine.total:SetText (Loc ["STRING_DAMAGE"]..": " .. _tostring (MySelf.total))
+ else
+ SpellDetails.SummaryLine.time:SetText (Loc ["STRING_TEMPO"]..":".." 0.0")
+ SpellDetails.SummaryLine.dps:SetText (Loc ["STRING_DPS"]..":".." 0")
+ SpellDetails.SummaryLine.total:SetText (Loc ["STRING_DAMAGE"]..": 0")
+ end
+ end
+
+ function SpellDetails:SoloUpdater (elapsed)
+
+ self.SoloTimer = self.SoloTimer + elapsed
+ self.SoloDps = self.SoloDps + elapsed
+ self.AtualizarJanelaDetalhes = self.AtualizarJanelaDetalhes + elapsed
+
+ if (self.SoloTimer > 0.1) then
+ local tempo_agora = (_GetTime() - self.SoloInicioTimer)
+ SpellDetails.SummaryLine.time:SetText (Loc ["STRING_TEMPO"]..":".." ".._string_format ("%.1f", tempo_agora))
+ self.SoloTimer = 0
+ end
+
+ if (self.SoloDps > 0.2) then
+
+ --print (_GetTime() .. " " .._detalhes._tempo .. " " .. time())
+ --print (self.MySelf.start_time)
+ --_detalhes.SoloTables.SummaryLine.dps:SetText (Loc ["STRING_DPS"]..":".." ".._detalhes:comma_value( _math_floor (self.MySelf.total/(_tempo - self.SoloInicioCombate))) )
+ --print (self.MySelf.total .. " / " .. (time() - self.MySelf.start_time))
+ SpellDetails.SummaryLine.dps:SetText (Loc ["STRING_DPS"]..":".." ".._detalhes:comma_value( _math_floor (self.MySelf.total/( time() - self.MySelf.start_time))) )
+ self.SoloDps = 0
+ end
+
+ if (self.AtualizarJanelaDetalhes > 1.0) then
+ SpellDetails:AtualizaSoloMode()
+ SpellDetails:DetalhesDaMagia (SpellDetails.CurrentSpellSlot)
+ self.AtualizarJanelaDetalhes = 0
+ if (not _UFC ("player")) then
+ return SpellDetails:CombatEnd()
+ end
+ end
+ end
+
+ function SpellDetails:AtualizaSoloMode()
+
+ if (not _detalhes.SoloTables.CombatID) then
+ return
+ end
+
+ -- self.atributo <- retorna o que esta sendo mostrado na instancia
+ local atributo = _detalhes.SoloTables.Attribute
+ local MySelf
+
+ if (_detalhes.SoloTables.CombatID == _detalhes:NumeroCombate()) then
+ MySelf = _detalhes.tabela_vigente (atributo, _detalhes.playername)
+ else
+ local vigente = _detalhes.tabela_historico.tabelas[_detalhes:NumeroCombate() - _detalhes.SoloTables.CombatID]
+ if (not vigente) then
+ --print ("!Vigente> solo_id = ".._detalhes.SoloTables.CombatID.." <> " .. _detalhes:NumeroCombate() - _detalhes.SoloTables.CombatID)
+ return
+ end
+ MySelf = vigente (atributo, _detalhes.playername)
+ end
+
+ local janela = SpellDetailsFrame
+
+ if (MySelf) then
+ local meu_total, dps = MySelf.total, MySelf.last_dps
+
+ SpellDetails.SummaryLine.total:SetText (Loc ["STRING_DAMAGE"]..": ".._detalhes:comma_value (meu_total)) --> gravar total
+
+ --> pegar as magias que castei
+
+ local tabela = MySelf.spell_tables._ActorTable
+ local meus_danos = {}
+
+ local SpellsTotalHits = 0
+ for _spellid, _tabela in _pairs (tabela) do
+ meus_danos [#meus_danos+1] = {_spellid, _tabela, _tabela.total}
+ SpellsTotalHits = SpellsTotalHits + _tabela.counter
+ end
+
+ --> spellvalue
+ for _, _tabela in _ipairs (meus_danos) do
+ local PercentDamage = (_tabela[3]/MySelf.total)+1 -- a escala é de 0.0 a 0.9 + 1 então é de 1 a 1.999
+ local PercentHits = ((_tabela[2].counter/SpellsTotalHits)*0.1) + 1 --> 0.1 scale down --> 1.09
+ local pow = math.pow (PercentDamage, PercentHits)
+ local scaled = _detalhes:Scale (1, 2.15, 1, 100, pow)
+ _tabela[4] = scaled
+ end
+
+ _table_sort (meus_danos, function (_spell1, _spell2) return _spell1[4] > _spell2[4] end)
+
+ for i = 1, 9 do
+ local esta_magia = meus_danos[i]
+ if (esta_magia) then
+ local SpellName, _, Icon = _GetSpellInfo (esta_magia[1])
+ local SpellBoxObject = SpellDetails.SpellButtons [i]
+
+ SpellDetails:ChangeSpellBox (i, esta_magia[1], Icon,
+ "DPS: ".. _detalhes:ToK (_math_floor (esta_magia[3]/MySelf:Tempo())),
+ "SV: ".. _string_format ("%.1f", esta_magia[4]),
+ nil)
+ else
+ SpellDetails:ClearSpellBox (i)
+ end
+ end
+ end
+ end
+
+ function SpellDetails:DetalhesDaMagia (slot)
+
+ local SoloCombatID = _detalhes.SoloTables.CombatID
+
+ if (not SoloCombatID) then
+ return
+ end
+
+ if (not slot) then --> slot é qual dos 9 quadros vai mostrar
+ slot = 1
+ SpellDetails.CurrentSpellSlot = 1
+ SpellDetails.SpellButtons.LastSelected = slot
+ SpellDetails.SpellButtons.selected:SetPoint ("TOPLEFT", SpellDetails.SpellButtons [slot].background, "TOPLEFT", -5, 3)
+ SpellDetails.SpellButtons [slot].background:Show()
+ end
+
+ if (slot ~= SpellDetails.CurrentSpellSlot) then --> se o player clicou em outro quadro
+ SpellDetails.CurrentSpellSlot = slot
+ SpellDetails:ClearBuffTexts()
+ SpellDetails.SpellButtons.LastSelected = slot
+ SpellDetails.SpellButtons.selected:SetPoint ("TOPLEFT", SpellDetails.SpellButtons [slot].background, "TOPLEFT", -5, 3)
+ SpellDetails.SpellButtons [slot].background:Show()
+ end
+
+ local SpellBoxTable = SpellDetails.SpellButtons [slot]
+ local spellid = SpellBoxTable.spellid
+ local CombatTable
+
+ local MySelf
+ if (SoloCombatID == _detalhes:NumeroCombate()) then
+ MySelf = _detalhes.tabela_vigente (_detalhes.SoloTables.Attribute, _detalhes.playername)
+ CombatTable = _detalhes.tabela_vigente
+ else
+ if (_detalhes.SoloTables.CombatID == 0) then
+ return
+ end
+
+ local vigente = _detalhes.tabela_historico.tabelas [_detalhes:NumeroCombate() - SoloCombatID]
+ if (not vigente) then
+ --print ("!Vigente> solo_id = "..SoloCombatID.." <> " .. _detalhes:NumeroCombate() .. " table: " .. (_detalhes:NumeroCombate() - SoloCombatID))
+ return
+ end
+ MySelf = vigente (_detalhes.SoloTables.Attribute, _detalhes.playername)
+ CombatTable = vigente
+ end
+
+ if (not MySelf) then --> caso o jogador não esteja em combate
+ return
+ end
+
+ local habilidade = MySelf.spell_tables._ActorTable [spellid] --> agora tem o objeto classe_TIPO_habilidade
+ if (not habilidade) then --> caso a tabela do jogador não tenha a skill pedida.
+ return
+ end
+
+ local SpellInfoLabels = SpellDetails.SpellInfoLabels --> shortcut
+
+ SpellInfoLabels.total:SetText (Loc ["STRING_DAMAGE"]..": ".._detalhes:comma_value (habilidade.total))
+ SpellInfoLabels.dps:SetText (Loc ["STRING_DPS"]..":".." ".._detalhes:comma_value (_math_floor (habilidade.total/(MySelf:Tempo()))))
+ SpellInfoLabels.porcento:SetText (Loc ["STRING_PERCENT"]..":".." ".. _detalhes:comma_value ( _math_floor (habilidade.total/MySelf.total*100)).."%")
+
+ local SoloDebuffUptime = CombatTable.SoloDebuffUptime
+ if (SoloDebuffUptime) then
+ local DebuffTable = SoloDebuffUptime [spellid]
+ if (DebuffTable) then
+ --SpellInfoLabels.uptime:SetText (Loc ["STRING_UPTIME"]..":".." ".._math_floor (DebuffTable.duration).."s (".._math_floor (DebuffTable.duration/MySelf:Tempo()*100).."%) "..DebuffTable.castedAmt.."/"..DebuffTable.refreshAmt.."/"..DebuffTable.droppedAmt) --> localize-me
+
+ local duration = DebuffTable.duration
+ if (DebuffTable.Active) then
+ duration = duration + (_detalhes._tempo - DebuffTable.start)
+ end
+
+ SpellInfoLabels.uptime:SetText (Loc ["STRING_UPTIME"]..":".." ".._math_floor (duration).."s (".._math_floor (duration/MySelf:Tempo()*100).."%) ") --> localize-me
+ else
+ SpellInfoLabels.uptime:SetText (Loc ["STRING_UPTIME"]..":".." 0") --> localize-me
+ end
+ else
+ SpellInfoLabels.uptime:SetText (Loc ["STRING_UPTIME"]..":".." 0") --> localize-me
+ end
+
+ SpellInfoLabels.critical:SetText (Loc ["STRING_CRIT"]..":".." "..habilidade.c_amt.." (".. _math_floor ( habilidade.c_amt/habilidade.counter*100 ) .."%)") -- /"..habilidade.counter.."
+ if (habilidade.c_amt < 1) then
+ SpellInfoLabels.critical:SetTextColor (0.5, 0.5, 0.5)
+ SpellInfoLabels.critical:SetText (Loc ["STRING_CRIT"]..":".." "..habilidade.c_amt.."/"..habilidade.counter) --> localize-me
+ else
+ SpellInfoLabels.critical:SetTextColor (1, 1, 1)
+ end
+
+ local erros = 0
+ for _, missType in _ipairs (MySelf.missTypes) do
+ local este_erro = habilidade [missType]
+ if (este_erro) then
+ erros = erros + este_erro
+ end
+ end
+
+ SpellInfoLabels.miss:SetText (Loc ["STRING_MISS"]..":".." "..erros.. " (".._string_format ("%.1f", erros/habilidade.counter*100).."%)") --> localize-me
+ if (erros < 1) then
+ SpellInfoLabels.miss:SetTextColor (0.5, 0.5, 0.5)
+ else
+ SpellInfoLabels.miss:SetTextColor (1, 1, 1)
+ end
+
+ SpellInfoLabels.block:SetText (Loc ["STRING_BLOCKED"]..":".." ".. _string_format ("%.1f", habilidade.b_amt/habilidade.counter*100).."%") --> ..habilidade.b_dmg
+ if (habilidade.b_dmg < 1) then
+ SpellInfoLabels.block:SetTextColor (0.5, 0.5, 0.5)
+ else
+ SpellInfoLabels.block:SetTextColor (1, 1, 1)
+ end
+
+ SpellInfoLabels.glancing:SetText ("Glancing: "..habilidade.g_amt.. " (".._string_format ("%.1f", habilidade.g_amt/habilidade.counter*100).."%)") --> localize-me
+ if (habilidade.g_amt < 1) then
+ SpellInfoLabels.glancing:SetTextColor (0.5, 0.5, 0.5)
+ else
+ SpellInfoLabels.glancing:SetTextColor (1, 1, 1)
+ end
+
+ --> BUFFS
+
+ local HabilidadeDetails = habilidade.BuffTable
+ if (not HabilidadeDetails) then
+ print ("!buffs -> !habilidade.BuffTable")
+ return
+ end
+
+ local BuffTextEntry = SpellDetails.BuffTextEntry --> { 1,2,3,4 }
+ --local SoloBuffUptime = _detalhes.SoloTables.SoloBuffUptime
+ local SoloBuffUptime = _detalhes.Buffs.BuffsTable
+
+ for BuffName, BuffTable in _pairs (_detalhes.Buffs.BuffsTable) do
+ local tabela = HabilidadeDetails [BuffName]
+ if (tabela) then
+ local EntryObject = BuffIndex [BuffName]
+ if (EntryObject) then
+
+ local tempo = MySelf:Tempo()
+ local EntryObject = BuffIndex [BuffName]
+ EntryObject.amtdone:SetText ("Hits: "..tabela.counter)
+
+ local duration = BuffTable.duration
+ if (BuffTable.active) then
+ if (not BuffTable.start) then
+ print ("BUFF " .. BuffTable.name.." sem START")
+ else
+ duration = duration + (_detalhes._tempo - BuffTable.start)
+ end
+ end
+ tempo = duration
+
+ --SpellInfoLabels.uptime:SetText (Loc ["STRING_UPTIME"]..":".." ".._math_floor (DebuffTable.duration).."s (".._math_floor (DebuffTable.duration/MySelf:Tempo()*100).."%) "..DebuffTable.castedAmt.."/"..DebuffTable.refreshAmt.."/"..DebuffTable.droppedAmt) --> localize-me
+ EntryObject.uptime:SetText (Loc ["STRING_UPTIME"]..":" .. " " .. _math_floor (tempo/MySelf:Tempo()*100).."%") --me _math_floor (BuffTable.duration).."s ("..
+ EntryObject.dps:SetText ("Dps: ".._detalhes:comma_value (_math_floor (tabela.total/tempo)))
+
+ end
+ end
+ end
+
+ end
+
+end
+
+function SpellDetails:OnEvent (_, event, ...)
+
+ if (event == "ADDON_LOADED") then
+ local AddonName = select (1, ...)
+ if (AddonName == "Details_SpellDetails") then
+
+ if (_G._detalhes) then
+
+ --> create main plugin object
+ CreatePluginFrames (_detalhes_databaseSpellDetails)
+
+ local MINIMAL_DETAILS_VERSION_REQUIRED = 1
+
+ --> Install plugin inside details
+ local install = _G._detalhes:InstallPlugin ("SOLO", Loc ["PLUGIN_NAME"], "Interface\\Icons\\INV_Fabric_Spellweave", SpellDetails, "DETAILS_PLUGIN_SPELL_DETAILS", MINIMAL_DETAILS_VERSION_REQUIRED)
+ if (type (install) == "table" and install.error) then
+ print (install.error)
+ end
+
+ --> Register needed events
+ _G._detalhes:RegisterEvent (SpellDetails, "COMBAT_PLAYER_TIMESTARTED")
+
+ end
+ end
+
+ elseif (event == "PLAYER_LOGOUT") then
+ _detalhes_databaseSpellDetails = SpellDetails.data
+ end
+end
diff --git a/plugins/Details_SpellDetails/Details_SpellDetails.toc b/plugins/Details_SpellDetails/Details_SpellDetails.toc
new file mode 100644
index 00000000..a6113c73
--- /dev/null
+++ b/plugins/Details_SpellDetails/Details_SpellDetails.toc
@@ -0,0 +1,15 @@
+## Interface: 50300
+## Title: Details Spells (plugin)
+## Notes: Plugin for Details
+## SavedVariablesPerCharacter: _detalhes_databaseSpellDetails
+## RequiredDeps: Details
+## OptionalDeps: Ace3
+
+#@no-lib-strip@
+embeds.xml
+#@end-no-lib-strip@
+
+enUS.lua
+ptBR.lua
+
+Details_SpellDetails.lua
\ No newline at end of file
diff --git a/plugins/Details_SpellDetails/Libs/AceLocale-3.0/AceLocale-3.0.lua b/plugins/Details_SpellDetails/Libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 00000000..2ecc0cb8
--- /dev/null
+++ b/plugins/Details_SpellDetails/Libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/plugins/Details_SpellDetails/Libs/AceLocale-3.0/AceLocale-3.0.xml b/plugins/Details_SpellDetails/Libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 00000000..d69dbb13
--- /dev/null
+++ b/plugins/Details_SpellDetails/Libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/Details_SpellDetails/Libs/LibStub/LibStub.lua b/plugins/Details_SpellDetails/Libs/LibStub/LibStub.lua
new file mode 100644
index 00000000..f5fc9192
--- /dev/null
+++ b/plugins/Details_SpellDetails/Libs/LibStub/LibStub.lua
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ -- LibStub:NewLibrary(major, minor)
+ -- major (string) - the major version of the library
+ -- minor (string or number ) - the minor version of the library
+ --
+ -- returns nil if a newer or same version of the lib is already present
+ -- returns empty library object or old library object if upgrade is needed
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ -- LibStub:GetLibrary(major, [silent])
+ -- major (string) - the major version of the library
+ -- silent (boolean) - if true, library is optional, silently return nil if its not found
+ --
+ -- throws an error if the library can not be found (except silent is set)
+ -- returns the library object if found
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ -- LibStub:IterateLibraries()
+ --
+ -- Returns an iterator for the currently registered libraries
+ function LibStub:IterateLibraries()
+ return pairs(self.libs)
+ end
+
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/plugins/Details_SpellDetails/Libs/LibStub/LibStub.toc b/plugins/Details_SpellDetails/Libs/LibStub/LibStub.toc
new file mode 100644
index 00000000..c3dc3656
--- /dev/null
+++ b/plugins/Details_SpellDetails/Libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 40200
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: r95
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/plugins/Details_SpellDetails/Libs/LibStub/tests/test.lua b/plugins/Details_SpellDetails/Libs/LibStub/tests/test.lua
new file mode 100644
index 00000000..645a08b1
--- /dev/null
+++ b/plugins/Details_SpellDetails/Libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/plugins/Details_SpellDetails/Libs/LibStub/tests/test2.lua b/plugins/Details_SpellDetails/Libs/LibStub/tests/test2.lua
new file mode 100644
index 00000000..af431dd3
--- /dev/null
+++ b/plugins/Details_SpellDetails/Libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib doesn't exist yet, by iterating through all the libraries
+ assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+ if major == "MyLib" then -- we found it!
+ count = count +1
+ assert(rawequal(library, lib)) -- verify that the references are equal
+ end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/plugins/Details_SpellDetails/Libs/LibStub/tests/test3.lua b/plugins/Details_SpellDetails/Libs/LibStub/tests/test3.lua
new file mode 100644
index 00000000..01aabb8d
--- /dev/null
+++ b/plugins/Details_SpellDetails/Libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/plugins/Details_SpellDetails/Libs/LibStub/tests/test4.lua b/plugins/Details_SpellDetails/Libs/LibStub/tests/test4.lua
new file mode 100644
index 00000000..15a9c9cd
--- /dev/null
+++ b/plugins/Details_SpellDetails/Libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/plugins/Details_SpellDetails/embeds.xml b/plugins/Details_SpellDetails/embeds.xml
new file mode 100644
index 00000000..a5cb37d2
--- /dev/null
+++ b/plugins/Details_SpellDetails/embeds.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/plugins/Details_SpellDetails/enUS.lua b/plugins/Details_SpellDetails/enUS.lua
new file mode 100644
index 00000000..060e8932
--- /dev/null
+++ b/plugins/Details_SpellDetails/enUS.lua
@@ -0,0 +1,20 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_SpellDetails", "enUS", true)
+
+if (not Loc) then
+ return
+end
+
+Loc ["PLUGIN_NAME"] = "Spell Details"
+Loc ["STRING_TOOSHORT"] = "Combat time was too short \n and the graph cannot be generated."
+
+Loc ["STRING_DAMAGE"] = "DMG"
+Loc ["STRING_DPS"] = "DPS"
+Loc ["STRING_TEMPO"] = "TIME"
+Loc ["STRING_PERCENT"] = "Percent"
+Loc ["STRING_UPTIME"] = "Uptime"
+Loc ["STRING_CRIT"] = "Critical"
+Loc ["STRING_MISS"] = "Miss"
+Loc ["STRING_BLOCKED"] = "Blocked"
+Loc ["STRING_GLANCING"] = "Glancing"
+Loc ["STRING_DEBUFFNAME"] = "insert buff name"
+Loc ["STRING_INCOMBAT"] = "You are in combat"
diff --git a/plugins/Details_SpellDetails/images/solo_bg.tga b/plugins/Details_SpellDetails/images/solo_bg.tga
new file mode 100644
index 00000000..0b5dbe06
Binary files /dev/null and b/plugins/Details_SpellDetails/images/solo_bg.tga differ
diff --git a/plugins/Details_SpellDetails/ptBR.lua b/plugins/Details_SpellDetails/ptBR.lua
new file mode 100644
index 00000000..f88d3f98
--- /dev/null
+++ b/plugins/Details_SpellDetails/ptBR.lua
@@ -0,0 +1,21 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_SpellDetails", "ptBR")
+
+if (not Loc) then
+ return
+end
+
+Loc ["PLUGIN_NAME"] = "Detalhes das Magias"
+Loc ["STRING_TOOSHORT"] = "O tempo do combat foi curto\n e o grafico nao pode ser gerado."
+
+Loc ["STRING_DAMAGE"] = "Dano"
+Loc ["STRING_DPS"] = "Dps"
+Loc ["STRING_TEMPO"] = "Tempo"
+Loc ["STRING_PERCENT"] = "Porcentagem"
+Loc ["STRING_UPTIME"] = "Ativo"
+Loc ["STRING_CRIT"] = "Critico"
+Loc ["STRING_MISS"] = "Erros"
+Loc ["STRING_BLOCKED"] = "Bloqueios"
+
+Loc ["STRING_GLANCING"] = "Golpes Fracos"
+Loc ["STRING_DEBUFFNAME"] = "insira o nome do buff"
+Loc ["STRING_INCOMBAT"] = "Voce esta em combate"
diff --git a/plugins/Details_TimeAttack/Details_TimeAttack.lua b/plugins/Details_TimeAttack/Details_TimeAttack.lua
new file mode 100644
index 00000000..301801b6
--- /dev/null
+++ b/plugins/Details_TimeAttack/Details_TimeAttack.lua
@@ -0,0 +1,690 @@
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ("Details_TimeAttack")
+
+local _GetTime = GetTime --> wow api local
+local _UFC = UnitAffectingCombat --> wow api local
+local _IsInRaid = IsInRaid --> wow api local
+local _IsInGroup = IsInGroup --> wow api local
+local _UnitAura = UnitAura --> wow api local
+
+local _math_floor = math.floor --> lua library local
+local _cstr = string.format --> lua library local
+
+--> Create the plugin Object
+local TimeAttack = _detalhes:NewPluginObject ("Details_TimeAttack")
+--> Main Frame
+local TimeAttackFrame = TimeAttack.Frame
+
+local function CreatePluginFrames (data)
+
+ --> catch Details! main object
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+ local instance --> shortcut for details instance wich are holding solo plugins
+ local GameCooltip = GameCooltip
+
+
+ --> default rank table
+ TimeAttack.data = data or {time = 180, dps = 0, history = {}}
+ TimeAttack.try = 1
+
+ --> OnEvent Table
+ function TimeAttack:OnDetailsEvent (event)
+ if (event == "HIDE") then --> plugin hidded, disabled
+ TimeAttackFrame:SetScript ("OnUpdate", nil)
+ TimeAttack:Cancel()
+
+ elseif (event == "SHOW") then
+ instance = _detalhes.SoloTables.instancia --> update wich instance solo mode are running
+ DetailsFrameWork:RegisterForDetailsMove (DetailsTimeAttackHistoryBackground, instance)
+
+ elseif (event == "COMBAT_PLAYER_ENTER") then --> combat started
+ TimeAttack:ScheduleTimer ("TimeAttackPluginStart", 2)
+
+ end
+ end
+
+------------- Build TimeAttack Object ------------------------------------------------------------------------------------------------
+
+ --> main frame and background texture
+ TimeAttackFrame:SetResizable (false) --> cant resize, this is a fixed size
+ TimeAttackFrame:SetWidth (300) --> need to be 300x300 to fit details window
+ TimeAttackFrame:SetHeight (300) --> need to be 300x300 to fit details window
+
+ --> default background picture, will hold the actor spec background, like old school talent frame
+ local background = TimeAttackFrame:CreateTexture (nil, "background")
+
+ --> some times the current spec isn't avaliable yet, so we try to catch 5 seconds after character logon
+ function _detalhes:TimeAttackStartupBackground()
+ local spec = GetSpecialization()
+ if (spec) then
+ local id, name, description, icon, _background, role = GetSpecializationInfo (spec)
+ if (_background) then
+ background:SetTexture ("Interface\\TALENTFRAME\\".._background)
+ end
+ end
+ end
+ TimeAttack:ScheduleTimer ("TimeAttackStartupBackground", 5)
+
+ background:SetTexCoord (0, 1, 0, 0.705078125)
+ background:SetPoint ("topleft", TimeAttackFrame, "topleft", 2, 0)
+ background:SetPoint ("bottomright", TimeAttackFrame, "bottomright", -2, 0)
+ background:SetVertexColor (.3, .3, .3, 1)
+ background:SetDrawLayer ("background", 1)
+ TimeAttack.BackgroundTex = background
+
+ --> Time attack string
+ local title = DetailsFrameWork:NewLabel (TimeAttackFrame, TimeAttackFrame, nil, "title", "Time Attack", "QuestFont_Super_Huge", _, {1, 1, 1, 1})
+ title:SetPoint ("topleft", TimeAttackFrame, 5, -8)
+
+ --> background glow bellow title string
+ local texturetitle = TimeAttackFrame:CreateTexture (nil, "artwork")
+ texturetitle:SetTexture ("Interface\\ACHIEVEMENTFRAME\\UI-Achievement-Borders")
+ texturetitle:SetTexCoord (0.287109375, 1, 0.26, 0.5)
+ texturetitle:SetVertexColor (1, 1, 1, .5)
+ texturetitle:SetPoint ("topleft", TimeAttackFrame)
+ texturetitle:SetWidth (300)
+ texturetitle:SetHeight (128)
+
+ --> help button
+ --> after 10 logins on the character this help button will not be show any more
+ if (_detalhes.tutorial.main_help_button < 10) then
+ local help = DetailsFrameWork:NewHelp (TimeAttackFrame, 280, 280, 0, -20, 40, 40)
+ help:SetPoint ("topright", TimeAttackFrame, "topright", 8, 9)
+ help:AddHelp (300, 300, 0, 0, 138, -138, Loc ["STRING_HELP"])
+ help:SetFrameLevel (TimeAttackFrame:GetFrameLevel()+2)
+ end
+
+ --> a dark blue image on bottom of window
+ local texturedown = TimeAttackFrame:CreateTexture (nil, "artwork")
+ texturedown:SetTexture ("Interface\\PetBattles\\Weather-Darkness")
+ texturedown:SetTexCoord (.15, .85, 1, 0)
+ texturedown:SetVertexColor (1, 1, 1, .25)
+ texturedown:SetPoint ("bottomright", TimeAttackFrame)
+ texturedown:SetWidth (300)
+
+ --> text informing about the amount of time
+ local TimeDesc = DetailsFrameWork:NewLabel (TimeAttackFrame, TimeAttackFrame, nil, "TimeDesc", Loc ["STRING_TIME_SELECTION"])
+ TimeDesc:SetPoint ("topleft", TimeAttackFrame, 15, -260)
+ --> slider
+ local TimeAmount = DetailsFrameWork:NewSlider (TimeAttackFrame, nil, "DetailsTimeAttackTimeSelect", "TimeSelect", 270, 20, 30, 330, 10, TimeAttack.data.time)
+ --local TimeAmount = DetailsFrameWork:NewSlider2 (TimeAttackFrame, "DetailsTimeAttackTimeSelect", "TimeSelect", 270, 20, 30, 330, 10, TimeAttack.data.time)
+ TimeAmount:SetPoint ("topleft", TimeAttackFrame, 15, -270)
+ TimeAmount.OnChangeHook = function() TimeAttack.data.time = TimeAmount.value end
+
+ --> main time/damage/dps texts
+ local clock = DetailsFrameWork:NewLabel (TimeAttackFrame, TimeAttackFrame, nil, "TIMER", "00:00:00", "GameFontHighlightLarge")
+ clock:SetPoint ("center", TimeAttackFrame, 0, -20)
+ local damage = DetailsFrameWork:NewLabel (TimeAttackFrame, TimeAttackFrame, nil, "DAMAGE", "00.000.000", "GameFontHighlightLarge")
+ damage:SetPoint ("center", TimeAttackFrame, 0, -40)
+ local persecond = DetailsFrameWork:NewLabel (TimeAttackFrame, TimeAttackFrame, nil, "DPS", "000.000", "GameFontHighlightLarge")
+ persecond:SetPoint ("center", TimeAttackFrame, 0, -60)
+
+ --> two yellow rows
+ local barraUP = TimeAttackFrame:CreateTexture (nil, "overlay")
+ barraUP:SetTexture ("Interface\\TALENTFRAME\\talent-main")
+ barraUP:SetWidth (300)
+ barraUP:SetHeight (3)
+ barraUP:SetPoint ("topleft", TimeAttackFrame, 0, -49)
+ barraUP:SetTexCoord (0, 0.7890625, 0.248046875, 0.264625)
+
+ local barraDOWN = TimeAttackFrame:CreateTexture (nil, "overlay")
+ barraDOWN:SetTexture ("Interface\\TALENTFRAME\\talent-main")
+ barraDOWN:SetWidth (300)
+ barraDOWN:SetHeight (3)
+ barraDOWN:SetPoint ("topleft", TimeAttackFrame, 0, -148)
+ barraDOWN:SetTexCoord (0, 0.7890625, 0.248046875, 0.264625)
+
+ --> background between the two yellow rows
+ local bg1 = DetailsFrameWork:NewPanel (TimeAttackFrame, _, "DetailsTimeAttackHistoryBackground", _, 295, 100)
+ bg1:SetBackdrop ({tile = true, tileSize = 16, bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"})
+ bg1:SetBackdropColor ({.95, .95, .95, .6})
+ bg1:SetPoint ("center", TimeAttackFrame, 0, 50)
+ --> default panel options come with enabled gradiens, we want to disable this
+ bg1:DisableGradient()
+
+ --> this is the main table wich will hold the times and labels also is a class
+ local HistoryPanelObject = {
+ NowShowing = 1, --> 1 for recently 2 for saved
+ LabelsCreated = {},
+ Recently = {},
+ Hystory = TimeAttack.data.history
+ }
+ HistoryPanelObject.__index = HistoryPanelObject
+
+ --> build the button to switch between recent times and saved times
+ local displayTipes = {Loc ["STRING_RECENTLY"], Loc ["STRING_SAVED"]}
+ local switchButton
+ function changedisplay()
+ HistoryPanelObject.NowShowing = math.abs (HistoryPanelObject.NowShowing-3)
+ HistoryPanelObject:Refresh()
+ switchButton.text = displayTipes [HistoryPanelObject.NowShowing]
+ end
+
+ switchButton = DetailsFrameWork:NewButton (TimeAttackFrame, nil, "DetailsTimeAttackSwitchButton", "switchButton", 70, 15, changedisplay)
+ switchButton:InstallCustomTexture()
+ switchButton:SetPoint (227, -35)
+ switchButton.text = displayTipes [HistoryPanelObject.NowShowing]
+
+ local leftSwitchTexture = switchButton:CreateTexture (nil, "overlay")
+ leftSwitchTexture:SetTexture ("Interface\\TALENTFRAME\\talent-main")
+ leftSwitchTexture:SetTexCoord (0.13671875, 0.25, 0.486328125, 0.576171875)
+ leftSwitchTexture:SetPoint ("left", switchButton.button, 0, 0)
+ leftSwitchTexture:SetWidth (10)
+ leftSwitchTexture:SetHeight (17)
+
+ local rightSwitchTexture = switchButton:CreateTexture (nil, "overlay")
+ rightSwitchTexture:SetTexture ("Interface\\TALENTFRAME\\talent-main")
+ rightSwitchTexture:SetTexCoord (0.01953125, 0.13671875, 0.486328125, 0.576171875)
+ rightSwitchTexture:SetPoint ("right", switchButton.button, 0, 0)
+ rightSwitchTexture:SetWidth (10)
+ rightSwitchTexture:SetHeight (17)
+
+ --> remove a saved or recently time
+ local remove = function (index)
+ if (HistoryPanelObject.NowShowing == 1) then --> recently
+ table.remove (HistoryPanelObject.Recently, index)
+ else --> history
+ table.remove (TimeAttack.data.history, index)
+ end
+ HistoryPanelObject:Refresh()
+ end
+
+ --> save a recently time
+ local save = function (RecentlyIndex)
+ if (RecentlyIndex) then --> click on any label
+ local ToSaveTimeObject = HistoryPanelObject.Recently [RecentlyIndex]
+ if (ToSaveTimeObject and not ToSaveTimeObject.FinishSaved) then
+ local NewSave = {}
+ NewSave.DamageDone = ToSaveTimeObject.FinishDamage
+ NewSave.Dps = ToSaveTimeObject.FinishDps
+ NewSave.Time = ToSaveTimeObject.FinishTime
+ NewSave.ItemLevel = ToSaveTimeObject.FinishIlevel
+ NewSave.Date = ToSaveTimeObject.Date
+ NewSave.note = ToSaveTimeObject.note
+
+ table.insert (TimeAttack.data.history, 1, NewSave)
+ table.remove (TimeAttack.data.history, 25)
+ HistoryPanelObject:AddHistory (NewSave)
+ ToSaveTimeObject.FinishSaved = true
+ HistoryPanelObject:Refresh()
+
+ if (TimeAttack.Time == ToSaveTimeObject) then
+ TimeAttackFrame ["SaveButton"]:Disable()
+ end
+ end
+
+ elseif (TimeAttack.Time and TimeAttack.Time.FinishOkey and not TimeAttack.Time.FinishSaved) then --> click on SAVE button
+ local NewSave = {}
+ NewSave.DamageDone = TimeAttack.Time.FinishDamage
+ NewSave.Dps = TimeAttack.Time.FinishDps
+ NewSave.Time = TimeAttack.Time.FinishTime
+ NewSave.ItemLevel = TimeAttack.Time.FinishIlevel
+ NewSave.Date = TimeAttack.Time.Date
+ TimeAttack.Time.FinishSaved = true
+ table.insert (TimeAttack.data.history, 1, NewSave)
+ table.remove (TimeAttack.data.history, 25)
+ HistoryPanelObject:AddHistory (NewSave)
+ HistoryPanelObject:Refresh()
+ TimeAttackFrame ["SaveButton"]:Disable()
+ end
+ end
+
+ --> save button
+
+ local SaveButton = DetailsFrameWork:NewButton (TimeAttackFrame, nil, "DetailsTimeAttackSaveButton", "SaveButton", 70, 20, save)
+ SaveButton:InstallCustomTexture()
+ SaveButton.text = Loc ["STRING_SAVE"]
+ SaveButton:SetPoint ("center", 0, -90)
+ SaveButton:Disable()
+
+ function HistoryPanelObject:AddRecently (data)
+ table.insert (self.Recently, 1, data)
+ table.remove (self.Recently, 24)
+ if (self.NowShowing == 1) then
+ HistoryPanelObject:Refresh()
+ end
+ end
+
+ function HistoryPanelObject:AddHistory (data)
+ if (self.NowShowing == 2) then
+ HistoryPanelObject:Refresh()
+ end
+ end
+
+ --> report button
+ local reportFunc = function (IsCurrent, IsReverse, AmtLines) --> localize-me
+ local lines = { Loc ["STRING_REPORT"]..":",
+ TimeAttack:comma_value (TimeAttack.Time.FinishDamage) .. " " .. Loc ["STRING_DAMAGEOVER"] .. " " .. TimeAttack.Time.FinishTime .. " " .. Loc ["STRING_SECONDS"] .. ".",
+ Loc ["STRING_AVERAGEDPS"] .. " " .. TimeAttack:comma_value (_math_floor (TimeAttack.Time.FinishDps)) .. " " .. Loc ["STRING_WITH"] .. " " .. _cstr ("%.1f", TimeAttack.Time.FinishIlevel) .. " " .. Loc ["STRING_ITEMLEVEL"] .. "."}
+ TimeAttack:SendReportLines (lines)
+ end
+
+ --[1] fucntion wich will build report lines after click on 'Send Button' [2] enable current button [3] enable reverse button
+ local ReportButton = DetailsFrameWork:NewButton (TimeAttackFrame, nil, "DetailsTimeAttackReportButton", "ReportButton", 20, 20, function() TimeAttack:SendReportWindow (reportFunc) end)
+ ReportButton.texture = "Interface\\COMMON\\VOICECHAT-ON"
+ ReportButton:SetPoint ("left", DetailsTimeAttackSaveButton, "right", -10, 0)
+ ReportButton:Hide()
+
+--------------> general functions: ----------------
+
+ function HistoryPanelObject:RefreshLabel (AttemptTable, AlreadySaved, First)
+
+ self.table = AttemptTable
+ if (AlreadySaved) then --> showing historic
+ self.remove:SetPoint ("left", self.background.frame, "left")
+ self.note:SetPoint ("left", self.remove.button, "right")
+ if (AttemptTable.note) then
+ self.note:SetNormalTexture ("Interface\\Buttons\\UI-GuildButton-PublicNote-Up")
+ self.note.tooltip = AttemptTable.note
+ else
+ self.note:SetNormalTexture ("Interface\\Buttons\\UI-GuildButton-PublicNote-Disabled")
+ self.note.tooltip = Loc ["STRING_SETNOTE"]
+ end
+ self.save:Hide()
+ local diamesano = string.gsub (AttemptTable.Date, "(.-)%s", "")
+ self.text:SetText (diamesano)
+
+ elseif (not AttemptTable.FinishSaved) then --> não foi salvo ainda
+ self.remove:Show()
+ self.save:Show()
+ self.note:SetPoint ("left", self.save.button, "right")
+ if (AttemptTable.note) then
+ self.note:SetNormalTexture ("Interface\\Buttons\\UI-GuildButton-PublicNote-Up")
+ self.note.tooltip = AttemptTable.note
+ else
+ self.note:SetNormalTexture ("Interface\\Buttons\\UI-GuildButton-PublicNote-Disabled")
+ self.note.tooltip = Loc ["STRING_SETNOTE"]
+ end
+ if (First) then
+ self.text:SetText ("-".. TimeAttack:ToK (First-AttemptTable.FinishDamage).." (#"..AttemptTable.N..")")
+ else
+ self.text:SetText (TimeAttack:ToK (AttemptTable.FinishDamage).." (#"..AttemptTable.N..")")
+ end
+ else --> ta mostrando recentes e ja foi salvo
+ self.remove:Show()
+ self.note:SetPoint ("left", self.remove.button, "right")
+ if (AttemptTable.note) then
+ self.note:SetNormalTexture ("Interface\\Buttons\\UI-GuildButton-PublicNote-Up")
+ self.note.tooltip = AttemptTable.note
+ else
+ self.note:SetNormalTexture ("Interface\\Buttons\\UI-GuildButton-PublicNote-Disabled")
+ self.note.tooltip = Loc ["STRING_SETNOTE"]
+ end
+ self.save:Hide()
+ if (First) then
+ self.text:SetText ("-".. TimeAttack:ToK (First-AttemptTable.FinishDamage).." (#"..AttemptTable.N..")")
+ else
+ self.text:SetText (TimeAttack:ToK (AttemptTable.FinishDamage).." (#"..AttemptTable.N..")")
+ end
+ end
+ self.background:Show()
+ end
+
+ local OnEnterHook = function (self, arg2, arg3)
+
+ self = self.BoxObject
+
+ if (HistoryPanelObject.NowShowing == 1) then --> recently
+
+ GameCooltip:Reset()
+
+ local TimeObject = HistoryPanelObject.Recently [self.index]
+
+ GameCooltip:AddLine (TimeAttack:comma_value (TimeObject.FinishDamage))
+ GameCooltip:AddIcon ("Interface\\TARGETINGFRAME\\PetBadge-Undead")
+
+ GameCooltip:AddLine (TimeAttack:comma_value (math.floor (TimeObject.FinishDps)))
+ GameCooltip:AddIcon ("Interface\\TARGETINGFRAME\\PetBadge-Elemental")
+
+ GameCooltip:AddLine (TimeObject.FinishTime.." " .. Loc ["STRING_SECONDS"])
+ GameCooltip:AddIcon ("Interface\\TARGETINGFRAME\\PetBadge-Mechanical")
+
+ GameCooltip:AddLine (string.format ("%.1f", TimeObject.FinishIlevel))
+ GameCooltip:AddIcon ("Interface\\TARGETINGFRAME\\PetBadge-Humanoid")
+
+ GameCooltip:SetOption ("TextHeightMod", -4)
+ GameCooltip:ShowCooltip (self.background, "tooltip")
+
+ else --> history
+
+ GameCooltip:Reset()
+
+ local TimeObject = TimeAttack.data.history [self.index]
+
+ GameCooltip:AddLine (TimeAttack:comma_value (TimeObject.DamageDone))
+ GameCooltip:AddIcon ("Interface\\TARGETINGFRAME\\PetBadge-Undead")
+
+ GameCooltip:AddLine (TimeAttack:comma_value (math.floor (TimeObject.Dps)))
+ GameCooltip:AddIcon ("Interface\\TARGETINGFRAME\\PetBadge-Elemental")
+
+ GameCooltip:AddLine (TimeObject.Time.." " .. Loc ["STRING_SECONDS"])
+ GameCooltip:AddIcon ("Interface\\TARGETINGFRAME\\PetBadge-Mechanical")
+
+ GameCooltip:AddLine (string.format ("%.1f", TimeObject.ItemLevel))
+ GameCooltip:AddIcon ("Interface\\TARGETINGFRAME\\PetBadge-Humanoid")
+
+ GameCooltip:SetOption ("TextHeightMod", -4)
+ GameCooltip:ShowCooltip (self.background, "tooltip")
+ end
+ end
+
+ local OnLeaveHook= function (self)
+ GameCooltip:ShowMe (false)
+ end
+
+ TimeAttack.HistoryX = 4
+ TimeAttack.HistoryY = -52
+
+ local WriteNoteStop = function()
+
+ local editbox = TimeAttackFrame ["NoteEntry"]
+
+ local texto = editbox:GetText()
+ if (string.len (texto) > 0) then
+ if (HistoryPanelObject.NowShowing == 1) then --> recently
+ HistoryPanelObject.Recently [editbox.editing].note = texto
+ else
+ TimeAttack.data.history [editbox.editing].note = texto
+ end
+ end
+ editbox:SetText ("")
+ editbox.editing = nil
+ editbox:Hide()
+ switchButton:Enable()
+
+ if (TimeAttack.Time and TimeAttack.Time.FinishOkey and not TimeAttack.Time.FinishSaved) then
+ SaveButton:Enable()
+ ReportButton:Show()
+ end
+
+ HistoryPanelObject:Refresh()
+ end
+
+ --local NoteInsertField = DetailsFrameWork:NewTextBox (TimeAttackFrame, TimeAttackFrame, "NoteEntry", WriteNoteStop, _, _, 296, 15)
+ local NoteInsertField = DetailsFrameWork:NewTextEntry (TimeAttackFrame, nil, "DetailsTimeAttackNoteEntry", "NoteEntry", 296, 15, WriteNoteStop)
+ NoteInsertField:SetBackdropColor (0, 0, 0, 1)
+ NoteInsertField:SetPoint ("bottom", barraDOWN, "top", 0, 0)
+ NoteInsertField:SetFrameLevel (TimeAttackFrame:GetFrameLevel()+3)
+ NoteInsertField:Hide()
+
+ NoteInsertField.OnEscapePressedHook = function()
+ NoteInsertField.editing = nil
+ NoteInsertField:SetText ("")
+ switchButton:Enable()
+ NoteInsertField:Hide()
+
+ if (TimeAttack.Time and TimeAttack.Time.FinishOkey and not TimeAttack.Time.FinishSaved) then
+ SaveButton:Enable()
+ ReportButton:Show()
+ end
+
+ end
+
+ local WriteNoteStart = function (index)
+
+ if (HistoryPanelObject.NowShowing == 1 and HistoryPanelObject.Recently [index].note) then --> recently
+ NoteInsertField:SetText (HistoryPanelObject.Recently [index].note)
+ elseif (HistoryPanelObject.NowShowing == 2 and TimeAttack.data.history [index].note) then
+ NoteInsertField:SetText (TimeAttack.data.history [index].note)
+ else
+ NoteInsertField:SetText ("")
+ end
+
+ NoteInsertField.editing = index
+ NoteInsertField:Show()
+ NoteInsertField:SetFocus()
+ switchButton:Disable()
+ SaveButton:Disable()
+ ReportButton:Hide()
+ end
+
+ function HistoryPanelObject:CreateNewLabel (index)
+
+ local LabelBoxObject = {}
+ self.LabelsCreated [#self.LabelsCreated+1] = LabelBoxObject
+ setmetatable (LabelBoxObject, HistoryPanelObject)
+ LabelBoxObject.index = index
+
+ local LabelBackground = DetailsFrameWork:NewPanel (bg1.frame, bg1.frame, "DetailsTimeAttackPanel"..index, "label"..index, 95, 12,
+ {tile = true, tileSize = 16, bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background"}, {.5, .5, .5, 1})
+
+ LabelBackground:SetPoint ("topleft", TimeAttackFrame, TimeAttack.HistoryX, TimeAttack.HistoryY)
+ LabelBackground.frame.Gradient.OnEnter = {.9, .9, .9, 1}
+ LabelBackground.frame:SetFrameLevel (bg1.frame:GetFrameLevel()+1)
+
+ LabelBackground:SetHook ("OnEnter", OnEnterHook)
+ LabelBackground:SetHook ("OnLeave", OnLeaveHook)
+
+ LabelBackground.frame.BoxObject = LabelBoxObject
+
+ TimeAttack.HistoryY = TimeAttack.HistoryY - 12
+ if (TimeAttack.HistoryY <= -148) then
+ TimeAttack.HistoryY = -52
+ TimeAttack.HistoryX = TimeAttack.HistoryX + 99
+ end
+
+ local LabelText = DetailsFrameWork:NewLabel (LabelBackground.frame, LabelBackground.frame, nil, "text", "000.000", "GameFontHighlightSmall")
+ LabelText:SetPoint ("right", LabelBackground.frame, 0, 0)
+ LabelText:SetJustifyH ("right")
+
+ --local LabelRemoveButton = DetailsFrameWork:NewDetailsButton (LabelBackground.frame, LabelBackground.frame, _, remove, index, index, 10, 10, "Interface\\PetBattles\\DeadPetIcon")
+ local LabelRemoveButton = DetailsFrameWork:NewButton (LabelBackground.frame, nil, "DetailsTimeAttackRemoveButton"..index, "RemoveButton"..index, 10, 10, remove, index, index, "Interface\\PetBattles\\DeadPetIcon")
+ LabelRemoveButton:SetPoint ("left", LabelBackground.frame)
+ LabelRemoveButton.tooltip = Loc ["STRING_REMOVERECORD"]
+
+ --local LabelSaveButton = DetailsFrameWork:NewDetailsButton (LabelBackground.frame, LabelBackground.frame, _, save, index, index, 10, 10, "Interface\\Scenarios\\ScenarioIcon-Check")
+ local LabelSaveButton = DetailsFrameWork:NewButton (LabelBackground.frame, nil, "DetailsTimeAttackSaveButton"..index, "SaveButton"..index, 10, 10, save, index, index, "Interface\\Scenarios\\ScenarioIcon-Check")
+ LabelSaveButton:SetPoint ("left", LabelRemoveButton.button, "right", 0, 0)
+ LabelSaveButton.tooltip = Loc ["STRING_SAVERECORD"]
+
+ --local LabelSetnoteButton = DetailsFrameWork:NewDetailsButton (LabelBackground.frame, LabelBackground.frame, _, WriteNoteStart, index, index, 10, 10, "Interface\\Buttons\\UI-GuildButton-PublicNote-Disabled")
+ local LabelSetnoteButton = DetailsFrameWork:NewButton (LabelBackground.frame, nil, "DetailsTimeAttackSetNoteButton"..index, "SetNoteButton"..index, 10, 10, WriteNoteStart, index, index, "Interface\\Buttons\\UI-GuildButton-PublicNote-Disabled")
+ LabelSetnoteButton:SetPoint ("left", LabelSaveButton.button, "right", 0, 0)
+ LabelSetnoteButton.tooltip = Loc ["STRING_SETNOTE"]
+
+ LabelBoxObject.text = LabelText
+ LabelBoxObject.background = LabelBackground
+ LabelBoxObject.remove = LabelRemoveButton
+ LabelBoxObject.save = LabelSaveButton
+ LabelBoxObject.note = LabelSetnoteButton
+ LabelBoxObject.HaveNote = false
+
+ return LabelBoxObject
+ end
+
+ function HistoryPanelObject:Refresh()
+ if (self.NowShowing == 1) then --> recent
+
+ --> sort by damage done
+ table.sort (self.Recently, function (a,b) return a.FinishDamage > b.FinishDamage end)
+ local first = self.Recently [1]
+ if (first) then
+ first = first.FinishDamage
+ end
+ for index, AttemptTable in ipairs (self.Recently) do
+
+ local thisLabel = self.LabelsCreated [index]
+ if (not thisLabel) then
+ thisLabel = self:CreateNewLabel (index)
+ end
+ if (index == 1) then
+ thisLabel:RefreshLabel (AttemptTable, false)
+ else
+ thisLabel:RefreshLabel (AttemptTable, false, first)
+ end
+ end
+
+ for amt = #self.Recently+1, #self.LabelsCreated do
+ local thisLabel = self.LabelsCreated [amt]
+ thisLabel.background:Hide()
+ end
+
+ elseif (self.NowShowing == 2) then
+ for index, AttemptTable in ipairs (TimeAttack.data.history) do
+ local thisLabel = self.LabelsCreated [index]
+ if (not thisLabel) then
+ thisLabel = self:CreateNewLabel (index)
+ end
+ thisLabel:RefreshLabel (AttemptTable, true)
+ end
+
+ for amt = #TimeAttack.data.history+1, #self.LabelsCreated do
+ local thisLabel = self.LabelsCreated [amt]
+ thisLabel.background:Hide()
+ end
+ end
+ end
+
+ HistoryPanelObject:Refresh()
+
+ local update = 0
+ local player --> short cut for Player Actor Object
+
+ --> Cancel function
+ function TimeAttack:Cancel()
+ if (TimeAttack.Time and TimeAttack.Time.Working) then
+ TimeAttack.Time.Working = false
+ TimeAttack.Time.Done = true
+ end
+ TimeAttack.Frame:SetScript ("OnUpdate", nil)
+ end
+
+ --> Exec function
+ local DoTimeAttack = function (self, elapsed)
+
+ TimeAttack.Time.Elapsed = TimeAttack.Time.Elapsed + elapsed
+ update = update + elapsed
+ if (_GetTime() > TimeAttack.Time.EndTime) then --> reached the end time
+ if (TimeAttack.Time.Working and not TimeAttack.Time.Done) then
+ TimeAttack:Cancel()
+ TimeAttack:Finish()
+ end
+ else
+ --> aqui vem as funções que verificam se o jogador esta em grupo ou se tem algum buff proibido
+ TimeAttack.Time.Tick = TimeAttack.Time.Tick + elapsed
+ if (TimeAttack.Time.Tick > 1) then
+ TimeAttack.Time.Tick = 0
+ if (not _UFC ("player")) then --> isn't in combat
+ TimeAttack:Cancel()
+ end
+ else
+ if (update > 0.050) then
+ --> Update Timer Here
+
+ local minutos, segundos = _math_floor (TimeAttack.Time.Elapsed/60), _math_floor (TimeAttack.Time.Elapsed%60)
+
+ if (segundos < 10) then
+ segundos = "0"..segundos
+ end
+
+ local mili = _cstr ("%.2f", TimeAttack.Time.Elapsed-_math_floor (TimeAttack.Time.Elapsed))*100
+ if (mili < 10) then
+ mili = "0"..mili
+ end
+
+ clock:SetText ("0".. minutos .. ":"..segundos ..":"..mili)
+ damage:SetText (TimeAttack:comma_value (player.total))
+
+ if (TimeAttack.Time.Elapsed > 3) then
+ persecond:SetText (TimeAttack:comma_value (_math_floor (player.total/TimeAttack.Time.Elapsed)))
+ end
+
+ update = 0
+ end
+ end
+ end
+
+ end
+
+
+ --> When the time is gone
+ function TimeAttack:Finish()
+ TimeAttack.Time.FinishOkey = true
+ TimeAttack.Time.FinishSaved = false
+ TimeAttack.Time.FinishDamage = player.total
+ TimeAttack.Time.FinishDps = player.total/TimeAttack.Time.Elapsed
+ local _, equipped = GetAverageItemLevel()
+ TimeAttack.Time.FinishIlevel = equipped
+ TimeAttack.Time.Date = date ("%H:%M %d/%m/%y")
+ TimeAttack.Time.N = TimeAttack.try
+ HistoryPanelObject:AddRecently (TimeAttack.Time)
+ TimeAttack.try = TimeAttack.try + 1
+ SaveButton:Enable()
+ ReportButton:Show()
+ end
+
+ function _detalhes:TimeAttackPluginStart()
+ TimeAttack:Start()
+ end
+
+ --> When a new combat is received by the PlugIn
+ function TimeAttack:Start()
+
+ if (TimeAttack.Time and TimeAttack.Time.Working) then
+ return
+ end
+
+ TimeAttack.Time = {}
+ TimeAttack.Time.StartTime = _GetTime()
+ TimeAttack.Time.EndTime = TimeAttack.Time.StartTime + TimeAmount.value - 2
+ TimeAttack.Time.Elapsed = 2
+ TimeAttack.Time.Done = nil
+ TimeAttack.Time.Working = true
+ TimeAttack.Time.Tick = 0
+
+ TimeAttack.Time.FinishOkey = false
+ TimeAttack.Time.FinishSaved = false
+ TimeAttack.Time.FinishDamage = nil
+ TimeAttack.Time.FinishTime = TimeAmount.value
+ TimeAttack.Time.FinishDps = nil
+ TimeAttack.Time.FinishIlevel = nil
+ TimeAttack.Time.Date = nil
+
+ SaveButton:Disable()
+ ReportButton:Hide()
+
+ player = TimeAttack:GetActor ("current", 1, UnitName ("player")) --> param 1 = combat | param 2 = attribute | param 3 = player name | all none = current, damage, player
+
+ if (not player) then
+ print (Loc ["STRING_COMBATFAIL"])
+ return
+ end
+
+ update = 0
+ TimeAttack.Frame:SetScript ("OnUpdate", DoTimeAttack)
+
+ end
+
+end
+
+function TimeAttack:OnEvent (_, event, ...)
+
+ if (event == "ADDON_LOADED") then
+ local AddonName = select (1, ...)
+ if (AddonName == "Details_TimeAttack") then
+
+ if (_G._detalhes) then
+
+ --> create widgets
+ CreatePluginFrames (_detalhes_databaseTimeAttack)
+
+ local MINIMAL_DETAILS_VERSION_REQUIRED = 1
+
+ --> Install
+ local install = _G._detalhes:InstallPlugin ("SOLO", Loc ["STRING_PLUGIN_NAME"], "Interface\\Icons\\SPELL_HOLY_BORROWEDTIME", TimeAttack, "DETAILS_PLUGIN_TIME_ATTACK", MINIMAL_DETAILS_VERSION_REQUIRED)
+ if (type (install) == "table" and install.error) then
+ print (install.errortext)
+ return
+ end
+
+ --> Register needed events
+ _G._detalhes:RegisterEvent (TimeAttack, "COMBAT_PLAYER_ENTER")
+
+ end
+ end
+
+ elseif (event == "PLAYER_LOGOUT") then
+ _detalhes_databaseTimeAttack = TimeAttack.data
+ end
+end
diff --git a/plugins/Details_TimeAttack/Details_TimeAttack.toc b/plugins/Details_TimeAttack/Details_TimeAttack.toc
new file mode 100644
index 00000000..dfb6bb2e
--- /dev/null
+++ b/plugins/Details_TimeAttack/Details_TimeAttack.toc
@@ -0,0 +1,15 @@
+## Interface: 50300
+## Title: Details TimeAttack (plugin)
+## Notes: Plugin for Details
+## SavedVariablesPerCharacter: _detalhes_databaseTimeAttack
+## RequiredDeps: Details
+## OptionalDeps: Ace3
+
+#@no-lib-strip@
+embeds.xml
+#@end-no-lib-strip@
+
+enUS.lua
+ptBR.lua
+
+Details_TimeAttack.lua
\ No newline at end of file
diff --git a/plugins/Details_TimeAttack/Libs/AceLocale-3.0/AceLocale-3.0.lua b/plugins/Details_TimeAttack/Libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 00000000..2ecc0cb8
--- /dev/null
+++ b/plugins/Details_TimeAttack/Libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/plugins/Details_TimeAttack/Libs/AceLocale-3.0/AceLocale-3.0.xml b/plugins/Details_TimeAttack/Libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 00000000..d69dbb13
--- /dev/null
+++ b/plugins/Details_TimeAttack/Libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/Details_TimeAttack/Libs/LibStub/LibStub.lua b/plugins/Details_TimeAttack/Libs/LibStub/LibStub.lua
new file mode 100644
index 00000000..f5fc9192
--- /dev/null
+++ b/plugins/Details_TimeAttack/Libs/LibStub/LibStub.lua
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ -- LibStub:NewLibrary(major, minor)
+ -- major (string) - the major version of the library
+ -- minor (string or number ) - the minor version of the library
+ --
+ -- returns nil if a newer or same version of the lib is already present
+ -- returns empty library object or old library object if upgrade is needed
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ -- LibStub:GetLibrary(major, [silent])
+ -- major (string) - the major version of the library
+ -- silent (boolean) - if true, library is optional, silently return nil if its not found
+ --
+ -- throws an error if the library can not be found (except silent is set)
+ -- returns the library object if found
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ -- LibStub:IterateLibraries()
+ --
+ -- Returns an iterator for the currently registered libraries
+ function LibStub:IterateLibraries()
+ return pairs(self.libs)
+ end
+
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/plugins/Details_TimeAttack/Libs/LibStub/LibStub.toc b/plugins/Details_TimeAttack/Libs/LibStub/LibStub.toc
new file mode 100644
index 00000000..c3dc3656
--- /dev/null
+++ b/plugins/Details_TimeAttack/Libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 40200
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: r95
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/plugins/Details_TimeAttack/Libs/LibStub/tests/test.lua b/plugins/Details_TimeAttack/Libs/LibStub/tests/test.lua
new file mode 100644
index 00000000..645a08b1
--- /dev/null
+++ b/plugins/Details_TimeAttack/Libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/plugins/Details_TimeAttack/Libs/LibStub/tests/test2.lua b/plugins/Details_TimeAttack/Libs/LibStub/tests/test2.lua
new file mode 100644
index 00000000..af431dd3
--- /dev/null
+++ b/plugins/Details_TimeAttack/Libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib doesn't exist yet, by iterating through all the libraries
+ assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+ if major == "MyLib" then -- we found it!
+ count = count +1
+ assert(rawequal(library, lib)) -- verify that the references are equal
+ end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/plugins/Details_TimeAttack/Libs/LibStub/tests/test3.lua b/plugins/Details_TimeAttack/Libs/LibStub/tests/test3.lua
new file mode 100644
index 00000000..01aabb8d
--- /dev/null
+++ b/plugins/Details_TimeAttack/Libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/plugins/Details_TimeAttack/Libs/LibStub/tests/test4.lua b/plugins/Details_TimeAttack/Libs/LibStub/tests/test4.lua
new file mode 100644
index 00000000..15a9c9cd
--- /dev/null
+++ b/plugins/Details_TimeAttack/Libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/plugins/Details_TimeAttack/embeds.xml b/plugins/Details_TimeAttack/embeds.xml
new file mode 100644
index 00000000..9cd274d8
--- /dev/null
+++ b/plugins/Details_TimeAttack/embeds.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/plugins/Details_TimeAttack/enUS.lua b/plugins/Details_TimeAttack/enUS.lua
new file mode 100644
index 00000000..a9ee6e6d
--- /dev/null
+++ b/plugins/Details_TimeAttack/enUS.lua
@@ -0,0 +1,23 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_TimeAttack", "enUS", true)
+
+if (not Loc) then
+ return
+end
+
+Loc ["STRING_PLUGIN_NAME"] = "Time Attack"
+Loc ["STRING_TIME_SELECTION"] = "Select the amount of time (seconds):"
+Loc ["STRING_SAVE"] = "Save"
+Loc ["STRING_SAVED"] = "Saved"
+Loc ["STRING_SAVERECORD"] = "save record"
+Loc ["STRING_REMOVERECORD"] = "remove record"
+Loc ["STRING_RECENTLY"] = "Recently"
+Loc ["STRING_SETNOTE"] = "set note"
+Loc ["STRING_SECONDS"] = "seconds"
+Loc ["STRING_COMBATFAIL"] = "Combat wasn't started by you, try leave your group or raid."
+Loc ["STRING_HELP"] = "Use timeattack to measure your damage within a certain time window. You can choose the amount of time from on the slider bar below. After reaching the time you can save the attempt to compare with others attempts in the future. When you save an attempt, Timeattack record your item level and the date together with the damage and time."
+
+Loc ["STRING_REPORT"] = "Details Time Attack Report"
+Loc ["STRING_DAMAGEOVER"] = "damage over"
+Loc ["STRING_AVERAGEDPS"] = "Average DPS of"
+Loc ["STRING_WITH"] = "with"
+Loc ["STRING_ITEMLEVEL"] = "gear score"
\ No newline at end of file
diff --git a/plugins/Details_TimeAttack/ptBR.lua b/plugins/Details_TimeAttack/ptBR.lua
new file mode 100644
index 00000000..9b4a3aa2
--- /dev/null
+++ b/plugins/Details_TimeAttack/ptBR.lua
@@ -0,0 +1,23 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_TimeAttack", "ptBR")
+
+if (not Loc) then
+ return
+end
+
+Loc ["STRING_PLUGIN_NAME"] = "Cronometro"
+Loc ["STRING_TIME_SELECTION"] = "Selecione o tempo desejado (em segundos):"
+Loc ["STRING_SAVE"] = "Salvar"
+Loc ["STRING_SAVED"] = "Salvo"
+Loc ["STRING_SAVERECORD"] = "salvar"
+Loc ["STRING_REMOVERECORD"] = "remover"
+Loc ["STRING_RECENTLY"] = "Recente"
+Loc ["STRING_SETNOTE"] = "escrever comentario"
+Loc ["STRING_SECONDS"] = "segundos"
+Loc ["STRING_COMBATFAIL"] = "O combate não foi iniciado por voce, tente saido do grupo ou da raide."
+Loc ["STRING_HELP"] = "Use o Cronometro para medir o seu dano dentro de um determinado tempo. Voce pode escolher a quantidade de tempo na barra de deslizar logo abaixo. Apos alcancar o tempo voce pode salvar a quantidade de dano que fez para comparar com outras no futuro."
+
+Loc ["STRING_REPORT"] = "Details Relatorio do Cronometro"
+Loc ["STRING_DAMAGEOVER"] = "de dano em"
+Loc ["STRING_AVERAGEDPS"] = "media de dano de"
+Loc ["STRING_WITH"] = "com"
+Loc ["STRING_ITEMLEVEL"] = "level dos equipamentos"
\ No newline at end of file
diff --git a/plugins/Details_TinyThreat/Details_TinyThreat.lua b/plugins/Details_TinyThreat/Details_TinyThreat.lua
new file mode 100644
index 00000000..bc8c4c2d
--- /dev/null
+++ b/plugins/Details_TinyThreat/Details_TinyThreat.lua
@@ -0,0 +1,326 @@
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ("Details_Threat")
+
+local _GetNumSubgroupMembers = GetNumSubgroupMembers --> wow api
+local _GetNumGroupMembers = GetNumGroupMembers --> wow api
+local _UnitIsFriend = UnitIsFriend --> wow api
+local _UnitName = UnitName --> wow api
+local _UnitDetailedThreatSituation = UnitDetailedThreatSituation
+local _IsInRaid = IsInRaid --> wow api
+local _IsInGroup = IsInGroup --> wow api
+local _UnitGroupRolesAssigned = UnitGroupRolesAssigned --> wow api
+
+local _ipairs = ipairs --> lua api
+local _table_sort = table.sort --> lua api
+local _cstr = string.format --> lua api
+local _unpack = unpack
+
+--> Create the plugin Object
+local ThreatMeter = _detalhes:NewPluginObject ("Details_Threat")
+--> Main Frame
+local ThreatMeterFrame = ThreatMeter.Frame
+
+local function CreatePluginFrames (data)
+
+ --> catch Details! main object
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+
+ --> data
+ ThreatMeter.data = data or {}
+
+ --> defaults
+ ThreatMeter.RowWidth = 294
+ ThreatMeter.RowHeight = 14
+ --> amount of row wich can be displayed
+ ThreatMeter.CanShow = 0
+ --> all rows already created
+ ThreatMeter.Rows = {}
+ --> current shown rows
+ ThreatMeter.ShownRows = {}
+
+ --> window reference
+ local instance
+ local player
+
+ --> OnEvent Table
+ function ThreatMeter:OnDetailsEvent (event)
+
+ if (event == "HIDE") then --> plugin hidded, disabled
+ ThreatMeterFrame:SetScript ("OnUpdate", nil)
+ ThreatMeter:Cancel()
+
+ elseif (event == "SHOW") then
+ instance = _detalhes.RaidTables.instancia
+
+ ThreatMeter.RowWidth = instance.baseframe:GetWidth()-6
+
+ ThreatMeter:UpdateContainers()
+ ThreatMeter:UpdateRows()
+
+ ThreatMeter:SizeChanged()
+
+ if (ThreatMeter:IsInCombat()) then
+ ThreatMeter:Start()
+ end
+
+ player = UnitName ("player")
+
+ elseif (event == "REFRESH") then --> requested a refresh window
+ -->
+
+ elseif (event == "COMBAT_PLAYER_ENTER") then --> combat started
+ --print ("ENTER COMBAT - nova tabela")
+ ThreatMeter:Start()
+
+ elseif (event == "COMBAT_PLAYER_LEAVE") then --> combat ended
+ ThreatMeter:End()
+
+ elseif (event == "DETAILS_INSTANCE_ENDRESIZE" or event == "DETAILS_INSTANCE_SIZECHANGED") then
+ ThreatMeter:SizeChanged()
+
+ elseif (event == "DETAILS_INSTANCE_STARTSTRETCH") then
+ ThreatMeterFrame:SetFrameStrata ("TOOLTIP")
+ ThreatMeterFrame:SetFrameLevel (instance.baseframe:GetFrameLevel()+1)
+
+ elseif (event == "DETAILS_INSTANCE_ENDSTRETCH") then
+ ThreatMeterFrame:SetFrameStrata ("MEDIUM")
+
+ end
+ end
+
+ ThreatMeterFrame:SetWidth (300)
+ ThreatMeterFrame:SetHeight (100)
+ ThreatMeterFrame:SetBackdrop ({
+ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
+ tile = true, tileSize = 16,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ ThreatMeterFrame:SetBackdropColor (.3, .3, .3, .3)
+
+ function ThreatMeter:UpdateContainers()
+ for _, row in _ipairs (ThreatMeter.Rows) do
+ row:SetContainer (instance.baseframe)
+ end
+ end
+
+ function ThreatMeter:UpdateRows()
+ for _, row in _ipairs (ThreatMeter.Rows) do
+ row.width = ThreatMeter.RowWidth
+ end
+ end
+
+ function ThreatMeter:HideBars()
+ for _, row in _ipairs (ThreatMeter.Rows) do
+ row:Hide()
+ end
+ end
+
+ local target = nil
+ local timer = 0
+ local interval = 1.0
+
+ function ThreatMeter:TargetChanged()
+ local NewTarget = _UnitName ("target")
+ if (NewTarget and not _UnitIsFriend ("player", "target")) then
+ target = NewTarget
+ end
+ ThreatMeter:HideBars()
+ end
+
+ local RoleIconCoord = {
+ ["TANK"] = {0, 0.28125, 0.328125, 0.625},
+ ["HEALER"] = {0.3125, 0.59375, 0, 0.296875},
+ ["DAMAGER"] = {0.3125, 0.59375, 0.328125, 0.625}
+ }
+
+ function ThreatMeter:SizeChanged()
+
+ local w, h = instance:GetSize()
+ ThreatMeterFrame:SetWidth (w)
+ ThreatMeterFrame:SetHeight (h)
+
+ ThreatMeter.CanShow = math.floor ( h / (ThreatMeter.RowHeight+1))
+
+ for i = #ThreatMeter.Rows+1, ThreatMeter.CanShow do
+ ThreatMeter:NewRow (i)
+ end
+
+ ThreatMeter.ShownRows = {}
+
+ for i = 1, ThreatMeter.CanShow do
+ ThreatMeter.ShownRows [#ThreatMeter.ShownRows+1] = ThreatMeter.Rows[i]
+ if (_detalhes.in_combat) then
+ ThreatMeter.Rows[i]:Show()
+ end
+ ThreatMeter.Rows[i].width = w-5
+ end
+
+ for i = #ThreatMeter.ShownRows+1, #ThreatMeter.Rows do
+ ThreatMeter.Rows [i]:Hide()
+ end
+
+ end
+
+ function ThreatMeter:NewRow (i)
+ local newrow = DetailsFrameWork:NewBar (ThreatMeterFrame, _, "DetailsThreatRow"..i, _, 300, 14)
+ newrow:SetPoint (3, -((i-1)*15))
+ newrow.lefttext = "bar " .. i
+ newrow.color = "skyblue"
+ newrow.fontsize = 9.9
+ newrow.fontface = "GameFontHighlightSmall"
+ newrow:SetIcon ("Interface\\LFGFRAME\\UI-LFG-ICON-PORTRAITROLES", RoleIconCoord ["DAMAGER"])
+ ThreatMeter.Rows [#ThreatMeter.Rows+1] = newrow
+ newrow:Hide()
+ return newrow
+ end
+
+ local sort = function (table1, table2)
+ if (table1[2] > table2[2]) then
+ return true
+ else
+ return false
+ end
+ end
+
+ local Threater = function()
+
+ local threat_table = {}
+
+ if (target) then
+ if (_IsInRaid()) then
+ for i = 1, _GetNumGroupMembers(), 1 do
+ local isTanking, status, threatpct, rawthreatpct, threatvalue = _UnitDetailedThreatSituation ("raid"..i, "target")
+ if (status) then
+ threat_table [#threat_table+1] = {_UnitName ("raid"..i), threatpct, isTanking}
+ end
+ end
+ elseif (_IsInGroup()) then
+ for i = 1, _GetNumGroupMembers()-1, 1 do
+ local isTanking, status, threatpct, rawthreatpct, threatvalue = _UnitDetailedThreatSituation ("party"..i, "target")
+ if (status) then
+ threat_table [#threat_table+1] = {_UnitName ("party"..i), threatpct, isTanking}
+ end
+ end
+ end
+
+ _table_sort (threat_table, sort)
+
+ local lastIndex = 0
+ local shownMe = false
+
+ for index = 1, #ThreatMeter.ShownRows do
+ local thisRow = ThreatMeter.ShownRows [index]
+ local threat_actor = threat_table [index]
+
+ if (threat_actor) then
+ local role = _UnitGroupRolesAssigned (threat_actor [1])
+ thisRow.icon:SetTexCoord (_unpack (RoleIconCoord [role]))
+ thisRow:SetLeftText (threat_actor [1])
+ thisRow:SetRightText (_cstr ("%.1f", threat_actor [2]).."%")
+ thisRow:SetValue (threat_actor [2])
+ if (index == 1) then
+ thisRow:SetColor (threat_actor [2]*0.01, math.abs (threat_actor [2]-100)*0.01, 0, 1)
+ else
+ thisRow:SetColor (threat_actor [2]*0.01, math.abs (threat_actor [2]-100)*0.01, 0, .3)
+ end
+ if (not thisRow.statusbar:IsShown()) then
+ thisRow:Show()
+ end
+ if (threat_actor [1] == player) then
+ shownMe = true
+ end
+ else
+ thisRow:Hide()
+ end
+ end
+
+ if (not shownMe) then
+ --> show my self into last bar
+ local isTanking, status, threatpct, rawthreatpct, threatvalue = _UnitDetailedThreatSituation ("player", "target")
+ if (threatpct and threatpct > 0.1) then
+ local thisRow = ThreatMeter.ShownRows [#ThreatMeter.ShownRows]
+ thisRow:SetLeftText (player)
+ local role = _UnitGroupRolesAssigned (player)
+ thisRow.icon:SetTexCoord (_unpack (RoleIconCoord [role]))
+ thisRow:SetRightText (_cstr ("%.1f", threatpct).."%")
+ thisRow:SetValue (threatpct)
+ thisRow:SetColor (threatpct*0.01, math.abs (threatpct-100)*0.01, 0, .3)
+ end
+ end
+
+ end
+
+ end
+
+ local OnUpdate = function (self, elapsed)
+ timer = timer + elapsed
+ if (timer > interval) then
+ timer = 0
+ --if (_IsInRaid() or _IsInGroup()) then
+ --print ("aqui")
+ Threater()
+ --end
+
+ end
+ end
+
+ function ThreatMeter:Start()
+ ThreatMeter:HideBars()
+ if (_IsInRaid() or _IsInGroup()) then
+ --print ("Iniciando analizador de Threat")
+ ThreatMeterFrame:SetScript ("OnUpdate", OnUpdate)
+ end
+ end
+
+ function ThreatMeter:End()
+ --print ("=== COMBAT LEAVE ===")
+ ThreatMeter:HideBars()
+ ThreatMeterFrame:SetScript ("OnEvent", nil)
+ end
+
+ function ThreatMeter:Cancel()
+ ThreatMeter:HideBars()
+ end
+
+end
+
+function ThreatMeter:OnEvent (_, event, ...)
+
+ if (event == "ADDON_LOADED") then
+ local AddonName = select (1, ...)
+ if (AddonName == "Details_TinyThreat") then
+
+ if (_G._detalhes) then
+
+ --> create widgets
+ CreatePluginFrames (data)
+
+ local MINIMAL_DETAILS_VERSION_REQUIRED = 1
+
+ --> Install
+ local install = _G._detalhes:InstallPlugin ("TANK", Loc ["STRING_PLUGIN_NAME"], "Interface\\Icons\\Ability_Paladin_ShieldofVengeance", ThreatMeter, "DETAILS_PLUGIN_TINY_THREAT", MINIMAL_DETAILS_VERSION_REQUIRED)
+ if (type (install) == "table" and install.error) then
+ print (install.error)
+ end
+
+ --> Register needed events
+ _G._detalhes:RegisterEvent (ThreatMeter, "COMBAT_PLAYER_ENTER")
+ _G._detalhes:RegisterEvent (ThreatMeter, "COMBAT_PLAYER_LEAVE")
+ _G._detalhes:RegisterEvent (ThreatMeter, "DETAILS_INSTANCE_ENDRESIZE")
+ _G._detalhes:RegisterEvent (ThreatMeter, "DETAILS_INSTANCE_SIZECHANGED")
+ _G._detalhes:RegisterEvent (ThreatMeter, "DETAILS_INSTANCE_STARTSTRETCH")
+ _G._detalhes:RegisterEvent (ThreatMeter, "DETAILS_INSTANCE_ENDSTRETCH")
+
+ ThreatMeterFrame:RegisterEvent ("PLAYER_TARGET_CHANGED")
+
+ end
+ end
+
+ elseif (event == "PLAYER_TARGET_CHANGED") then
+ ThreatMeter:TargetChanged()
+
+ elseif (event == "PLAYER_LOGOUT") then
+ _detalhes_databaseThreat = ThreatMeter.data
+
+ end
+end
diff --git a/plugins/Details_TinyThreat/Details_TinyThreat.toc b/plugins/Details_TinyThreat/Details_TinyThreat.toc
new file mode 100644
index 00000000..2b949b70
--- /dev/null
+++ b/plugins/Details_TinyThreat/Details_TinyThreat.toc
@@ -0,0 +1,15 @@
+## Interface: 50300
+## Title: Details Tiny Threat (plugin)
+## Notes: Plugin for Details
+## SavedVariablesPerCharacter: _detalhes_databaseThreat
+## RequiredDeps: Details
+## OptionalDeps: Ace3
+
+#@no-lib-strip@
+embeds.xml
+#@end-no-lib-strip@
+
+enUS.lua
+ptBR.lua
+
+Details_TinyThreat.lua
\ No newline at end of file
diff --git a/plugins/Details_TinyThreat/Libs/AceLocale-3.0/AceLocale-3.0.lua b/plugins/Details_TinyThreat/Libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 00000000..2ecc0cb8
--- /dev/null
+++ b/plugins/Details_TinyThreat/Libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/plugins/Details_TinyThreat/Libs/AceLocale-3.0/AceLocale-3.0.xml b/plugins/Details_TinyThreat/Libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 00000000..d69dbb13
--- /dev/null
+++ b/plugins/Details_TinyThreat/Libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/Details_TinyThreat/Libs/LibStub/LibStub.lua b/plugins/Details_TinyThreat/Libs/LibStub/LibStub.lua
new file mode 100644
index 00000000..f5fc9192
--- /dev/null
+++ b/plugins/Details_TinyThreat/Libs/LibStub/LibStub.lua
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ -- LibStub:NewLibrary(major, minor)
+ -- major (string) - the major version of the library
+ -- minor (string or number ) - the minor version of the library
+ --
+ -- returns nil if a newer or same version of the lib is already present
+ -- returns empty library object or old library object if upgrade is needed
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ -- LibStub:GetLibrary(major, [silent])
+ -- major (string) - the major version of the library
+ -- silent (boolean) - if true, library is optional, silently return nil if its not found
+ --
+ -- throws an error if the library can not be found (except silent is set)
+ -- returns the library object if found
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ -- LibStub:IterateLibraries()
+ --
+ -- Returns an iterator for the currently registered libraries
+ function LibStub:IterateLibraries()
+ return pairs(self.libs)
+ end
+
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/plugins/Details_TinyThreat/Libs/LibStub/LibStub.toc b/plugins/Details_TinyThreat/Libs/LibStub/LibStub.toc
new file mode 100644
index 00000000..c3dc3656
--- /dev/null
+++ b/plugins/Details_TinyThreat/Libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 40200
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: r95
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/plugins/Details_TinyThreat/Libs/LibStub/tests/test.lua b/plugins/Details_TinyThreat/Libs/LibStub/tests/test.lua
new file mode 100644
index 00000000..645a08b1
--- /dev/null
+++ b/plugins/Details_TinyThreat/Libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/plugins/Details_TinyThreat/Libs/LibStub/tests/test2.lua b/plugins/Details_TinyThreat/Libs/LibStub/tests/test2.lua
new file mode 100644
index 00000000..af431dd3
--- /dev/null
+++ b/plugins/Details_TinyThreat/Libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib doesn't exist yet, by iterating through all the libraries
+ assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+ if major == "MyLib" then -- we found it!
+ count = count +1
+ assert(rawequal(library, lib)) -- verify that the references are equal
+ end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/plugins/Details_TinyThreat/Libs/LibStub/tests/test3.lua b/plugins/Details_TinyThreat/Libs/LibStub/tests/test3.lua
new file mode 100644
index 00000000..01aabb8d
--- /dev/null
+++ b/plugins/Details_TinyThreat/Libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/plugins/Details_TinyThreat/Libs/LibStub/tests/test4.lua b/plugins/Details_TinyThreat/Libs/LibStub/tests/test4.lua
new file mode 100644
index 00000000..15a9c9cd
--- /dev/null
+++ b/plugins/Details_TinyThreat/Libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/plugins/Details_TinyThreat/embeds.xml b/plugins/Details_TinyThreat/embeds.xml
new file mode 100644
index 00000000..9cd274d8
--- /dev/null
+++ b/plugins/Details_TinyThreat/embeds.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/plugins/Details_TinyThreat/enUS.lua b/plugins/Details_TinyThreat/enUS.lua
new file mode 100644
index 00000000..551f1354
--- /dev/null
+++ b/plugins/Details_TinyThreat/enUS.lua
@@ -0,0 +1,7 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_Threat", "enUS", true)
+
+if (not Loc) then
+ return
+end
+
+Loc ["STRING_PLUGIN_NAME"] = "Tiny Threat"
\ No newline at end of file
diff --git a/plugins/Details_TinyThreat/ptBR.lua b/plugins/Details_TinyThreat/ptBR.lua
new file mode 100644
index 00000000..2c95b2cb
--- /dev/null
+++ b/plugins/Details_TinyThreat/ptBR.lua
@@ -0,0 +1,7 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_Threat", "ptBR")
+
+if (not Loc) then
+ return
+end
+
+Loc ["STRING_PLUGIN_NAME"] = "Mini Ameaca"
\ No newline at end of file
diff --git a/plugins/Details_Vanguard/Details_Vanguard.lua b/plugins/Details_Vanguard/Details_Vanguard.lua
new file mode 100644
index 00000000..a42c8932
--- /dev/null
+++ b/plugins/Details_Vanguard/Details_Vanguard.lua
@@ -0,0 +1,1173 @@
+local AceLocale = LibStub ("AceLocale-3.0")
+local Loc = AceLocale:GetLocale ("Details_Vanguard")
+
+---------------------------------------------------------------------------------------------
+local _GetTime = GetTime --> wow api local
+local _UFC = UnitAffectingCombat --> wow api local
+local _IsInRaid = IsInRaid --> wow api local
+local _IsInGroup = IsInGroup --> wow api local
+local _UnitAura = UnitAura --> wow api local
+local _UnitName = UnitName --> wow api local
+local _UnitGroupRolesAssigned = UnitGroupRolesAssigned --> wow api local
+local _UnitHealthMax = UnitHealthMax --> wow api local
+local _UnitIsPlayer = UnitIsPlayer --> wow api local
+local _UnitClass = UnitClass --> wow api local
+local _UnitDebuff = UnitDebuff --> wow api local
+---------------------------------------------------------------------------------------------
+local _cstr = string.format --> lua library local
+local _table_insert = table.insert --> lua library local
+local _table_remove = table.remove --> lua library local
+local _ipairs = ipairs --> lua library local
+local _pairs = pairs --> lua library local
+local _math_floor = math.floor --> lua library local
+local _math_abs = math.abs --> lua library local
+local _math_min = math.min --> lua library local
+---------------------------------------------------------------------------------------------
+
+--> Create plugin Object
+local Vanguard = _detalhes:NewPluginObject ("Details_Vanguard")
+--> Main Frame
+local VanguardFrame = Vanguard.Frame
+
+--> Create plugin objects, function and widgets
+local function CreatePluginFrames (data)
+
+ --> catch Details! main object
+ local _detalhes = _G._detalhes
+ local DetailsFrameWork = _detalhes.gump
+
+ --> any saved data cames here
+ Vanguard.data = data or {}
+
+ --> main locals
+ local _combat_object = nil --> demais current combat object
+ local _track_player_object = nil --> Damage Actor in current damage object
+ local _track_player_unit = "player" --> current tracking unit
+ local _track_player_name = _UnitName (_track_player_unit) --> current tracking unit name
+ local instancia --> instancia object (details window)
+ local MyName = _UnitName ("player") --> player name
+
+ --> running yes or not
+ Vanguard.Running = false
+
+ --> window size requirements
+ Vanguard.MinWidth = 300
+ Vanguard.MinHeight = 100
+
+ --> OnDetailsEvent Parser
+ function Vanguard:OnDetailsEvent (event, ...)
+
+ if (event == "HIDE") then --> plugin hidded, disabled
+ VanguardFrame:SetScript ("OnUpdate", nil)
+ VanguardFrame:UnregisterEvent ("ROLE_CHANGED_INFORM")
+ VanguardFrame:UnregisterEvent ("RAID_ROSTER_UPDATE")
+ VanguardFrame:UnregisterEvent ("PLAYER_TARGET_CHANGED")
+ Vanguard:Cancel()
+
+ elseif (event == "SHOW") then --> plugin shown, enabled
+
+ instancia = _detalhes.RaidTables.instancia
+ for index, tankframe in _ipairs (Vanguard.TankFrames) do
+ DetailsFrameWork:RegisterForDetailsMove (tankframe.Frame.frame, instancia)
+ end
+ DetailsFrameWork:RegisterForDetailsMove (VanguardFrame ["DamageRowBackground"].frame, instancia)
+
+ Vanguard:OnResize()
+
+ VanguardFrame:RegisterEvent ("ROLE_CHANGED_INFORM")
+ VanguardFrame:RegisterEvent ("RAID_ROSTER_UPDATE")
+ VanguardFrame:RegisterEvent ("PLAYER_TARGET_CHANGED")
+
+ Vanguard:ResetBars()
+ Vanguard:ResetDamage()
+ Vanguard:ResetDebuffs()
+
+ Vanguard:IdentifyTanks()
+
+ if (Vanguard:IsInCombat()) then
+ instancia = _detalhes.RaidTables.instancia
+ _combat_object = _detalhes.tabela_vigente
+ _track_player_object = nil
+ _track_player_name = nil
+ Vanguard.Running = true
+
+ VanguardFrame:RegisterEvent ("PLAYER_TARGET_CHANGED")
+
+ Vanguard:Start()
+ end
+
+ elseif (event == "REFRESH") then --> requested a refresh window
+ -->
+
+ elseif (event == "COMBAT_PLAYER_ENTER") then --> a new combat has been started
+
+ instancia = _detalhes.RaidTables.instancia
+ _combat_object = select (1, ...)
+ _track_player_object = nil
+ _track_player_name = nil
+ Vanguard.Running = true
+
+ VanguardFrame:RegisterEvent ("UNIT_HEALTH")
+
+ Vanguard:Start()
+
+ elseif (event == "DETAILS_INSTANCE_ENDRESIZE" or event == "DETAILS_INSTANCE_SIZECHANGED") then
+ Vanguard:OnResize()
+
+ elseif (event == "DETAILS_INSTANCE_STARTSTRETCH") then
+ VanguardFrame:SetFrameStrata ("TOOLTIP")
+ VanguardFrame:SetFrameLevel (instancia.baseframe:GetFrameLevel()+1)
+
+ elseif (event == "DETAILS_INSTANCE_ENDSTRETCH") then
+ VanguardFrame:SetFrameStrata ("MEDIUM")
+ Vanguard:OnResize()
+
+ elseif (event == "COMBAT_PLAYER_LEAVE") then --> current combat has finished
+
+ _combat_object = select (1, ...)
+
+ Vanguard.Running = false
+ VanguardFrame:SetScript ("OnUpdate", onupdate)
+
+ Vanguard:ResetBars()
+ Vanguard:ResetDamage()
+ Vanguard:ResetDebuffs()
+
+ VanguardFrame:UnregisterEvent ("UNIT_HEALTH")
+
+ for i = 1, 3 do
+ Vanguard.TankFrames [i].Life (100)
+ end
+
+ end
+ end
+
+ function Vanguard:OnResize()
+
+ local w, h = instancia:GetSize()
+ VanguardFrame:SetHeight (h)
+
+ if (h >= 95) then
+ --> show two bars
+ Vanguard.DamageVsHeal:Show()
+ Vanguard.TookVsAvoid:Show()
+ --> show last hit box
+ Vanguard.LastHitsBackground:Show()
+ Vanguard.LastHitsBackground:SetPoint ("topleft", VanguardFrame, 2, -35)
+ --> show tank boxes
+ for i = 1, 3 do
+ Vanguard.TankFrames [i].Frame:SetPoint ("bottomleft", VanguardFrame, 2 + ((i-1)*98), 0)
+ end
+
+ return
+ end
+
+ if (h < 95 and h >= 60) then
+ --> hide two bars
+ Vanguard.DamageVsHeal:Hide()
+ Vanguard.TookVsAvoid:Hide()
+ --> move up last hit box
+ Vanguard.LastHitsBackground:Show()
+ Vanguard.LastHitsBackground:SetPoint (3, -3)
+ --> move up the 3 tank boxes
+ for i = 1, 3 do
+ Vanguard.TankFrames [i].Frame:SetPoint ("bottomleft", VanguardFrame, 2 + ((i-1)*98), 0)
+ end
+
+ return
+ end
+
+ if (h < 60) then
+ --> hide two bars (hide again due stretch)
+ Vanguard.DamageVsHeal:Hide()
+ Vanguard.TookVsAvoid:Hide()
+ --> hide last hit box
+ Vanguard.LastHitsBackground:Hide()
+ --> move up the 3 tank boxes
+ for i = 1, 3 do
+ Vanguard.TankFrames [i].Frame:SetPoint ("bottomleft", VanguardFrame, 2 + ((i-1)*98), 0)
+ end
+ end
+ end
+
+ function Vanguard:HealthChanged (unitId)
+ if (Vanguard.TankListHash [unitId]) then
+ Vanguard:UpdateHealth (Vanguard.TankListHash [unitId], unitId)
+ end
+ end
+
+ --> list with tank names
+ Vanguard.TankList = {} --> indexes
+ Vanguard.TankListHash = {} --> name hash
+
+ --> search for tanks in the raid or party group
+ function Vanguard:IdentifyTanks()
+
+ table.wipe (Vanguard.TankList)
+ table.wipe (Vanguard.TankListHash)
+
+ if (IsInRaid()) then
+
+ local playerName = _UnitName ("player")
+
+ for i = 1, GetNumGroupMembers(), 1 do
+ local role = _UnitGroupRolesAssigned ("raid"..i)
+ if (role == "TANK") then
+ local tankName = _UnitName ("raid"..i)
+ if (tankName == playerName) then
+ playerName = "SELFISTANK"
+ end
+ Vanguard.TankList [#Vanguard.TankList+1] = tankName
+ Vanguard.TankListHash ["raid"..i] = #Vanguard.TankList
+ if (#Vanguard.TankList == 3) then
+ break
+ end
+ end
+ end
+
+ if (#Vanguard.TankList < 3 and playerName ~= "SELFISTANK") then
+ Vanguard.TankList [#Vanguard.TankList+1] = _UnitName ("player")
+ Vanguard.TankListHash ["player"] = #Vanguard.TankList
+ end
+
+ elseif (IsInGroup()) then
+
+ local playerName = _UnitName ("player")
+
+ for i = 1, GetNumGroupMembers()-1, 1 do
+ local role = _UnitGroupRolesAssigned ("party"..i)
+ if (role == "TANK") then
+ local tankName = _UnitName ("party"..i)
+ if (tankName == playerName) then
+ playerName = "SELFISTANK"
+ end
+ Vanguard.TankList [#Vanguard.TankList+1] = tankName
+ Vanguard.TankListHash ["party"..i] = #Vanguard.TankList
+ if (#Vanguard.TankList == 3) then
+ break
+ end
+ end
+ end
+
+ if (#Vanguard.TankList < 3 and playerName ~= "SELFISTANK") then
+ Vanguard.TankList [#Vanguard.TankList+1] = _UnitName ("player")
+ Vanguard.TankListHash ["player"] =#Vanguard.TankList
+ end
+
+ else
+ Vanguard.TankList [#Vanguard.TankList+1] = _UnitName ("player")
+ Vanguard.TankListHash ["player"] =#Vanguard.TankList
+ end
+
+ for index, tankname in _ipairs (Vanguard.TankList) do
+ Vanguard.TankFrames [index]:SetTank (tankname)
+ end
+
+ for i = #Vanguard.TankList+1, 3 do
+ Vanguard.TankFrames [i]:SetTank (nil, i)
+ end
+
+ end
+
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> Build Frames and Gadgets
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> Vanguard frame attributes
+ VanguardFrame:SetBackdrop ({
+ bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
+ tile = true, tileSize = 16,
+ insets = {left = 1, right = 1, top = 0, bottom = 1},})
+ VanguardFrame:SetBackdropColor (.3, .3, .3, .3)
+
+ VanguardFrame:SetWidth (300)
+ VanguardFrame:SetHeight (100)
+
+-------> Build two splits bars for damage vs heal and avoid vs hits --------------------------------------------------------------------------------------------------
+
+ --> Damage Vs Healing bar
+
+ local infoFrame = DetailsFrameWork:NewPanel (VanguardFrame, VanguardFrame, "VanguardInfoFrame", "infoFrame", 300, 100)
+ infoFrame:SetPoint ("topleft", VanguardFrame, "topleft")
+ infoFrame:Hide()
+ infoFrame:SetFrameLevel (5)
+ VanguardFrame.InfoShown = false
+
+ infoFrame:SetBackdrop ("Interface\\DialogFrame\\UI-DialogBox-Background-Dark")
+ infoFrame:SetBackdropColor ("black")
+ infoFrame:SetGradient ("OnEnter", "black")
+
+ infoFrame:SetHook ("OnMouseUp", function (_, button)
+ if (string.lower (button):find ("right")) then
+ VanguardFrame.InfoShown = false
+ infoFrame:Hide()
+ if (infoFrame.refreshTick) then
+ Vanguard:CancelTimer (infoFrame.refreshTick)
+ infoFrame.refreshTick = nil
+ end
+ end
+ end)
+
+ local funcInfo = function()
+ VanguardFrame.InfoShown = true
+ Vanguard:VanguardRefreshInfoFrame()
+ infoFrame:Show()
+ infoFrame.refreshTick = Vanguard:ScheduleRepeatingTimer ("VanguardRefreshInfoFrame", 1)
+ end
+
+ --> Info frame widgets:
+ local healReceived = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealReceived", nil, Loc ["STRING_HEALRECEIVED"]..":", "GameFontHighlightSmall", 9.5)
+ healReceived:SetPoint (10, -5)
+ local healReceivedNumber = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealReceivedAmount", nil, "0", "GameFontHighlightSmall", 9.5)
+ healReceivedNumber:SetPoint ("left", healReceived, "right", 2)
+
+ local healPerSecond = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealHps", nil, Loc ["STRING_HPS"]..":", "GameFontHighlightSmall", 9.5)
+ healPerSecond:SetPoint (10, -20)
+ local healPerSecondNumber = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealHealHpsAmount", nil, "0", "GameFontHighlightSmall", 9.5)
+ healPerSecondNumber:SetPoint ("left", healPerSecond, "right", 2)
+
+ local icon1 = DetailsFrameWork:NewImage (infoFrame, nil, "VanguardInfoHealTop1Icon", nil, 14, 14)
+ local topHealer1 = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealTop1", nil, "", "GameFontHighlightSmall", 9.5)
+ topHealer1:SetWidth (80)
+ topHealer1:SetHeight (10)
+ local topHealer1Amount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealTop1Amount", nil, "", "GameFontHighlightSmall", 9.5)
+ icon1:SetPoint (10, -35)
+ topHealer1:SetPoint ("left", icon1, "right", 2)
+ topHealer1Amount:SetPoint ("left", topHealer1, "right", 2)
+
+ local icon2 = DetailsFrameWork:NewImage (infoFrame, nil, "VanguardInfoHealTop2Icon", nil, 14, 14)
+ local topHealer2 = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealTop2", nil, "", "GameFontHighlightSmall", 9.5)
+ topHealer2:SetWidth (80)
+ topHealer2:SetHeight (10)
+ local topHealer2Amount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealTop2Amount", nil, "", "GameFontHighlightSmall", 9.5)
+ icon2:SetPoint (10, -50)
+ topHealer2:SetPoint ("left", icon2, "right", 2)
+ topHealer2Amount:SetPoint ("left", topHealer2, "right", 2)
+
+ local icon3 = DetailsFrameWork:NewImage (infoFrame, nil, "VanguardInfoHealTop3Icon", nil, 14, 14)
+ local topHealer3 = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealTop3", nil, "", "GameFontHighlightSmall", 9.5)
+ topHealer3:SetWidth (80)
+ topHealer3:SetHeight (10)
+ local topHealer3Amount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealTop3Amount", nil, "", "GameFontHighlightSmall", 9.5)
+ icon3:SetPoint (10, -64)
+ topHealer3:SetPoint ("left", icon3, "right", 2)
+ topHealer3Amount:SetPoint ("left", topHealer3, "right", 2)
+
+ local icon4 = DetailsFrameWork:NewImage (infoFrame, nil, "VanguardInfoHealTop4Icon", nil, 14, 14)
+ local topHealer4 = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealTop4", nil, "", "GameFontHighlightSmall", 9.5)
+ topHealer4:SetWidth (80)
+ topHealer4:SetHeight (10)
+ local topHealer4Amount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHealTop4Amount", nil, "", "GameFontHighlightSmall", 9.5)
+ icon4:SetPoint (10, -80)
+ topHealer4:SetPoint ("left", icon4, "right", 2)
+ topHealer4Amount:SetPoint ("left", topHealer4, "right", 2)
+
+ local iconTable = {icon1, icon2, icon3, icon4}
+ local healerTable = {topHealer1, topHealer2, topHealer3, topHealer4}
+ local healerAmountTable = {topHealer1Amount, topHealer2Amount, topHealer3Amount, topHealer4Amount}
+
+ local hitsReceived = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHitsReceived", nil, Loc ["STRING_HITS"], "GameFontHighlightSmall", 9.5)
+ hitsReceived:SetPoint (150, -5)
+ local hitsReceivedAmount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoHitsReceivedAmount", nil, "0", "GameFontHighlightSmall", 9.5)
+ hitsReceivedAmount:SetPoint ("left", hitsReceived, "right", 2)
+
+ local dodge = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoDodge", nil, Loc ["STRING_DODGE"], "GameFontHighlightSmall", 9.5)
+ dodge:SetPoint (150, -20)
+ local dodgeAmount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoDodgeAmount", nil, "0", "GameFontHighlightSmall", 9.5)
+ dodgeAmount:SetPoint ("left", dodge, "right", 2)
+
+ local parry = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoParry", nil, Loc ["STRING_PARRY"], "GameFontHighlightSmall", 9.5)
+ parry:SetPoint (150, -35)
+ local parryAmount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoParryAmount", nil, "0", "GameFontHighlightSmall", 9.5)
+ parryAmount:SetPoint ("left", parry, "right", 2)
+
+ local damageTaken = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoDamageTaken", nil, Loc ["STRING_DAMAGETAKEN"], "GameFontHighlightSmall", 9.5)
+ damageTaken:SetPoint (150, -50)
+ local damageTakenAmount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoDamageTakenAmount", nil, "0", "GameFontHighlightSmall", 9.5)
+ damageTakenAmount:SetPoint ("left", damageTaken, "right", 2)
+
+ local damageTakenSec = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoDamageSec", nil, Loc ["STRING_DTPS"], "GameFontHighlightSmall", 9.5)
+ damageTakenSec:SetPoint (150, -65)
+ local damageTakenSecAmount = DetailsFrameWork:NewLabel (infoFrame, nil, "VanguardInfoDamageTakenSecAmount", nil, "0", "GameFontHighlightSmall", 9.5)
+ damageTakenSecAmount:SetPoint ("left", damageTakenSec, "right", 2)
+ ----------
+
+ --> need to be a member of _detalhes bacause we want to use a schedule timer
+ --> once a member of _detalhes we can call through plugin object like Vanguard:VanguardRefreshInfoFrame()
+ _detalhes.VanguardRefreshInfoFrame = function()
+
+ --> data mine
+
+ --> Get heal actor
+ local actorHeal = Vanguard:GetActor ("current", DETAILS_ATTRIBUTE_HEAL, _track_player_name) --> [1] combat [2] attribute [3] name
+ local combat = Vanguard:GetCombat ("current")
+
+ if (actorHeal) then
+ --> members can be found at details/classes/classe_heal line 75
+ healReceivedNumber.text = Vanguard:ToK (actorHeal.healing_taken or 0)
+ healPerSecondNumber.text = Vanguard:ToK (actorHeal.healing_taken / combat:GetCombatTime())
+
+ local heal_from = actorHeal.healing_from --> table with [name] = true
+ local myReceivedHeal = {}
+
+ for actorName, _ in pairs (heal_from) do
+ local thisActor = Vanguard:GetActor ("current", DETAILS_ATTRIBUTE_HEAL, actorName)
+ local targets = thisActor.targets --> targets is a container with target classes
+ local amount = targets:GetAmount (_track_player_name, "total")
+ myReceivedHeal [#myReceivedHeal+1] = {actorName, amount}
+ end
+
+ table.sort (myReceivedHeal, Vanguard.Sort2) --> Sort2 sort by second index
+
+ for i = 1, 4 do
+ if (myReceivedHeal[i]) then
+ healerTable [i].text = myReceivedHeal[i][1]..":"
+ healerAmountTable[i].text = Vanguard:ToK (myReceivedHeal[i][2] or 0)
+ iconTable [i].texture = Vanguard.class_icons_small
+
+ local _, L, R, T, B = Vanguard:GetClass (myReceivedHeal[i][1])
+ if (L) then
+ iconTable [i]:SetTexCoord (L, R, T, B)
+ end
+ else
+ iconTable [i].texture = nil
+ healerTable [i].text = "-- -- --"
+ healerAmountTable[i].text = ""
+ end
+ end
+ else
+ --> reset
+ healReceivedNumber.text = "0"
+ healPerSecondNumber.text = "0"
+ for i = 1, 4 do
+ iconTable [i].texture = nil
+ healerTable [i].text = "-- -- --"
+ healerAmountTable[i].text = ""
+ end
+ end
+
+ --> Get damage actor
+ local actorDamage = Vanguard:GetActor ("current", DETAILS_ATTRIBUTE_DAMAGE, _track_player_name) --> [1] combat [2] attribute [3] name
+ if (actorDamage) then
+ --> members can be found at details/classes/classe_damage line 75
+ local avoidance = actorDamage.avoidance --> table with DODGE, PARRY, HITS members
+
+ local totalAvoid = avoidance.DODGE + avoidance.PARRY
+ local totalOver = totalAvoid + avoidance.HITS
+
+ if (totalOver > 0) then
+ hitsReceivedAmount.text = avoidance.HITS .. " (" .. _math_floor (avoidance.HITS / totalOver * 100) .. "%)"
+ dodgeAmount.text = avoidance.DODGE .. " (" .. _math_floor (avoidance.DODGE / totalOver * 100) .. "%)"
+ parryAmount.text = avoidance.PARRY .. " (" .. _math_floor (avoidance.PARRY / totalOver * 100) .. "%)"
+ else
+ hitsReceivedAmount.text = "0 (0%)"
+ dodgeAmount.text = "0 (0%)"
+ parryAmount.text = "0 (0%)"
+ end
+
+ damageTakenAmount.text = Vanguard:ToK (actorDamage.damage_taken)
+ damageTakenSecAmount.text = Vanguard:ToK (actorDamage.damage_taken / combat:GetCombatTime())
+ else
+ hitsReceivedAmount.text = "0"
+ dodgeAmount.text = "0"
+ parryAmount.text = "0"
+ damageTakenAmount.text = "0"
+ damageTakenSecAmount.text = "0"
+ end
+
+ end
+
+ local DamageVsHeal = DetailsFrameWork:NewSplitBar (VanguardFrame, VanguardFrame, "VanguardDamageVsHealBar", _, 294, 14)
+ DamageVsHeal:SetPoint (3, -3)
+ DamageVsHeal.fontsize = 10
+ DamageVsHeal.lefticon = "Interface\\ICONS\\misc_arrowright"
+ DamageVsHeal.righticon = "Interface\\ICONS\\misc_arrowleft"
+ DamageVsHeal.tooltip = Loc ["STRING_MOREINFORMATION"]
+ DamageVsHeal:SetHook ("OnMouseUp", funcInfo)
+
+ DamageVsHeal.iconleft:SetVertexColor (.5, 1, .5, 1)
+ DamageVsHeal.iconright:SetVertexColor (1, .5, .5, 1)
+
+ Vanguard.DamageVsHeal = DamageVsHeal
+
+ --> Hits vs Avoidance bar
+ local TookVsAvoid = DetailsFrameWork:NewSplitBar (VanguardFrame, VanguardFrame, "VanguardTookVsAvoidBar", _, 294, 14)
+ TookVsAvoid:SetPoint ("topleft", VanguardFrame, 3, -18)
+ TookVsAvoid.lefticon = "Interface\\TIMEMANAGER\\RWButton"
+ TookVsAvoid.righticon = "Interface\\TIMEMANAGER\\FFButton"
+ TookVsAvoid.tooltip = Loc ["STRING_MOREINFORMATION"]
+ TookVsAvoid:SetHook ("OnMouseUp", funcInfo)
+
+ TookVsAvoid.iconleft:SetWidth (18)
+ TookVsAvoid.iconleft:SetHeight (18)
+ TookVsAvoid.iconleft:SetPoint ("left", VanguardTookVsAvoidBar, "left", -2, 0)
+ TookVsAvoid.iconright:SetWidth (18)
+ TookVsAvoid.iconright:SetHeight (18)
+ TookVsAvoid.iconright:SetPoint ("right", VanguardTookVsAvoidBar, "right", 3, 0)
+
+ Vanguard.TookVsAvoid = TookVsAvoid
+
+ --> Reset both splits bars
+ function Vanguard:ResetBars()
+
+ TookVsAvoid:SetSplit (50)
+ TookVsAvoid:SetLeftText ("Avoid") --> localize-me
+ TookVsAvoid:SetRightText ("Hits") --> localize-me
+ TookVsAvoid:SetRightColor (.25, 0, 0, 1) --> .1, .5, .5, 1 cor boa pr pet
+ TookVsAvoid:SetLeftColor (0, .25, 0, 1)
+
+ DamageVsHeal:SetSplit (50)
+ DamageVsHeal:SetLeftText ("Inc Heal") --> localize-me
+ DamageVsHeal:SetRightText ("Inc Damage") --> localize-me
+ DamageVsHeal:SetLeftColor (.1, .9, .1, 1)
+ DamageVsHeal:SetRightColor (.9, .1, .1, 1)
+ end
+
+---------> build 6 damage text entries ---------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> entry functions
+ Vanguard.DamageLabels = {}
+
+ function Vanguard:InsertDamage (damage, index, hp)
+ Vanguard.DamageLabels [index]:SetText (_detalhes:ToK (damage))
+ local percent = damage / hp
+ local abs = _math_abs (percent-1)
+ Vanguard.DamageLabels [index]:SetTextColor (1, abs, abs, 1)
+ end
+
+ function Vanguard:NewDamage (damage)
+ local hp = _UnitHealthMax (_track_player_name) / 3
+ for i = 6, 2 do
+ Vanguard.DamageLabels [i]:SetText (Vanguard.DamageLabels [i-1]:GetText())
+ Vanguard.DamageLabels [i]:SetTextColor (Vanguard.DamageLabels [i-1]:GetTextColor())
+ end
+ Vanguard.DamageLabels [1]:SetText (_detalhes:ToK (damage))
+ Vanguard.DamageLabels [1]:SetTextColor (_math_min (damage/hp, 1), .1, .1, 1)
+ end
+
+ function Vanguard:ResetDamage()
+ for i = 1, 6 do
+ Vanguard.DamageLabels [i]:SetText ("0.0k")
+ Vanguard.DamageLabels [i]:SetTextColor (1, 1, 1, 1)
+ end
+ end
+
+ --> bg frame
+ local LastHitsBackground = DetailsFrameWork:NewPanel (VanguardFrame, _, "DetailsVanguardRowBackground", "DamageRowBackground", 296, 20)
+ LastHitsBackground:SetPoint ("topleft", VanguardFrame, 2, -35)
+ Vanguard.LastHitsBackground = LastHitsBackground
+
+ --> labels
+ for i = 1, 6 do
+ local ThisLabel = DetailsFrameWork:NewLabel (LastHitsBackground, Vanguard, nil, "DamageLabel"..i, "0.0k", "GameFontHighlightSmall", 11, {1, 1, 1, 1})
+ Vanguard.DamageLabels [i] = ThisLabel
+ ThisLabel:SetPoint ("left", LastHitsBackground.frame, 9 + ((i-1)*50), 0)
+ end
+
+
+---------> build 3 tanks debuff frames -------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ local tankframemeta = {}
+ tankframemeta.__index = tankframemeta
+
+ --> update tank information
+ function tankframemeta:SetTank (name, index)
+ if (not name) then
+ self.name = nil
+ self.TankName:SetText ("Tank "..index)
+ self.Frame:SetBackdropBorderColor (.5, .5, .5, 1)
+
+ else
+ self.name = name
+ self.TankName:SetText (name)
+
+ -- GetClass return [1] unlocalized class [2-5] TexCoords [6-8] RGB colors
+ local class, L, R, T, B, Red, Green, Blue = Vanguard:GetClass (name)
+ if (class) then
+ local color = RAID_CLASS_COLORS [class]
+ self.Frame:SetBackdropBorderColor (Red, Green, Blue, 1)
+ self.Frame:SetBackdropColor (Red, Green, Blue, 1)
+ self.Frame.tanknamebg:SetVertexColor (Red, Green, Blue, .8)
+ end
+ end
+
+ self:Disable()
+ end
+
+ --> refresh debuff information
+ function tankframemeta:Update (index, icon, expire, count, name)
+
+ if (not icon) then
+ self ["Icon"..index]:SetTexture (nil)
+ self ["Icon"..index.."DurationText"]:SetText ("")
+ self ["Icon"..index.."StackText"]:SetText ("")
+ self ["BlackBG"..index]:Hide()
+ self ["Icon"..index.."Frame"].tooltip = nil
+
+ local debuffName = self.DebuffsName [index]
+ self.DebuffsName [index] = nil
+ self.DebuffsIndex [debuffName] = nil
+ self.FreeSpots [index] = true
+ self.InUse = self.InUse - 1
+ return
+ end
+
+ self ["Icon"..index]:SetTexture (icon)
+ local minutos, segundos = _math_floor (expire/60), _math_floor (expire%60)
+ if (minutos > 0) then
+ self ["Icon"..index.."DurationText"]:SetText (minutos..":"..segundos)
+ Vanguard:SetFontSize (self ["Icon"..index.."DurationText"], 10)
+ self ["Icon"..index.."Frame"].tooltip = Loc ["STRING_DEBUFF"] .. ": " .. name .. "\n" .. Loc ["STRING_DURATION"] .. ":" .. minutos..":"..segundos
+ else
+ self ["Icon"..index.."DurationText"]:SetText (_math_floor (expire))
+ Vanguard:SetFontSize (self ["Icon"..index.."DurationText"], 18)
+ self ["Icon"..index.."Frame"].tooltip = Loc ["STRING_DEBUFF"] .. ": " .. name .. "\n" .. Loc ["STRING_DURATION"] .. ":" .. _math_floor (expire)
+ end
+ self ["Icon"..index.."StackText"]:SetText (count)
+ self ["BlackBG"..index]:Show()
+ end
+
+ --> clear all texts and icons
+ function tankframemeta:Disable()
+ self.Icon1:SetTexture (nil)
+ self.Icon1DurationText:SetText ("")
+ self.Icon1StackText:SetText ("")
+ self.Icon1Frame.tooltip = nil
+ self.BlackBG1:Hide()
+
+ self.Icon2:SetTexture (nil)
+ self.Icon2DurationText:SetText ("")
+ self.Icon2StackText:SetText ("")
+ self.Icon2Frame.tooltip = nil
+ self.BlackBG2:Hide()
+
+ self.Icon3:SetTexture (nil)
+ self.Icon3DurationText:SetText ("")
+ self.Icon3StackText:SetText ("")
+ self.Icon3Frame.tooltip = nil
+ self.BlackBG3:Hide()
+
+ table.wipe (self.DebuffsName)
+ table.wipe (self.DebuffsIndex)
+ for i = 1, 3 do
+ self.FreeSpots [i] = true
+ end
+ self.InUse = 0
+ end
+
+ function Vanguard:ResetDebuffs()
+ for _, TankFrame in _ipairs (Vanguard.TankFrames) do
+ TankFrame:Disable()
+ end
+ end
+
+ function Vanguard:UpdateHealth (index, unit)
+ local percent = UnitHealth (unit) / UnitHealthMax (unit) * 100
+ Vanguard.TankFrames [index].Life (percent)
+ end
+
+ --> build the 3 boxes
+ Vanguard.TankFrames = {}
+
+ local iconMouseOver = function (iconFrame)
+ iconFrame.icon:SetBlendMode ("ADD")
+ local OnEnterColors = iconFrame.parent.Gradient.OnEnter
+ local _r, _g, _b, _a = iconFrame.parent:GetBackdropColor()
+ DetailsFrameWork:GradientEffect (iconFrame.parent, "frame", _r, _g, _b, _a, OnEnterColors[1], OnEnterColors[2], OnEnterColors[3], OnEnterColors[4], .3)
+ end
+ local iconMouseOut = function (iconFrame)
+ iconFrame.icon:SetBlendMode ("BLEND")
+ local _r, _g, _b, _a = iconFrame.parent:GetBackdropColor()
+ if (_r) then
+ local OnLeaveColors = iconFrame.parent.Gradient.OnLeave
+ DetailsFrameWork:GradientEffect (iconFrame.parent, "frame", _r, _g, _b, _a, OnLeaveColors[1], OnLeaveColors[2], OnLeaveColors[3], OnLeaveColors[4], .3)
+ end
+ end
+
+ for i = 1, 3 do
+
+ local ThisBoxObject = {}
+ setmetatable (ThisBoxObject, tankframemeta)
+
+ ThisBoxObject.DebuffsIndex = {}
+ ThisBoxObject.DebuffsName = {}
+ ThisBoxObject.FreeSpots = {true, true, true}
+ ThisBoxObject.InUse = 0
+
+ local Frame = DetailsFrameWork:NewPanel (VanguardFrame, nil, "DetailsVanguardFrameBox"..i, _, 98, 40)
+ Frame:SetPoint ("bottomleft", VanguardFrame, 2 + ((i-1)*98), 0)
+ Frame.color = {.1, .1, .1, 1}
+ ThisBoxObject.Frame = Frame
+
+ local life = DetailsFrameWork:NewBar (Frame, Frame, "DetailsVanguardFrameBox"..i.."Life", nil, 94, 36, 100)
+ life:SetPoint (Frame, 2, -2)
+ life:SetFrameLevel (-1, Frame)
+ ThisBoxObject.Life = life
+
+ local tanknameTexture = DetailsFrameWork:NewImage (Frame, Frame, "DetailsVanguardTankName"..i.."bG", "tanknamebg", 80, 10, "Interface\\ACHIEVEMENTFRAME\\UI-Achievement-Parchment-Highlight")
+
+ tanknameTexture:SetTexCoord (0.15234375, 0.82421875, 0, 0.2734375)
+ tanknameTexture:SetPoint ("center", Frame)
+ tanknameTexture:SetPoint ("top", Frame, "top", 0, -3)
+
+
+ local tankname = DetailsFrameWork:NewLabel (Frame, Vanguard, nil, "DetailsVanguardTankName"..i, "Tank "..i, "GameFontHighlightSmall", 10, {1, 1, 1, 1})
+ tankname:SetPoint ("center", Frame)
+ tankname:SetPoint ("top", Frame, "top", 0, -2)
+ ThisBoxObject.TankName = tankname
+
+ -------------------------------------------------------------------------------------
+
+ local Icon1 = DetailsFrameWork:NewImage (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."Icon1", nil, 24, 24, "Interface\\ICONS\\Ability_Creature_Amber_02")
+ Icon1:SetDrawLayer ("overlay", 1)
+ Icon1:SetPoint ("bottomleft", ThisBoxObject.Frame.frame, 4, 3)
+
+ local frameIcon1 = DetailsFrameWork:NewPanel (Frame, VanguardFrame, "DetailsVanguardFrameBox"..i.."IconBG1", nil, 24, 24, false)
+ frameIcon1:SetPoint (Icon1)
+ frameIcon1.widget.icon = Icon1
+ frameIcon1.widget.parent = Frame.widget
+ frameIcon1:SetHook ("OnEnter", iconMouseOver)
+ frameIcon1:SetHook ("OnLeave", iconMouseOut)
+
+ local Icon1Text = DetailsFrameWork:NewLabel (ThisBoxObject.Frame.frame, Vanguard, "DetailsVanguardFrameBox"..i.."Text1", nil, "25", "GameFontHighlightLarge", 18, {1, 1, 0, 1})
+ Icon1Text:SetPoint ("center", Icon1, "center")
+
+ local blackbg1 = DetailsFrameWork:NewImage (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."BlackBG1", nil, 12, 12)
+ blackbg1:SetDrawLayer ("overlay", 2)
+ blackbg1:SetTexture (0, 0, 0, 1)
+ blackbg1:SetPoint ("bottomright", Icon1, 5, -5)
+
+ local Icon1Text2 = DetailsFrameWork:NewLabel (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."Text21", nil, "1", "GameFontHighlightSmall", 13, {1, 1, 1, 1})
+ Icon1Text2:SetPoint ("center", blackbg1, "center")
+
+ ThisBoxObject.Icon1 = Icon1
+ ThisBoxObject.Icon1Frame = frameIcon1
+ ThisBoxObject.Icon1DurationText = Icon1Text
+ ThisBoxObject.Icon1StackText = Icon1Text2
+ ThisBoxObject.BlackBG1 = blackbg1
+
+ -------------------------------------------------------------------------------------
+
+ local Icon2 = DetailsFrameWork:NewImage (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."Icon2", nil, 24, 24, "Interface\\ICONS\\Ability_Creature_Amber_02")
+ Icon2:SetDrawLayer ("overlay", 1)
+ Icon2:SetPoint ("bottomleft", Frame, 37, 3)
+
+ local frameIcon2 = DetailsFrameWork:NewPanel (Frame, VanguardFrame, "DetailsVanguardFrameBox"..i.."IconBG2", nil, 24, 24, false)
+ frameIcon2:SetPoint (Icon2)
+ frameIcon2.widget.icon = Icon2
+ frameIcon2.widget.parent = Frame.widget
+ frameIcon2:SetHook ("OnEnter", iconMouseOver)
+ frameIcon2:SetHook ("OnLeave", iconMouseOut)
+
+ local Icon2Text = DetailsFrameWork:NewLabel (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."Text2", nil, "3", "GameFontHighlightLarge", 18, {1, 1, 0, 1})
+ Icon2Text:SetPoint ("center", Icon2, "center")
+
+ local blackbg2 = DetailsFrameWork:NewImage (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."BlackBG2", nil, 12, 12)
+ blackbg2:SetDrawLayer ("overlay", 2)
+ blackbg2:SetTexture (0, 0, 0, 1)
+ blackbg2:SetPoint ("bottomright", Icon2, 5, -5)
+
+ local Icon2Text2 = DetailsFrameWork:NewLabel (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."Text22", nil, "2", "GameFontHighlightSmall", 13, {1, 1, 1, 1})
+ Icon2Text2:SetPoint ("center", blackbg2, "center")
+
+ ThisBoxObject.Icon2 = Icon2
+ ThisBoxObject.Icon2Frame = frameIcon2
+ ThisBoxObject.Icon2DurationText = Icon2Text
+ ThisBoxObject.Icon2StackText = Icon2Text2
+ ThisBoxObject.BlackBG2 = blackbg2
+
+ -------------------------------------------------------------------------------------
+
+ local Icon3 = DetailsFrameWork:NewImage (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."Icon3", nil, 24, 24, "Interface\\ICONS\\Ability_Creature_Amber_02")
+ Icon3:SetDrawLayer ("overlay", 1)
+ Icon3:SetPoint ("bottomleft", ThisBoxObject.Frame.frame, 70, 3)
+
+ local frameIcon3 = DetailsFrameWork:NewPanel (Frame, VanguardFrame, "DetailsVanguardFrameBox"..i.."IconBG3", nil, 24, 24, false)
+ frameIcon3:SetPoint (Icon3)
+ frameIcon3.widget.icon = Icon3
+ frameIcon3.widget.parent = Frame.widget
+ frameIcon3:SetHook ("OnEnter", iconMouseOver)
+ frameIcon3:SetHook ("OnLeave", iconMouseOut)
+
+ local Icon3Text = DetailsFrameWork:NewLabel (ThisBoxObject.Frame.frame, Vanguard, "DetailsVanguardFrameBox"..i.."Text3", nil, "5", "GameFontHighlightLarge", 18, {1, 1, 0, 1})
+ Icon3Text:SetPoint ("center", Icon3, "center")
+
+ local blackbg3 = DetailsFrameWork:NewImage (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."BlackBG3", nil, 12, 12)
+ blackbg3:SetDrawLayer ("overlay", 2)
+ blackbg3:SetTexture (0, 0, 0, 1)
+ blackbg3:SetPoint ("bottomright", Icon3, 5, -5)
+
+ local Icon3Text2 = DetailsFrameWork:NewLabel (Frame, Vanguard, "DetailsVanguardFrameBox"..i.."Text23", nil, "3", "GameFontHighlightSmall", 13, {1, 1, 1, 1})
+ Icon3Text2:SetPoint ("center", blackbg2, "center")
+
+ ThisBoxObject.Icon3 = Icon3
+ ThisBoxObject.Icon3Frame = frameIcon3
+ ThisBoxObject.Icon3DurationText = Icon3Text
+ ThisBoxObject.Icon3StackText = Icon3Text2
+ ThisBoxObject.BlackBG3 = blackbg3
+
+ Vanguard.TankFrames [#Vanguard.TankFrames+1] = ThisBoxObject
+
+ blackbg1:Hide()
+ blackbg2:Hide()
+ blackbg3:Hide()
+ end
+
+-------> Core function --------------------------------------------------------------------------------------------------------------------------------------------------------------------
+
+ --> cancel function
+ function Vanguard:Cancel()
+ VanguardFrame:SetScript ("OnUpdate", nil)
+ return true
+ end
+
+ --> when target change, need to verify if the new target is a player, if true, cancel everething and restart
+ function Vanguard:TargetChanged()
+
+ local NewTarget = _UnitName ("target")
+ if (NewTarget and _UnitIsPlayer ("target")) then
+ if (VanguardFrame.InfoShown and not Vanguard.Running) then
+ _track_player_name = NewTarget
+ Vanguard:VanguardRefreshInfoFrame()
+ return
+ end
+
+ Vanguard:Cancel()
+ Vanguard:Start()
+ else
+ _track_player_name = UnitName ("player")
+
+ end
+ end
+
+ --> inject into details a delayed function for vanguard
+ function _detalhes:VanguardWait()
+ Vanguard:Start()
+ end
+
+ --> main onupdate locals
+ local hits_last = 0
+ local hits_taken = {}
+ local hits_now = 0
+
+ local avoid_last = 0
+ local avoid_taken = {}
+ local avoid_now = 0
+
+ local damage_last = 0
+ local damage_taken = {}
+ local damage_now = 0
+
+ local on_second_tick = 0
+ local half_second_tick = 0
+
+ local onupdate = function (self, elapsed)
+
+ half_second_tick = half_second_tick + elapsed
+ on_second_tick = on_second_tick + elapsed
+
+ if (on_second_tick >= 1) then
+
+ --> capture debuffs
+ for TankIndex, TankName in _ipairs (Vanguard.TankList) do
+
+ local ThisTankFrame = Vanguard.TankFrames [TankIndex]
+ local updated = {false, false, false}
+
+ for i = 1, 41 do
+
+ -- pega o primeiro debuff
+ local name, _, icon, count, _, duration, expirationTime, _, _, _, spellId = _UnitDebuff (TankName, i)
+
+ if (name) then
+
+ --> already shown?
+ local debuffShowingIndex = ThisTankFrame.DebuffsIndex [name]
+ if (debuffShowingIndex) then
+
+ local expire = expirationTime - _GetTime()
+ updated [debuffShowingIndex] = true
+ ThisTankFrame:Update (debuffShowingIndex, icon, expire, count, name)
+
+ --> have a free slot?
+ elseif (ThisTankFrame.InUse < 3) then
+
+ local expire = expirationTime - _GetTime()
+ if (expire < 180 and expire > 0) then
+ for o = 1, 3 do
+ if (ThisTankFrame.FreeSpots [o]) then
+ ThisTankFrame.DebuffsIndex [name] = o
+ ThisTankFrame.DebuffsName [o] = name
+ ThisTankFrame.FreeSpots [o] = false
+ ThisTankFrame.InUse = ThisTankFrame.InUse + 1
+ updated [o] = true
+ ThisTankFrame:Update (o, icon, expire, count, name)
+ break
+ end
+ end
+ end
+ end
+
+ else
+ break
+ end
+ end
+
+ for i = 1, 3 do
+ if (not updated [i] and ThisTankFrame.DebuffsName [i]) then
+ ThisTankFrame:Update (i, false)
+ end
+ end
+
+ end
+
+ on_second_tick = 0
+ end
+
+ if (half_second_tick > 0.5) then
+
+ --> capture the amount of hits and avoids
+
+ _table_insert (hits_taken, 1, _track_player_object.avoidance.HITS - hits_last)
+ hits_now = hits_now + (_track_player_object.avoidance.HITS - hits_last)
+ if (#hits_taken > 10) then
+ hits_now = hits_now - hits_taken [11]
+ _table_remove (hits_taken, 11)
+ end
+ hits_last = _track_player_object.avoidance.HITS
+
+ _table_insert (avoid_taken, 1, _track_player_object.avoidance.DODGE + _track_player_object.avoidance.PARRY - avoid_last)
+ avoid_now = avoid_now + (_track_player_object.avoidance.DODGE + _track_player_object.avoidance.PARRY - avoid_last)
+ if (#avoid_taken > 10) then
+ avoid_now = avoid_now - avoid_taken [11]
+ _table_remove (avoid_taken, 11)
+ end
+ avoid_last = _track_player_object.avoidance.DODGE + _track_player_object.avoidance.PARRY
+
+ --> compute the hits vs avoid
+
+ if (hits_now == 0 and avoid_now == 0) then
+ TookVsAvoid:SetLeftText ("50%")
+ TookVsAvoid:SetRightText ("50%")
+ TookVsAvoid:SetSplit (50)
+ else
+ local avoidance = avoid_now
+
+ local avoid_percentage = _math_floor (avoidance / (hits_now+avoid_now) * 100)
+ local hit_percentage = _math_abs (avoid_percentage-100)
+
+ avoid_percentage = avoid_percentage or 0
+ hit_percentage = hit_percentage or 0
+
+ TookVsAvoid:SetLeftText (avoid_percentage.."%")
+ TookVsAvoid:SetRightText (hit_percentage.."%")
+
+ TookVsAvoid:SetRightColor (hit_percentage/100, 0, 0, 1)
+ TookVsAvoid:SetLeftColor (0, avoid_percentage/100, 0, 1)
+
+ if (hit_percentage > 0 and avoid_percentage > 0) then
+ if (hit_percentage > avoid_percentage) then
+ local p = avoid_percentage / hit_percentage * 100
+ p = _math_abs (p - 100)
+ p = p / 2
+ p = p + 50
+ p = _math_abs (p - 100)
+ TookVsAvoid:SetSplit (p)
+ else
+ local p = hit_percentage / avoid_percentage * 100
+ p = _math_abs (p - 100)
+ p = p / 2
+ p = p + 50
+
+ TookVsAvoid:SetSplit (p)
+ end
+ elseif (hit_percentage > 0) then
+ TookVsAvoid:SetSplit (6)
+ elseif (avoid_percentage > 0) then
+ TookVsAvoid:SetSplit (96)
+ else
+ TookVsAvoid:SetSplit (50)
+ end
+ end
+
+ --> capture the amount of damage taken in last 5 seconds
+
+ _table_insert (damage_taken, 1, _track_player_object.damage_taken - damage_last)
+ damage_now = damage_now + (_track_player_object.damage_taken - damage_last)
+ if (#damage_taken > 10) then
+ damage_now = damage_now - damage_taken [11]
+ _table_remove (damage_taken, 11)
+ end
+ damage_last = _track_player_object.damage_taken
+
+ --> compute the damage taken vs incoming heal
+
+ local dmgAmt = damage_now / #damage_taken
+ DamageVsHeal:SetRightText (Vanguard:ToK ( _math_floor (dmgAmt)))
+
+ local IncomingHeal = UnitGetIncomingHeals (_track_player_name) or 0
+ DamageVsHeal:SetLeftText (Vanguard:ToK (IncomingHeal))
+
+ if (dmgAmt > 0 and IncomingHeal > 0) then
+ if (dmgAmt > IncomingHeal) then
+ local p = IncomingHeal / dmgAmt * 100
+
+ --DamageVsHeal:SetLeftColor (0, p/100, 0, 1)
+ p = _math_abs (p - 100)
+ --DamageVsHeal:SetRightColor (p/100, 0, 0, 1)
+
+ p = p / 2
+ p = p + 50
+ p = _math_abs (p - 100)
+ DamageVsHeal:SetSplit (p)
+ else
+ local p = dmgAmt / IncomingHeal * 100
+ --DamageVsHeal:SetRightColor (p/100, 0, 0, 1)
+ p = _math_abs (p - 100)
+ --DamageVsHeal:SetLeftColor (0, p/100, 0, 1)
+ p = p / 2
+ p = p + 50
+
+ DamageVsHeal:SetSplit (p)
+ end
+ elseif (dmgAmt > 0) then
+ DamageVsHeal:SetSplit (6)
+ elseif (IncomingHeal > 0) then
+ DamageVsHeal:SetSplit (94)
+ end
+
+ --> capture the last 6 hits taken
+
+ local amt = 1
+ local hp = _UnitHealthMax (_track_player_name)/3
+
+ for _, tabela in _ipairs (_track_player_object.last_events_table) do
+ if (tabela[1]) then
+ Vanguard:InsertDamage (tabela[3], amt, hp)
+ if (amt == 6) then
+ break
+ end
+ amt = amt+1
+ end
+ end
+
+ half_second_tick = 0
+ end
+ end
+
+ function Vanguard:Start()
+
+ if (not Vanguard.Running) then
+ return
+ else
+ --> reset widgets
+ Vanguard:ResetDamage()
+ Vanguard:ResetBars()
+ end
+
+ --> first, we need to get what we want to track:
+ local MyTarget, Realm = _UnitName ("target")
+ if (MyTarget and _UnitIsPlayer ("target")) then
+ if (Realm) then
+ MyTarget = MyTarget.."-"..Realm
+ end
+ _track_player_object = _combat_object (1, MyTarget)
+ if (not _track_player_object) then
+ --print ("Vanguard: Object not found 1.")
+ _detalhes:ScheduleTimer ("VanguardWait", 1)
+ return
+ end
+
+ _track_player_name = MyTarget
+
+ if (VanguardFrame.InfoShown) then
+ Vanguard:VanguardRefreshInfoFrame()
+ end
+ else
+ _track_player_object = _combat_object (1, MyName)
+ if (not _track_player_object) then
+ --print ("Vanguard: Object not found 2.")
+ _detalhes:ScheduleTimer ("VanguardWait", 1)
+ return
+ end
+
+ _track_player_name = MyName
+
+ if (VanguardFrame.InfoShown) then
+ Vanguard:VanguardRefreshInfoFrame()
+ end
+ end
+
+ --print ("Vanguard: playername: ".. _track_player_name)
+
+ hits_last = 0
+ hits_now = 0
+ hits_taken = {}
+
+ avoid_last = 0
+ avoid_now = 0
+ avoid_taken = {}
+
+ damage_last = 0
+ damage_now = 0
+ damage_taken = {}
+
+ VanguardFrame:SetScript ("OnUpdate", onupdate)
+
+ end
+
+ --> identify tanks on startup
+ Vanguard:IdentifyTanks()
+ Vanguard:ResetBars()
+
+end
+
+function Vanguard:OnEvent (_, event, ...)
+
+ if (event == "UNIT_HEALTH") then
+ Vanguard:HealthChanged (...)
+
+ elseif (event == "ADDON_LOADED") then
+ local AddonName = select (1, ...)
+ if (AddonName == "Details_Vanguard") then
+
+ if (_G._detalhes) then
+
+ --> create widgets
+ CreatePluginFrames (data)
+
+ local MINIMAL_DETAILS_VERSION_REQUIRED = 1
+
+ --> Install
+ local install = _G._detalhes:InstallPlugin ("TANK", Loc ["STRING_PLUGIN_NAME"], "Interface\\Icons\\INV_Shield_77", Vanguard, "DETAILS_PLUGIN_VANGUARD", MINIMAL_DETAILS_VERSION_REQUIRED)
+ if (type (install) == "table" and install.error) then
+ print (install.error)
+ end
+
+ --> Register needed events
+ _G._detalhes:RegisterEvent (Vanguard, "COMBAT_PLAYER_ENTER")
+ _G._detalhes:RegisterEvent (Vanguard, "COMBAT_PLAYER_LEAVE")
+ _G._detalhes:RegisterEvent (Vanguard, "DETAILS_INSTANCE_ENDRESIZE")
+ _G._detalhes:RegisterEvent (Vanguard, "DETAILS_INSTANCE_SIZECHANGED")
+ _G._detalhes:RegisterEvent (Vanguard, "DETAILS_INSTANCE_STARTSTRETCH")
+ _G._detalhes:RegisterEvent (Vanguard, "DETAILS_INSTANCE_ENDSTRETCH")
+
+ VanguardFrame:RegisterEvent ("ZONE_CHANGED_NEW_AREA")
+ VanguardFrame:RegisterEvent ("PLAYER_ENTERING_WORLD")
+ end
+ end
+
+ elseif (event == "PLAYER_LOGOUT") then
+ _detalhes_databaseVanguard = Vanguard.data
+
+ elseif (event == "PLAYER_TARGET_CHANGED") then
+ Vanguard:TargetChanged()
+
+ elseif (event == "ROLE_CHANGED_INFORM" or event == "RAID_ROSTER_UPDATE") then --> raid changes
+ Vanguard:IdentifyTanks()
+
+ elseif (event == "ZONE_CHANGED_NEW_AREA" or event == "PLAYER_ENTERING_WORLD") then --> logon or map changes
+ Vanguard:IdentifyTanks()
+
+ end
+end
diff --git a/plugins/Details_Vanguard/Details_Vanguard.toc b/plugins/Details_Vanguard/Details_Vanguard.toc
new file mode 100644
index 00000000..46f1b351
--- /dev/null
+++ b/plugins/Details_Vanguard/Details_Vanguard.toc
@@ -0,0 +1,15 @@
+## Interface: 50300
+## Title: Details Vanguard (plugin)
+## Notes: Plugin for Details
+## SavedVariablesPerCharacter: _detalhes_databaseVanguard
+## RequiredDeps: Details
+## OptionalDeps: Ace3
+
+#@no-lib-strip@
+embeds.xml
+#@end-no-lib-strip@
+
+enUS.lua
+ptBR.lua
+
+Details_Vanguard.lua
\ No newline at end of file
diff --git a/plugins/Details_Vanguard/Libs/AceLocale-3.0/AceLocale-3.0.lua b/plugins/Details_Vanguard/Libs/AceLocale-3.0/AceLocale-3.0.lua
new file mode 100644
index 00000000..2ecc0cb8
--- /dev/null
+++ b/plugins/Details_Vanguard/Libs/AceLocale-3.0/AceLocale-3.0.lua
@@ -0,0 +1,137 @@
+--- **AceLocale-3.0** manages localization in addons, allowing for multiple locale to be registered with fallback to the base locale for untranslated strings.
+-- @class file
+-- @name AceLocale-3.0
+-- @release $Id: AceLocale-3.0.lua 1035 2011-07-09 03:20:13Z kaelten $
+local MAJOR,MINOR = "AceLocale-3.0", 6
+
+local AceLocale, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not AceLocale then return end -- no upgrade needed
+
+-- Lua APIs
+local assert, tostring, error = assert, tostring, error
+local getmetatable, setmetatable, rawset, rawget = getmetatable, setmetatable, rawset, rawget
+
+-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
+-- List them here for Mikk's FindGlobals script
+-- GLOBALS: GAME_LOCALE, geterrorhandler
+
+local gameLocale = GetLocale()
+if gameLocale == "enGB" then
+ gameLocale = "enUS"
+end
+
+AceLocale.apps = AceLocale.apps or {} -- array of ["AppName"]=localetableref
+AceLocale.appnames = AceLocale.appnames or {} -- array of [localetableref]="AppName"
+
+-- This metatable is used on all tables returned from GetLocale
+local readmeta = {
+ __index = function(self, key) -- requesting totally unknown entries: fire off a nonbreaking error and return key
+ rawset(self, key, key) -- only need to see the warning once, really
+ geterrorhandler()(MAJOR..": "..tostring(AceLocale.appnames[self])..": Missing entry for '"..tostring(key).."'")
+ return key
+ end
+}
+
+-- This metatable is used on all tables returned from GetLocale if the silent flag is true, it does not issue a warning on unknown keys
+local readmetasilent = {
+ __index = function(self, key) -- requesting totally unknown entries: return key
+ rawset(self, key, key) -- only need to invoke this function once
+ return key
+ end
+}
+
+-- Remember the locale table being registered right now (it gets set by :NewLocale())
+-- NOTE: Do never try to register 2 locale tables at once and mix their definition.
+local registering
+
+-- local assert false function
+local assertfalse = function() assert(false) end
+
+-- This metatable proxy is used when registering nondefault locales
+local writeproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ rawset(registering, key, value == true and key or value) -- assigning values: replace 'true' with key string
+ end,
+ __index = assertfalse
+})
+
+-- This metatable proxy is used when registering the default locale.
+-- It refuses to overwrite existing values
+-- Reason 1: Allows loading locales in any order
+-- Reason 2: If 2 modules have the same string, but only the first one to be
+-- loaded has a translation for the current locale, the translation
+-- doesn't get overwritten.
+--
+local writedefaultproxy = setmetatable({}, {
+ __newindex = function(self, key, value)
+ if not rawget(registering, key) then
+ rawset(registering, key, value == true and key or value)
+ end
+ end,
+ __index = assertfalse
+})
+
+--- Register a new locale (or extend an existing one) for the specified application.
+-- :NewLocale will return a table you can fill your locale into, or nil if the locale isn't needed for the players
+-- game locale.
+-- @paramsig application, locale[, isDefault[, silent]]
+-- @param application Unique name of addon / module
+-- @param locale Name of the locale to register, e.g. "enUS", "deDE", etc.
+-- @param isDefault If this is the default locale being registered (your addon is written in this language, generally enUS)
+-- @param silent If true, the locale will not issue warnings for missing keys. Must be set on the first locale registered. If set to "raw", nils will be returned for unknown keys (no metatable used).
+-- @usage
+-- -- enUS.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "enUS", true)
+-- L["string1"] = true
+--
+-- -- deDE.lua
+-- local L = LibStub("AceLocale-3.0"):NewLocale("TestLocale", "deDE")
+-- if not L then return end
+-- L["string1"] = "Zeichenkette1"
+-- @return Locale Table to add localizations to, or nil if the current locale is not required.
+function AceLocale:NewLocale(application, locale, isDefault, silent)
+
+ -- GAME_LOCALE allows translators to test translations of addons without having that wow client installed
+ local gameLocale = GAME_LOCALE or gameLocale
+
+ local app = AceLocale.apps[application]
+
+ if silent and app and getmetatable(app) ~= readmetasilent then
+ geterrorhandler()("Usage: NewLocale(application, locale[, isDefault[, silent]]): 'silent' must be specified for the first locale registered")
+ end
+
+ if not app then
+ if silent=="raw" then
+ app = {}
+ else
+ app = setmetatable({}, silent and readmetasilent or readmeta)
+ end
+ AceLocale.apps[application] = app
+ AceLocale.appnames[app] = application
+ end
+
+ if locale ~= gameLocale and not isDefault then
+ return -- nop, we don't need these translations
+ end
+
+ registering = app -- remember globally for writeproxy and writedefaultproxy
+
+ if isDefault then
+ return writedefaultproxy
+ end
+
+ return writeproxy
+end
+
+--- Returns localizations for the current locale (or default locale if translations are missing).
+-- Errors if nothing is registered (spank developer, not just a missing translation)
+-- @param application Unique name of addon / module
+-- @param silent If true, the locale is optional, silently return nil if it's not found (defaults to false, optional)
+-- @return The locale table for the current language.
+function AceLocale:GetLocale(application, silent)
+ if not silent and not AceLocale.apps[application] then
+ error("Usage: GetLocale(application[, silent]): 'application' - No locales registered for '"..tostring(application).."'", 2)
+ end
+ return AceLocale.apps[application]
+end
diff --git a/plugins/Details_Vanguard/Libs/AceLocale-3.0/AceLocale-3.0.xml b/plugins/Details_Vanguard/Libs/AceLocale-3.0/AceLocale-3.0.xml
new file mode 100644
index 00000000..d69dbb13
--- /dev/null
+++ b/plugins/Details_Vanguard/Libs/AceLocale-3.0/AceLocale-3.0.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/plugins/Details_Vanguard/Libs/LibStub/LibStub.lua b/plugins/Details_Vanguard/Libs/LibStub/LibStub.lua
new file mode 100644
index 00000000..f5fc9192
--- /dev/null
+++ b/plugins/Details_Vanguard/Libs/LibStub/LibStub.lua
@@ -0,0 +1,51 @@
+-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
+-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain
+-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+-- Check to see is this version of the stub is obsolete
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+ LibStub = LibStub or {libs = {}, minors = {} }
+ _G[LIBSTUB_MAJOR] = LibStub
+ LibStub.minor = LIBSTUB_MINOR
+
+ -- LibStub:NewLibrary(major, minor)
+ -- major (string) - the major version of the library
+ -- minor (string or number ) - the minor version of the library
+ --
+ -- returns nil if a newer or same version of the lib is already present
+ -- returns empty library object or old library object if upgrade is needed
+ function LibStub:NewLibrary(major, minor)
+ assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+ minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+ local oldminor = self.minors[major]
+ if oldminor and oldminor >= minor then return nil end
+ self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+ return self.libs[major], oldminor
+ end
+
+ -- LibStub:GetLibrary(major, [silent])
+ -- major (string) - the major version of the library
+ -- silent (boolean) - if true, library is optional, silently return nil if its not found
+ --
+ -- throws an error if the library can not be found (except silent is set)
+ -- returns the library object if found
+ function LibStub:GetLibrary(major, silent)
+ if not self.libs[major] and not silent then
+ error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+ end
+ return self.libs[major], self.minors[major]
+ end
+
+ -- LibStub:IterateLibraries()
+ --
+ -- Returns an iterator for the currently registered libraries
+ function LibStub:IterateLibraries()
+ return pairs(self.libs)
+ end
+
+ setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end
diff --git a/plugins/Details_Vanguard/Libs/LibStub/LibStub.toc b/plugins/Details_Vanguard/Libs/LibStub/LibStub.toc
new file mode 100644
index 00000000..c3dc3656
--- /dev/null
+++ b/plugins/Details_Vanguard/Libs/LibStub/LibStub.toc
@@ -0,0 +1,13 @@
+## Interface: 40200
+## Title: Lib: LibStub
+## Notes: Universal Library Stub
+## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
+## X-Website: http://www.wowace.com/addons/libstub/
+## X-Category: Library
+## X-License: Public Domain
+## X-Curse-Packaged-Version: r95
+## X-Curse-Project-Name: LibStub
+## X-Curse-Project-ID: libstub
+## X-Curse-Repository-ID: wow/libstub/mainline
+
+LibStub.lua
diff --git a/plugins/Details_Vanguard/Libs/LibStub/tests/test.lua b/plugins/Details_Vanguard/Libs/LibStub/tests/test.lua
new file mode 100644
index 00000000..645a08b1
--- /dev/null
+++ b/plugins/Details_Vanguard/Libs/LibStub/tests/test.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
+assert(lib) -- should return the library table
+assert(not oldMinor) -- should not return the old minor, since it didn't exist
+
+-- the following is to create data and then be able to check if the same data exists after the fact
+function lib:MyMethod()
+end
+local MyMethod = lib.MyMethod
+lib.MyTable = {}
+local MyTable = lib.MyTable
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
+assert(not newLib) -- should not return since out of date
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
+assert(newLib) -- library table
+assert(rawequal(newLib, lib)) -- should be the same reference as the previous
+assert(newOldMinor == 1) -- should return the minor version of the previous version
+
+assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
+assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib) -- library table
+assert(newOldMinor == 2) -- previous version was 2
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
+assert(newLib)
+assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
+
+local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
+assert(newLib)
+assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
\ No newline at end of file
diff --git a/plugins/Details_Vanguard/Libs/LibStub/tests/test2.lua b/plugins/Details_Vanguard/Libs/LibStub/tests/test2.lua
new file mode 100644
index 00000000..af431dd3
--- /dev/null
+++ b/plugins/Details_Vanguard/Libs/LibStub/tests/test2.lua
@@ -0,0 +1,27 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib doesn't exist yet, by iterating through all the libraries
+ assert(major ~= "MyLib")
+end
+
+assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
+assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
+local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
+assert(lib) -- check it exists
+assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
+
+assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
+
+local count=0
+for major, library in LibStub:IterateLibraries() do
+ -- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
+ if major == "MyLib" then -- we found it!
+ count = count +1
+ assert(rawequal(library, lib)) -- verify that the references are equal
+ end
+end
+assert(count == 1) -- verify that we actually found it, and only once
diff --git a/plugins/Details_Vanguard/Libs/LibStub/tests/test3.lua b/plugins/Details_Vanguard/Libs/LibStub/tests/test3.lua
new file mode 100644
index 00000000..01aabb8d
--- /dev/null
+++ b/plugins/Details_Vanguard/Libs/LibStub/tests/test3.lua
@@ -0,0 +1,14 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+local proxy = newproxy() -- non-string
+
+assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
+local success, ret = pcall(LibStub.GetLibrary, proxy, true)
+assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
+
+assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
+
+assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
\ No newline at end of file
diff --git a/plugins/Details_Vanguard/Libs/LibStub/tests/test4.lua b/plugins/Details_Vanguard/Libs/LibStub/tests/test4.lua
new file mode 100644
index 00000000..15a9c9cd
--- /dev/null
+++ b/plugins/Details_Vanguard/Libs/LibStub/tests/test4.lua
@@ -0,0 +1,41 @@
+debugstack = debug.traceback
+strmatch = string.match
+
+loadfile("../LibStub.lua")()
+
+
+-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
+assert(LibStub.minor)
+LibStub.minor = LibStub.minor - 0.0001
+LibStub.IterateLibraries = nil
+
+loadfile("../LibStub.lua")()
+
+assert(type(LibStub.IterateLibraries)=="function")
+
+
+-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
+LibStub.IterateLibraries = 123
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
+LibStub.minor = LibStub.minor + 0.0001
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+-- Again with a huge number
+LibStub.minor = LibStub.minor + 1234567890
+
+loadfile("../LibStub.lua")()
+
+assert(LibStub.IterateLibraries == 123)
+
+
+print("OK")
\ No newline at end of file
diff --git a/plugins/Details_Vanguard/embeds.xml b/plugins/Details_Vanguard/embeds.xml
new file mode 100644
index 00000000..9cd274d8
--- /dev/null
+++ b/plugins/Details_Vanguard/embeds.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/plugins/Details_Vanguard/enUS.lua b/plugins/Details_Vanguard/enUS.lua
new file mode 100644
index 00000000..aeeb69e7
--- /dev/null
+++ b/plugins/Details_Vanguard/enUS.lua
@@ -0,0 +1,18 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_Vanguard", "enUS", true)
+
+if (not Loc) then
+ return
+end
+
+Loc ["STRING_PLUGIN_NAME"] = "Vanguard"
+Loc ["STRING_MOREINFORMATION"] = "Click for more information"
+
+Loc ["STRING_HEALRECEIVED"] = "Heal Received"
+Loc ["STRING_HPS"] = "RHPS"
+Loc ["STRING_HITS"] = "Hits Received"
+Loc ["STRING_DODGE"] = "Dodge"
+Loc ["STRING_PARRY"] = "Parry"
+Loc ["STRING_DAMAGETAKEN"] = "Damage Taken"
+Loc ["STRING_DTPS"] = "DTPS"
+Loc ["STRING_DEBUFF"] = "Debuff"
+Loc ["STRING_DURATION"] = "Duration"
\ No newline at end of file
diff --git a/plugins/Details_Vanguard/ptBR.lua b/plugins/Details_Vanguard/ptBR.lua
new file mode 100644
index 00000000..f97f6120
--- /dev/null
+++ b/plugins/Details_Vanguard/ptBR.lua
@@ -0,0 +1,18 @@
+local Loc = LibStub("AceLocale-3.0"):NewLocale("Details_Vanguard", "ptBR")
+
+if (not Loc) then
+ return
+end
+
+Loc ["STRING_PLUGIN_NAME"] = "Vanguard"
+Loc ["STRING_MOREINFORMATION"] = "Clique para mais informacoes"
+
+Loc ["STRING_HEALRECEIVED"] = "Cura recebida"
+Loc ["STRING_HPS"] = "CRPS"
+Loc ["STRING_HITS"] = "Golpes sofridos"
+Loc ["STRING_DODGE"] = "Esquiva"
+Loc ["STRING_PARRY"] = "Bloqueio"
+Loc ["STRING_DAMAGETAKEN"] = "Dano recebido"
+Loc ["STRING_DTPS"] = "DRPS"
+Loc ["STRING_DEBUFF"] = "Debuff"
+Loc ["STRING_DURATION"] = "Duracao"
\ No newline at end of file
diff --git a/startup.lua b/startup.lua
new file mode 100644
index 00000000..8929a0ee
--- /dev/null
+++ b/startup.lua
@@ -0,0 +1,265 @@
+--File Revision: 1
+--Last Modification: 27/07/2013
+-- Change Log:
+ -- 27/07/2013: Finished alpha version.
+
+function _G._detalhes:Start()
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> details defaults
+
+ -- _detalhes.debug = true
+
+ --> who is
+ self.playername = UnitName ("player")
+ self.playerserial = UnitGUID ("player")
+
+ --> player faction and enemy faction
+ self.faction = UnitFactionGroup ("player")
+ if (self.faction == PLAYER_FACTION_GROUP[0]) then --> player is horde
+ self.faction_against = PLAYER_FACTION_GROUP[1] --> ally
+ elseif (self.faction == PLAYER_FACTION_GROUP[1]) then --> player is alliance
+ self.faction_against = PLAYER_FACTION_GROUP[0] --> horde
+ end
+
+ self.zone_type = nil
+ _detalhes.temp_table1 = {}
+
+ --> combat
+ self.in_combat = false
+ self.combat_id = self.combat_id or 0
+ self.segments_amount = self.segments_amount or 3
+ self.segments_amount_to_save = self.segments_amount_to_save or 2
+ self.deadlog_limit = self.deadlog_limit or 12
+ self.minimum_combat_time = self.minimum_combat_time or 5
+
+ if (type (self.segments_panic_mode) ~= "boolean") then
+ self.segments_panic_mode = true
+ end
+
+ if (type (self.clear_graphic) ~= "boolean") then
+ self.clear_graphic = self.clear_graphic or true
+ end
+
+ if (type (self.clear_ungrouped) ~= "boolean") then
+ self.clear_ungrouped = self.clear_ungrouped or true
+ end
+
+ if (type (self.use_row_animations) ~= "boolean") then
+ self.use_row_animations = self.use_row_animations or false
+ end
+
+ --> instances (windows)
+ self.solo = self.solo or nil
+ self.raid = self.raid or nil
+ self.opened_windows = 0
+
+ self.update_speed = self.update_speed or 1
+ self.time_type = self.time_type or 1
+
+ self.row_fade_in = self.row_fade_in or {"in", 0.2}
+ self.row_fade_out = self.row_fade_out or {"out", 0.2}
+ self.windows_fade_in = self.windows_fade_in or {"in", 0.2}
+ self.windows_fade_out = self.windows_fade_out or {"out", 0.2}
+
+ self.default_texture = [[Interface\AddOns\Details\images\bar4]]
+ self.default_texture_name = "Details D'ictum"
+
+ self.default_bg_color = self.default_bg_color or 0.0941
+ self.default_bg_alpha = self.default_bg_alpha or 0.7
+
+ self.new_window_size = self.new_window_size or {width = 300, height = 95}
+ self.max_window_size = self.max_window_size or {width = 480, height = 450}
+ self.window_clamp = self.window_clamp or {-8, 0, 30, -14}
+
+ self.report_lines = self.report_lines or 5
+ self.report_to_who = self.report_to_who or ""
+
+ self.animate_scroll = self.animate_scroll or false
+ self.use_scroll = self.use_scroll or false
+
+ self.tooltip_max_targets = 3
+ self.tooltip_max_abilities = 3
+ self.tooltip_max_pets = 1
+
+ self.font_sizes = self.font_sizes or {
+ menus = 10
+ }
+
+ self.tutorial = self.tutorial or {}
+ self.tutorial.unlock_button = self.tutorial.unlock_button or 0
+ self.tutorial.version_announce = self.tutorial.version_announce or 0
+ self.tutorial.main_help_button = self.tutorial.main_help_button or 0
+
+ --> class colors and tcoords
+ if (not self.class_colors) then
+ self.class_colors = {}
+ for classe, tabela_cor in pairs ( RAID_CLASS_COLORS ) do
+ self.class_colors [classe] = {tabela_cor.r, tabela_cor.g, tabela_cor.b}
+ end
+ --self.class_colors ["UNKNOW"] = {0.3921, 0.0980, 0.0980}
+ self.class_colors ["UNKNOW"] = {0.2, 0.2, 0.2}
+ self.class_colors ["UNGROUPPLAYER"] = {0.4, 0.4, 0.4}
+ self.class_colors ["PET"] = {0.3, 0.4, 0.5}
+ end
+
+ self.class_coords = {}
+ for class, tcoord in pairs (_G.CLASS_ICON_TCOORDS) do
+ self.class_coords [class] = tcoord
+ end
+
+ self.class_icons_small = [[Interface\AddOns\Details\images\classes_small]]
+ self.class_coords ["Alliance"] = {0.49609375, 0.7421875, 0.75, 1}
+ self.class_coords ["Horde"] = {0.7421875, 0.98828125, 0.75, 1}
+ self.class_coords ["PET"] = {0.25, 0.49609375, 0.75, 1}
+ self.class_coords ["MONSTER"] = {0, 0.25, 0.75, 1}
+
+ self.class_coords ["UNKNOW"] = {0.5, 0.75, 0.75, 1}
+ self.class_coords ["UNGROUPPLAYER"] = {0.5, 0.75, 0.75, 1}
+
+
+
+
+ --> single click row function replace
+ --damage, dps, damage taken, friendly fire
+ self.row_singleclick_overwrite [1] = {true, true, true, true}
+ --healing, hps, overheal, healing taken
+ self.row_singleclick_overwrite [2] = {true, true, true, true}
+ --mana, rage, energy, runepower
+ self.row_singleclick_overwrite [3] = {true, true, true, true}
+ --cc breaks, ress, interrupts, dispells, deaths
+ self.row_singleclick_overwrite [4] = {true, true, true, true, self.atributo_misc.ReportSingleDeadLine}
+
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--> initialize
+
+ --> build frames
+ --> cooltip
+ self.popup = DetailsCreateCoolTip()
+ --> fast switch
+ if (self.switch.InitSwitch) then
+ self.switch:InitSwitch()
+ end
+ --> custom window
+ self.custom = self.custom or {}
+ self:InitCustom()
+ --> actor info
+ self.janela_info = self.gump:CriaJanelaInfo()
+ self.gump:Fade (self.janela_info, 1)
+ --> copy and paste window
+ self:CreateCopyPasteWindow()
+ self.CreateCopyPasteWindow = nil
+
+ --> start instances
+ if (self:QuantasInstancias() == 0) then
+ self:CriarInstancia()
+ else
+ self:ReativarInstancias()
+ end
+ self:GetLowerInstanceNumber()
+ self:CheckConsolidates()
+
+ --> start time machine
+ self.timeMachine:Ligar()
+
+ --> start instances updater
+ self:AtualizaGumpPrincipal (-1, true)
+ self.atualizador = self:ScheduleRepeatingTimer ("AtualizaGumpPrincipal", _detalhes.update_speed, -1)
+
+ for index = 1, #self.tabela_instancias do
+ local instance = self.tabela_instancias [index]
+ if (instance:IsAtiva()) then
+ self:ScheduleTimer ("RefreshBars", 1, instance)
+ end
+ end
+
+ function self:AtualizaGumps()
+ self:AtualizaGumpPrincipal (-1, true)
+ self.AtualizaGumps = nil
+ for index = 1, #self.tabela_instancias do
+ local instance = self.tabela_instancias [index]
+ if (instance:IsAtiva()) then
+ if (instance.wallpaper.enabled) then
+ instance:InstanceWallpaper (true)
+ end
+ end
+ end
+ end
+ self:ScheduleTimer ("AtualizaGumps", 4)
+
+ --> start garbage collector
+ self.ultima_coleta = 0
+ self.intervalo_coleta = 1800
+ self.garbagecollect = self:ScheduleRepeatingTimer ("IniciarColetaDeLixo", self.intervalo_coleta)
+
+ --> start parser
+
+ --> load parser capture options
+ self:CaptureRefresh()
+ --> register parser events
+ self.listener:RegisterEvent ("COMBAT_LOG_EVENT_UNFILTERED")
+ self.listener:RegisterEvent ("PLAYER_REGEN_DISABLED")
+ self.listener:RegisterEvent ("PLAYER_REGEN_ENABLED")
+ self.listener:RegisterEvent ("SPELL_SUMMON")
+ self.listener:RegisterEvent ("UNIT_PET")
+
+ self.listener:RegisterEvent ("PARTY_MEMBERS_CHANGED")
+ self.listener:RegisterEvent ("RAID_ROSTER_UPDATE")
+ self.listener:RegisterEvent ("PARTY_CONVERTED_TO_RAID")
+
+ self.listener:RegisterEvent ("INSTANCE_ENCOUNTER_ENGAGE_UNIT")
+
+ self.listener:RegisterEvent ("ZONE_CHANGED_NEW_AREA")
+ self.listener:RegisterEvent ("PLAYER_ENTERING_WORLD")
+
+ -- self.listener:RegisterEvent ("SPELL_CAST_START")
+ -- self.listener:RegisterEvent ("UNIT_SPELLCAST_STOP")
+ -- self.listener:RegisterEvent ("UNIT_SPELLCAST_SUCCEEDED")
+ -- self.listener:RegisterEvent ("UNIT_SPELLCAST_FAILED")
+ -- self.listener:RegisterEvent ("UNIT_SPELLCAST_FAILED_QUIET")
+ -- self.listener:RegisterEvent ("UNIT_SPELLCAST_INTERRUPTED")
+ ----------------------------------------------------------------------------------------------------------------------------------------
+
+
+ --> done
+ self.initializing = nil
+
+ --> send messages gathered on initialization
+ self:ScheduleTimer ("ShowDelayMsg", 7)
+
+ --> send instance open signal
+ for index, instancia in ipairs (self.tabela_instancias) do
+ if (instancia.ativa) then
+ self:SendEvent ("DETAILS_INSTANCE_OPEN", nil, instancia)
+ end
+ end
+
+ --> all done, send started signal and we are ready
+ function self:AnnounceStartup()
+ self:SendEvent ("DETAILS_STARTED", "SEND_TO_ALL")
+ end
+ self:ScheduleTimer ("AnnounceStartup", 5)
+
+ --> announce alpha version
+ function self:AnnounceVersion()
+ for index, instancia in ipairs (self.tabela_instancias) do
+ if (instancia.ativa) then
+ self.gump:Fade (instancia._version, "in", 5)
+ end
+ end
+ end
+
+ if (self.tutorial.version_announce < 4) then
+ self:ScheduleTimer ("AnnounceVersion", 20)
+ self.tutorial.version_announce = self.tutorial.version_announce + 1
+ else
+ for index, instancia in ipairs (self.tabela_instancias) do
+ if (instancia.ativa) then
+ instancia._version:SetText ("Details Alpha (" .. self.realversion..")")
+ instancia._version:SetPoint ("bottomleft", self.baseframe, "bottomleft", 0, 16)
+ self.gump:Fade (instancia._version, "in", 10)
+ end
+ end
+ end
+
+end