--[[ StarterLDB.lua This is a simplistic example of a LDB (LibDataBroker) Addon. It is assumed that you understand the Blizzard addon basics. It is based loosely on the Titan Bag addon but is not Titan specific. It is not required that a display addon exist for your addon to run; Such as Titan :-) However your addon will need to enable command line commands or the user will not be able to see or do anything. If running this example, it shows up in the Titan right click menu > General > LDBStarter NOTE: Before running this addon, the folder and file prefix must be the same to be considered for loading into WoW! For example to just run this as is, remove the 'Example' from the folder name then start or reload WoW. This is explained in more detail below in 'Folder Structure'. Enjoy! By: The Titan Development Team --]] --[[ Folder Structure NOTE: Before running this addon, the folder and file prefix must be the same to be considered for loading into WoW! For example, to just run this as is, remove the 'Example' from the folder name then start or reload WoW. This is explained in more detail below. This plugin folder must be added to the Addon folder to be considered for loading into WoW. Inside this folder you will notice : - three .toc files - one .lua file - one .tga file. There are sites (wowhead or wow wiki as examples) that have deeper explainations on addon development. Please use these sites for more general addon information. === .toc The folder and the .toc files MUST have the same name! Sort of... the name prior to the underscore(_) must be the same. The name after that (postfix) has meaning to WoW. WoW has three versions represented by the three postix values. _Mainline : current retail version _Wrath : Wrath of the Lich King version. _Vanilla : Classic Era version These values may change as the versions evolve, say Cata is added to Wrath. Or they may not :). Years from now we may wonder why Wrath represents Dragonflight! If your plugin is only for Classic Era then delete or rename the 'mainline' and 'wrath' .toc files. Changing the filename will prevent WoW from loading the addon into that version of the game. Titan uses this method. Notice Titan folder has no 'wrath' or 'vanilla' .toc. TitanClassic has has both 'wrath' and 'vanilla' .toc but no 'mainline' .toc. This allows Titan plugins intended for Classic versions to run without change. NOTE: The ## Interface value should match the current interface value of the coorsponding WoW version. In BattleNet this typcially shown below the 'Play' button. DragonFlight 10.02.05 is represented without dots - 100205 - in the .toc. If the interface value is close (but lower) WoW will complain that you are running 'older' addons. If WoW finds a Classic Era value (say 11500) in a 'mainline' .toc, it will just ignore it (not load). The reverse (a higher value) is true as well. === .lua This is the code for the plugin - and this file. === .tga This file is the icon used by the plugin. It is specified in the .obj created for the LDB init routine. WoW can use several different types of icons. This discussion is outside the scope of this example. === libs This file implementing the LDB functions. See https://github.com/tekkub/libdatabroker-1-1/wiki/ for an API description. LibDataBroker-1.1.lua at https://github.com/tekkub/libdatabroker-1-1/ It *should* be included in the LDB compliant display addon. It *should* included in the display addon. Anyone can extract the code and art from WoW. This can be handy to get code examples. And to grab icons to use for a plugin. My undestanding is any icon can be used within WoW without violating the ToS. WoW icons tend to be .blp files. These files are NOT easy to look at or manipulate!! You will need to research third party tools to manipulate .blp files. --]] -- ******************************** Constants ******************************* local ADDON_NAME = ... -- Set the name we want in the global name space. Ensure the name is unique across all addons. StarterLDB = {} local id = "LDBStarter"; -- What the user will see as the name local addon = ADDON_NAME -- addon name / folder name / toc name -- Localized strings are outside the scope of this example. --[[ The artwork path must start with Interface\\AddOns Then the name of the plugin Then any additional folder(s) to your artwork / icons. --]] local artwork_path = "Interface\\AddOns\\TitanLDB\\" -- Get data from the TOC file. local version = tostring(GetAddOnMetadata(addon, "Version")) or "Unknown" local author = GetAddOnMetadata(addon, "Author") or "Unknown" -- NOTE: GetAddOnMetadata expects the addon name : -- The addon folder name or .toc name needs to be the same. -- ******************************** Variables ******************************* local trace = false -- toggle to show / hide debug statements in this addon -- ******************************** Functions ******************************* local function Debug(debug_message, debug_type) if trace then local dtype = "" local time_stamp = "" local msg = "" if debug_type == "error" then dtype = "Error: " elseif debug_type == "warning" then dtype = "Warning: " end if debug_type == "normal" then time_stamp = "" else time_stamp = date("%H:%M:%S")..": " end msg = "Debug".." " ..time_stamp ..dtype ..debug_message _G["DEFAULT_CHAT_FRAME"]:AddMessage(msg) else -- not requested end --date("%m/%d/%y %H:%M:%S") end -- Calculate bag space then return text and icon to display local function GetBagSlotInfo() local totalSlots, usedSlots, availableSlots, icon totalSlots = 0; usedSlots = 0; for bag = 0, 4 do local size = C_Container.GetContainerNumSlots(bag); if (size and size > 0) then totalSlots = totalSlots + size; local free = C_Container.GetContainerNumFreeSlots(bag) local used = size - free usedSlots = usedSlots + used; end end availableSlots = totalSlots - usedSlots; local i,r = math.modf(availableSlots/2) if (r == 0) then icon = artwork_path.."Starter.tga" else icon = "Interface\\PetPaperDollFrame\\UI-PetHappiness" --PET_DISMISS_TEXTURE end local bagText bagText = format("%d/%d", availableSlots, totalSlots); bagText = HIGHLIGHT_FONT_COLOR_CODE..bagText..FONT_COLOR_CODE_CLOSE return bagText, icon --]] end -- Create the tooltip local function LDB_OnTooltipShow(tooltip) tooltip = tooltip or GameTooltip local tt_str = "" tt_str = GREEN_FONT_COLOR_CODE ..id.." Info" ..FONT_COLOR_CODE_CLOSE tooltip:AddLine(tt_str) local text, icon = GetBagSlotInfo() tt_str = "Available bag slots" .." "..text.."\n" .."\n".."Hint: Left-click to open all bags." tooltip:AddLine(tt_str) end local function LDB_Init(LDB_frame) Debug(id.." Init ..."); --[[ Initialize the Data Broker 'button'. This is the heart of a LDB plugin. It determines how the display addon is to treat this addon. Setting the type is required so the LDB lib and display addon know what to do. See the LDB spec. --]] -- The .obj is the key link to the display addon!! LDB_frame.obj = LibStub("LibDataBroker-1.1"):NewDataObject(id, { type = "data source", -- required -- SDK: The two options are: -- "data source" - A data source is expected to show some type of info -- "launcher" - Expected to open another window or perform some action icon = artwork_path.."Starter.tga", -- The icon to display on the display addon label = id, -- label is the text the user will use to find this addon in the display addon. text = "nyl", -- will be updated later OnTooltipShow = function(tooltip) LDB_OnTooltipShow(tooltip) end, OnClick = function(self, button) if ( button == "LeftButton" ) then -- Just a simple action to illustrate an LDB addon. ToggleAllBags(); elseif ( button == "RightButton" ) then -- There is no action to take in this example. --[[ Add code here if your addon needs to do something on right click. Typically an options menu which is outside the scope of this example. --]] end end, }) Debug(id.." Init fini."); --]===] end -- Update the Bags Data Broker 'button' local function LDB_Update(LDB_frame) local text, icon = GetBagSlotInfo() LDB_frame.obj.text = text LDB_frame.obj.icon = icon end -- Parse events registered to plugin and act on them local function Button_OnEvent(self, event, ...) Debug("OnEvent" .." "..tostring(event).."" ) if (event == "PLAYER_ENTERING_WORLD") then -- Do any additional set up needed -- print("" .." "..tostring(id).."" .." "..tostring(version).."" .." by "..tostring(author).."" ) -- Now that events have settled, register the one(s) we really want. -- This may not be needed but it could reduce churn and possible timing issues. self:RegisterEvent("BAG_UPDATE"); -- Unregister events no longer needed. -- Good practice although this event is only fired on login self:UnregisterEvent("PLAYER_ENTERING_WORLD"); end if event == "BAG_UPDATE" then LDB_Update(self) end end -- ====== Create needed frames local function Create_Frames() -- general container frame -- The frame pointer is passed as a parameter rather than an addon local. local window = CreateFrame("Frame", "StarterLDBExample", UIParent) -- window:Hide() -- Set strata as desired window:SetFrameStrata("FULLSCREEN") -- Using SetScript("OnLoad", does not work window:SetScript("OnEvent", function(self, event, ...) Button_OnEvent(self, event, ...) end) -- Tell Blizzard this frame needs player entering world event. window:RegisterEvent("PLAYER_ENTERING_WORLD"); -- Any other addon specific "on load" code here LDB_Init(window) -- Update the text (bag numbers) LDB_Update(window) -- shamelessly print a load message to chat window DEFAULT_CHAT_FRAME:AddMessage( GREEN_FONT_COLOR_CODE ..addon..id.." "..version .." by " ..FONT_COLOR_CODE_CLOSE .."|cFFFFFF00"..author..FONT_COLOR_CODE_CLOSE); end Create_Frames() -- do the work