Mercurial > wow > ouroloot
comparison mleqdkp.lua @ 1:822b6ca3ef89
Import of 2.15, moving to wowace svn.
| author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
|---|---|
| date | Sat, 16 Apr 2011 06:03:29 +0000 |
| parents | |
| children | 67b8537e8432 |
comparison
equal
deleted
inserted
replaced
| 0:0f14a1e5364d | 1:822b6ca3ef89 |
|---|---|
| 1 if UnitName"player" ~= "Farmbuyer" then return end | |
| 2 local addon = select(2,...) | |
| 3 | |
| 4 -- We keep some local state bundled up rather than trying to pass it around | |
| 5 -- as paramters (which would have entailed creating a ton of closures). | |
| 6 local state = {} | |
| 7 local tag_lookup_handlers = {} | |
| 8 local do_tag_lookup_handler | |
| 9 | |
| 10 | |
| 11 --[[ | |
| 12 This is taken from CT_RaidTracker 1.7.32, reconstructing the output from | |
| 13 code inspection. No official format documents are available on the web | |
| 14 without downloading and installing the EQDKP webserver package. Bah. | |
| 15 | |
| 16 Case of tag names shouldn't matter, but is preserved here from CT_RaidTracker | |
| 17 code for comparison of generated output. | |
| 18 | |
| 19 There is some waste adding newlines between elements here only to strip them | |
| 20 out later, but it's worth the extra cycles for debugging and verification. | |
| 21 | |
| 22 $TIMESTAMP,$ENDTIME MM/DD/YY HH:mm:ss except we don't have seconds available | |
| 23 $REALM GetRealmName() | |
| 24 $ZONE raw name, not snarky | |
| 25 $RAIDNOTE arbitrary text for the raid event | |
| 26 $PHAT_LEWTS all accumulated loot entries | |
| 27 ]] | |
| 28 local XML = ([====[ | |
| 29 <RaidInfo> | |
| 30 <Version>1.4</Version> {In live output, this is missing due to scoping bug in ct_raidtracker.lua:3471} | |
| 31 <key>$TIMESTAMP</key> | |
| 32 <realm>$REALM</realm> | |
| 33 <start>$TIMESTAMP</start> {Same as the key, apparently?} | |
| 34 <end>$ENDTIME</end> {Set by the "end the raid" command in the raid tracker, here just the final entry time} | |
| 35 <zone>$ZONE</zone> {may be optional. first one on the list in case of multiple zones?} | |
| 36 {<difficulty>$DIFFICULTY</difficulty> {this scales badly in places like ICC. may be optional?}} | |
| 37 | |
| 38 {<PlayerInfos>... {guh.}} | |
| 39 | |
| 40 <BossKills> | |
| 41 $BOSS_KILLS | |
| 42 </BossKills> | |
| 43 | |
| 44 {<Wipes> bleh} | |
| 45 {<NextBoss>Baron Steamroller</NextBoss> {only one "next boss" for the whole raid event? huh?}} | |
| 46 | |
| 47 <note><![CDATA[$RAIDNOTE - Zone: $ZONE]]></note> | |
| 48 | |
| 49 {<Join>...</Join><Leave>...</Leave> {specific timestamps per player. meh.}} | |
| 50 | |
| 51 <Loot> | |
| 52 $PHAT_LEWTS | |
| 53 </Loot> | |
| 54 </RaidInfo>]====]):gsub('%b{}', "") | |
| 55 | |
| 56 --[[ | |
| 57 See the loot markup, next block. | |
| 58 ]] | |
| 59 local boss_kills_xml = ([====[ | |
| 60 <key$N> | |
| 61 <name>$BOSS_NAME</name> | |
| 62 <time>$BOSS_TIME</time> | |
| 63 <attendees></attendees> {this is actually empty in the working example...} | |
| 64 <difficulty>$DIFFICULTY</difficulty> | |
| 65 </key$N> | |
| 66 ]====]):gsub('%b{}', "") | |
| 67 | |
| 68 local function boss_kills_tag_lookup (tag) | |
| 69 if tag == 'N' then | |
| 70 return tostring(state.key) | |
| 71 elseif tag == 'BOSS_NAME' then | |
| 72 return state.entry.bosskill | |
| 73 elseif tag == 'BOSS_TIME' then | |
| 74 return do_tag_lookup_handler (state.index, state.entry, 'TIME') | |
| 75 else | |
| 76 return do_tag_lookup_handler (state.index, state.entry, tag) or 'NYI' | |
| 77 end | |
| 78 end | |
| 79 | |
| 80 --[[ | |
| 81 $N 1-based loop variable for key element | |
| 82 $ITEMNAME Without The Brackets | |
| 83 $ITEMID Not the ID, actually a full itemstring without the leading "item:" | |
| 84 $ICON Last component of texture path? | |
| 85 $CLASS,$SUBCLASS ItemType | |
| 86 $COLOR GetItemQualityColor, full 8-digit string | |
| 87 $COUNT,$BOSS,$ZONE, | |
| 88 $PLAYER all self-explanatory | |
| 89 $COSTS in DKP points... hmmm | |
| 90 $ITEMNOTE take the notes field for this one | |
| 91 $TIME another formatted timestamp | |
| 92 ]] | |
| 93 local phat_lewt_xml = ([====[ | |
| 94 <key$N> | |
| 95 $LEWT_GRUNTWORK | |
| 96 <zone>$ZONE</zone> {may be optional} | |
| 97 <difficulty>$DIFFICULTY</difficulty> {this scales badly in places like ICC. may be optional?} | |
| 98 <Note><![CDATA[$ITEMNOTE - Zone: $ZONE - Boss: $BOSS - $COSTS DKP]]></Note> {zone can be followed by difficulty} | |
| 99 </key$N> | |
| 100 ]====]):gsub('%b{}', "") | |
| 101 | |
| 102 local function phat_lewt_tag_lookup (tag) | |
| 103 if tag == 'N' then | |
| 104 return tostring(state.key) | |
| 105 elseif tag == 'COSTS' | |
| 106 then return '1' | |
| 107 else | |
| 108 return do_tag_lookup_handler (state.index, state.entry, tag) or 'NYI' | |
| 109 end | |
| 110 end | |
| 111 | |
| 112 do | |
| 113 local gruntwork_tags = { | |
| 114 "ItemName", "ItemID", "Icon", "Class", "SubClass", "Color", "Count", | |
| 115 "Player", "Costs", "Boss", "Time", | |
| 116 } | |
| 117 for i,tag in ipairs(gruntwork_tags) do | |
| 118 gruntwork_tags[i] = (" <%s>$%s</%s>"):format(tag,tag:upper(),tag) | |
| 119 end | |
| 120 phat_lewt_xml = phat_lewt_xml:gsub('$LEWT_GRUNTWORK', table.concat(gruntwork_tags,'\n')) | |
| 121 end | |
| 122 | |
| 123 | |
| 124 local function format_EQDKP_timestamp (day_entry, time_entry) | |
| 125 --assert(day_entry.kind == 'time', day_entry.kind .. " passed to MLEQDKP timestamp") | |
| 126 return addon:format_timestamp ("$M/$D/$Y $h:$m:00", day_entry, time_entry) | |
| 127 end | |
| 128 | |
| 129 | |
| 130 -- Look up tag strings for a particular item, given index and entry table. | |
| 131 tag_lookup_handlers.ITEMNAME = | |
| 132 function (i, e) | |
| 133 return e.itemname | |
| 134 end | |
| 135 | |
| 136 tag_lookup_handlers.ITEMID = | |
| 137 function (i, e) | |
| 138 return e.itemlink:match("^|c%x+|H(item[%d:]+)|h%[") | |
| 139 end | |
| 140 | |
| 141 tag_lookup_handlers.ICON = | |
| 142 function (i, e) | |
| 143 local str = e.itexture | |
| 144 repeat | |
| 145 local s = str:find('\\') | |
| 146 if s then str = str:sub(s+1) end | |
| 147 until not s | |
| 148 return str | |
| 149 end | |
| 150 | |
| 151 tag_lookup_handlers.CLASS = | |
| 152 function (i, e) | |
| 153 return state.class | |
| 154 end | |
| 155 | |
| 156 tag_lookup_handlers.SUBCLASS = | |
| 157 function (i, e) | |
| 158 return state.subclass | |
| 159 end | |
| 160 | |
| 161 tag_lookup_handlers.COLOR = | |
| 162 function (i, e) | |
| 163 local q = select(4, GetItemQualityColor(e.quality)) | |
| 164 return q:sub(3) -- skip leading |c | |
| 165 end | |
| 166 | |
| 167 tag_lookup_handlers.COUNT = | |
| 168 function (i, e) | |
| 169 return e.count and e.count:sub(2) or "1" -- skip the leading "x" | |
| 170 end | |
| 171 | |
| 172 -- maybe combine these next two | |
| 173 tag_lookup_handlers.BOSS = | |
| 174 function (i, e) | |
| 175 while i > 0 and state.loot[i].kind ~= 'boss' do | |
| 176 i = i - 1 | |
| 177 end | |
| 178 if i == 0 then return "No Boss Entry Found, Unknown Boss" end | |
| 179 return state.loot[i].bosskill | |
| 180 end | |
| 181 | |
| 182 tag_lookup_handlers.ZONE = | |
| 183 function (i, e) | |
| 184 while i > 0 and state.loot[i].kind ~= 'boss' do | |
| 185 i = i - 1 | |
| 186 end | |
| 187 if i == 0 then return "No Boss Entry Found, Unknown Zone" end | |
| 188 return state.loot[i].instance | |
| 189 end | |
| 190 | |
| 191 tag_lookup_handlers.DIFFICULTY = | |
| 192 function (i, e) | |
| 193 local tag = tag_lookup_handlers.ZONE(i,e) | |
| 194 local N,h = tag:match("%((%d+)(h?)%)") | |
| 195 if not N then return "1" end -- maybe signal an error instead? | |
| 196 N = tonumber(N) | |
| 197 N = ( (N==10) and 1 or 2 ) + ( (h=='h') and 2 or 0 ) | |
| 198 return tostring(N) | |
| 199 end | |
| 200 | |
| 201 tag_lookup_handlers.PLAYER = | |
| 202 function (i, e) | |
| 203 return state.player | |
| 204 end | |
| 205 | |
| 206 tag_lookup_handlers.ITEMNOTE = | |
| 207 function (i, e) | |
| 208 return state.itemnote | |
| 209 end | |
| 210 | |
| 211 tag_lookup_handlers.TIME = | |
| 212 function (i, e) | |
| 213 local ti,tl = addon:find_previous_time_entry(i) | |
| 214 return format_EQDKP_timestamp(tl,e) | |
| 215 end | |
| 216 | |
| 217 | |
| 218 function do_tag_lookup_handler (index, entry, tag) | |
| 219 local h = tag_lookup_handlers[tag] | |
| 220 if h then | |
| 221 return h(index,entry) | |
| 222 else | |
| 223 error(("MLDKP tag lookup (index %d) on tag %s with no handler"):format(index,tag)) | |
| 224 end | |
| 225 end | |
| 226 | |
| 227 local function generator (ttype, loot, last_printed, generated, cache) | |
| 228 -- Because it's XML, generated text is "grown" by shoving more crap into | |
| 229 -- the middle instead of appending to the end. Only easy way of doing that | |
| 230 -- here is regenerating it from scratch each time. | |
| 231 generated[ttype] = nil | |
| 232 | |
| 233 local _ | |
| 234 local text = XML | |
| 235 state.loot = loot | |
| 236 | |
| 237 -- TIMESTAMPs | |
| 238 do | |
| 239 local f,l -- first and last timestamps in the table | |
| 240 for i = 1, #loot do | |
| 241 if loot[i].kind == 'time' then | |
| 242 f = format_EQDKP_timestamp(loot[i]) | |
| 243 break | |
| 244 end | |
| 245 end | |
| 246 _,l = addon:find_previous_time_entry(#loot) -- latest timestamp | |
| 247 l = format_EQDKP_timestamp(l,loot[#loot]) | |
| 248 text = text:gsub('$TIMESTAMP', f):gsub('$ENDTIME', l) | |
| 249 end | |
| 250 | |
| 251 -- Loot | |
| 252 do | |
| 253 local all_lewts = {} | |
| 254 local lewt_template = phat_lewt_xml | |
| 255 | |
| 256 state.key = 1 | |
| 257 for i,e in addon:filtered_loot_iter('loot') do | |
| 258 state.index, state.entry = i, e | |
| 259 -- no sense doing repeated getiteminfo calls | |
| 260 state.class, state.subclass = select(6, GetItemInfo(e.id)) | |
| 261 | |
| 262 -- similar logic as text_tabs.lua: | |
| 263 -- assuming nobody names a toon "offspec" or "gvault" | |
| 264 local P, N | |
| 265 local disp = e.disposition or e.person | |
| 266 if disp == 'offspec' then | |
| 267 P,N = e.person, "offspec" | |
| 268 elseif disp == 'gvault' then | |
| 269 P,N = "guild vault", e.person | |
| 270 else | |
| 271 P,N = disp, "" | |
| 272 end | |
| 273 if e.extratext_byhand then | |
| 274 N = N .. " -- " .. e.extratext | |
| 275 end | |
| 276 state.player, state.itemnote = P, N | |
| 277 | |
| 278 all_lewts[#all_lewts+1] = lewt_template:gsub('%$([%w_]+)', | |
| 279 phat_lewt_tag_lookup) | |
| 280 state.key = state.key + 1 | |
| 281 end | |
| 282 | |
| 283 text = text:gsub('$PHAT_LEWTS', table.concat(all_lewts, '\n')) | |
| 284 end | |
| 285 | |
| 286 -- Bosses | |
| 287 do | |
| 288 local all_bosses = {} | |
| 289 local boss_template = boss_kills_xml | |
| 290 | |
| 291 state.key = 1 | |
| 292 for i,e in addon:filtered_loot_iter('boss') do | |
| 293 if e.reason == 'kill' then -- oh, for a 'continue' statement... | |
| 294 state.index, state.entry = i, e | |
| 295 all_bosses[#all_bosses+1] = boss_template:gsub('%$([%w_]+)', | |
| 296 boss_kills_tag_lookup) | |
| 297 state.key = state.key + 1 | |
| 298 end | |
| 299 end | |
| 300 | |
| 301 text = text:gsub('$BOSS_KILLS', table.concat(all_bosses, '\n')) | |
| 302 end | |
| 303 | |
| 304 -- In addition to doing the top-level zone, this will also catch any | |
| 305 -- leftover $ZONE tags. There could be multiple places in the raid, so | |
| 306 -- we default to the first one we saw. | |
| 307 do | |
| 308 local iter = addon:filtered_loot_iter() -- HACK | |
| 309 local first_boss = iter('boss',0) | |
| 310 local zone = first_boss and loot[first_boss].instance or "Unknown" | |
| 311 text = text:gsub('$ZONE', zone) | |
| 312 end | |
| 313 | |
| 314 -- Misc | |
| 315 text = text:gsub('$REALM', (GetRealmName())) | |
| 316 --text = text:gsub('$DIFFICULTY', ) | |
| 317 text = text:gsub('$RAIDNOTE', "") | |
| 318 | |
| 319 cache[#cache+1] = "Formatted version (scroll down for unformatted):" | |
| 320 cache[#cache+1] = "===========================" | |
| 321 cache[#cache+1] = text | |
| 322 cache[#cache+1] = '\n' | |
| 323 | |
| 324 cache[#cache+1] = "Unformatted version:" | |
| 325 cache[#cache+1] = "===========================" | |
| 326 text = text:gsub('>%s+<', "><") | |
| 327 cache[#cache+1] = text | |
| 328 cache[#cache+1] = '\n' | |
| 329 | |
| 330 wipe(state) | |
| 331 return true | |
| 332 end | |
| 333 | |
| 334 local function specials (_, editbox, container, mkbutton) | |
| 335 local hl = mkbutton("Highlight", | |
| 336 [[Highlight the unformatted copy for copy-and-pasting.]]) | |
| 337 hl:SetFullWidth(true) | |
| 338 hl:SetCallback("OnClick", function(_hl) | |
| 339 local txt = editbox:GetText() | |
| 340 local _,start = txt:find("Unformatted version:\n=+\n") | |
| 341 local _,finish = txt:find("</RaidInfo>", start) | |
| 342 editbox.editBox:HighlightText(start,finish) | |
| 343 editbox.editBox:SetCursorPosition(start) | |
| 344 end) | |
| 345 container:AddChild(hl) | |
| 346 end | |
| 347 | |
| 348 addon:register_text_generator ("mleqdkp", [[ML/EQ-DKP]], [[MLdkp 1.1 EQDKP format]], generator, specials) | |
| 349 | |
| 350 -- vim:noet |
