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:

kind
string - 'time', 'boss', 'loot'
hour
0-23, on the physical instance server, not the realm server
minute
0-59, ditto
stamp
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.

startday
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.

bossname
name of encounter; this may be changed from the official name if the "snarky boss names" option is enabled
reason
string - 'wipe', 'kill'
instance
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)
maxsize
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
duration
in seconds; only present and useful in locally-generated entries, may be missing or zero in broadcast entries
raidersnap
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.

person
recipient of loot
person_class
recipient's class ID (e.g., DEATHKNIGHT) if that data is available
person_realm
recipient's realm name if different from the player's; missing otherwise
itemname
does not include traditional square brackets
id
item ID, as a number
itemlink
full clickable link
itexture
icon path (e.g., Interface\Icons\INV_Misc_Rune_01)
quality
ITEM_QUALITY_* constant number
unique
an almost-certainly-unique string, content meaningless, used to identify this specific loot event
disposition
string - missing for normal/mainspec loot, otherwise a tag such as 'offspec' or 'gvault'
count
stack size, e.g., "x3", missing otherwise
variant
1 = heroic item, 2 = raid finder item; missing otherwise
bcast_from
a player's name, if received this event from that player's rebroadcast; missing otherwise
extratext
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
extratext_byhand
true if extratext was edited directly by the player; missing otherwise
cache_miss
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.

fname
fully-qualified name; "PlayerName" for people on the same realm as the player, or "PlayerName-RealmName" for cross-realm people
realm
player's realm name, or missing if from the same realm as the player
class
class ID (e.g., DEATHKNIGHT)
race
English codename as returned by Blizzard API (e.g., "BloodElf")
sex
1 = unknown/error, 2 = male, 3 = female
level
can be 0 if the player was offline at the time the data were gathered
guild
player's guild name, or missing if unguilded
online
string - 'online', 'offline', 'no_longer' (no longer in raid group)
join
time (in time_t format) when the player joined the raid (or the first time they've been seen by this client)
leave
time (in time_t format) when the player left the raid (or the time when this client left the raid, if 'online' =/= 'no_longer')
subgroup
1-8 (rather, 1 through NUM_RAID_GROUPS), or NUM_RAID_GROUPS+1 in case of errors
needinfo
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.

Arguments

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.

Returns

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

Example

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.

Example

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.

plugin:register_text_generator

plugin:register_tab_control

These are described later.


Disposition

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.

Arguments

code
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.
notes
string - The text to initially write into the Notes column for this disposition.
menu
string - The text in the "Mark As..." dropdown menu. This can be specified as nil in which case the notes text will be used.
tooltip
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.
can_reassign
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.
affects_history
boolean - True if an item in this state should be recorded in the recipient's running history.
from_notes_text
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.

Returns

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.

Example

myplugin:add_loot_disposition ('recipe', "38","ff","4f",
    "BoP recipe",
    "recipe/pattern",
    [[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