Ouro Loot

Everything on this page assumes you've got a reference to the addon like so (the Ace libraries shipped with Ouro Loot are also assumed):

  local ouroloot = LibStub('AceAddon-3.0'):GetAddon('Ouro Loot',true)
  if not ouroloot then return end

Loot Entry

At its core, the flow of information through Ouro Loot is simple: new data entries are appended to an array (called g_loot here and in the code). The most accurate description of an entry's fields is the comment block at the start of Ouro_Loot/core.lua, with a more or less recent copy here. Fields denoted as 'string' call attention to non-localized key words.

Common g_loot keys

Each entry in the array represents an "event of interest". Currently these are date-and-time entries, boss fights, and looting. Every entry will have these fields:

string - 'time', 'boss', 'loot'
0-23, on the physical instance server, not the realm server
0-59, ditto
time_t on the local computer clock (which may be wildly useless)

Time-specific g_loot keys

These are generated once per day. More specifically, any "event of interest" after this one is taken to have happened sometime on this day.

table with fields month, day, year, text; the first three are numbers, text is "dd Month yyyy"

Boss-specific g_loot keys

These are generated at the conclusion of a boss fight, as determined by your locally installed boss-timer-etc addon (e.g., DBM). More specifically, any loot event after this one is presumed to have dropped from this boss.

name of encounter; this may be changed from the official name if the "snarky boss names" option is enabled
string - 'wipe', 'kill'
name of instance, including size and difficulty; note that this is the location of the player at the time the event was recorded (if you were in the graveyard when your guild beat the encounter, it will be recorded as the outdoor continent)
5/10/15/25/40; can be 0 if the recording player is outside and the broadcasting player inside has an older version of Ouro Loot
in seconds; only present and useful in locally-generated entries, may be missing or zero in broadcast entries
copy of raiders table at the time of the boss event; may be missing for manual snapshots if the player chose to not use one

Loot-specific g_loot keys

There is some redundancy here for ease of use elsewhere in the code. Several of the fields are optional.

recipient of loot
recipient's class ID (e.g., DEATHKNIGHT) if that data is available
recipient's realm name if different from the player's; missing otherwise
does not include traditional square brackets
item ID, as a number
full clickable link
icon path (e.g., Interface\Icons\INV_Misc_Rune_01)
ITEM_QUALITY_* constant number
an almost-certainly-unique string, content meaningless, used to identify this specific loot event
string - missing for normal/mainspec loot, otherwise a tag such as 'offspec' or 'gvault'
stack size, e.g., "x3", missing otherwise
1 = heroic item, 2 = raid finder item; missing otherwise
a player's name, if received this event from that player's rebroadcast; missing otherwise
the text in the Loot tab's Note column; this can be typed by the player or generated programmatically (by changing disposition, receiving a broadcast, etc); missing if no text is present
true if extratext was edited directly by the player; missing otherwise
item wasn't in the local game client's item cache; this SHOULD be missing

Raiders Table

This table accumulates demographic information about the raid roster as the player gets close enough to each raid member for the Blizzard APIs to work. The table is indexed by player name (without any "-realm"); each entry is a subtable with the following fields.

