first Details commit
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
## 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\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
|
||||
@@ -0,0 +1,17 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\..\FrameXML\UI.xsd">
|
||||
|
||||
<Frame name="_detalhes_listener">
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self:RegisterEvent ("ADDON_LOADED");
|
||||
self:RegisterEvent ("PLAYER_LOGOUT");
|
||||
</OnLoad>
|
||||
<OnEvent>
|
||||
_detalhes.OnEvent (self, event, ...);
|
||||
</OnEvent>
|
||||
</Scripts>
|
||||
</Frame>
|
||||
</Ui>
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceAddon-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="ChatThrottleLib.lua"/>
|
||||
<Script file="AceComm-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -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 an addon somewhere. Get the addon updated or copy in a newer ChatThrottleLib.lua (>=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
|
||||
]]
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceLocale-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -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<mantissa>^f<exponent>
|
||||
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
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceSerializer-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -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 when<soon ... else
|
||||
end -- while nexttimer do
|
||||
end -- for curint=lastint,nowint
|
||||
|
||||
lastint = nowint
|
||||
end
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- Reg( callback, delay, arg, repeating )
|
||||
--
|
||||
-- callback( function or string ) - direct function ref or method name in our object for the callback
|
||||
-- delay(int) - delay for the timer
|
||||
-- arg(variant) - any argument to be passed to the callback function
|
||||
-- repeating(boolean) - repeating timer, or oneshot
|
||||
--
|
||||
-- returns the handle of the timer for later processing (canceling etc)
|
||||
local function Reg(self, callback, delay, arg, repeating)
|
||||
if type(callback) ~= "string" and type(callback) ~= "function" then
|
||||
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
|
||||
error(MAJOR..": " .. error_origin .. "(callback, delay, arg): 'callback' - function or method name expected.", 3)
|
||||
end
|
||||
if type(callback) == "string" then
|
||||
if type(self)~="table" then
|
||||
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
|
||||
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'self' - must be a table.", 3)
|
||||
end
|
||||
if type(self[callback]) ~= "function" then
|
||||
local error_origin = repeating and "ScheduleRepeatingTimer" or "ScheduleTimer"
|
||||
error(MAJOR..": " .. error_origin .. "(\"methodName\", delay, arg): 'methodName' - method not found on target object.", 3)
|
||||
end
|
||||
end
|
||||
|
||||
if delay < (1 / (HZ - 1)) then
|
||||
delay = 1 / (HZ - 1)
|
||||
end
|
||||
|
||||
-- Create and stuff timer in the correct hash bucket
|
||||
local now = GetTime()
|
||||
|
||||
local timer = timerCache or {} -- Get new timer object (from cache if available)
|
||||
timerCache = nil
|
||||
|
||||
timer.object = self
|
||||
timer.callback = callback
|
||||
timer.delay = (repeating and delay)
|
||||
timer.arg = arg
|
||||
timer.when = now + delay
|
||||
|
||||
local bucket = (floor((now+delay)*HZ) % BUCKETS) + 1
|
||||
timer.next = hash[bucket]
|
||||
hash[bucket] = timer
|
||||
|
||||
-- Insert timer in our self->handle->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.
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="AceTimer-3.0.lua"/>
|
||||
</Ui>
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="CallbackHandler-1.0.lua"/>
|
||||
</Ui>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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
|
||||
@@ -0,0 +1,4 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="LibSharedMedia-3.0.lua" />
|
||||
</Ui>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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")
|
||||
@@ -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
|
||||
@@ -0,0 +1,456 @@
|
||||
--[[
|
||||
-------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
|
||||
return self.end_time - self.start_time
|
||||
elseif (self.start_time and _detalhes.in_combat) then
|
||||
return _tempo - self.start_time
|
||||
else
|
||||
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
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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 <instancia.esta_barra> "..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
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
--]]
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,9 @@
|
||||
local _detalhes = _G._detalhes
|
||||
|
||||
function _detalhes:UpdateGears()
|
||||
|
||||
_detalhes:UpdateParser()
|
||||
_detalhes:UpdateControl()
|
||||
_detalhes:UpdateCombat()
|
||||
|
||||
end
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,286 @@
|
||||
--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()
|
||||
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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,565 @@
|
||||
--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
|
||||
|
||||
-- -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
|
||||
@@ -0,0 +1,11 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
|
||||
<Script file="Libs\LibStub\LibStub.lua"/>
|
||||
<Include file="Libs\CallbackHandler-1.0\CallbackHandler-1.0.xml" />
|
||||
<Include file="Libs\AceLocale-3.0\AceLocale-3.0.xml" />
|
||||
<Include file="Libs\AceAddon-3.0\AceAddon-3.0.xml" />
|
||||
<Include file="Libs\AceComm-3.0\AceComm-3.0.xml" />
|
||||
<Include file="Libs\AceSerializer-3.0\AceSerializer-3.0.xml" />
|
||||
<Include file="Libs\AceTimer-3.0\AceTimer-3.0.xml" />
|
||||
<Include file="Libs\LibSharedMedia-3.0\lib.xml"/>
|
||||
<Script file="Libs\LibGraph-2.0\LibGraph-2.0.lua"/>
|
||||
</Ui>
|
||||
@@ -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
|
||||
@@ -0,0 +1,40 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
|
||||
<Script file="button.lua"/>
|
||||
|
||||
<Button name="DetailsButtonTemplate" virtual="true">
|
||||
<Size x="100" y="20"/>
|
||||
|
||||
<Layers>
|
||||
|
||||
<Layer level="ARTWORK">
|
||||
|
||||
<!-- text -->
|
||||
<FontString name="$parent_Text" parentKey="text" inherits="GameFontNormal" justifyH="CENTER" nonspacewrap="false">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="$parent" relativePoint="CENTER" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
</Layer>
|
||||
|
||||
<Layer level="OVERLAY">
|
||||
<Texture name="$parent_TextureDisabled" setAllPoints="true" hidden="true" parentKey="texture_disabled" file = "Interface\AddOns\Details\images\button_disable_overlay"/>
|
||||
</Layer>
|
||||
|
||||
</Layers>
|
||||
|
||||
<Scripts>
|
||||
|
||||
<OnDisable>
|
||||
self.texture_disabled:Show()
|
||||
</OnDisable>
|
||||
|
||||
<OnEnable>
|
||||
self.texture_disabled:Hide()
|
||||
</OnEnable>
|
||||
|
||||
</Scripts>
|
||||
|
||||
</Button>
|
||||
</Ui>
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,194 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
|
||||
<Script file="cooltip.lua"/>
|
||||
|
||||
<Frame name="CooltipMainFrameTemplate" virtual="true" frameStrata="TOOLTIP">
|
||||
<Size x="1" y="1"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="$parent" relativePoint="CENTER" x="0" y="0"/>
|
||||
</Anchors>
|
||||
|
||||
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background-Dark" edgeFile="Interface\Tooltips\UI-Tooltip-Border" tile="true">
|
||||
<EdgeSize>
|
||||
<AbsValue val="16"/>
|
||||
</EdgeSize>
|
||||
<TileSize>
|
||||
<AbsValue val="16"/>
|
||||
</TileSize>
|
||||
<BackgroundInsets>
|
||||
<AbsInset left="5" right="5" top="5" bottom="5"/>
|
||||
</BackgroundInsets>
|
||||
</Backdrop>
|
||||
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self:SetBackdropColor (0.09019, 0.09019, 0.18823, 1)
|
||||
self:SetBackdropBorderColor (1, 1, 1, 1)
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
|
||||
<Layers>
|
||||
|
||||
<Layer level="BORDER">
|
||||
<!-- frame background -->
|
||||
<Texture name="$parent_FrameBackground" parentKey="framebackground" file = "Interface\AddOns\Details\images\cooltip_selected">
|
||||
<Color a = "1" r = "0" g = "1" b = "0" />
|
||||
<Anchors>
|
||||
<Anchor point="TOP" relativeTo="$parent" relativePoint="TOP" x="0" y="-5"/>
|
||||
<Anchor point="BOTTOM" relativeTo="$parent" relativePoint="BOTTOM" x="0" y="5"/>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="3" y="0"/>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="-3" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="ARTWORK">
|
||||
<!-- selected bar -->
|
||||
<Texture name="$parent_Selected" parentKey="selected" file = "Interface\AddOns\Details\images\cooltip_selected">
|
||||
<Size y="20"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="3" y="0"/>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="-3" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="OVERLAY">
|
||||
<!-- title icon -->
|
||||
<Texture name="$parent_TitleIcon" hidden="true" parentKey="titleIcon" file = "Interface\AddOns\Details\images\cooltip_selected">
|
||||
<Anchors>
|
||||
<Anchor point="TOP" relativeTo="$parent" relativePoint="TOP" x="0" y="0"/>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<!-- title text -->
|
||||
<FontString name="$parent_TitleText" parentKey="titleText" inherits="GameFontHighlightSmall" justifyH="LEFT" nonspacewrap="true">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent_Selected" relativePoint="RIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
</Layer>
|
||||
|
||||
</Layers>
|
||||
</Frame>
|
||||
|
||||
<Button name="CooltipButtonTemplate" virtual="true">
|
||||
<Size x="1" y="20"/>
|
||||
|
||||
<Frames>
|
||||
|
||||
<StatusBar name="$Parent_StatusBar" parentKey="statusbar">
|
||||
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="10" y="0"/>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="-10" y="0"/>
|
||||
<Anchor point="TOP" relativeTo="$parent" relativePoint="TOP" x="0" y="0"/>
|
||||
<Anchor point="BOTTOM" relativeTo="$parent" relativePoint="BOTTOM" x="0" y="0"/>
|
||||
</Anchors>
|
||||
|
||||
<Size y="20" />
|
||||
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<!-- statusbar texture -->
|
||||
<Texture name="$parent_Texture" hidden="false" parentKey="texture" file = "Interface\PaperDollInfoFrame\UI-Character-Skills-Bar" horizTile="false" vertTile="false">
|
||||
<Size x="300" y="14" />
|
||||
<Color a = "1" r = "1" g = "1" b = "1" />
|
||||
</Texture>
|
||||
<!-- spark -->
|
||||
<Texture name="$parent_Spark" hidden="true" parentKey="spark" file = "Interface\AddOns\Details\images\bar_detalhes2_end">
|
||||
<Size>
|
||||
<AbsDimension x="8" y="18"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="RIGHT" x="-16" y="-1"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="ARTWORK">
|
||||
<!-- background texture -->
|
||||
<Texture name="$parent_Background" hidden="true" parentKey="background" file = "Interface\FriendsFrame\UI-FriendsFrame-HighlightBar" horizTile="false" vertTile="false">
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="-6" y="0"/>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="6" y="0"/>
|
||||
<Anchor point="TOP" relativeTo="$parent" relativePoint="TOP" x="0" y="0"/>
|
||||
<Anchor point="BOTTOM" relativeTo="$parent" relativePoint="BOTTOM" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="OVERLAY">
|
||||
<!-- left icon texture -->
|
||||
<Texture name="$parent_LeftIcon" parentKey="leftIcon">
|
||||
<Size x="16" y="16" />
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<!-- right icon texture -->
|
||||
<Texture name="$parent_RightIcon" parentKey="rightIcon">
|
||||
<Size x="16" y="16" />
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
|
||||
<!-- left text -->
|
||||
<FontString name="$parent_LeftText" parentKey="leftText" inherits="GameFontHighlight" justifyH="LEFT" nonspacewrap="false">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="$parent_LeftIcon" relativePoint="CENTER" x="0" y="0"/>
|
||||
<Anchor point="LEFT" relativeTo="$parent_LeftIcon" relativePoint="RIGHT" x="3" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
<!-- right text -->
|
||||
<FontString name="$parent_TextRight" parentKey="rightText" inherits="GameFontHighlight" justifyH="RIGHT" nonspacewrap="false">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="CENTER" relativeTo="$parent_RightIcon" relativePoint="CENTER" x="0" y="0"/>
|
||||
<Anchor point="RIGHT" relativeTo="$parent_RightIcon" relativePoint="LEFT" x="-3" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
</Layer>
|
||||
|
||||
</Layers>
|
||||
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self:SetStatusBarTexture (self.texture);
|
||||
<!-- note to my self, never forget statusbar MinMaxValues -->
|
||||
self:SetMinMaxValues (0, 100);
|
||||
self:GetParent().background = self.background
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
|
||||
</StatusBar>
|
||||
|
||||
</Frames>
|
||||
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self:RegisterForClicks ("LeftButtonDown")
|
||||
self.leftIcon = self.statusbar.leftIcon
|
||||
self.rightIcon = self.statusbar.rightIcon
|
||||
self.texture = self.statusbar.texture
|
||||
self.spark = self.statusbar.spark
|
||||
self.leftText = self.statusbar.leftText
|
||||
self.rightText = self.statusbar.rightText
|
||||
</OnLoad>
|
||||
|
||||
<OnMouseDown>
|
||||
GameCooltipButtonMouseDown (self);
|
||||
</OnMouseDown>
|
||||
|
||||
<OnMouseUp>
|
||||
GameCooltipButtonMouseUp (self);
|
||||
</OnMouseUp>
|
||||
|
||||
</Scripts>
|
||||
</Button>
|
||||
|
||||
</Ui>
|
||||
@@ -0,0 +1,770 @@
|
||||
--> 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: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
|
||||
@@ -0,0 +1,238 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
|
||||
<Script file="dropdown.lua"/>
|
||||
|
||||
<Button name="DetailsDropDownTemplate" virtual="true">
|
||||
<Size x="150" y="20"/>
|
||||
|
||||
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
|
||||
<EdgeSize>
|
||||
<AbsValue val="10"/>
|
||||
</EdgeSize>
|
||||
<TileSize>
|
||||
<AbsValue val="16"/>
|
||||
</TileSize>
|
||||
<BackgroundInsets>
|
||||
<AbsInset left="1" right="1" top="0" bottom="1"/>
|
||||
</BackgroundInsets>
|
||||
</Backdrop>
|
||||
|
||||
<Layers>
|
||||
|
||||
<Layer level="BACKGROUND">
|
||||
<!-- statusbar texture -->
|
||||
<Texture name="$parent_StatusBarTexture" parentKey="statusbar">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$parent" relativePoint="TOPLEFT" x="3" y="-3"/>
|
||||
<Anchor point="BOTTOMRIGHT" relativeTo="$parent" relativePoint="BOTTOMRIGHT" x="-3" y="3"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="ARTWORK">
|
||||
<!-- icon texture -->
|
||||
<Texture name="$parent_IconTexture" parentKey="icon" file = "Interface\ICONS\Spell_ChargePositive">
|
||||
<Size x="20" y="20" />
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="2" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<!-- text -->
|
||||
<FontString name="$parent_Text" parentKey="text" inherits="GameFontHighlightSmall" justifyH="LEFT" nonspacewrap="true">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent_IconTexture" relativePoint="RIGHT" x="5" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
<!-- <Texture name="$parent_ArrowTextureDisabled" parentKey="textureDisabled" file = "Interface\Buttons\UI-ScrollBar-UI-ScrollBar-ScrollDownButton-Disabled">
|
||||
<Size x="32" y="32" />
|
||||
</Texture> -->
|
||||
</Layer>
|
||||
|
||||
<Layer level="OVERLAY">
|
||||
<Texture name="$parent_ArrowTexture2" alphaMode="ADD" parentKey="arrowTexture2" file = "Interface\Buttons\UI-ScrollBar-ScrollDownButton-Highlight" hidden="true">
|
||||
<Size x="32" y="28"/>
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="5" y="-1"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<!-- button textures -->
|
||||
<Texture name="$parent_ArrowTexture" parentKey="arrowTexture" file = "Interface\Buttons\UI-ScrollBar-ScrollDownButton-Up">
|
||||
<Size x="32" y="28"/>
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="5" y="-1"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
</Layers>
|
||||
|
||||
<Frames>
|
||||
|
||||
<Frame name="$Parent_Border" parentKey="dropdownborder" hidden="true">
|
||||
<Size x="150" y="170"/>
|
||||
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$Parent" relativePoint="BOTTOMLEFT"/>
|
||||
</Anchors>
|
||||
|
||||
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background-Dark" edgeFile="Interface\Buttons\UI-SliderBar-Border" tile="true">
|
||||
<EdgeSize>
|
||||
<AbsValue val="10"/>
|
||||
</EdgeSize>
|
||||
<TileSize>
|
||||
<AbsValue val="256"/>
|
||||
</TileSize>
|
||||
<BackgroundInsets>
|
||||
<AbsInset left="0" right="0" top="5" bottom="5"/>
|
||||
</BackgroundInsets>
|
||||
</Backdrop>
|
||||
|
||||
<Scripts>
|
||||
<OnHide>
|
||||
DetailsDropDownOptionsFrameOnHide (self);
|
||||
</OnHide>
|
||||
<OnLoad>
|
||||
self:SetBackdropColor (1, 1, 1, 1);
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
|
||||
</Frame>
|
||||
|
||||
<ScrollFrame name="$Parent_ScrollFrame" parentKey="dropdownframe" hidden="true">
|
||||
<Size x="150" y="150"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$Parent" relativePoint="BOTTOMLEFT" x="0" y="-10" />
|
||||
</Anchors>
|
||||
|
||||
<ScrollChild>
|
||||
<Frame name="$Parent_ScrollChild">
|
||||
|
||||
<Size x="150" y="150"/>
|
||||
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="$Parent" relativePoint="TOPLEFT" x="0" y="0" />
|
||||
</Anchors>
|
||||
|
||||
<Layers>
|
||||
<Layer level="BACKGROUND">
|
||||
<!-- selected texture -->
|
||||
<Texture name="$parent_SelectedTexture" parentKey="selected" hidden="true" file="Interface\SPELLBOOK\Spellbook-Parts">
|
||||
<Size x="150" y="35" />
|
||||
<TexCoords left="0.31250000" right="0.78515625" top="0.00390625" bottom="0.36328125"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="2" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="ARTWORK">
|
||||
<!-- mouse over texture -->
|
||||
<Texture name="$parent_MouseOverTexture" alphaMode="ADD" parentKey="mouseover" hidden="true" file="Interface\Buttons\UI-Listbox-Highlight">
|
||||
<Size x="150" y="15" />
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="2" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
</Layers>
|
||||
|
||||
</Frame>
|
||||
|
||||
</ScrollChild>
|
||||
|
||||
</ScrollFrame>
|
||||
|
||||
</Frames>
|
||||
|
||||
<Scripts>
|
||||
|
||||
<OnLoad>
|
||||
self:SetBackdropColor (1, 1, 1, .5);
|
||||
self.arrowTexture:SetDrawLayer ("OVERLAY", 1);
|
||||
self.arrowTexture2:SetDrawLayer ("OVERLAY", 2);
|
||||
|
||||
tinsert (UISpecialFrames, self.dropdownborder:GetName());
|
||||
tinsert (UISpecialFrames, self.dropdownframe:GetName());
|
||||
</OnLoad>
|
||||
|
||||
<OnShow>
|
||||
DetailsDropDownOnShow (self);
|
||||
</OnShow>
|
||||
|
||||
<OnHide>
|
||||
DetailsDropDownOnHide (self);
|
||||
</OnHide>
|
||||
|
||||
<OnEnter>
|
||||
DetailsDropDownOnEnter (self);
|
||||
</OnEnter>
|
||||
|
||||
<OnLeave>
|
||||
DetailsDropDownOnLeave (self);
|
||||
</OnLeave>
|
||||
|
||||
<OnSizeChanged>
|
||||
DetailsDropDownOnSizeChanged (self);
|
||||
</OnSizeChanged>
|
||||
|
||||
<OnMouseDown>
|
||||
DetailsDropDownOnMouseDown (self);
|
||||
</OnMouseDown>
|
||||
</Scripts>
|
||||
|
||||
</Button>
|
||||
|
||||
<Button name="DetailsDropDownOptionTemplate" virtual="true">
|
||||
<Size x="150" y="20" />
|
||||
|
||||
<Layers>
|
||||
|
||||
<Layer level="ARTWORK">
|
||||
<!-- statusbar texture -->
|
||||
<Texture name="$parent_StatusBarTexture" parentKey="statusbar">
|
||||
<Size x="150" y="20" />
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="0" y="0"/>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="OVERLAY">
|
||||
<!-- icon texture -->
|
||||
<Texture name="$parent_IconTexture" parentKey="icon" file = "Interface\ICONS\Spell_ChargePositive">
|
||||
<Size x="20" y="20" />
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="2" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
<!-- text -->
|
||||
<FontString name="$parent_Text" parentKey="label" inherits="GameFontHighlightSmall" justifyH="LEFT" nonspacewrap="false">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent_IconTexture" relativePoint="RIGHT" x="5" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
</Layer>
|
||||
</Layers>
|
||||
|
||||
<Scripts>
|
||||
<OnMouseDown>
|
||||
DetailsDropDownOptionClick (self);
|
||||
</OnMouseDown>
|
||||
|
||||
<OnEnter>
|
||||
DetailsDropDownOptionOnEnter (self);
|
||||
</OnEnter>
|
||||
|
||||
<OnLeave>
|
||||
DetailsDropDownOptionOnLeave (self);
|
||||
</OnLeave>
|
||||
|
||||
</Scripts>
|
||||
|
||||
</Button>
|
||||
|
||||
</Ui>
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,90 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
|
||||
<Script file="normal_bar.lua"/>
|
||||
|
||||
<StatusBar name="DetailsNormalBarTemplate" virtual="true">
|
||||
<Size x="300" y="14"/>
|
||||
|
||||
<Layers>
|
||||
|
||||
<Layer level="BACKGROUND">
|
||||
<!-- background texture -->
|
||||
<Texture name="$parent_background" hidden="false" setAllPoints="true" parentKey="background" file = "Interface\PaperDollInfoFrame\UI-Character-Skills-Bar" horizTile="false" vertTile="false">
|
||||
<Size x="300" y="14" />
|
||||
<Color a = "0.3" r = "0.3" g = "0.3" b = "0.3" />
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="ARTWORK">
|
||||
<!-- timer texture -->
|
||||
<Texture name="$parent_timerTexture" hidden="true" parentKey="timertexture" file = "Interface\PaperDollInfoFrame\UI-Character-Skills-Bar" horizTile="false" vertTile="false">
|
||||
<Size x="300" y="14" />
|
||||
<Color a = "1" r = "1" g = "1" b = "1" />
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" />
|
||||
</Anchors>
|
||||
</Texture>
|
||||
|
||||
<!-- statusbar texture -->
|
||||
<Texture name="$parent_statusbarTexture" hidden="false" parentKey="texture" file = "Interface\PaperDollInfoFrame\UI-Character-Skills-Bar" horizTile="false" vertTile="false">
|
||||
<Size x="300" y="14" />
|
||||
<Color a = "1" r = "1" g = "1" b = "1" />
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="OVERLAY">
|
||||
<!-- icon texture -->
|
||||
<Texture name="$parent_icon" parentKey="icontexture">
|
||||
<Size x="14" y="14" />
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
|
||||
<!-- spark mouse over -->
|
||||
<Texture name="$parent_sparkMouseover" hidden="true" parentKey="sparkmouseover" file = "Interface\CastingBar\UI-CastingBar-Spark" alphaMode="ADD">
|
||||
<Size>
|
||||
<AbsDimension x="32" y="32"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="RIGHT" x="-16" y="-1"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
|
||||
<!-- timer spark -->
|
||||
<Texture name="$parent_sparkTimer" hidden="true" parentKey="sparktimer" file = "Interface\CastingBar\UI-CastingBar-Spark" alphaMode="ADD">
|
||||
<Size>
|
||||
<AbsDimension x="32" y="32"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent_timerTexture" relativePoint="RIGHT" x="-16" y="-1"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
|
||||
<!-- left text -->
|
||||
<FontString name="$parent_TextLeft" parentKey="lefttext" inherits="GameFontHighlight" justifyH="LEFT" nonspacewrap="false">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent_icon" relativePoint="RIGHT" x="3" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
<!-- right text -->
|
||||
<FontString name="$parent_TextRight" parentKey="righttext" inherits="GameFontHighlight" justifyH="RIGHT" nonspacewrap="false">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="-3" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
</Layer>
|
||||
|
||||
</Layers>
|
||||
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self:SetStatusBarTexture (self.texture);
|
||||
DetailsNormalBar_OnCreate (self);
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
</StatusBar>
|
||||
</Ui>
|
||||
@@ -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
|
||||
@@ -0,0 +1,32 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
|
||||
|
||||
<Script file="panel.lua"/>
|
||||
|
||||
<Frame name="DetailsPanelTemplate" virtual="true">
|
||||
|
||||
<Size x="100" y="100"/>
|
||||
|
||||
<Backdrop bgFile="Interface\DialogFrame\UI-DialogBox-Background" edgeFile="Interface\DialogFrame\UI-DialogBox-Border" tile="true">
|
||||
<EdgeSize>
|
||||
<AbsValue val="10"/>
|
||||
</EdgeSize>
|
||||
<TileSize>
|
||||
<AbsValue val="16"/>
|
||||
</TileSize>
|
||||
<BackgroundInsets>
|
||||
<AbsInset left="1" right="1" top="0" bottom="1"/>
|
||||
</BackgroundInsets>
|
||||
</Backdrop>
|
||||
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self.Gradient = {
|
||||
["OnEnter"] = {0.3, 0.3, 0.3, 0.5},
|
||||
["OnLeave"] = {0.9, 0.7, 0.7, 1}
|
||||
}
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
|
||||
</Frame>
|
||||
|
||||
</Ui>
|
||||
@@ -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
|
||||
@@ -0,0 +1,474 @@
|
||||
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()
|
||||
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()
|
||||
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)
|
||||
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)
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,82 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
|
||||
|
||||
<Script file="split_bar.lua"/>
|
||||
|
||||
<StatusBar name="DetailsSplitBarTemplate" virtual="true">
|
||||
<Size x="300" y="14"/>
|
||||
|
||||
<Layers>
|
||||
|
||||
<Layer level="BACKGROUND">
|
||||
<!-- background texture -->
|
||||
<Texture name="$parent_StatusBarBackground" setAllPoints="true" parentKey="background" file = "Interface\PaperDollInfoFrame\UI-Character-Skills-Bar" horizTile="false" vertTile="false">
|
||||
<Color a = "1" r = ".5" g = ".5" b = ".5" />
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="ARTWORK">
|
||||
<!-- statusbar texture -->
|
||||
<Texture name="$parent_StatusBarTexture" hidden="true" parentKey="texture" file = "Interface\PaperDollInfoFrame\UI-Character-Skills-Bar" horizTile="false" vertTile="false">
|
||||
<Size x="300" y="14" />
|
||||
<Color a = "1" r = "1" g = "1" b = "1" />
|
||||
</Texture>
|
||||
</Layer>
|
||||
|
||||
<Layer level="OVERLAY">
|
||||
<!-- left icon -->
|
||||
<Texture name="$parent_IconLeft" parentKey="lefticon">
|
||||
<Size x="14" y="14" />
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
|
||||
<!-- right icon -->
|
||||
<Texture name="$parent_IconRight" parentKey="righticon">
|
||||
<Size x="14" y="14" />
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="RIGHT" x="0" y="0"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
|
||||
<!-- left text -->
|
||||
<FontString name="$parent_TextLeft" parentKey="lefttext" inherits="GameFontHighlight" justifyH="LEFT" nonspacewrap="false">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent_IconLeft" relativePoint="RIGHT" x="3" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
<!-- right text -->
|
||||
<FontString name="$parent_TextRight" parentKey="righttext" inherits="GameFontHighlight" justifyH="RIGHT" nonspacewrap="false">
|
||||
<FontHeight val="10.5"/>
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parent_IconRight" relativePoint="LEFT" x="-3" y="0"/>
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
<!-- div spark -->
|
||||
<Texture name="$parent_Spark" parentKey="spark" file = "Interface\CastingBar\UI-CastingBar-Spark" alphaMode="ADD">
|
||||
<Size>
|
||||
<AbsDimension x="32" y="32"/>
|
||||
</Size>
|
||||
<Anchors>
|
||||
<Anchor point="LEFT" relativeTo="$parent" relativePoint="RIGHT" x="-17" y="-1"/>
|
||||
</Anchors>
|
||||
</Texture>
|
||||
|
||||
</Layer>
|
||||
|
||||
</Layers>
|
||||
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
self:SetStatusBarTexture (self.texture);
|
||||
self:SetMinMaxValues (1, 100);
|
||||
self:SetValue (50);
|
||||
DetailsSplitlBar_OnCreate (self);
|
||||
</OnLoad>
|
||||
</Scripts>
|
||||
|
||||
</StatusBar>
|
||||
</Ui>
|
||||
@@ -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
|
||||
@@ -0,0 +1,36 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
|
||||
|
||||
<Script file="textentry.lua"/>
|
||||
|
||||
<EditBox name="DetailsEditBoxTemplate2" virtual="true">
|
||||
<Size x="232" y="20"/>
|
||||
|
||||
<Backdrop bgFile="Interface\\ChatFrame\\ChatFrameBackground" edgeFile="Interface\\ChatFrame\\ChatFrameBackground" tile="true">
|
||||
<EdgeSize>
|
||||
<AbsValue val="1"/>
|
||||
</EdgeSize>
|
||||
<TileSize>
|
||||
<AbsValue val="16"/>
|
||||
</TileSize>
|
||||
<BackgroundInsets>
|
||||
<AbsInset left="0" right="0" top="0" bottom="0"/>
|
||||
</BackgroundInsets>
|
||||
</Backdrop>
|
||||
|
||||
<Layers>
|
||||
|
||||
<Layer level="OVERLAY">
|
||||
<!-- box description -->
|
||||
<FontString name="$parent_Desc" text="" parentKey="label" inherits="GameFontHighlightSmall" justifyH="LEFT" nonspacewrap="false">
|
||||
<Color r = "0.8" g = "0.8" b = "0.8" a = "1"/>
|
||||
<Anchors>
|
||||
<Anchor point="RIGHT" relativeTo="$parent" relativePoint="LEFT" x="-2" y="0" />
|
||||
</Anchors>
|
||||
</FontString>
|
||||
|
||||
</Layer>
|
||||
|
||||
</Layers>
|
||||
|
||||
</EditBox>
|
||||
</Ui>
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,287 @@
|
||||
--[[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.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
|
||||
-- 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
|
||||
-- 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
|
||||
@@ -0,0 +1,157 @@
|
||||
|
||||
|
||||
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 (msg == Loc ["STRING_SLASH_NEW"]) then
|
||||
_detalhes:CriarInstancia()
|
||||
|
||||
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()
|
||||
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
@@ -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
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user