fully-qualified name; "PlayerName" for people on the same realm as the player, or "PlayerName-RealmName" for cross-realm people
player's realm name, or missing if from the same realm as the player
class ID (e.g., DEATHKNIGHT)
English codename as returned by Blizzard API (e.g., "BloodElf")
1 = unknown/error, 2 = male, 3 = female
can be 0 if the player was offline at the time the data were gathered
player's guild name, or missing if unguilded
string - 'online', 'offline', 'no_longer' (no longer in raid group)
time (in time_t format) when the player joined the raid (or the first time they've been seen by this client)
time (in time_t format) when the player left the raid (or the time when this client left the raid, if 'online' =/= 'no_longer')
1-8 (rather, 1 through NUM_RAID_GROUPS), or NUM_RAID_GROUPS+1 in case of errors
true if the current player has not yet gotten close enough to the other player to request data; this SHOULD be missing

Note that the entry for a player remains in the raiders table after that player leaves the raid, to aid in attendance tracking. Note also that the table is not reset when your own player leaves the raid, so that useful information can still be gotten after the raid is over. This means that raid roster information will continue to accumulate until the 'Clear Loot' button is pressed.

Plugin creation and features

Plugin modules are standard Ace3 modules, created in one of two ways:

  1. ouroloot:NewModule, the usual Ace3 routine
  2. ouroloot:ConstrainedNewModule, a wrapper around the previous call

Modules inherit several functions unique to Ouro Loot, described here. By default, modules all embed the AceConsole-3.0 library.

Certain field ("member") data names are special: option_defaults, db, and opts. They are described below.

ouroloot:ConstrainedNewModule (module_name, minrev, mincomm, mindata [,...])

Tests major aspects of the main addon before creating the module.


module_name, ...
strings - The module name and optional library names are passed to :NewModule if all tests pass.
minrev, mincomm, mindata
numbers or nil - Each argument specifies the minimum revision, minimum communication version, or minimum saved data format, of the main Ouro Loot addon. If the installed Ouro Loot is too old, then an error is printed and module creation fails. Pass nil to not test that aspect; passing nil for all three is therefore equivalent to calling NewModule directly.


A standard addon table on success, or false if any of the specified constraints failed.


local myplugin = ouroloot:ConstrainedNewModule ('Example', nil, 16)
if not myplugin then return end

Here, the installed Ouro Loot must support communications format 16 or higher.

plugin.option_defaults = { profile = { <defaults> } }

Modules can store AceDB-3.0 data as a namespace inside the parent Ouro Loot savedvariables. If you define an .option_defaults table at "file scope" (i.e., so that it runs as the plugin file is being loaded) then the inherited OnInitialize will register the new namespace using those defaults. The table reference returned from AceDB will be stored in plugin.db, the traditional field. Another pointer will be stored in plugin.opts, referring to plugin.db.profile.

Defining your own :OnInitialize will discard all this behavior. (There is no inherited OnEnable, so if you need to do one-time actions and wish to keep the inherited OnInitialize, you should define an OnEnable.)

plugin.GetOption, plugin.SetOption

These functions are for use with AceConfig-style options tables in :register_options_entry. They require that config key names match their corresponding option key names, and get/set those options accordingly. If the 'arg' key is the name of a plugin function, then SetOption will call that method after setting the option data.

plugin:Print (str[, ...])

Overrides the Print function from AceConsole. This version acts like Printf if the initial str argument contains any %-specifiers. Additionally the printed prefix of each line is not the colored module name (the default from AceConsole) but rather a clickable hyperlink.


myplugin:Print("Hello, world!")
ouroloot:Print("Begin the looting!")
myplugin:Print("%s, %s!", my_greeting, my_planet_name)
[Example]  Hello, world!
[Ouro Loot]  Begin the looting!
[Example]  Hello, world!

The default behavior for left-clicking the module hyperlink is displaying the Ouro Loot GUI. If your module defines a plugin:PrefixLeftClick function, then that is called instead.

Right-clicking the module hyperlink brings up Ouro Loot options; if the module has registered an options entry on that tab, it will be selected for you. You cannot override this behavior, but if your module defines a plugin:PrefixRightClick member function, then its return value is used instead of plugin.name as the options entry to select.



These are described later.


The disposition of a loot entry refers to any additional circumstances beyond "item X went to player Y". By default, loot entries have no disposition data: their .disposition field is nil and loot is recorded as "normal" or "main spec" or similar. There are three more possible dispositions built into Ouro Loot:

  • An offspec tag still records the item as going to this player, and adds the text "offspec" to generated forum markup text.
  • A gvault tag does not record the item in this player's running history, and generated forum text will show "guild vault" instead of this player's name.
  • A shard tag works like gvault but will show "disenchanted" instead.

Dispositions can be set automatically, or through the GUI's dropdown menu. Changing a disposition has two direct effects and one side effect:

  1. The g_loot entry for that event will have a .disposition field set to the corresponding tag. These tags are simple string keywords except for the default disposition, which is nil (removing the field).
  2. The text in the Notes column (and .extratext field) is replaced by the corresponding text for that disposition. This is usually not much more than the tag itself (e.g., "guild vault" for a gvault tag).
  3. As a side effect, changing the .disposition field will change the text color of the Notes column. This color remains even if you later edit the Notes text directly, adding to or removing the disposition text. The color is meant to serve as a visual reminder of the change, even when the note is altered.

Plugin modules can register their own dispositions:

plugin:add_loot_disposition (code, rhex, ghex, bhex, notes, menu, tooltip, can_reassign, affects_history, from_notes_text)

Creates a new disposition and adds it to the right-click dropdown menu's "Mark As..." list.


string - A short tag; this will be the value of the .disposition key.
rhex, ghex, bhex
string - RGB hex strings for the text color. Yes, these are three separate arguments.
string - The text to initially write into the Notes column for this disposition.
string - The text in the "Mark As..." dropdown menu. This can be specified as nil in which case the notes text will be used.
string - Optional tooltip text. Hovering the mouse over this entry on the dropdown menu will display a short tooltip if this is present. Specify as nil for no tooltip.
boolean - True if an item in this state may be reassigned directly to another player. False if the item must be changed to normal or offspec before reassigning.
boolean - True if an item in this state should be recorded in the recipient's running history.
boolean - As described above, changing a disposition always changes the Notes text to match. If this flag is true, then the reverse also works: editing the Notes field to be exactly the same text as notes will trigger a disposition change to this state. If this flag is false, then editing the Notes field will have no effect on disposition, no matter what you type.


A pointer to the generated info table used by UIDropDownMenu.lua to represent the new entry in the "Mark As..." menu. There is little that you can safely change here. In particular, do not touch the func/arg1/arg2 fields or we will all live to regret it.


myplugin:add_loot_disposition ('recipe', "38","ff","4f",
    "BoP recipe",
    [[BoP patterns go to raider rank or higher]],
    true, true, false)

TODO: add mark here

Unique IDs

Because reassigning loot and changing dispositions are actions that take effect for everybody in the raid running Ouro Loot, there must be a way of uniquely identifying a loot event. These short string tokens are the canonical method of refering to a specific loot. (Outside of an instance, they are not truly unique in the UUID sense of uniqueness, but merely "unique enough" for purposes of a raid.)

TODO: relevent functions

New Text Output

Event Callbacks