annotate Main.lua @ 306:7feb687b1b22

Fixes
author James D. Callahan III <jcallahan@curse.com>
date Tue, 23 Jul 2013 18:07:07 -0500
parents 4986ef8a338a
children c33ab3413737
rev   line source
jcallahan@246 1 -- LUA API ------------------------------------------------------------
jcallahan@246 2
jcallahan@0 3 local _G = getfenv(0)
jcallahan@0 4
jcallahan@0 5 local pairs = _G.pairs
jcallahan@1 6 local tonumber = _G.tonumber
jcallahan@1 7
jcallahan@1 8 local bit = _G.bit
jcallahan@1 9 local math = _G.math
jcallahan@1 10 local table = _G.table
jcallahan@1 11
jcallahan@78 12 local select = _G.select
jcallahan@306 13 local unpack = _G.unpack
jcallahan@78 14
jcallahan@0 15
jcallahan@246 16 -- ADDON NAMESPACE ----------------------------------------------------
jcallahan@246 17
jcallahan@0 18 local ADDON_NAME, private = ...
jcallahan@0 19
jcallahan@0 20 local LibStub = _G.LibStub
jcallahan@249 21 local WDP = LibStub("AceAddon-3.0"):NewAddon(ADDON_NAME, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0")
jcallahan@0 22
jcallahan@48 23 local deformat = LibStub("LibDeformat-3.0")
jcallahan@115 24 local LPJ = LibStub("LibPetJournal-2.0")
jcallahan@141 25 local MapData = LibStub("LibMapData-1.0")
jcallahan@48 26
jcallahan@4 27 local DatamineTT = _G.CreateFrame("GameTooltip", "WDPDatamineTT", _G.UIParent, "GameTooltipTemplate")
jcallahan@5 28 DatamineTT:SetOwner(_G.WorldFrame, "ANCHOR_NONE")
jcallahan@5 29
jcallahan@0 30
jcallahan@246 31 -- CONSTANTS ----------------------------------------------------------
jcallahan@246 32
jcallahan@246 33 local AF = private.ACTION_TYPE_FLAGS
jcallahan@246 34 local CLIENT_LOCALE = _G.GetLocale()
jcallahan@294 35 local DB_VERSION = 17
jcallahan@246 36 local DEBUGGING = false
jcallahan@156 37 local EVENT_DEBUG = false
jcallahan@246 38 local OBJECT_ID_ANVIL = 192628
jcallahan@246 39 local OBJECT_ID_FORGE = 1685
jcallahan@246 40 local PLAYER_CLASS = _G.select(2, _G.UnitClass("player"))
jcallahan@246 41 local PLAYER_FACTION = _G.UnitFactionGroup("player")
jcallahan@300 42 local PLAYER_GUID
jcallahan@246 43 local PLAYER_NAME = _G.UnitName("player")
jcallahan@246 44 local PLAYER_RACE = _G.select(2, _G.UnitRace("player"))
jcallahan@246 45
jcallahan@246 46 local ALLOWED_LOCALES = {
jcallahan@246 47 enUS = true,
jcallahan@246 48 enGB = true,
jcallahan@246 49 }
jcallahan@157 50
jcallahan@0 51 local DATABASE_DEFAULTS = {
jcallahan@128 52 char = {},
jcallahan@0 53 global = {
jcallahan@270 54 config = {
jcallahan@270 55 minimap_icon = {
jcallahan@270 56 hide = true,
jcallahan@270 57 },
jcallahan@270 58 },
jcallahan@0 59 items = {},
jcallahan@0 60 npcs = {},
jcallahan@0 61 objects = {},
jcallahan@0 62 quests = {},
jcallahan@167 63 spells = {},
jcallahan@17 64 zones = {},
jcallahan@0 65 }
jcallahan@0 66 }
jcallahan@0 67
jcallahan@1 68 local EVENT_MAPPING = {
jcallahan@90 69 AUCTION_HOUSE_SHOW = true,
jcallahan@90 70 BANKFRAME_OPENED = true,
jcallahan@90 71 BATTLEFIELDS_SHOW = true,
jcallahan@56 72 BLACK_MARKET_ITEM_UPDATE = true,
jcallahan@48 73 CHAT_MSG_LOOT = true,
jcallahan@95 74 CHAT_MSG_MONSTER_SAY = "RecordQuote",
jcallahan@95 75 CHAT_MSG_MONSTER_WHISPER = "RecordQuote",
jcallahan@95 76 CHAT_MSG_MONSTER_YELL = "RecordQuote",
jcallahan@40 77 CHAT_MSG_SYSTEM = true,
jcallahan@23 78 COMBAT_LOG_EVENT_UNFILTERED = true,
jcallahan@18 79 COMBAT_TEXT_UPDATE = true,
jcallahan@140 80 CURSOR_UPDATE = true,
jcallahan@90 81 FORGE_MASTER_OPENED = true,
jcallahan@90 82 GOSSIP_SHOW = true,
jcallahan@290 83 GROUP_ROSTER_UPDATE = true,
jcallahan@93 84 GUILDBANKFRAME_OPENED = true,
jcallahan@42 85 ITEM_TEXT_BEGIN = true,
jcallahan@189 86 ITEM_UPGRADE_MASTER_OPENED = true,
jcallahan@124 87 LOOT_CLOSED = true,
jcallahan@1 88 LOOT_OPENED = true,
jcallahan@89 89 MAIL_SHOW = true,
jcallahan@133 90 MERCHANT_CLOSED = true,
jcallahan@7 91 MERCHANT_SHOW = "UpdateMerchantItems",
jcallahan@61 92 MERCHANT_UPDATE = "UpdateMerchantItems",
jcallahan@25 93 PET_BAR_UPDATE = true,
jcallahan@115 94 PET_JOURNAL_LIST_UPDATE = true,
jcallahan@156 95 PLAYER_REGEN_DISABLED = true,
jcallahan@156 96 PLAYER_REGEN_ENABLED = true,
jcallahan@2 97 PLAYER_TARGET_CHANGED = true,
jcallahan@9 98 QUEST_COMPLETE = true,
jcallahan@9 99 QUEST_DETAIL = true,
jcallahan@9 100 QUEST_LOG_UPDATE = true,
jcallahan@97 101 QUEST_PROGRESS = true,
jcallahan@178 102 SHOW_LOOT_TOAST = true,
jcallahan@306 103 SPELL_CONFIRMATION_PROMPT = true,
jcallahan@88 104 TAXIMAP_OPENED = true,
jcallahan@92 105 TRADE_SKILL_SHOW = true,
jcallahan@167 106 TRAINER_CLOSED = true,
jcallahan@27 107 TRAINER_SHOW = true,
jcallahan@90 108 TRANSMOGRIFY_OPEN = true,
jcallahan@246 109 UNIT_PET = true,
jcallahan@4 110 UNIT_QUEST_LOG_CHANGED = true,
jcallahan@1 111 UNIT_SPELLCAST_FAILED = "HandleSpellFailure",
jcallahan@1 112 UNIT_SPELLCAST_FAILED_QUIET = "HandleSpellFailure",
jcallahan@1 113 UNIT_SPELLCAST_INTERRUPTED = "HandleSpellFailure",
jcallahan@1 114 UNIT_SPELLCAST_SENT = true,
jcallahan@1 115 UNIT_SPELLCAST_SUCCEEDED = true,
jcallahan@90 116 VOID_STORAGE_OPEN = true,
jcallahan@299 117 ZONE_CHANGED = "HandleZoneChange",
jcallahan@299 118 ZONE_CHANGED_INDOORS = "HandleZoneChange",
jcallahan@299 119 ZONE_CHANGED_NEW_AREA = "HandleZoneChange",
jcallahan@0 120 }
jcallahan@0 121
jcallahan@4 122
jcallahan@246 123 -- VARIABLES ----------------------------------------------------------
jcallahan@246 124
jcallahan@92 125 local anvil_spell_ids = {}
jcallahan@92 126 local currently_drunk
jcallahan@128 127 local char_db
jcallahan@128 128 local global_db
jcallahan@299 129 local group_member_guids = {}
jcallahan@246 130 local group_owner_guids_to_pet_guids = {}
jcallahan@246 131 local group_pet_guids = {}
jcallahan@299 132 local in_instance
jcallahan@187 133 local item_process_timer_handle
jcallahan@92 134 local faction_standings = {}
jcallahan@92 135 local forge_spell_ids = {}
jcallahan@95 136 local languages_known = {}
jcallahan@306 137 local loot_toast_container_timer_handle
jcallahan@95 138 local name_to_id_map = {}
jcallahan@306 139 local killed_boss_id_timer_handle
jcallahan@177 140 local killed_npc_id
jcallahan@2 141 local target_location_timer_handle
jcallahan@86 142 local current_target_id
jcallahan@126 143 local current_area_id
jcallahan@131 144 local current_loot
jcallahan@1 145
jcallahan@121 146 -- Data for our current action. Including possible values as a reference.
jcallahan@122 147 local current_action = {
jcallahan@121 148 identifier = nil,
jcallahan@121 149 loot_label = nil,
jcallahan@121 150 loot_list = nil,
jcallahan@121 151 loot_sources = nil,
jcallahan@121 152 map_level = nil,
jcallahan@121 153 spell_label = nil,
jcallahan@123 154 target_type = nil,
jcallahan@121 155 x = nil,
jcallahan@121 156 y = nil,
jcallahan@121 157 zone_data = nil,
jcallahan@121 158 }
jcallahan@92 159
jcallahan@246 160
jcallahan@246 161 -- HELPERS ------------------------------------------------------------
jcallahan@246 162
jcallahan@245 163 local function Debug(message, ...)
jcallahan@306 164 if not DEBUGGING or not message or not ... then
jcallahan@151 165 return
jcallahan@151 166 end
jcallahan@306 167 local args = { ... }
jcallahan@306 168
jcallahan@306 169 for index = 1, #args do
jcallahan@306 170 if args[index] == nil then
jcallahan@306 171 args[index] = "nil"
jcallahan@306 172 end
jcallahan@306 173 end
jcallahan@306 174 _G.print(message:format(unpack(args)))
jcallahan@151 175 end
jcallahan@151 176
jcallahan@151 177
jcallahan@169 178 local TradeSkillExecutePer
jcallahan@169 179 do
jcallahan@169 180 local header_list = {}
jcallahan@169 181
jcallahan@169 182 function TradeSkillExecutePer(iter_func)
jcallahan@169 183 if not _G.TradeSkillFrame or not _G.TradeSkillFrame:IsVisible() then
jcallahan@169 184 return
jcallahan@169 185 end
jcallahan@167 186 -- Clear the search box focus so the scan will have correct results.
jcallahan@167 187 local search_box = _G.TradeSkillFrameSearchBox
jcallahan@167 188 search_box:SetText("")
jcallahan@169 189
jcallahan@167 190 _G.TradeSkillSearch_OnTextChanged(search_box)
jcallahan@167 191 search_box:ClearFocus()
jcallahan@167 192 search_box:GetScript("OnEditFocusLost")(search_box)
jcallahan@169 193
jcallahan@169 194 table.wipe(header_list)
jcallahan@169 195
jcallahan@169 196 -- Save the current state of the TradeSkillFrame so it can be restored after we muck with it.
jcallahan@169 197 local have_materials = _G.TradeSkillFrame.filterTbl.hasMaterials
jcallahan@169 198 local have_skillup = _G.TradeSkillFrame.filterTbl.hasSkillUp
jcallahan@169 199
jcallahan@169 200 if have_materials then
jcallahan@169 201 _G.TradeSkillFrame.filterTbl.hasMaterials = false
jcallahan@169 202 _G.TradeSkillOnlyShowMakeable(false)
jcallahan@169 203 end
jcallahan@169 204
jcallahan@169 205 if have_skillup then
jcallahan@169 206 _G.TradeSkillFrame.filterTbl.hasSkillUp = false
jcallahan@169 207 _G.TradeSkillOnlyShowSkillUps(false)
jcallahan@169 208 end
jcallahan@169 209 _G.SetTradeSkillInvSlotFilter(0, 1, 1)
jcallahan@169 210 _G.TradeSkillUpdateFilterBar()
jcallahan@169 211 _G.TradeSkillFrame_Update()
jcallahan@169 212
jcallahan@169 213 -- Expand all headers so we can see all the recipes there are
jcallahan@169 214 for tradeskill_index = 1, _G.GetNumTradeSkills() do
jcallahan@169 215 local name, tradeskill_type, _, is_expanded = _G.GetTradeSkillInfo(tradeskill_index)
jcallahan@169 216
jcallahan@169 217 if tradeskill_type == "header" or tradeskill_type == "subheader" then
jcallahan@169 218 if not is_expanded then
jcallahan@169 219 header_list[name] = true
jcallahan@169 220 _G.ExpandTradeSkillSubClass(tradeskill_index)
jcallahan@169 221 end
jcallahan@169 222 elseif iter_func(name, tradeskill_index) then
jcallahan@169 223 break
jcallahan@169 224 end
jcallahan@169 225 end
jcallahan@169 226
jcallahan@169 227 -- Restore the state of the things we changed.
jcallahan@169 228 for tradeskill_index = 1, _G.GetNumTradeSkills() do
jcallahan@169 229 local name, tradeskill_type, _, is_expanded = _G.GetTradeSkillInfo(tradeskill_index)
jcallahan@169 230
jcallahan@169 231 if header_list[name] then
jcallahan@169 232 _G.CollapseTradeSkillSubClass(tradeskill_index)
jcallahan@169 233 end
jcallahan@169 234 end
jcallahan@169 235 _G.TradeSkillFrame.filterTbl.hasMaterials = have_materials
jcallahan@169 236 _G.TradeSkillOnlyShowMakeable(have_materials)
jcallahan@169 237 _G.TradeSkillFrame.filterTbl.hasSkillUp = have_skillup
jcallahan@169 238 _G.TradeSkillOnlyShowSkillUps(have_skillup)
jcallahan@169 239
jcallahan@169 240 _G.TradeSkillUpdateFilterBar()
jcallahan@169 241 _G.TradeSkillFrame_Update()
jcallahan@167 242 end
jcallahan@169 243 end -- do-block
jcallahan@167 244
jcallahan@167 245
jcallahan@39 246 local ActualCopperCost
jcallahan@39 247 do
jcallahan@39 248 local BARTERING_SPELL_ID = 83964
jcallahan@39 249
jcallahan@39 250 local STANDING_DISCOUNTS = {
jcallahan@39 251 HATED = 0,
jcallahan@39 252 HOSTILE = 0,
jcallahan@39 253 UNFRIENDLY = 0,
jcallahan@39 254 NEUTRAL = 0,
jcallahan@39 255 FRIENDLY = 0.05,
jcallahan@39 256 HONORED = 0.1,
jcallahan@39 257 REVERED = 0.15,
jcallahan@39 258 EXALTED = 0.2,
jcallahan@39 259 }
jcallahan@39 260
jcallahan@39 261
jcallahan@39 262 function ActualCopperCost(copper_cost, rep_standing)
jcallahan@39 263 if not copper_cost or copper_cost == 0 then
jcallahan@39 264 return 0
jcallahan@39 265 end
jcallahan@39 266 local modifier = 1
jcallahan@39 267
jcallahan@39 268 if _G.IsSpellKnown(BARTERING_SPELL_ID) then
jcallahan@39 269 modifier = modifier - 0.1
jcallahan@39 270 end
jcallahan@39 271
jcallahan@39 272 if rep_standing then
jcallahan@39 273 if PLAYER_RACE == "Goblin" then
jcallahan@39 274 modifier = modifier - STANDING_DISCOUNTS["EXALTED"]
jcallahan@39 275 elseif STANDING_DISCOUNTS[rep_standing] then
jcallahan@39 276 modifier = modifier - STANDING_DISCOUNTS[rep_standing]
jcallahan@39 277 end
jcallahan@39 278 end
jcallahan@39 279 return math.floor(copper_cost / modifier)
jcallahan@39 280 end
jcallahan@39 281 end -- do-block
jcallahan@39 282
jcallahan@39 283
jcallahan@153 284 -- Called on a timer
jcallahan@177 285 local function ClearKilledNPC()
jcallahan@177 286 killed_npc_id = nil
jcallahan@177 287 end
jcallahan@177 288
jcallahan@177 289
jcallahan@203 290 local function ClearKilledBossID()
jcallahan@306 291 if killed_boss_id_timer_handle then
jcallahan@306 292 WDP:CancelTimer(killed_boss_id_timer_handle)
jcallahan@306 293 end
jcallahan@306 294 private.boss_loot_toasting = false
jcallahan@203 295 private.raid_finder_boss_id = nil
jcallahan@203 296 private.world_boss_id = nil
jcallahan@306 297 killed_boss_id_timer_handle = nil
jcallahan@306 298 end
jcallahan@306 299
jcallahan@306 300
jcallahan@306 301 local function ClearLootToastContainerID()
jcallahan@306 302 if loot_toast_container_timer_handle then
jcallahan@306 303 WDP:CancelTimer(loot_toast_container_timer_handle)
jcallahan@306 304 end
jcallahan@306 305 private.container_loot_toasting = false
jcallahan@306 306 private.loot_toast_container_id = nil
jcallahan@306 307 loot_toast_container_timer_handle = nil
jcallahan@203 308 end
jcallahan@203 309
jcallahan@203 310
jcallahan@29 311 local function InstanceDifficultyToken()
jcallahan@233 312 local _, instance_type, instance_difficulty, _, _, _, is_dynamic = _G.GetInstanceInfo()
jcallahan@59 313
jcallahan@59 314 if not instance_type or instance_type == "" then
jcallahan@59 315 instance_type = "NONE"
jcallahan@59 316 end
jcallahan@233 317 return ("%s:%d:%s"):format(instance_type:upper(), instance_difficulty, _G.tostring(is_dynamic))
jcallahan@29 318 end
jcallahan@29 319
jcallahan@29 320
jcallahan@19 321 local function DBEntry(data_type, unit_id)
jcallahan@19 322 if not data_type or not unit_id then
jcallahan@6 323 return
jcallahan@6 324 end
jcallahan@289 325 local category = global_db[data_type]
jcallahan@289 326
jcallahan@289 327 if not category then
jcallahan@289 328 category = {}
jcallahan@289 329 global_db[data_type] = category
jcallahan@289 330 end
jcallahan@289 331 local unit = category[unit_id]
jcallahan@6 332
jcallahan@10 333 if not unit then
jcallahan@187 334 unit = {}
jcallahan@289 335 category[unit_id] = unit
jcallahan@6 336 end
jcallahan@10 337 return unit
jcallahan@6 338 end
jcallahan@270 339
jcallahan@263 340 private.DBEntry = DBEntry
jcallahan@6 341
jcallahan@214 342 local NPCEntry
jcallahan@214 343 do
jcallahan@214 344 local npc_prototype = {}
jcallahan@214 345 local npc_meta = {
jcallahan@214 346 __index = npc_prototype
jcallahan@214 347 }
jcallahan@6 348
jcallahan@214 349 function NPCEntry(identifier)
jcallahan@227 350 local npc = DBEntry("npcs", identifier)
jcallahan@29 351
jcallahan@214 352 if not npc then
jcallahan@214 353 return
jcallahan@214 354 end
jcallahan@227 355 return _G.setmetatable(npc, npc_meta)
jcallahan@22 356 end
jcallahan@214 357
jcallahan@248 358 function npc_prototype:EncounterData(difficulty_token)
jcallahan@214 359 self.encounter_data = self.encounter_data or {}
jcallahan@248 360 self.encounter_data[difficulty_token] = self.encounter_data[difficulty_token] or {}
jcallahan@248 361 self.encounter_data[difficulty_token].stats = self.encounter_data[difficulty_token].stats or {}
jcallahan@248 362
jcallahan@248 363 return self.encounter_data[difficulty_token]
jcallahan@214 364 end
jcallahan@22 365 end
jcallahan@22 366
jcallahan@22 367
jcallahan@1 368 local function CurrentLocationData()
jcallahan@161 369 if _G.GetCurrentMapAreaID() ~= current_area_id then
jcallahan@145 370 return _G.GetRealZoneText(), current_area_id, 0, 0, 0, InstanceDifficultyToken()
jcallahan@145 371 end
jcallahan@1 372 local map_level = _G.GetCurrentMapDungeonLevel() or 0
jcallahan@1 373 local x, y = _G.GetPlayerMapPosition("player")
jcallahan@1 374
jcallahan@1 375 x = x or 0
jcallahan@1 376 y = y or 0
jcallahan@1 377
jcallahan@1 378 if x == 0 and y == 0 then
jcallahan@1 379 for level_index = 1, _G.GetNumDungeonMapLevels() do
jcallahan@1 380 _G.SetDungeonMapLevel(level_index)
jcallahan@1 381 x, y = _G.GetPlayerMapPosition("player")
jcallahan@1 382
jcallahan@1 383 if x and y and (x > 0 or y > 0) then
jcallahan@1 384 _G.SetDungeonMapLevel(map_level)
jcallahan@1 385 map_level = level_index
jcallahan@1 386 break
jcallahan@1 387 end
jcallahan@1 388 end
jcallahan@1 389 end
jcallahan@1 390
jcallahan@1 391 if _G.DungeonUsesTerrainMap() then
jcallahan@1 392 map_level = map_level - 1
jcallahan@1 393 end
jcallahan@31 394 local x = _G.floor(x * 1000)
jcallahan@31 395 local y = _G.floor(y * 1000)
jcallahan@28 396
jcallahan@31 397 if x % 2 ~= 0 then
jcallahan@31 398 x = x + 1
jcallahan@28 399 end
jcallahan@28 400
jcallahan@31 401 if y % 2 ~= 0 then
jcallahan@31 402 y = y + 1
jcallahan@28 403 end
jcallahan@126 404 return _G.GetRealZoneText(), current_area_id, x, y, map_level, InstanceDifficultyToken()
jcallahan@1 405 end
jcallahan@1 406
jcallahan@1 407
jcallahan@1 408 local function ItemLinkToID(item_link)
jcallahan@1 409 if not item_link then
jcallahan@1 410 return
jcallahan@1 411 end
jcallahan@7 412 return tonumber(item_link:match("item:(%d+)"))
jcallahan@1 413 end
jcallahan@270 414
jcallahan@260 415 private.ItemLinkToID = ItemLinkToID
jcallahan@4 416
jcallahan@171 417 local function UnitTypeIsNPC(unit_type)
jcallahan@171 418 return unit_type == private.UNIT_TYPES.NPC or unit_type == private.UNIT_TYPES.VEHICLE
jcallahan@171 419 end
jcallahan@171 420
jcallahan@171 421
jcallahan@34 422 local ParseGUID
jcallahan@4 423 do
jcallahan@229 424 local UNIT_TYPES = private.UNIT_TYPES
jcallahan@4 425 local UNIT_TYPE_BITMASK = 0x007
jcallahan@4 426
jcallahan@281 427 local NPC_ID_MAPPING = {
jcallahan@281 428 [62164] = 63191, -- Garalon
jcallahan@281 429 }
jcallahan@281 430
jcallahan@281 431
jcallahan@34 432 function ParseGUID(guid)
jcallahan@5 433 if not guid then
jcallahan@5 434 return
jcallahan@5 435 end
jcallahan@229 436 local bitfield = tonumber(guid:sub(1, 5))
jcallahan@4 437
jcallahan@229 438 if not bitfield then
jcallahan@229 439 return UNIT_TYPES.UNKNOWN
jcallahan@229 440 end
jcallahan@229 441 local unit_type = _G.bit.band(bitfield, UNIT_TYPE_BITMASK)
jcallahan@229 442
jcallahan@229 443 if unit_type ~= UNIT_TYPES.PLAYER and unit_type ~= UNIT_TYPES.PET then
jcallahan@281 444 local unit_idnum = tonumber(guid:sub(6, 10), 16)
jcallahan@281 445 local id_mapping = NPC_ID_MAPPING[unit_idnum]
jcallahan@281 446
jcallahan@281 447 if id_mapping and UnitTypeIsNPC(unit_type) then
jcallahan@281 448 unit_idnum = id_mapping
jcallahan@281 449 end
jcallahan@281 450 return unit_type, unit_idnum
jcallahan@4 451 end
jcallahan@4 452 return unit_type
jcallahan@4 453 end
jcallahan@249 454
jcallahan@249 455 private.ParseGUID = ParseGUID
jcallahan@4 456 end -- do-block
jcallahan@4 457
jcallahan@4 458
jcallahan@141 459 local UpdateDBEntryLocation
jcallahan@141 460 do
jcallahan@141 461 -- Fishing node coordinate code based on code in GatherMate2 with permission from Kagaro.
jcallahan@141 462 local function FishingCoordinates(x, y, yard_width, yard_height)
jcallahan@141 463 local facing = _G.GetPlayerFacing()
jcallahan@141 464
jcallahan@141 465 if not facing then
jcallahan@141 466 return x, y
jcallahan@141 467 end
jcallahan@246 468 local rad = facing + math.pi
jcallahan@141 469 return x + math.sin(rad) * 15 / yard_width, y + math.cos(rad) * 15 / yard_height
jcallahan@10 470 end
jcallahan@10 471
jcallahan@24 472
jcallahan@141 473 function UpdateDBEntryLocation(entry_type, identifier)
jcallahan@141 474 if not identifier then
jcallahan@141 475 return
jcallahan@141 476 end
jcallahan@141 477 local zone_name, area_id, x, y, map_level, difficulty_token = CurrentLocationData()
jcallahan@141 478 local entry = DBEntry(entry_type, identifier)
jcallahan@141 479 entry[difficulty_token] = entry[difficulty_token] or {}
jcallahan@141 480 entry[difficulty_token].locations = entry[difficulty_token].locations or {}
jcallahan@141 481
jcallahan@141 482 local zone_token = ("%s:%d"):format(zone_name, area_id)
jcallahan@141 483 local zone_data = entry[difficulty_token].locations[zone_token]
jcallahan@141 484
jcallahan@141 485 if not zone_data then
jcallahan@141 486 zone_data = {}
jcallahan@141 487 entry[difficulty_token].locations[zone_token] = zone_data
jcallahan@141 488 end
jcallahan@141 489
jcallahan@141 490 -- Special case for Fishing.
jcallahan@141 491 if current_action.spell_label == "FISHING" then
jcallahan@141 492 local yard_width, yard_height = MapData:MapArea(area_id, map_level)
jcallahan@141 493
jcallahan@141 494 if yard_width > 0 and yard_height > 0 then
jcallahan@141 495 x, y = FishingCoordinates(x, y, yard_width, yard_height)
jcallahan@141 496 current_action.x = x
jcallahan@141 497 current_action.y = y
jcallahan@141 498 end
jcallahan@141 499 end
jcallahan@141 500 local location_token = ("%d:%d:%d"):format(map_level, x, y)
jcallahan@141 501
jcallahan@141 502 zone_data[location_token] = zone_data[location_token] or true
jcallahan@141 503 return zone_data
jcallahan@10 504 end
jcallahan@141 505 end -- do-block
jcallahan@10 506
jcallahan@10 507
jcallahan@19 508 local function HandleItemUse(item_link, bag_index, slot_index)
jcallahan@19 509 if not item_link then
jcallahan@19 510 return
jcallahan@19 511 end
jcallahan@19 512 local item_id = ItemLinkToID(item_link)
jcallahan@19 513
jcallahan@19 514 if not bag_index or not slot_index then
jcallahan@19 515 for new_bag_index = 0, _G.NUM_BAG_FRAMES do
jcallahan@19 516 for new_slot_index = 1, _G.GetContainerNumSlots(new_bag_index) do
jcallahan@19 517 if item_id == ItemLinkToID(_G.GetContainerItemLink(new_bag_index, new_slot_index)) then
jcallahan@19 518 bag_index = new_bag_index
jcallahan@19 519 slot_index = new_slot_index
jcallahan@19 520 break
jcallahan@19 521 end
jcallahan@19 522 end
jcallahan@19 523 end
jcallahan@19 524 end
jcallahan@19 525
jcallahan@19 526 if not bag_index or not slot_index then
jcallahan@19 527 return
jcallahan@19 528 end
jcallahan@19 529 local _, _, _, _, _, is_lootable = _G.GetContainerItemInfo(bag_index, slot_index)
jcallahan@19 530
jcallahan@19 531 if not is_lootable then
jcallahan@19 532 return
jcallahan@19 533 end
jcallahan@19 534 DatamineTT:ClearLines()
jcallahan@19 535 DatamineTT:SetBagItem(bag_index, slot_index)
jcallahan@19 536
jcallahan@19 537 for line_index = 1, DatamineTT:NumLines() do
jcallahan@19 538 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
jcallahan@19 539
jcallahan@19 540 if not current_line then
jcallahan@19 541 break
jcallahan@19 542 end
jcallahan@306 543
jcallahan@306 544 if current_line:GetText() == _G.ITEM_OPENABLE then
jcallahan@122 545 table.wipe(current_action)
jcallahan@123 546 current_action.target_type = AF.ITEM
jcallahan@122 547 current_action.identifier = item_id
jcallahan@122 548 current_action.loot_label = "contains"
jcallahan@19 549 break
jcallahan@19 550 end
jcallahan@19 551 end
jcallahan@19 552 end
jcallahan@19 553
jcallahan@19 554
jcallahan@39 555 local UnitFactionStanding
jcallahan@32 556 local UpdateFactionData
jcallahan@32 557 do
jcallahan@32 558 local MAX_FACTION_INDEX = 1000
jcallahan@20 559
jcallahan@32 560 local STANDING_NAMES = {
jcallahan@32 561 "HATED",
jcallahan@32 562 "HOSTILE",
jcallahan@32 563 "UNFRIENDLY",
jcallahan@32 564 "NEUTRAL",
jcallahan@32 565 "FRIENDLY",
jcallahan@32 566 "HONORED",
jcallahan@32 567 "REVERED",
jcallahan@32 568 "EXALTED",
jcallahan@32 569 }
jcallahan@32 570
jcallahan@39 571
jcallahan@39 572 function UnitFactionStanding(unit)
jcallahan@135 573 local unit_name = _G.UnitName(unit)
jcallahan@39 574 UpdateFactionData()
jcallahan@39 575 DatamineTT:ClearLines()
jcallahan@39 576 DatamineTT:SetUnit(unit)
jcallahan@39 577
jcallahan@39 578 for line_index = 1, DatamineTT:NumLines() do
jcallahan@64 579 local faction_name = _G["WDPDatamineTTTextLeft" .. line_index]:GetText():trim()
jcallahan@39 580
jcallahan@135 581 if faction_name and faction_name ~= unit_name and faction_standings[faction_name] then
jcallahan@39 582 return faction_name, faction_standings[faction_name]
jcallahan@39 583 end
jcallahan@39 584 end
jcallahan@39 585 end
jcallahan@39 586
jcallahan@39 587
jcallahan@32 588 function UpdateFactionData()
jcallahan@32 589 for faction_index = 1, MAX_FACTION_INDEX do
jcallahan@32 590 local faction_name, _, current_standing, _, _, _, _, _, is_header = _G.GetFactionInfo(faction_index)
jcallahan@32 591
jcallahan@86 592 if faction_name then
jcallahan@32 593 faction_standings[faction_name] = STANDING_NAMES[current_standing]
jcallahan@32 594 elseif not faction_name then
jcallahan@32 595 break
jcallahan@32 596 end
jcallahan@20 597 end
jcallahan@20 598 end
jcallahan@32 599 end -- do-block
jcallahan@20 600
jcallahan@48 601
jcallahan@75 602 local GenericLootUpdate
jcallahan@75 603 do
jcallahan@77 604 local function LootTable(entry, loot_type, top_field)
jcallahan@75 605 if top_field then
jcallahan@75 606 entry[top_field] = entry[top_field] or {}
jcallahan@75 607 entry[top_field][loot_type] = entry[top_field][loot_type] or {}
jcallahan@75 608 return entry[top_field][loot_type]
jcallahan@75 609 end
jcallahan@48 610 entry[loot_type] = entry[loot_type] or {}
jcallahan@75 611 return entry[loot_type]
jcallahan@48 612 end
jcallahan@48 613
jcallahan@75 614 function GenericLootUpdate(data_type, top_field)
jcallahan@132 615 local loot_type = current_loot.label
jcallahan@75 616 local loot_count = ("%s_count"):format(loot_type)
jcallahan@77 617 local source_list = {}
jcallahan@75 618
jcallahan@131 619 if current_loot.sources then
jcallahan@131 620 for source_guid, loot_data in pairs(current_loot.sources) do
jcallahan@304 621 local source_id
jcallahan@78 622
jcallahan@131 623 if current_loot.target_type == AF.ITEM then
jcallahan@119 624 -- Items return the player as the source, so we need to use the item's ID (disenchant, milling, etc)
jcallahan@131 625 source_id = current_loot.identifier
jcallahan@131 626 elseif current_loot.target_type == AF.OBJECT then
jcallahan@131 627 source_id = ("%s:%s"):format(current_loot.spell_label, select(2, ParseGUID(source_guid)))
jcallahan@119 628 else
jcallahan@119 629 source_id = select(2, ParseGUID(source_guid))
jcallahan@119 630 end
jcallahan@304 631 local entry = DBEntry(data_type, source_id)
jcallahan@75 632
jcallahan@119 633 if entry then
jcallahan@119 634 local loot_table = LootTable(entry, loot_type, top_field)
jcallahan@77 635
jcallahan@304 636 if not source_list[source_id] then
jcallahan@119 637 if top_field then
jcallahan@119 638 entry[top_field][loot_count] = (entry[top_field][loot_count] or 0) + 1
jcallahan@306 639 elseif not private.container_loot_toasting then
jcallahan@119 640 entry[loot_count] = (entry[loot_count] or 0) + 1
jcallahan@119 641 end
jcallahan@304 642 source_list[source_id] = true
jcallahan@77 643 end
jcallahan@119 644 UpdateDBEntryLocation(data_type, source_id)
jcallahan@75 645
jcallahan@119 646 for item_id, quantity in pairs(loot_data) do
jcallahan@119 647 table.insert(loot_table, ("%d:%d"):format(item_id, quantity))
jcallahan@119 648 end
jcallahan@75 649 end
jcallahan@75 650 end
jcallahan@75 651 end
jcallahan@121 652
jcallahan@121 653 -- This is used for Gas Extractions.
jcallahan@131 654 if #current_loot.list <= 0 then
jcallahan@78 655 return
jcallahan@78 656 end
jcallahan@82 657 local entry
jcallahan@82 658
jcallahan@82 659 -- At this point we only have a name if it's an object.
jcallahan@131 660 if current_loot.target_type == AF.OBJECT then
jcallahan@131 661 entry = DBEntry(data_type, ("%s:%s"):format(current_loot.spell_label, current_loot.object_name))
jcallahan@82 662 else
jcallahan@131 663 entry = DBEntry(data_type, current_loot.identifier)
jcallahan@82 664 end
jcallahan@75 665
jcallahan@75 666 if not entry then
jcallahan@75 667 return
jcallahan@75 668 end
jcallahan@77 669 local loot_table = LootTable(entry, loot_type, top_field)
jcallahan@77 670
jcallahan@131 671 if not source_list[current_loot.identifier] then
jcallahan@77 672 if top_field then
jcallahan@77 673 entry[top_field][loot_count] = (entry[top_field][loot_count] or 0) + 1
jcallahan@77 674 else
jcallahan@77 675 entry[loot_count] = (entry[loot_count] or 0) + 1
jcallahan@77 676 end
jcallahan@304 677 source_list[current_loot.identifier] = true
jcallahan@77 678 end
jcallahan@75 679
jcallahan@131 680 for index = 1, #current_loot.list do
jcallahan@131 681 table.insert(loot_table, current_loot.list[index])
jcallahan@75 682 end
jcallahan@48 683 end
jcallahan@75 684 end -- do-block
jcallahan@48 685
jcallahan@97 686
jcallahan@97 687 local ReplaceKeywords
jcallahan@97 688 do
jcallahan@97 689 local KEYWORD_SUBSTITUTIONS = {
jcallahan@97 690 class = PLAYER_CLASS,
jcallahan@97 691 name = PLAYER_NAME,
jcallahan@97 692 race = PLAYER_RACE,
jcallahan@97 693 }
jcallahan@97 694
jcallahan@97 695
jcallahan@97 696 function ReplaceKeywords(text)
jcallahan@97 697 if not text or text == "" then
jcallahan@97 698 return ""
jcallahan@97 699 end
jcallahan@97 700
jcallahan@97 701 for category, lookup in pairs(KEYWORD_SUBSTITUTIONS) do
jcallahan@97 702 local category_format = ("<%s>"):format(category)
jcallahan@97 703 text = text:gsub(lookup, category_format):gsub(lookup:lower(), category_format)
jcallahan@97 704 end
jcallahan@97 705 return text
jcallahan@97 706 end
jcallahan@97 707 end -- do-block
jcallahan@97 708
jcallahan@97 709
jcallahan@154 710 -- Contains a dirty hack due to Blizzard's strange handling of Micro Dungeons; GetMapInfo() will not return correct information
jcallahan@154 711 -- unless the WorldMapFrame is shown.
jcallahan@143 712 do
jcallahan@143 713 -- MapFileName = MapAreaID
jcallahan@143 714 local MICRO_DUNGEON_IDS = {
jcallahan@143 715 ShrineofTwoMoons = 903,
jcallahan@143 716 ShrineofSevenStars = 905,
jcallahan@143 717 }
jcallahan@126 718
jcallahan@299 719 local function SetCurrentAreaID()
jcallahan@156 720 if private.in_combat then
jcallahan@156 721 private.set_area_id = true
jcallahan@156 722 return
jcallahan@156 723 end
jcallahan@155 724 local map_area_id = _G.GetCurrentMapAreaID()
jcallahan@155 725
jcallahan@155 726 if map_area_id == current_area_id then
jcallahan@155 727 return
jcallahan@155 728 end
jcallahan@143 729 local world_map = _G.WorldMapFrame
jcallahan@143 730 local map_visible = world_map:IsVisible()
jcallahan@143 731 local sfx_value = _G.tonumber(_G.GetCVar("Sound_EnableSFX"))
jcallahan@143 732
jcallahan@143 733 if not map_visible then
jcallahan@143 734 _G.SetCVar("Sound_EnableSFX", 0)
jcallahan@143 735 world_map:Show()
jcallahan@143 736 end
jcallahan@143 737 local micro_dungeon_id = MICRO_DUNGEON_IDS[select(5, _G.GetMapInfo())]
jcallahan@143 738
jcallahan@154 739 _G.SetMapToCurrentZone()
jcallahan@154 740
jcallahan@143 741 if micro_dungeon_id then
jcallahan@143 742 current_area_id = micro_dungeon_id
jcallahan@143 743 else
jcallahan@143 744 current_area_id = _G.GetCurrentMapAreaID()
jcallahan@143 745 end
jcallahan@143 746
jcallahan@154 747 if map_visible then
jcallahan@154 748 _G.SetMapByID(map_area_id)
jcallahan@154 749 else
jcallahan@143 750 world_map:Hide()
jcallahan@143 751 _G.SetCVar("Sound_EnableSFX", sfx_value)
jcallahan@143 752 end
jcallahan@143 753 end
jcallahan@299 754
jcallahan@299 755 function WDP:HandleZoneChange(event_name)
jcallahan@299 756 in_instance = _G.IsInInstance()
jcallahan@299 757 SetCurrentAreaID()
jcallahan@299 758 end
jcallahan@154 759 end
jcallahan@126 760
jcallahan@301 761 local function InitializeCurrentLoot()
jcallahan@301 762 current_loot = {
jcallahan@301 763 list = {},
jcallahan@301 764 sources = {},
jcallahan@301 765 identifier = current_action.identifier,
jcallahan@301 766 label = current_action.loot_label or "drops",
jcallahan@301 767 map_level = current_action.map_level,
jcallahan@301 768 object_name = current_action.object_name,
jcallahan@301 769 spell_label = current_action.spell_label,
jcallahan@301 770 target_type = current_action.target_type,
jcallahan@301 771 x = current_action.x,
jcallahan@301 772 y = current_action.y,
jcallahan@301 773 zone_data = current_action.zone_data,
jcallahan@301 774 }
jcallahan@301 775
jcallahan@301 776 table.wipe(current_action)
jcallahan@301 777 end
jcallahan@246 778
jcallahan@246 779 -- METHODS ------------------------------------------------------------
jcallahan@246 780
jcallahan@0 781 function WDP:OnInitialize()
jcallahan@128 782 local db = LibStub("AceDB-3.0"):New("WoWDBProfilerData", DATABASE_DEFAULTS, "Default")
jcallahan@270 783 private.db = db
jcallahan@128 784 global_db = db.global
jcallahan@128 785 char_db = db.char
jcallahan@14 786
jcallahan@270 787 local raw_db = _G.WoWDBProfilerData
jcallahan@18 788 local build_num = tonumber(private.build_num)
jcallahan@14 789
jcallahan@136 790 if (raw_db.version and raw_db.version < DB_VERSION) or (raw_db.build_num and raw_db.build_num < build_num) then
jcallahan@74 791 for entry in pairs(DATABASE_DEFAULTS.global) do
jcallahan@128 792 global_db[entry] = {}
jcallahan@74 793 end
jcallahan@74 794 end
jcallahan@35 795 raw_db.build_num = build_num
jcallahan@63 796 raw_db.version = DB_VERSION
jcallahan@249 797
jcallahan@251 798 if DEBUGGING then -- TODO: Remove this when comment subsystem is finished.
jcallahan@270 799 private.InitializeCommentSystem()
jcallahan@251 800 self:RegisterChatCommand("comment", private.ProcessCommentCommand)
jcallahan@251 801 end
jcallahan@0 802 end
jcallahan@0 803
jcallahan@0 804
jcallahan@153 805 function WDP:EventDispatcher(...)
jcallahan@153 806 local event_name = ...
jcallahan@153 807
jcallahan@153 808 if DEBUGGING then
jcallahan@154 809 if event_name == "COMBAT_LOG_EVENT_UNFILTERED" then
jcallahan@154 810 Debug(event_name)
jcallahan@154 811 else
jcallahan@154 812 Debug(...)
jcallahan@153 813 end
jcallahan@153 814 end
jcallahan@153 815 local func = EVENT_MAPPING[event_name]
jcallahan@153 816
jcallahan@153 817 if _G.type(func) == "boolean" then
jcallahan@153 818 self[event_name](self, ...)
jcallahan@153 819 elseif _G.type(func) == "function" then
jcallahan@159 820 self[func](self, ...)
jcallahan@153 821 end
jcallahan@153 822 end
jcallahan@153 823
jcallahan@153 824
jcallahan@0 825 function WDP:OnEnable()
jcallahan@300 826 PLAYER_GUID = _G.UnitGUID("player")
jcallahan@300 827
jcallahan@0 828 for event_name, mapping in pairs(EVENT_MAPPING) do
jcallahan@156 829 if EVENT_DEBUG then
jcallahan@153 830 self:RegisterEvent(event_name, "EventDispatcher")
jcallahan@153 831 else
jcallahan@153 832 self:RegisterEvent(event_name, (_G.type(mapping) ~= "boolean") and mapping or nil)
jcallahan@153 833 end
jcallahan@0 834 end
jcallahan@95 835
jcallahan@95 836 for index = 1, _G.GetNumLanguages() do
jcallahan@95 837 languages_known[_G.GetLanguageByIndex(index)] = true
jcallahan@95 838 end
jcallahan@187 839 item_process_timer_handle = self:ScheduleRepeatingTimer("ProcessItems", 30)
jcallahan@31 840 target_location_timer_handle = self:ScheduleRepeatingTimer("UpdateTargetLocation", 0.5)
jcallahan@19 841
jcallahan@19 842 _G.hooksecurefunc("UseContainerItem", function(bag_index, slot_index, target_unit)
jcallahan@19 843 if target_unit then
jcallahan@19 844 return
jcallahan@19 845 end
jcallahan@19 846 HandleItemUse(_G.GetContainerItemLink(bag_index, slot_index), bag_index, slot_index)
jcallahan@19 847 end)
jcallahan@19 848
jcallahan@19 849 _G.hooksecurefunc("UseItemByName", function(identifier, target_unit)
jcallahan@19 850 if target_unit then
jcallahan@19 851 return
jcallahan@19 852 end
jcallahan@19 853 local _, item_link = _G.GetItemInfo(identifier)
jcallahan@19 854 HandleItemUse(item_link)
jcallahan@19 855 end)
jcallahan@263 856
jcallahan@299 857 self:HandleZoneChange("OnEnable")
jcallahan@290 858 self:GROUP_ROSTER_UPDATE()
jcallahan@0 859 end
jcallahan@0 860
jcallahan@0 861
jcallahan@219 862 local ScrapeItemUpgradeStats
jcallahan@219 863 do
jcallahan@219 864 local intermediary = {}
jcallahan@219 865
jcallahan@220 866 function ScrapeItemUpgradeStats(item_id, upgrade_id, reforge_id)
jcallahan@220 867 if not ALLOWED_LOCALES[CLIENT_LOCALE] then
jcallahan@220 868 return
jcallahan@220 869 end
jcallahan@219 870 local create_entry
jcallahan@219 871
jcallahan@219 872 table.wipe(intermediary)
jcallahan@219 873
jcallahan@219 874 for line_index = 1, DatamineTT:NumLines() do
jcallahan@293 875 local left_text = _G["WDPDatamineTTTextLeft" .. line_index]:GetText():trim()
jcallahan@293 876
jcallahan@293 877 if not left_text or left_text == "" or left_text:find("Socket") or left_text:find("Set:") then
jcallahan@293 878 break
jcallahan@219 879 end
jcallahan@219 880 local amount, stat = left_text:match("+(.-) (.*)")
jcallahan@219 881
jcallahan@219 882 if amount and stat then
jcallahan@220 883 if reforge_id and reforge_id ~= 0 then
jcallahan@220 884 local reforge_string = stat:find("Reforged")
jcallahan@220 885
jcallahan@220 886 if reforge_string then
jcallahan@220 887 stat = stat:sub(0, reforge_string - 3)
jcallahan@220 888 intermediary.reforge_id = reforge_id
jcallahan@220 889 end
jcallahan@219 890 end
jcallahan@219 891 create_entry = true
jcallahan@295 892 intermediary[stat:lower():gsub(" ", "_"):gsub("|r", "")] = tonumber((amount:gsub(",", "")))
jcallahan@219 893 end
jcallahan@219 894 end
jcallahan@219 895
jcallahan@219 896 if not create_entry then
jcallahan@219 897 return
jcallahan@219 898 end
jcallahan@219 899 local item = DBEntry("items", item_id)
jcallahan@225 900 item.upgrade_id = upgrade_id
jcallahan@219 901 item.upgrades = item.upgrades or {}
jcallahan@219 902 item.upgrades[upgrade_id] = item.upgrades[upgrade_id] or {}
jcallahan@219 903
jcallahan@219 904 for stat, amount in pairs(intermediary) do
jcallahan@219 905 item.upgrades[upgrade_id][stat] = amount
jcallahan@219 906 end
jcallahan@219 907 end
jcallahan@220 908 end
jcallahan@220 909
jcallahan@220 910 -- do-block
jcallahan@219 911
jcallahan@219 912
jcallahan@187 913 local function RecordItemData(item_id, item_link, durability)
jcallahan@191 914 local item_string = select(3, item_link:find("^|%x+|H(.+)|h%[.+%]"))
jcallahan@219 915 local item
jcallahan@0 916
jcallahan@191 917 if item_string then
jcallahan@220 918 local _, _, _, _, _, _, _, suffix_id, unique_id, _, reforge_id, upgrade_id = (":"):split(item_string)
jcallahan@201 919 suffix_id = tonumber(suffix_id)
jcallahan@219 920 upgrade_id = tonumber(upgrade_id)
jcallahan@199 921
jcallahan@201 922 if suffix_id and suffix_id ~= 0 then
jcallahan@219 923 item = DBEntry("items", item_id)
jcallahan@201 924 item.suffix_id = suffix_id
jcallahan@201 925 item.unique_id = bit.band(unique_id, 0xFFFF)
jcallahan@201 926 end
jcallahan@191 927
jcallahan@219 928 if upgrade_id and upgrade_id ~= 0 then
jcallahan@220 929 DatamineTT:SetHyperlink(item_link)
jcallahan@220 930 ScrapeItemUpgradeStats(item_id, upgrade_id, reforge_id)
jcallahan@191 931 end
jcallahan@0 932 end
jcallahan@212 933
jcallahan@212 934 if durability and durability > 0 then
jcallahan@219 935 item = item or DBEntry("items", item_id)
jcallahan@212 936 item.durability = durability
jcallahan@212 937 end
jcallahan@0 938 end
jcallahan@0 939
jcallahan@0 940
jcallahan@187 941 function WDP:ProcessItems()
jcallahan@187 942 for slot_index = _G.INVSLOT_FIRST_EQUIPPED, _G.INVSLOT_LAST_EQUIPPED do
jcallahan@1 943 local item_id = _G.GetInventoryItemID("player", slot_index)
jcallahan@0 944
jcallahan@0 945 if item_id and item_id > 0 then
jcallahan@1 946 local _, max_durability = _G.GetInventoryItemDurability(slot_index)
jcallahan@187 947 RecordItemData(item_id, _G.GetInventoryItemLink("player", slot_index), max_durability)
jcallahan@0 948 end
jcallahan@0 949 end
jcallahan@0 950
jcallahan@0 951 for bag_index = 0, _G.NUM_BAG_SLOTS do
jcallahan@0 952 for slot_index = 1, _G.GetContainerNumSlots(bag_index) do
jcallahan@1 953 local item_id = _G.GetContainerItemID(bag_index, slot_index)
jcallahan@0 954
jcallahan@0 955 if item_id and item_id > 0 then
jcallahan@1 956 local _, max_durability = _G.GetContainerItemDurability(bag_index, slot_index)
jcallahan@187 957 RecordItemData(item_id, _G.GetContainerItemLink(bag_index, slot_index), max_durability)
jcallahan@0 958 end
jcallahan@0 959 end
jcallahan@0 960 end
jcallahan@0 961 end
jcallahan@0 962
jcallahan@118 963
jcallahan@215 964 local TargetedNPC
jcallahan@118 965 do
jcallahan@118 966 local GENDER_NAMES = {
jcallahan@118 967 "UNKNOWN",
jcallahan@118 968 "MALE",
jcallahan@118 969 "FEMALE",
jcallahan@118 970 }
jcallahan@118 971
jcallahan@118 972
jcallahan@118 973 local REACTION_NAMES = {
jcallahan@118 974 "HATED",
jcallahan@118 975 "HOSTILE",
jcallahan@118 976 "UNFRIENDLY",
jcallahan@118 977 "NEUTRAL",
jcallahan@118 978 "FRIENDLY",
jcallahan@118 979 "HONORED",
jcallahan@118 980 "REVERED",
jcallahan@118 981 "EXALTED",
jcallahan@118 982 }
jcallahan@118 983
jcallahan@118 984
jcallahan@118 985 local POWER_TYPE_NAMES = {
jcallahan@118 986 ["0"] = "MANA",
jcallahan@118 987 ["1"] = "RAGE",
jcallahan@118 988 ["2"] = "FOCUS",
jcallahan@118 989 ["3"] = "ENERGY",
jcallahan@118 990 ["6"] = "RUNIC_POWER",
jcallahan@118 991 }
jcallahan@118 992
jcallahan@118 993
jcallahan@215 994 function TargetedNPC()
jcallahan@118 995 if not _G.UnitExists("target") or _G.UnitPlayerControlled("target") or currently_drunk then
jcallahan@118 996 current_target_id = nil
jcallahan@118 997 return
jcallahan@118 998 end
jcallahan@118 999 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("target"))
jcallahan@118 1000
jcallahan@171 1001 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
jcallahan@118 1002 return
jcallahan@118 1003 end
jcallahan@118 1004 current_target_id = unit_idnum
jcallahan@118 1005
jcallahan@118 1006 local npc = NPCEntry(unit_idnum)
jcallahan@118 1007 local _, class_token = _G.UnitClass("target")
jcallahan@118 1008 npc.class = class_token
jcallahan@118 1009 npc.faction = UnitFactionStanding("target")
jcallahan@118 1010 npc.genders = npc.genders or {}
jcallahan@118 1011 npc.genders[GENDER_NAMES[_G.UnitSex("target")] or "UNDEFINED"] = true
jcallahan@118 1012 npc.is_pvp = _G.UnitIsPVP("target") and true or nil
jcallahan@118 1013 npc.reaction = ("%s:%s:%s"):format(_G.UnitLevel("player"), _G.UnitFactionGroup("player"), REACTION_NAMES[_G.UnitReaction("player", "target")])
jcallahan@118 1014
jcallahan@248 1015 local encounter_data = npc:EncounterData(InstanceDifficultyToken()).stats
jcallahan@118 1016 local npc_level = ("level_%d"):format(_G.UnitLevel("target"))
jcallahan@250 1017 local level_data = encounter_data[npc_level]
jcallahan@250 1018
jcallahan@250 1019 if not level_data then
jcallahan@250 1020 level_data = {}
jcallahan@250 1021 encounter_data[npc_level] = level_data
jcallahan@250 1022 end
jcallahan@257 1023 level_data.max_health = level_data.max_health or _G.UnitHealthMax("target")
jcallahan@257 1024
jcallahan@257 1025 if not level_data.power then
jcallahan@257 1026 local max_power = _G.UnitManaMax("target")
jcallahan@257 1027
jcallahan@257 1028 if max_power > 0 then
jcallahan@257 1029 local power_type = _G.UnitPowerType("target")
jcallahan@257 1030 level_data.power = ("%s:%d"):format(POWER_TYPE_NAMES[_G.tostring(power_type)] or power_type, max_power)
jcallahan@257 1031 end
jcallahan@118 1032 end
jcallahan@118 1033 name_to_id_map[_G.UnitName("target")] = unit_idnum
jcallahan@118 1034 return npc, unit_idnum
jcallahan@118 1035 end
jcallahan@118 1036 end -- do-block
jcallahan@118 1037
jcallahan@118 1038
jcallahan@113 1039 do
jcallahan@113 1040 local COORD_MAX = 5
jcallahan@0 1041
jcallahan@113 1042 function WDP:UpdateTargetLocation()
jcallahan@113 1043 if currently_drunk or not _G.UnitExists("target") or _G.UnitPlayerControlled("target") or (_G.UnitIsTapped("target") and not _G.UnitIsDead("target")) then
jcallahan@2 1044 return
jcallahan@2 1045 end
jcallahan@113 1046
jcallahan@113 1047 for index = 1, 4 do
jcallahan@113 1048 if not _G.CheckInteractDistance("target", index) then
jcallahan@113 1049 return
jcallahan@113 1050 end
jcallahan@113 1051 end
jcallahan@215 1052 local npc = TargetedNPC()
jcallahan@113 1053
jcallahan@113 1054 if not npc then
jcallahan@113 1055 return
jcallahan@113 1056 end
jcallahan@113 1057 local zone_name, area_id, x, y, map_level, difficulty_token = CurrentLocationData()
jcallahan@248 1058 local npc_data = npc:EncounterData(difficulty_token).stats[("level_%d"):format(_G.UnitLevel("target"))]
jcallahan@113 1059 local zone_token = ("%s:%d"):format(zone_name, area_id)
jcallahan@118 1060 npc_data.locations = npc_data.locations or {} -- TODO: Fix this. It is broken. Possibly something to do with the timed updates.
jcallahan@113 1061
jcallahan@113 1062 local zone_data = npc_data.locations[zone_token]
jcallahan@113 1063
jcallahan@113 1064 if not zone_data then
jcallahan@113 1065 zone_data = {}
jcallahan@113 1066 npc_data.locations[zone_token] = zone_data
jcallahan@113 1067 end
jcallahan@113 1068
jcallahan@113 1069 for location_token in pairs(zone_data) do
jcallahan@113 1070 local loc_level, loc_x, loc_y = (":"):split(location_token)
jcallahan@113 1071 loc_level = tonumber(loc_level)
jcallahan@113 1072
jcallahan@113 1073 if map_level == loc_level and math.abs(x - loc_x) <= COORD_MAX and math.abs(y - loc_y) <= COORD_MAX then
jcallahan@113 1074 return
jcallahan@113 1075 end
jcallahan@113 1076 end
jcallahan@141 1077 zone_data[("%d:%d:%d"):format(map_level, x, y)] = true
jcallahan@2 1078 end
jcallahan@113 1079 end -- do-block
jcallahan@2 1080
jcallahan@118 1081
jcallahan@246 1082 -- EVENT HANDLERS -----------------------------------------------------
jcallahan@246 1083
jcallahan@90 1084 function WDP:BLACK_MARKET_ITEM_UPDATE(event_name)
jcallahan@243 1085 if not ALLOWED_LOCALES[CLIENT_LOCALE] then
jcallahan@243 1086 return
jcallahan@243 1087 end
jcallahan@282 1088 local num_items = _G.C_BlackMarket.GetNumItems() or 0
jcallahan@56 1089
jcallahan@56 1090 for index = 1, num_items do
jcallahan@56 1091 local name, texture, quantity, item_type, is_usable, level, level_type, seller_name, min_bid, min_increment, current_bid, has_high_bid, num_bids, time_left, item_link, market_id = _G.C_BlackMarket.GetItemInfoByIndex(index);
jcallahan@56 1092
jcallahan@56 1093 if item_link then
jcallahan@56 1094 DBEntry("items", ItemLinkToID(item_link)).black_market = seller_name or "UNKNOWN"
jcallahan@56 1095 end
jcallahan@56 1096 end
jcallahan@56 1097 end
jcallahan@56 1098
jcallahan@56 1099
jcallahan@298 1100 local function UpdateUnitPet(unit_guid, unit_id)
jcallahan@246 1101 local current_pet_guid = group_owner_guids_to_pet_guids[unit_guid]
jcallahan@246 1102
jcallahan@246 1103 if current_pet_guid then
jcallahan@246 1104 group_owner_guids_to_pet_guids[unit_guid] = nil
jcallahan@246 1105 group_pet_guids[current_pet_guid] = nil
jcallahan@246 1106 end
jcallahan@246 1107 local pet_guid = _G.UnitGUID(unit_id .. "pet")
jcallahan@246 1108
jcallahan@246 1109 if pet_guid then
jcallahan@296 1110 group_owner_guids_to_pet_guids[unit_guid] = pet_guid
jcallahan@246 1111 group_pet_guids[pet_guid] = true
jcallahan@246 1112 end
jcallahan@246 1113 end
jcallahan@246 1114
jcallahan@246 1115
jcallahan@298 1116 function WDP:GROUP_ROSTER_UPDATE(event_name)
jcallahan@298 1117 local is_raid = _G.IsInRaid()
jcallahan@298 1118 local unit_type = is_raid and "raid" or "party"
jcallahan@298 1119 local group_size = is_raid and _G.GetNumGroupMembers() or _G.GetNumSubgroupMembers()
jcallahan@298 1120
jcallahan@299 1121 table.wipe(group_member_guids)
jcallahan@298 1122
jcallahan@298 1123 for index = 1, group_size do
jcallahan@298 1124 local unit_id = unit_type .. index
jcallahan@298 1125 local unit_guid = _G.UnitGUID(unit_id)
jcallahan@298 1126
jcallahan@299 1127 group_member_guids[unit_guid] = true
jcallahan@298 1128 UpdateUnitPet(unit_guid, unit_id)
jcallahan@298 1129 end
jcallahan@299 1130 group_member_guids[PLAYER_GUID] = true
jcallahan@298 1131 end
jcallahan@298 1132
jcallahan@298 1133
jcallahan@298 1134 function WDP:UNIT_PET(event_name, unit_id)
jcallahan@298 1135 UpdateUnitPet(_G.UnitGUID(unit_id), unit_id)
jcallahan@298 1136 end
jcallahan@298 1137
jcallahan@298 1138
jcallahan@178 1139 function WDP:SHOW_LOOT_TOAST(event_name, loot_type, item_link, quantity)
jcallahan@306 1140 if not loot_type or (loot_type ~= "item" and loot_type ~= "money") then
jcallahan@306 1141 Debug("%s: loot_type is %s. Item link is %s, and quantity is %d.", event_name, loot_type, item_link, quantity)
jcallahan@306 1142 return
jcallahan@306 1143 end
jcallahan@301 1144 local container_id = private.loot_toast_container_id
jcallahan@301 1145 local item_id = ItemLinkToID(item_link)
jcallahan@203 1146 local npc = NPCEntry(private.raid_finder_boss_id or private.world_boss_id)
jcallahan@178 1147
jcallahan@301 1148 if npc then
jcallahan@301 1149 if not item_id then
jcallahan@301 1150 Debug("%s: ItemID is nil, from item link %s", event_name, item_link)
jcallahan@301 1151 return
jcallahan@301 1152 end
jcallahan@306 1153 local loot_label = "drops"
jcallahan@301 1154 local encounter_data = npc:EncounterData(InstanceDifficultyToken())
jcallahan@306 1155 encounter_data[loot_label] = encounter_data[loot_label] or {}
jcallahan@301 1156 encounter_data.loot_counts = encounter_data.loot_counts or {}
jcallahan@306 1157
jcallahan@306 1158 if not private.boss_loot_toasting then
jcallahan@306 1159 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
jcallahan@306 1160 end
jcallahan@306 1161
jcallahan@306 1162 if loot_type == "item" then
jcallahan@306 1163 Debug("%s: %sX%d (%d)", event_name, item_link, quantity, item_id)
jcallahan@306 1164 table.insert(encounter_data[loot_label], ("%d:%d"):format(item_id, quantity))
jcallahan@306 1165 elseif loot_type == "money" then
jcallahan@306 1166 Debug("%s: money - %d", event_name, quantity)
jcallahan@306 1167 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
jcallahan@306 1168 end
jcallahan@306 1169 private.boss_loot_toasting = true -- Do not count further loots until timer expires or another boss is killed
jcallahan@301 1170 elseif container_id then
jcallahan@305 1171 InitializeCurrentLoot()
jcallahan@305 1172
jcallahan@306 1173 -- Fake the loot characteristics to match that of an actual container item
jcallahan@306 1174 current_loot.identifier = container_id
jcallahan@306 1175 current_loot.label = "contains"
jcallahan@306 1176 current_loot.target_type = AF.ITEM
jcallahan@306 1177
jcallahan@301 1178 if loot_type == "item" then
jcallahan@301 1179 if not item_id then
jcallahan@301 1180 Debug("%s: ItemID is nil, from item link %s", event_name, item_link)
jcallahan@301 1181 return
jcallahan@301 1182 end
jcallahan@301 1183 current_loot.sources[container_id] = {
jcallahan@301 1184 [item_id] = quantity,
jcallahan@301 1185 }
jcallahan@301 1186 elseif loot_type == "money" then
jcallahan@301 1187 table.insert(current_loot.list, ("money:%d"):format(quantity))
jcallahan@301 1188 end
jcallahan@301 1189 GenericLootUpdate("items")
jcallahan@301 1190 current_loot = nil
jcallahan@306 1191 private.container_loot_toasting = true -- do not count further loots until timer expires or another container is opened
jcallahan@301 1192 else
jcallahan@301 1193 Debug("%s: NPC and Container are nil.", event_name)
jcallahan@178 1194 end
jcallahan@178 1195 end
jcallahan@178 1196
jcallahan@178 1197
jcallahan@179 1198 do
jcallahan@179 1199 local CHAT_MSG_LOOT_UPDATE_FUNCS = {
jcallahan@179 1200 [AF.NPC] = function(item_id, quantity)
jcallahan@245 1201 Debug("CHAT_MSG_LOOT: %d (%d)", item_id, quantity)
jcallahan@179 1202 end,
jcallahan@179 1203 [AF.ZONE] = function(item_id, quantity)
jcallahan@179 1204 current_loot = {
jcallahan@179 1205 list = {
jcallahan@179 1206 ("%d:%d"):format(item_id, quantity)
jcallahan@179 1207 },
jcallahan@179 1208 identifier = current_action.identifier,
jcallahan@179 1209 label = current_action.loot_label or "drops",
jcallahan@179 1210 map_level = current_action.map_level,
jcallahan@179 1211 object_name = current_action.object_name,
jcallahan@179 1212 spell_label = current_action.spell_label,
jcallahan@179 1213 target_type = current_action.target_type,
jcallahan@179 1214 x = current_action.x,
jcallahan@179 1215 y = current_action.y,
jcallahan@179 1216 zone_data = current_action.zone_data,
jcallahan@179 1217 }
jcallahan@179 1218 table.wipe(current_action)
jcallahan@179 1219 GenericLootUpdate("zones")
jcallahan@179 1220 end,
jcallahan@179 1221 }
jcallahan@177 1222
jcallahan@177 1223
jcallahan@179 1224 function WDP:CHAT_MSG_LOOT(event_name, message)
jcallahan@179 1225 local category
jcallahan@177 1226
jcallahan@179 1227 if current_action.spell_label ~= "EXTRACT_GAS" then
jcallahan@179 1228 category = AF.ZONE
jcallahan@179 1229 elseif private.raid_finder_boss_id then
jcallahan@179 1230 category = AF.NPC
jcallahan@179 1231 end
jcallahan@179 1232 local update_func = CHAT_MSG_LOOT_UPDATE_FUNCS[category]
jcallahan@177 1233
jcallahan@179 1234 if not category or not update_func then
jcallahan@179 1235 return
jcallahan@179 1236 end
jcallahan@179 1237 local item_link, quantity = deformat(message, _G.LOOT_ITEM_PUSHED_SELF_MULTIPLE)
jcallahan@179 1238
jcallahan@179 1239 if not item_link then
jcallahan@179 1240 quantity, item_link = 1, deformat(message, _G.LOOT_ITEM_PUSHED_SELF)
jcallahan@179 1241 end
jcallahan@179 1242 local item_id = ItemLinkToID(item_link)
jcallahan@179 1243
jcallahan@179 1244 if not item_id then
jcallahan@179 1245 return
jcallahan@179 1246 end
jcallahan@179 1247 update_func(item_id, quantity)
jcallahan@177 1248 end
jcallahan@48 1249 end
jcallahan@48 1250
jcallahan@97 1251 function WDP:RecordQuote(event_name, message, source_name, language_name)
jcallahan@112 1252 if not ALLOWED_LOCALES[CLIENT_LOCALE] or not source_name or not name_to_id_map[source_name] or (language_name ~= "" and not languages_known[language_name]) then
jcallahan@97 1253 return
jcallahan@95 1254 end
jcallahan@97 1255 local npc = NPCEntry(name_to_id_map[source_name])
jcallahan@97 1256 npc.quotes = npc.quotes or {}
jcallahan@97 1257 npc.quotes[event_name] = npc.quotes[event_name] or {}
jcallahan@97 1258 npc.quotes[event_name][ReplaceKeywords(message)] = true
jcallahan@97 1259 end
jcallahan@95 1260
jcallahan@95 1261
jcallahan@95 1262 do
jcallahan@40 1263 local SOBER_MATCH = _G.DRUNK_MESSAGE_ITEM_SELF1:gsub("%%s", ".+")
jcallahan@40 1264
jcallahan@40 1265 local DRUNK_COMPARES = {
jcallahan@40 1266 _G.DRUNK_MESSAGE_SELF2,
jcallahan@40 1267 _G.DRUNK_MESSAGE_SELF3,
jcallahan@40 1268 _G.DRUNK_MESSAGE_SELF4,
jcallahan@40 1269 }
jcallahan@40 1270
jcallahan@40 1271 local DRUNK_MATCHES = {
jcallahan@254 1272 (_G.DRUNK_MESSAGE_SELF2:gsub("%%s", ".+")),
jcallahan@254 1273 (_G.DRUNK_MESSAGE_SELF3:gsub("%%s", ".+")),
jcallahan@254 1274 (_G.DRUNK_MESSAGE_SELF4:gsub("%%s", ".+")),
jcallahan@40 1275 }
jcallahan@40 1276
jcallahan@167 1277 local RECIPE_MATCH = _G.ERR_LEARN_RECIPE_S:gsub("%%s", "(.*)")
jcallahan@167 1278
jcallahan@167 1279
jcallahan@167 1280 local function RecordDiscovery(tradeskill_name, tradeskill_index)
jcallahan@167 1281 if tradeskill_name == private.discovered_recipe_name then
jcallahan@167 1282 DBEntry("spells", tonumber(_G.GetTradeSkillRecipeLink(tradeskill_index):match("^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)"))).discovery = ("%d:%d"):format(private.previous_spell_id, private.profession_level)
jcallahan@167 1283
jcallahan@167 1284 private.discovered_recipe_name = nil
jcallahan@167 1285 private.profession_level = nil
jcallahan@167 1286 private.previous_spell_id = nil
jcallahan@169 1287
jcallahan@169 1288 return true
jcallahan@167 1289 end
jcallahan@167 1290 end
jcallahan@167 1291
jcallahan@167 1292
jcallahan@167 1293 local function IterativeRecordDiscovery()
jcallahan@167 1294 TradeSkillExecutePer(RecordDiscovery)
jcallahan@167 1295 end
jcallahan@167 1296
jcallahan@167 1297
jcallahan@92 1298 function WDP:CHAT_MSG_SYSTEM(event_name, message)
jcallahan@167 1299 if not private.trainer_shown then
jcallahan@167 1300 local recipe_name = message:match(RECIPE_MATCH)
jcallahan@167 1301
jcallahan@167 1302 if recipe_name and private.previous_spell_id then
jcallahan@167 1303 local profession_name, prof_level = _G.GetTradeSkillLine()
jcallahan@167 1304
jcallahan@167 1305 if profession_name == _G.UNKNOWN then
jcallahan@167 1306 return
jcallahan@167 1307 end
jcallahan@167 1308 private.discovered_recipe_name = recipe_name
jcallahan@167 1309 private.profession_level = prof_level
jcallahan@167 1310
jcallahan@167 1311 self:ScheduleTimer(IterativeRecordDiscovery, 0.2)
jcallahan@167 1312 end
jcallahan@167 1313 end
jcallahan@167 1314
jcallahan@40 1315 if currently_drunk then
jcallahan@40 1316 if message == _G.DRUNK_MESSAGE_SELF1 or message:match(SOBER_MATCH) then
jcallahan@40 1317 currently_drunk = nil
jcallahan@40 1318 end
jcallahan@40 1319 return
jcallahan@40 1320 end
jcallahan@40 1321
jcallahan@40 1322 for index = 1, #DRUNK_MATCHES do
jcallahan@40 1323 if message == DRUNK_COMPARES[index] or message:match(DRUNK_MATCHES[index]) then
jcallahan@40 1324 currently_drunk = true
jcallahan@40 1325 break
jcallahan@40 1326 end
jcallahan@40 1327 end
jcallahan@40 1328 end
jcallahan@40 1329 end
jcallahan@40 1330
jcallahan@40 1331 -- do-block
jcallahan@40 1332
jcallahan@40 1333 do
jcallahan@23 1334 local FLAGS_NPC = bit.bor(_G.COMBATLOG_OBJECT_TYPE_GUARDIAN, _G.COMBATLOG_OBJECT_CONTROL_NPC)
jcallahan@23 1335 local FLAGS_NPC_CONTROL = bit.bor(_G.COMBATLOG_OBJECT_AFFILIATION_OUTSIDER, _G.COMBATLOG_OBJECT_CONTROL_NPC)
jcallahan@23 1336
jcallahan@23 1337 local function RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
jcallahan@23 1338 if not spell_id then
jcallahan@23 1339 return
jcallahan@23 1340 end
jcallahan@34 1341 local source_type, source_id = ParseGUID(source_guid)
jcallahan@23 1342
jcallahan@171 1343 if not source_id or not UnitTypeIsNPC(source_type) then
jcallahan@23 1344 return
jcallahan@23 1345 end
jcallahan@23 1346
jcallahan@23 1347 if bit.band(FLAGS_NPC_CONTROL, source_flags) == FLAGS_NPC_CONTROL and bit.band(FLAGS_NPC, source_flags) ~= 0 then
jcallahan@248 1348 local encounter_data = NPCEntry(source_id):EncounterData(InstanceDifficultyToken())
jcallahan@28 1349 encounter_data.spells = encounter_data.spells or {}
jcallahan@28 1350 encounter_data.spells[spell_id] = (encounter_data.spells[spell_id] or 0) + 1
jcallahan@23 1351 end
jcallahan@23 1352 end
jcallahan@23 1353
jcallahan@115 1354 local HEAL_BATTLE_PETS_SPELL_ID = 125801
jcallahan@115 1355
jcallahan@246 1356 local previous_combat_event = {}
jcallahan@246 1357
jcallahan@23 1358 local COMBAT_LOG_FUNCS = {
jcallahan@23 1359 SPELL_AURA_APPLIED = RecordNPCSpell,
jcallahan@23 1360 SPELL_CAST_START = RecordNPCSpell,
jcallahan@115 1361 SPELL_CAST_SUCCESS = function(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
jcallahan@115 1362 if spell_id == HEAL_BATTLE_PETS_SPELL_ID then
jcallahan@115 1363 local unit_type, unit_idnum = ParseGUID(source_guid)
jcallahan@115 1364
jcallahan@171 1365 if unit_idnum and UnitTypeIsNPC(unit_type) then
jcallahan@115 1366 NPCEntry(unit_idnum).stable_master = true
jcallahan@115 1367 end
jcallahan@115 1368 end
jcallahan@115 1369 RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
jcallahan@115 1370 end,
jcallahan@65 1371 UNIT_DIED = function(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
jcallahan@65 1372 local unit_type, unit_idnum = ParseGUID(dest_guid)
jcallahan@65 1373
jcallahan@171 1374 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
jcallahan@245 1375 Debug("%s: %s is not an NPC, or has no ID.", sub_event, dest_name or _G.UNKNOWN)
jcallahan@177 1376 ClearKilledNPC()
jcallahan@216 1377 ClearKilledBossID()
jcallahan@98 1378 private.harvesting = nil
jcallahan@65 1379 return
jcallahan@65 1380 end
jcallahan@177 1381
jcallahan@246 1382 if source_guid == "" then
jcallahan@246 1383 source_guid = nil
jcallahan@246 1384 end
jcallahan@246 1385 local killer_guid = source_guid or previous_combat_event.source_guid
jcallahan@246 1386 local killer_name = source_name or previous_combat_event.source_name
jcallahan@246 1387
jcallahan@299 1388 if not previous_combat_event.party_damage then
jcallahan@287 1389 Debug("%s: %s was killed by %s (not group member or pet).", sub_event, dest_name or _G.UNKNOWN, killer_name or _G.UNKNOWN)
jcallahan@299 1390 table.wipe(previous_combat_event)
jcallahan@217 1391 ClearKilledNPC()
jcallahan@306 1392 else
jcallahan@306 1393 Debug("%s: %s was killed by %s.", sub_event, dest_name or _G.UNKNOWN, killer_name or _G.UNKNOWN)
jcallahan@177 1394 end
jcallahan@177 1395 killed_npc_id = unit_idnum
jcallahan@177 1396 WDP:ScheduleTimer(ClearKilledNPC, 0.1)
jcallahan@65 1397 end,
jcallahan@23 1398 }
jcallahan@23 1399
jcallahan@23 1400
jcallahan@246 1401 local NON_DAMAGE_EVENTS = {
jcallahan@246 1402 SPELL_AURA_APPLIED = true,
jcallahan@246 1403 SPELL_AURA_REMOVED = true,
jcallahan@246 1404 SPELL_AURA_REMOVED_DOSE = true,
jcallahan@246 1405 SPELL_CAST_FAILED = true,
jcallahan@246 1406 SWING_MISSED = true,
jcallahan@246 1407 }
jcallahan@246 1408
jcallahan@299 1409 local DAMAGE_EVENTS = {
jcallahan@299 1410 RANGE_DAMAGE = true,
jcallahan@299 1411 SPELL_BUILDING_DAMAGE = true,
jcallahan@299 1412 SPELL_DAMAGE = true,
jcallahan@299 1413 SPELL_PERIODIC_DAMAGE = true,
jcallahan@299 1414 SWING_DAMAGE = true,
jcallahan@299 1415 }
jcallahan@299 1416
jcallahan@246 1417
jcallahan@92 1418 function WDP:COMBAT_LOG_EVENT_UNFILTERED(event_name, time_stamp, sub_event, hide_caster, source_guid, source_name, source_flags, source_raid_flags, dest_guid, dest_name, dest_flags, dest_raid_flags, ...)
jcallahan@23 1419 local combat_log_func = COMBAT_LOG_FUNCS[sub_event]
jcallahan@23 1420
jcallahan@23 1421 if not combat_log_func then
jcallahan@299 1422 if DAMAGE_EVENTS[sub_event] then
jcallahan@299 1423 table.wipe(previous_combat_event)
jcallahan@246 1424 previous_combat_event.source_name = source_name
jcallahan@299 1425
jcallahan@299 1426 if source_guid ~= dest_guid and (in_instance or group_member_guids[source_guid] or group_pet_guids[source_guid]) then
jcallahan@299 1427 previous_combat_event.party_damage = true
jcallahan@299 1428 end
jcallahan@246 1429 end
jcallahan@23 1430 return
jcallahan@23 1431 end
jcallahan@23 1432 combat_log_func(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, ...)
jcallahan@297 1433
jcallahan@297 1434 if NON_DAMAGE_EVENTS[sub_event] then
jcallahan@297 1435 table.wipe(previous_combat_event)
jcallahan@297 1436 end
jcallahan@23 1437 end
jcallahan@23 1438
jcallahan@44 1439 local DIPLOMACY_SPELL_ID = 20599
jcallahan@44 1440 local MR_POP_RANK1_SPELL_ID = 78634
jcallahan@44 1441 local MR_POP_RANK2_SPELL_ID = 78635
jcallahan@44 1442
jcallahan@44 1443 local REP_BUFFS = {
jcallahan@44 1444 [_G.GetSpellInfo(30754)] = "CENARION_FAVOR",
jcallahan@44 1445 [_G.GetSpellInfo(24705)] = "GRIM_VISAGE",
jcallahan@44 1446 [_G.GetSpellInfo(32098)] = "HONOR_HOLD_FAVOR",
jcallahan@44 1447 [_G.GetSpellInfo(39913)] = "NAZGRELS_FERVOR",
jcallahan@44 1448 [_G.GetSpellInfo(39953)] = "SONG_OF_BATTLE",
jcallahan@44 1449 [_G.GetSpellInfo(61849)] = "SPIRIT_OF_SHARING",
jcallahan@44 1450 [_G.GetSpellInfo(32096)] = "THRALLMARS_FAVOR",
jcallahan@44 1451 [_G.GetSpellInfo(39911)] = "TROLLBANES_COMMAND",
jcallahan@44 1452 [_G.GetSpellInfo(95987)] = "UNBURDENED",
jcallahan@44 1453 [_G.GetSpellInfo(100951)] = "WOW_ANNIVERSARY",
jcallahan@44 1454 }
jcallahan@44 1455
jcallahan@44 1456
jcallahan@44 1457 local FACTION_NAMES = {
jcallahan@44 1458 CENARION_CIRCLE = _G.GetFactionInfoByID(609),
jcallahan@44 1459 HONOR_HOLD = _G.GetFactionInfoByID(946),
jcallahan@44 1460 THE_SHATAR = _G.GetFactionInfoByID(935),
jcallahan@44 1461 THRALLMAR = _G.GetFactionInfoByID(947),
jcallahan@44 1462 }
jcallahan@44 1463
jcallahan@44 1464
jcallahan@44 1465 local MODIFIERS = {
jcallahan@44 1466 CENARION_FAVOR = {
jcallahan@44 1467 faction = FACTION_NAMES.CENARION_CIRCLE,
jcallahan@44 1468 modifier = 0.25,
jcallahan@44 1469 },
jcallahan@44 1470 GRIM_VISAGE = {
jcallahan@44 1471 modifier = 0.1,
jcallahan@44 1472 },
jcallahan@44 1473 HONOR_HOLD_FAVOR = {
jcallahan@44 1474 faction = FACTION_NAMES.HONOR_HOLD,
jcallahan@44 1475 modifier = 0.25,
jcallahan@44 1476 },
jcallahan@44 1477 NAZGRELS_FERVOR = {
jcallahan@44 1478 faction = FACTION_NAMES.THRALLMAR,
jcallahan@44 1479 modifier = 0.1,
jcallahan@44 1480 },
jcallahan@44 1481 SONG_OF_BATTLE = {
jcallahan@44 1482 faction = FACTION_NAMES.THE_SHATAR,
jcallahan@44 1483 modifier = 0.1,
jcallahan@44 1484 },
jcallahan@44 1485 SPIRIT_OF_SHARING = {
jcallahan@44 1486 modifier = 0.1,
jcallahan@44 1487 },
jcallahan@44 1488 THRALLMARS_FAVOR = {
jcallahan@44 1489 faction = FACTION_NAMES.THRALLMAR,
jcallahan@44 1490 modifier = 0.25,
jcallahan@44 1491 },
jcallahan@44 1492 TROLLBANES_COMMAND = {
jcallahan@44 1493 faction = FACTION_NAMES.HONOR_HOLD,
jcallahan@44 1494 modifier = 0.1,
jcallahan@44 1495 },
jcallahan@44 1496 UNBURDENED = {
jcallahan@44 1497 modifier = 0.1,
jcallahan@44 1498 },
jcallahan@44 1499 WOW_ANNIVERSARY = {
jcallahan@44 1500 modifier = 0.08,
jcallahan@44 1501 }
jcallahan@44 1502 }
jcallahan@44 1503
jcallahan@44 1504
jcallahan@92 1505 function WDP:COMBAT_TEXT_UPDATE(event_name, message_type, faction_name, amount)
jcallahan@177 1506 if message_type ~= "FACTION" or not killed_npc_id then
jcallahan@44 1507 return
jcallahan@44 1508 end
jcallahan@44 1509 UpdateFactionData()
jcallahan@44 1510
jcallahan@46 1511 if not faction_name or not faction_standings[faction_name] then
jcallahan@46 1512 return
jcallahan@46 1513 end
jcallahan@177 1514 local npc = NPCEntry(killed_npc_id)
jcallahan@177 1515 ClearKilledNPC()
jcallahan@46 1516
jcallahan@44 1517 if not npc then
jcallahan@98 1518 private.harvesting = nil
jcallahan@44 1519 return
jcallahan@44 1520 end
jcallahan@98 1521 npc.harvested = private.harvesting
jcallahan@98 1522 private.harvesting = nil
jcallahan@98 1523
jcallahan@44 1524 local modifier = 1
jcallahan@44 1525
jcallahan@44 1526 if _G.IsSpellKnown(DIPLOMACY_SPELL_ID) then
jcallahan@44 1527 modifier = modifier + 0.1
jcallahan@44 1528 end
jcallahan@44 1529
jcallahan@44 1530 if _G.IsSpellKnown(MR_POP_RANK2_SPELL_ID) then
jcallahan@44 1531 modifier = modifier + 0.1
jcallahan@44 1532 elseif _G.IsSpellKnown(MR_POP_RANK1_SPELL_ID) then
jcallahan@44 1533 modifier = modifier + 0.05
jcallahan@44 1534 end
jcallahan@44 1535
jcallahan@44 1536 for buff_name, buff_label in pairs(REP_BUFFS) do
jcallahan@44 1537 if _G.UnitBuff("player", buff_name) then
jcallahan@44 1538 local modded_faction = MODIFIERS[buff_label].faction
jcallahan@44 1539
jcallahan@44 1540 if not modded_faction or faction_name == modded_faction then
jcallahan@44 1541 modifier = modifier + MODIFIERS[buff_label].modifier
jcallahan@44 1542 end
jcallahan@44 1543 end
jcallahan@44 1544 end
jcallahan@65 1545 npc.reputations = npc.reputations or {}
jcallahan@65 1546 npc.reputations[("%s:%s"):format(faction_name, faction_standings[faction_name])] = math.floor(amount / modifier)
jcallahan@32 1547 end
jcallahan@44 1548 end -- do-block
jcallahan@18 1549
jcallahan@18 1550
jcallahan@140 1551 function WDP:CURSOR_UPDATE(event_name)
jcallahan@141 1552 if current_action.fishing_target or _G.Minimap:IsMouseOver() or current_action.spell_label ~= "FISHING" then
jcallahan@140 1553 return
jcallahan@140 1554 end
jcallahan@140 1555 local text = _G["GameTooltipTextLeft1"]:GetText()
jcallahan@140 1556
jcallahan@140 1557 if not text or text == "Fishing Bobber" then
jcallahan@140 1558 text = "NONE"
jcallahan@140 1559 else
jcallahan@140 1560 current_action.fishing_target = true
jcallahan@140 1561 end
jcallahan@140 1562 current_action.identifier = ("%s:%s"):format(current_action.spell_label, text)
jcallahan@140 1563 end
jcallahan@140 1564
jcallahan@140 1565
jcallahan@92 1566 function WDP:ITEM_TEXT_BEGIN(event_name)
jcallahan@42 1567 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
jcallahan@42 1568
jcallahan@42 1569 if not unit_idnum or unit_type ~= private.UNIT_TYPES.OBJECT or _G.UnitName("npc") ~= _G.ItemTextGetItem() then
jcallahan@42 1570 return
jcallahan@42 1571 end
jcallahan@42 1572 UpdateDBEntryLocation("objects", unit_idnum)
jcallahan@42 1573 end
jcallahan@42 1574
jcallahan@42 1575
jcallahan@13 1576 do
jcallahan@40 1577 local RE_GOLD = _G.GOLD_AMOUNT:gsub("%%d", "(%%d+)")
jcallahan@40 1578 local RE_SILVER = _G.SILVER_AMOUNT:gsub("%%d", "(%%d+)")
jcallahan@40 1579 local RE_COPPER = _G.COPPER_AMOUNT:gsub("%%d", "(%%d+)")
jcallahan@13 1580
jcallahan@13 1581
jcallahan@13 1582 local function _moneyMatch(money, re)
jcallahan@13 1583 return money:match(re) or 0
jcallahan@1 1584 end
jcallahan@1 1585
jcallahan@0 1586
jcallahan@13 1587 local function _toCopper(money)
jcallahan@13 1588 if not money then
jcallahan@13 1589 return 0
jcallahan@13 1590 end
jcallahan@40 1591 return _moneyMatch(money, RE_GOLD) * 10000 + _moneyMatch(money, RE_SILVER) * 100 + _moneyMatch(money, RE_COPPER)
jcallahan@1 1592 end
jcallahan@1 1593
jcallahan@1 1594
jcallahan@176 1595 local LOOT_OPENED_VERIFY_FUNCS = {
jcallahan@16 1596 [AF.ITEM] = function()
jcallahan@16 1597 local locked_item_id
jcallahan@16 1598
jcallahan@16 1599 for bag_index = 0, _G.NUM_BAG_FRAMES do
jcallahan@16 1600 for slot_index = 1, _G.GetContainerNumSlots(bag_index) do
jcallahan@16 1601 local _, _, is_locked = _G.GetContainerItemInfo(bag_index, slot_index)
jcallahan@16 1602
jcallahan@16 1603 if is_locked then
jcallahan@16 1604 locked_item_id = ItemLinkToID(_G.GetContainerItemLink(bag_index, slot_index))
jcallahan@165 1605 break
jcallahan@16 1606 end
jcallahan@16 1607 end
jcallahan@165 1608
jcallahan@165 1609 if locked_item_id then
jcallahan@165 1610 break
jcallahan@165 1611 end
jcallahan@16 1612 end
jcallahan@16 1613
jcallahan@122 1614 if not locked_item_id or (current_action.identifier and current_action.identifier ~= locked_item_id) then
jcallahan@16 1615 return false
jcallahan@16 1616 end
jcallahan@122 1617 current_action.identifier = locked_item_id
jcallahan@16 1618 return true
jcallahan@16 1619 end,
jcallahan@13 1620 [AF.NPC] = function()
jcallahan@17 1621 if not _G.UnitExists("target") or _G.UnitIsFriend("player", "target") or _G.UnitIsPlayer("target") or _G.UnitPlayerControlled("target") then
jcallahan@15 1622 return false
jcallahan@13 1623 end
jcallahan@205 1624
jcallahan@205 1625 if not current_action.identifier then
jcallahan@205 1626 local unit_type, id_num = ParseGUID(_G.UnitGUID("target"))
jcallahan@205 1627 current_action.identifier = id_num
jcallahan@205 1628 end
jcallahan@13 1629 return true
jcallahan@13 1630 end,
jcallahan@14 1631 [AF.OBJECT] = true,
jcallahan@17 1632 [AF.ZONE] = function()
jcallahan@140 1633 current_action.zone_data = UpdateDBEntryLocation("zones", current_action.identifier)
jcallahan@210 1634 return _G.IsFishingLoot()
jcallahan@17 1635 end,
jcallahan@13 1636 }
jcallahan@13 1637
jcallahan@13 1638
jcallahan@176 1639 local LOOT_OPENED_UPDATE_FUNCS = {
jcallahan@16 1640 [AF.ITEM] = function()
jcallahan@28 1641 GenericLootUpdate("items")
jcallahan@28 1642 end,
jcallahan@28 1643 [AF.NPC] = function()
jcallahan@75 1644 local difficulty_token = InstanceDifficultyToken()
jcallahan@132 1645 local loot_type = current_loot.label
jcallahan@77 1646 local source_list = {}
jcallahan@75 1647
jcallahan@131 1648 for source_guid, loot_data in pairs(current_loot.sources) do
jcallahan@78 1649 local source_id = select(2, ParseGUID(source_guid))
jcallahan@75 1650 local npc = NPCEntry(source_id)
jcallahan@75 1651
jcallahan@75 1652 if npc then
jcallahan@248 1653 local encounter_data = npc:EncounterData(difficulty_token)
jcallahan@75 1654 encounter_data[loot_type] = encounter_data[loot_type] or {}
jcallahan@75 1655
jcallahan@78 1656 if not source_list[source_guid] then
jcallahan@77 1657 encounter_data.loot_counts = encounter_data.loot_counts or {}
jcallahan@77 1658 encounter_data.loot_counts[loot_type] = (encounter_data.loot_counts[loot_type] or 0) + 1
jcallahan@77 1659 source_list[source_id] = true
jcallahan@77 1660 end
jcallahan@77 1661
jcallahan@75 1662 for item_id, quantity in pairs(loot_data) do
jcallahan@75 1663 table.insert(encounter_data[loot_type], ("%d:%d"):format(item_id, quantity))
jcallahan@75 1664 end
jcallahan@75 1665 end
jcallahan@75 1666 end
jcallahan@75 1667
jcallahan@75 1668 -- TODO: Remove this when GetLootSourceInfo() has values for money
jcallahan@131 1669 if #current_loot.list <= 0 then
jcallahan@79 1670 return
jcallahan@79 1671 end
jcallahan@131 1672 local npc = NPCEntry(current_loot.identifier)
jcallahan@28 1673
jcallahan@28 1674 if not npc then
jcallahan@28 1675 return
jcallahan@28 1676 end
jcallahan@248 1677 local encounter_data = npc:EncounterData(difficulty_token)
jcallahan@29 1678 encounter_data[loot_type] = encounter_data[loot_type] or {}
jcallahan@16 1679
jcallahan@131 1680 if not source_list[current_loot.identifier] then
jcallahan@77 1681 encounter_data.loot_counts = encounter_data.loot_counts or {}
jcallahan@77 1682 encounter_data.loot_counts[loot_type] = (encounter_data.loot_counts[loot_type] or 0) + 1
jcallahan@77 1683 end
jcallahan@77 1684
jcallahan@131 1685 for index = 1, #current_loot.list do
jcallahan@131 1686 table.insert(encounter_data[loot_type], current_loot.list[index])
jcallahan@16 1687 end
jcallahan@16 1688 end,
jcallahan@13 1689 [AF.OBJECT] = function()
jcallahan@28 1690 GenericLootUpdate("objects", InstanceDifficultyToken())
jcallahan@17 1691 end,
jcallahan@17 1692 [AF.ZONE] = function()
jcallahan@141 1693 local location_token = ("%d:%d:%d"):format(current_loot.map_level, current_loot.x, current_loot.y)
jcallahan@41 1694
jcallahan@41 1695 -- This will start life as a boolean true.
jcallahan@131 1696 if _G.type(current_loot.zone_data[location_token]) ~= "table" then
jcallahan@131 1697 current_loot.zone_data[location_token] = {
jcallahan@41 1698 drops = {}
jcallahan@41 1699 }
jcallahan@41 1700 end
jcallahan@132 1701 local loot_count = ("%s_count"):format(current_loot.label)
jcallahan@131 1702 current_loot.zone_data[location_token][loot_count] = (current_loot.zone_data[location_token][loot_count] or 0) + 1
jcallahan@41 1703
jcallahan@131 1704 if current_loot.sources then
jcallahan@131 1705 for source_guid, loot_data in pairs(current_loot.sources) do
jcallahan@131 1706 for item_id, quantity in pairs(loot_data) do
jcallahan@131 1707 table.insert(current_loot.zone_data[location_token].drops, ("%d:%d"):format(item_id, quantity))
jcallahan@131 1708 end
jcallahan@131 1709 end
jcallahan@131 1710 end
jcallahan@131 1711
jcallahan@131 1712 if #current_loot.list <= 0 then
jcallahan@131 1713 return
jcallahan@131 1714 end
jcallahan@131 1715
jcallahan@131 1716 for index = 1, #current_loot.list do
jcallahan@131 1717 table.insert(current_loot.zone_data[location_token].drops, current_loot.loot_list[index])
jcallahan@41 1718 end
jcallahan@13 1719 end,
jcallahan@13 1720 }
jcallahan@13 1721
jcallahan@79 1722 -- Prevent opening the same loot window multiple times from recording data multiple times.
jcallahan@79 1723 local loot_guid_registry = {}
jcallahan@124 1724
jcallahan@124 1725
jcallahan@124 1726 function WDP:LOOT_CLOSED(event_name)
jcallahan@131 1727 current_loot = nil
jcallahan@131 1728 table.wipe(current_action)
jcallahan@124 1729 end
jcallahan@124 1730
jcallahan@13 1731
jcallahan@92 1732 function WDP:LOOT_OPENED(event_name)
jcallahan@132 1733 if current_loot then
jcallahan@18 1734 return
jcallahan@18 1735 end
jcallahan@151 1736
jcallahan@151 1737 if not current_action.target_type then
jcallahan@151 1738 return
jcallahan@151 1739 end
jcallahan@176 1740 local verify_func = LOOT_OPENED_VERIFY_FUNCS[current_action.target_type]
jcallahan@176 1741 local update_func = LOOT_OPENED_UPDATE_FUNCS[current_action.target_type]
jcallahan@13 1742
jcallahan@14 1743 if not verify_func or not update_func then
jcallahan@13 1744 return
jcallahan@13 1745 end
jcallahan@13 1746
jcallahan@14 1747 if _G.type(verify_func) == "function" and not verify_func() then
jcallahan@14 1748 return
jcallahan@14 1749 end
jcallahan@80 1750 local guids_used = {}
jcallahan@132 1751
jcallahan@301 1752 InitializeCurrentLoot()
jcallahan@217 1753 loot_guid_registry[current_loot.label] = loot_guid_registry[current_loot.label] or {}
jcallahan@217 1754
jcallahan@55 1755 for loot_slot = 1, _G.GetNumLootItems() do
jcallahan@302 1756 local icon_texture, item_text, slot_quantity, quality, locked = _G.GetLootSlotInfo(loot_slot)
jcallahan@55 1757 local slot_type = _G.GetLootSlotType(loot_slot)
jcallahan@237 1758 local loot_info = {
jcallahan@237 1759 _G.GetLootSourceInfo(loot_slot)
jcallahan@237 1760 }
jcallahan@13 1761
jcallahan@237 1762 -- Odd index is GUID, even is count.
jcallahan@237 1763 for loot_index = 1, #loot_info, 2 do
jcallahan@237 1764 local source_guid = loot_info[loot_index]
jcallahan@75 1765
jcallahan@237 1766 if not loot_guid_registry[current_loot.label][source_guid] then
jcallahan@237 1767 local loot_quantity = loot_info[loot_index + 1]
jcallahan@237 1768 local source_type, source_id = ParseGUID(source_guid)
jcallahan@237 1769 local source_key = ("%s:%d"):format(private.UNIT_TYPE_NAMES[source_type + 1], source_id)
jcallahan@302 1770 Debug("GUID: %s - Type:ID: %s - Amount: %d (%d)", loot_info[loot_index], source_key, loot_quantity, slot_quantity)
jcallahan@77 1771
jcallahan@237 1772 if slot_type == _G.LOOT_SLOT_ITEM then
jcallahan@79 1773 local item_id = ItemLinkToID(_G.GetLootSlotLink(loot_slot))
jcallahan@131 1774 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
jcallahan@302 1775 current_loot.sources[source_guid][item_id] = current_loot.sources[source_guid][item_id] or 0 + slot_quantity
jcallahan@80 1776 guids_used[source_guid] = true
jcallahan@237 1777 elseif slot_type == _G.LOOT_SLOT_MONEY then
jcallahan@245 1778 Debug("money:%d", _toCopper(item_text))
jcallahan@237 1779 table.insert(current_loot.list, ("money:%d"):format(_toCopper(item_text)))
jcallahan@237 1780 elseif slot_type == _G.LOOT_SLOT_CURRENCY then
jcallahan@245 1781 Debug("Found currency: %s", icon_texture)
jcallahan@302 1782 table.insert(current_loot.list, ("currency:%d:%s"):format(slot_quantity, icon_texture:match("[^\\]+$"):lower()))
jcallahan@79 1783 end
jcallahan@75 1784 end
jcallahan@13 1785 end
jcallahan@13 1786 end
jcallahan@80 1787
jcallahan@81 1788 for guid in pairs(guids_used) do
jcallahan@217 1789 loot_guid_registry[current_loot.label][guid] = true
jcallahan@80 1790 end
jcallahan@13 1791 update_func()
jcallahan@1 1792 end
jcallahan@13 1793 end -- do-block
jcallahan@0 1794
jcallahan@0 1795
jcallahan@89 1796 function WDP:MAIL_SHOW(event_name)
jcallahan@89 1797 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
jcallahan@89 1798
jcallahan@89 1799 if not unit_idnum or unit_type ~= private.UNIT_TYPES.OBJECT then
jcallahan@89 1800 return
jcallahan@89 1801 end
jcallahan@89 1802 UpdateDBEntryLocation("objects", unit_idnum)
jcallahan@89 1803 end
jcallahan@89 1804
jcallahan@89 1805
jcallahan@44 1806 do
jcallahan@44 1807 local POINT_MATCH_PATTERNS = {
jcallahan@44 1808 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING:gsub("%%d", "(%%d+)")), -- May no longer be necessary
jcallahan@44 1809 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_3V3:gsub("%%d", "(%%d+)")), -- May no longer be necessary
jcallahan@44 1810 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_5V5:gsub("%%d", "(%%d+)")), -- May no longer be necessary
jcallahan@44 1811 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_BG:gsub("%%d", "(%%d+)")),
jcallahan@44 1812 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_3V3_BG:gsub("%%d", "(%%d+)")),
jcallahan@44 1813 }
jcallahan@5 1814
jcallahan@68 1815 local ITEM_REQ_REPUTATION_MATCH = "Requires (.-) %- (.*)"
jcallahan@87 1816 local ITEM_REQ_QUEST_MATCH1 = "Requires: .*"
jcallahan@87 1817 local ITEM_REQ_QUEST_MATCH2 = "Must have completed: .*"
jcallahan@68 1818
jcallahan@133 1819 local current_merchant
jcallahan@133 1820 local merchant_standing
jcallahan@133 1821
jcallahan@133 1822 function WDP:MERCHANT_CLOSED(event_name)
jcallahan@133 1823 current_merchant = nil
jcallahan@133 1824 merchant_standing = nil
jcallahan@133 1825 end
jcallahan@133 1826
jcallahan@133 1827
jcallahan@89 1828 function WDP:UpdateMerchantItems(event_name)
jcallahan@144 1829 if not current_merchant or event_name == "MERCHANT_SHOW" then
jcallahan@195 1830 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
jcallahan@4 1831
jcallahan@171 1832 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
jcallahan@133 1833 return
jcallahan@133 1834 end
jcallahan@195 1835 merchant_standing = select(2, UnitFactionStanding("npc"))
jcallahan@133 1836 current_merchant = NPCEntry(unit_idnum)
jcallahan@133 1837 current_merchant.sells = current_merchant.sells or {}
jcallahan@44 1838 end
jcallahan@55 1839 local current_filters = _G.GetMerchantFilter()
jcallahan@57 1840 _G.SetMerchantFilter(_G.LE_LOOT_FILTER_ALL)
jcallahan@57 1841 _G.MerchantFrame_Update()
jcallahan@57 1842
jcallahan@150 1843 local num_items = _G.GetMerchantNumItems()
jcallahan@150 1844
jcallahan@44 1845 for item_index = 1, num_items do
jcallahan@44 1846 local _, _, copper_price, stack_size, num_available, _, extended_cost = _G.GetMerchantItemInfo(item_index)
jcallahan@44 1847 local item_id = ItemLinkToID(_G.GetMerchantItemLink(item_index))
jcallahan@5 1848
jcallahan@44 1849 if item_id and item_id > 0 then
jcallahan@44 1850 local price_string = ActualCopperCost(copper_price, merchant_standing)
jcallahan@5 1851
jcallahan@68 1852 DatamineTT:ClearLines()
jcallahan@68 1853 DatamineTT:SetMerchantItem(item_index)
jcallahan@68 1854
jcallahan@68 1855 local num_lines = DatamineTT:NumLines()
jcallahan@68 1856
jcallahan@68 1857 for line_index = 1, num_lines do
jcallahan@68 1858 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
jcallahan@68 1859
jcallahan@68 1860 if not current_line then
jcallahan@68 1861 break
jcallahan@68 1862 end
jcallahan@68 1863 local faction, reputation = current_line:GetText():match(ITEM_REQ_REPUTATION_MATCH)
jcallahan@68 1864
jcallahan@68 1865 if faction or reputation then
jcallahan@68 1866 DBEntry("items", item_id).req_reputation = ("%s:%s"):format(faction:gsub("-", ""), reputation:upper())
jcallahan@68 1867 break
jcallahan@68 1868 end
jcallahan@68 1869 end
jcallahan@68 1870
jcallahan@87 1871 for line_index = 1, num_lines do
jcallahan@87 1872 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
jcallahan@87 1873
jcallahan@87 1874 if not current_line then
jcallahan@87 1875 break
jcallahan@87 1876 end
jcallahan@87 1877 local line_text = current_line:GetText()
jcallahan@87 1878 local quest_name = line_text:match(ITEM_REQ_QUEST_MATCH1) or line_text:match(ITEM_REQ_QUEST_MATCH2)
jcallahan@87 1879
jcallahan@87 1880 if quest_name then
jcallahan@87 1881 DBEntry("items", item_id).req_quest = ("%s"):format(quest_name:gsub("(.+): ", ""), quest_name)
jcallahan@87 1882 break
jcallahan@87 1883 end
jcallahan@87 1884 end
jcallahan@87 1885
jcallahan@44 1886 if extended_cost then
jcallahan@53 1887 local battleground_rating = 0
jcallahan@53 1888 local personal_rating = 0
jcallahan@53 1889 local required_season_amount
jcallahan@5 1890
jcallahan@68 1891 for line_index = 1, num_lines do
jcallahan@44 1892 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
jcallahan@5 1893
jcallahan@44 1894 if not current_line then
jcallahan@44 1895 break
jcallahan@44 1896 end
jcallahan@53 1897 required_season_amount = current_line:GetText():match("Requires earning a total of (%d+)\n(.-) for the season.")
jcallahan@5 1898
jcallahan@44 1899 for match_index = 1, #POINT_MATCH_PATTERNS do
jcallahan@44 1900 local match1, match2 = current_line:GetText():match(POINT_MATCH_PATTERNS[match_index])
jcallahan@53 1901 personal_rating = personal_rating + (match1 or 0)
jcallahan@53 1902 battleground_rating = battleground_rating + (match2 or 0)
jcallahan@5 1903
jcallahan@44 1904 if match1 or match2 then
jcallahan@44 1905 break
jcallahan@44 1906 end
jcallahan@44 1907 end
jcallahan@5 1908 end
jcallahan@44 1909 local currency_list = {}
jcallahan@44 1910 local item_count = _G.GetMerchantItemCostInfo(item_index)
jcallahan@50 1911
jcallahan@50 1912 -- Keeping this around in case Blizzard makes the two points diverge at some point.
jcallahan@53 1913 -- price_string = ("%s:%s:%s:%s"):format(price_string, battleground_rating, personal_rating, required_season_amount or 0)
jcallahan@53 1914 price_string = ("%s:%s:%s"):format(price_string, personal_rating, required_season_amount or 0)
jcallahan@5 1915
jcallahan@44 1916 for cost_index = 1, item_count do
jcallahan@44 1917 local icon_texture, amount_required, currency_link = _G.GetMerchantItemCostItem(item_index, cost_index)
jcallahan@44 1918 local currency_id = currency_link and ItemLinkToID(currency_link) or nil
jcallahan@44 1919
jcallahan@44 1920 if (not currency_id or currency_id < 1) and icon_texture then
jcallahan@44 1921 currency_id = icon_texture:match("[^\\]+$"):lower()
jcallahan@44 1922 end
jcallahan@44 1923
jcallahan@44 1924 if currency_id then
jcallahan@44 1925 currency_list[#currency_list + 1] = ("(%s:%s)"):format(amount_required, currency_id)
jcallahan@44 1926 end
jcallahan@44 1927 end
jcallahan@44 1928
jcallahan@44 1929 for currency_index = 1, #currency_list do
jcallahan@44 1930 price_string = ("%s:%s"):format(price_string, currency_list[currency_index])
jcallahan@5 1931 end
jcallahan@5 1932 end
jcallahan@133 1933 current_merchant.sells[item_id] = ("%s:%s:[%s]"):format(num_available, stack_size, price_string)
jcallahan@44 1934 end
jcallahan@44 1935 end
jcallahan@5 1936
jcallahan@44 1937 if _G.CanMerchantRepair() then
jcallahan@133 1938 current_merchant.can_repair = true
jcallahan@5 1939 end
jcallahan@57 1940 _G.SetMerchantFilter(current_filters)
jcallahan@57 1941 _G.MerchantFrame_Update()
jcallahan@4 1942 end
jcallahan@44 1943 end -- do-block
jcallahan@4 1944
jcallahan@89 1945
jcallahan@92 1946 function WDP:PET_BAR_UPDATE(event_name)
jcallahan@122 1947 if current_action.spell_label ~= "MIND_CONTROL" then
jcallahan@25 1948 return
jcallahan@25 1949 end
jcallahan@34 1950 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("pet"))
jcallahan@25 1951
jcallahan@171 1952 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
jcallahan@25 1953 return
jcallahan@25 1954 end
jcallahan@29 1955 NPCEntry(unit_idnum).mind_control = true
jcallahan@122 1956 table.wipe(current_action)
jcallahan@25 1957 end
jcallahan@25 1958
jcallahan@25 1959
jcallahan@115 1960 function WDP:PET_JOURNAL_LIST_UPDATE(event_name)
jcallahan@115 1961 local num_pets = LPJ:NumPets()
jcallahan@115 1962
jcallahan@115 1963 for index, pet_id in LPJ:IteratePetIDs() do
jcallahan@115 1964 local _, _, is_owned, _, level, _, _, name, icon, pet_type, npc_id, _, _, is_wild = _G.C_PetJournal.GetPetInfoByIndex(index)
jcallahan@115 1965
jcallahan@115 1966 if is_owned then
jcallahan@115 1967 local health, max_health, attack, speed, rarity = _G.C_PetJournal.GetPetStats(pet_id)
jcallahan@115 1968
jcallahan@139 1969 if rarity then
jcallahan@139 1970 local rarity_name = _G["BATTLE_PET_BREED_QUALITY" .. rarity]
jcallahan@139 1971 local npc = NPCEntry(npc_id)
jcallahan@139 1972 npc.wild_pet = is_wild or nil
jcallahan@139 1973 npc.battle_pet_data = npc.battle_pet_data or {}
jcallahan@139 1974 npc.battle_pet_data[rarity_name] = npc.battle_pet_data[rarity_name] or {}
jcallahan@139 1975 npc.battle_pet_data[rarity_name]["level_" .. level] = npc.battle_pet_data[rarity_name]["level_" .. level] or {}
jcallahan@139 1976
jcallahan@139 1977 local data = npc.battle_pet_data[rarity_name]["level_" .. level]
jcallahan@139 1978 data.max_health = max_health
jcallahan@139 1979 data.attack = attack
jcallahan@139 1980 data.speed = speed
jcallahan@139 1981 end
jcallahan@115 1982 end
jcallahan@115 1983 end
jcallahan@115 1984 end
jcallahan@115 1985
jcallahan@115 1986
jcallahan@156 1987 function WDP:PLAYER_REGEN_DISABLED(event_name)
jcallahan@156 1988 private.in_combat = true
jcallahan@156 1989 end
jcallahan@156 1990
jcallahan@156 1991
jcallahan@156 1992 function WDP:PLAYER_REGEN_ENABLED(event_name)
jcallahan@156 1993 private.in_combat = nil
jcallahan@156 1994
jcallahan@156 1995 if private.set_area_id then
jcallahan@299 1996 self:HandleZoneChange(event_name)
jcallahan@156 1997 private.set_area_id = nil
jcallahan@156 1998 end
jcallahan@156 1999 end
jcallahan@156 2000
jcallahan@156 2001
jcallahan@118 2002 function WDP:PLAYER_TARGET_CHANGED(event_name)
jcallahan@215 2003 if not TargetedNPC() then
jcallahan@118 2004 return
jcallahan@2 2005 end
jcallahan@151 2006 current_action.target_type = AF.NPC
jcallahan@118 2007 self:UpdateTargetLocation()
jcallahan@118 2008 end
jcallahan@2 2009
jcallahan@89 2010
jcallahan@12 2011 do
jcallahan@12 2012 local function UpdateQuestJuncture(point)
jcallahan@12 2013 local unit_name = _G.UnitName("questnpc")
jcallahan@9 2014
jcallahan@12 2015 if not unit_name then
jcallahan@12 2016 return
jcallahan@12 2017 end
jcallahan@34 2018 local unit_type, unit_id = ParseGUID(_G.UnitGUID("questnpc"))
jcallahan@9 2019
jcallahan@12 2020 if unit_type == private.UNIT_TYPES.OBJECT then
jcallahan@38 2021 UpdateDBEntryLocation("objects", unit_id)
jcallahan@12 2022 end
jcallahan@19 2023 local quest = DBEntry("quests", _G.GetQuestID())
jcallahan@12 2024 quest[point] = quest[point] or {}
jcallahan@12 2025 quest[point][("%s:%d"):format(private.UNIT_TYPE_NAMES[unit_type + 1], unit_id)] = true
jcallahan@24 2026
jcallahan@24 2027 return quest
jcallahan@12 2028 end
jcallahan@10 2029
jcallahan@12 2030
jcallahan@92 2031 function WDP:QUEST_COMPLETE(event_name)
jcallahan@97 2032 local quest = UpdateQuestJuncture("end")
jcallahan@97 2033
jcallahan@112 2034 if ALLOWED_LOCALES[CLIENT_LOCALE] then
jcallahan@112 2035 quest.reward_text = ReplaceKeywords(_G.GetRewardText())
jcallahan@112 2036 end
jcallahan@67 2037 -- Make sure the quest NPC isn't erroneously recorded as giving reputation for quests which award it.
jcallahan@177 2038 ClearKilledNPC()
jcallahan@10 2039 end
jcallahan@10 2040
jcallahan@12 2041
jcallahan@92 2042 function WDP:QUEST_DETAIL(event_name)
jcallahan@24 2043 local quest = UpdateQuestJuncture("begin")
jcallahan@24 2044
jcallahan@46 2045 if not quest then
jcallahan@46 2046 return
jcallahan@46 2047 end
jcallahan@24 2048 quest.classes = quest.classes or {}
jcallahan@27 2049 quest.classes[PLAYER_CLASS] = true
jcallahan@24 2050
jcallahan@24 2051 quest.races = quest.races or {}
jcallahan@100 2052 quest.races[(PLAYER_RACE == "Pandaren") and ("%s_%s"):format(PLAYER_RACE, PLAYER_FACTION or "Neutral") or PLAYER_RACE] = true
jcallahan@10 2053 end
jcallahan@12 2054 end -- do-block
jcallahan@9 2055
jcallahan@9 2056
jcallahan@92 2057 function WDP:QUEST_LOG_UPDATE(event_name)
jcallahan@38 2058 local selected_quest = _G.GetQuestLogSelection() -- Save current selection to be restored when we're done.
jcallahan@36 2059 local entry_index, processed_quests = 1, 0
jcallahan@36 2060 local _, num_quests = _G.GetNumQuestLogEntries()
jcallahan@36 2061
jcallahan@36 2062 while processed_quests <= num_quests do
jcallahan@36 2063 local _, _, _, _, is_header, _, _, _, quest_id = _G.GetQuestLogTitle(entry_index)
jcallahan@36 2064
jcallahan@84 2065 if quest_id == 0 then
jcallahan@84 2066 processed_quests = processed_quests + 1
jcallahan@84 2067 elseif not is_header then
jcallahan@36 2068 _G.SelectQuestLogEntry(entry_index);
jcallahan@36 2069
jcallahan@36 2070 local quest = DBEntry("quests", quest_id)
jcallahan@36 2071 quest.timer = _G.GetQuestLogTimeLeft()
jcallahan@37 2072 quest.can_share = _G.GetQuestLogPushable() and true or nil
jcallahan@36 2073 processed_quests = processed_quests + 1
jcallahan@36 2074 end
jcallahan@36 2075 entry_index = entry_index + 1
jcallahan@36 2076 end
jcallahan@36 2077 _G.SelectQuestLogEntry(selected_quest)
jcallahan@4 2078 self:UnregisterEvent("QUEST_LOG_UPDATE")
jcallahan@4 2079 end
jcallahan@4 2080
jcallahan@4 2081
jcallahan@97 2082 function WDP:QUEST_PROGRESS(event_name)
jcallahan@112 2083 if not ALLOWED_LOCALES[CLIENT_LOCALE] then
jcallahan@112 2084 return
jcallahan@112 2085 end
jcallahan@97 2086 DBEntry("quests", _G.GetQuestID()).progress_text = ReplaceKeywords(_G.GetProgressText())
jcallahan@97 2087 end
jcallahan@97 2088
jcallahan@97 2089
jcallahan@92 2090 function WDP:UNIT_QUEST_LOG_CHANGED(event_name, unit_id)
jcallahan@4 2091 if unit_id ~= "player" then
jcallahan@4 2092 return
jcallahan@4 2093 end
jcallahan@4 2094 self:RegisterEvent("QUEST_LOG_UPDATE")
jcallahan@4 2095 end
jcallahan@4 2096
jcallahan@4 2097
jcallahan@92 2098 do
jcallahan@92 2099 local TRADESKILL_TOOLS = {
jcallahan@92 2100 Anvil = anvil_spell_ids,
jcallahan@92 2101 Forge = forge_spell_ids,
jcallahan@92 2102 }
jcallahan@92 2103
jcallahan@92 2104
jcallahan@167 2105 local function RegisterTools(tradeskill_name, tradeskill_index)
jcallahan@167 2106 local spell_id = tonumber(_G.GetTradeSkillRecipeLink(tradeskill_index):match("^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)"))
jcallahan@167 2107 local required_tool = _G.GetTradeSkillTools(tradeskill_index)
jcallahan@167 2108
jcallahan@167 2109 if required_tool then
jcallahan@167 2110 for tool_name, registry in pairs(TRADESKILL_TOOLS) do
jcallahan@167 2111 if required_tool:find(tool_name) then
jcallahan@167 2112 registry[spell_id] = true
jcallahan@167 2113 end
jcallahan@167 2114 end
jcallahan@167 2115 end
jcallahan@167 2116 end
jcallahan@167 2117
jcallahan@167 2118
jcallahan@92 2119 function WDP:TRADE_SKILL_SHOW(event_name)
jcallahan@92 2120 local profession_name, prof_level = _G.GetTradeSkillLine()
jcallahan@92 2121
jcallahan@92 2122 if profession_name == _G.UNKNOWN then
jcallahan@92 2123 return
jcallahan@92 2124 end
jcallahan@167 2125 TradeSkillExecutePer(RegisterTools)
jcallahan@92 2126 end
jcallahan@92 2127 end -- do-block
jcallahan@92 2128
jcallahan@92 2129
jcallahan@167 2130 function WDP:TRAINER_CLOSED(event_name)
jcallahan@167 2131 private.trainer_shown = nil
jcallahan@167 2132 end
jcallahan@167 2133
jcallahan@167 2134
jcallahan@92 2135 function WDP:TRAINER_SHOW(event_name)
jcallahan@232 2136 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
jcallahan@164 2137 local trainer = NPCEntry(unit_idnum)
jcallahan@58 2138
jcallahan@164 2139 if not trainer then
jcallahan@58 2140 return
jcallahan@58 2141 end
jcallahan@232 2142 local trainer_standing = select(2, UnitFactionStanding("npc"))
jcallahan@164 2143 trainer.teaches = trainer.teaches or {}
jcallahan@27 2144
jcallahan@167 2145 private.trainer_shown = true
jcallahan@167 2146
jcallahan@27 2147 -- Get the initial trainer filters
jcallahan@27 2148 local available = _G.GetTrainerServiceTypeFilter("available")
jcallahan@27 2149 local unavailable = _G.GetTrainerServiceTypeFilter("unavailable")
jcallahan@27 2150 local used = _G.GetTrainerServiceTypeFilter("used")
jcallahan@27 2151
jcallahan@27 2152 -- Clear the trainer filters
jcallahan@27 2153 _G.SetTrainerServiceTypeFilter("available", 1)
jcallahan@27 2154 _G.SetTrainerServiceTypeFilter("unavailable", 1)
jcallahan@27 2155 _G.SetTrainerServiceTypeFilter("used", 1)
jcallahan@27 2156
jcallahan@27 2157 for index = 1, _G.GetNumTrainerServices(), 1 do
jcallahan@27 2158 local spell_name, rank_name, _, _, required_level = _G.GetTrainerServiceInfo(index)
jcallahan@27 2159
jcallahan@27 2160 if spell_name then
jcallahan@27 2161 DatamineTT:ClearLines()
jcallahan@27 2162 DatamineTT:SetTrainerService(index)
jcallahan@27 2163
jcallahan@27 2164 local _, _, spell_id = DatamineTT:GetSpell()
jcallahan@27 2165
jcallahan@43 2166 if spell_id then
jcallahan@164 2167 local class_professions = trainer.teaches[PLAYER_CLASS]
jcallahan@164 2168
jcallahan@164 2169 if not class_professions then
jcallahan@164 2170 trainer.teaches[PLAYER_CLASS] = {}
jcallahan@164 2171 class_professions = trainer.teaches[PLAYER_CLASS]
jcallahan@164 2172 end
jcallahan@43 2173 local profession, min_skill = _G.GetTrainerServiceSkillReq(index)
jcallahan@43 2174 profession = profession or "General"
jcallahan@43 2175
jcallahan@164 2176 local profession_skills = class_professions[profession]
jcallahan@43 2177
jcallahan@43 2178 if not profession_skills then
jcallahan@43 2179 class_professions[profession] = {}
jcallahan@43 2180 profession_skills = class_professions[profession]
jcallahan@43 2181 end
jcallahan@173 2182 profession_skills[spell_id] = ("%d:%d:%d"):format(required_level, min_skill, _G.GetTrainerServiceCost(index))
jcallahan@27 2183 end
jcallahan@27 2184 end
jcallahan@27 2185 end
jcallahan@27 2186 -- Reset the filters to what they were before
jcallahan@27 2187 _G.SetTrainerServiceTypeFilter("available", available or 0)
jcallahan@27 2188 _G.SetTrainerServiceTypeFilter("unavailable", unavailable or 0)
jcallahan@27 2189 _G.SetTrainerServiceTypeFilter("used", used or 0)
jcallahan@27 2190 end
jcallahan@27 2191
jcallahan@27 2192
jcallahan@1 2193 function WDP:UNIT_SPELLCAST_SENT(event_name, unit_id, spell_name, spell_rank, target_name, spell_line)
jcallahan@1 2194 if private.tracked_line or unit_id ~= "player" then
jcallahan@1 2195 return
jcallahan@1 2196 end
jcallahan@1 2197 local spell_label = private.SPELL_LABELS_BY_NAME[spell_name]
jcallahan@1 2198
jcallahan@1 2199 if not spell_label then
jcallahan@1 2200 return
jcallahan@1 2201 end
jcallahan@306 2202
jcallahan@150 2203 local item_name, item_link = _G.GameTooltip:GetItem()
jcallahan@150 2204 local unit_name, unit_id = _G.GameTooltip:GetUnit()
jcallahan@1 2205
jcallahan@150 2206 if not unit_name and _G.UnitName("target") == target_name then
jcallahan@150 2207 unit_name = target_name
jcallahan@150 2208 unit_id = "target"
jcallahan@1 2209 end
jcallahan@1 2210 local spell_flags = private.SPELL_FLAGS_BY_LABEL[spell_label]
jcallahan@28 2211 local zone_name, area_id, x, y, map_level, instance_token = CurrentLocationData()
jcallahan@28 2212
jcallahan@205 2213 table.wipe(current_action)
jcallahan@122 2214 current_action.instance_token = instance_token
jcallahan@122 2215 current_action.map_level = map_level
jcallahan@122 2216 current_action.x = x
jcallahan@122 2217 current_action.y = y
jcallahan@122 2218 current_action.zone_data = ("%s:%d"):format(zone_name, area_id)
jcallahan@122 2219 current_action.spell_label = spell_label
jcallahan@105 2220
jcallahan@105 2221 if not private.NON_LOOT_SPELL_LABELS[spell_label] then
jcallahan@122 2222 current_action.loot_label = spell_label:lower()
jcallahan@105 2223 end
jcallahan@1 2224
jcallahan@151 2225 if unit_name and unit_name == target_name and not item_name then
jcallahan@16 2226 if bit.band(spell_flags, AF.NPC) == AF.NPC then
jcallahan@150 2227 if not unit_id or unit_name ~= target_name then
jcallahan@16 2228 return
jcallahan@16 2229 end
jcallahan@123 2230 current_action.target_type = AF.NPC
jcallahan@16 2231 end
jcallahan@16 2232 elseif bit.band(spell_flags, AF.ITEM) == AF.ITEM then
jcallahan@123 2233 current_action.target_type = AF.ITEM
jcallahan@16 2234
jcallahan@150 2235 if item_name and item_name == target_name then
jcallahan@150 2236 current_action.identifier = ItemLinkToID(item_link)
jcallahan@16 2237 elseif target_name and target_name ~= "" then
jcallahan@150 2238 current_action.identifier = ItemLinkToID(select(2, _G.GetItemInfo(target_name)))
jcallahan@16 2239 end
jcallahan@150 2240 elseif not item_name and not unit_name then
jcallahan@1 2241 if bit.band(spell_flags, AF.OBJECT) == AF.OBJECT then
jcallahan@17 2242 if target_name == "" then
jcallahan@17 2243 return
jcallahan@17 2244 end
jcallahan@122 2245 current_action.object_name = target_name
jcallahan@123 2246 current_action.target_type = AF.OBJECT
jcallahan@1 2247 elseif bit.band(spell_flags, AF.ZONE) == AF.ZONE then
jcallahan@123 2248 current_action.target_type = AF.ZONE
jcallahan@1 2249 end
jcallahan@1 2250 end
jcallahan@1 2251 private.tracked_line = spell_line
jcallahan@0 2252 end
jcallahan@0 2253
jcallahan@94 2254
jcallahan@306 2255 function WDP:SPELL_CONFIRMATION_PROMPT(event_name, spell_id, confirm_type, text, duration, currency_id)
jcallahan@306 2256 if private.RAID_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id] then
jcallahan@306 2257 ClearKilledBossID()
jcallahan@306 2258 ClearLootToastContainerID()
jcallahan@306 2259 private.raid_finder_boss_id = private.RAID_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id]
jcallahan@306 2260 elseif private.WORLD_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id] then
jcallahan@306 2261 ClearKilledBossID()
jcallahan@306 2262 ClearLootToastContainerID()
jcallahan@306 2263 private.world_boss_id = private.WORLD_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id]
jcallahan@306 2264 else
jcallahan@306 2265 Debug("%s: Spell ID %d is not a known raid or world boss 'Bonus' spell.", event_name, spell_id)
jcallahan@306 2266 return
jcallahan@1 2267 end
jcallahan@306 2268
jcallahan@306 2269 killed_boss_id_timer_handle = WDP:ScheduleTimer(ClearKilledBossID, 1) -- we need to assign a handle here to cancel it later
jcallahan@306 2270 end
jcallahan@306 2271
jcallahan@306 2272
jcallahan@306 2273 function WDP:UNIT_SPELLCAST_SUCCEEDED(event_name, unit_id, spell_name, spell_rank, spell_line, spell_id)
jcallahan@306 2274 if unit_id ~= "player" then
jcallahan@306 2275 return
jcallahan@306 2276 end
jcallahan@306 2277 private.tracked_line = nil
jcallahan@306 2278 private.previous_spell_id = spell_id
jcallahan@306 2279
jcallahan@306 2280 if private.LOOT_SPELL_ID_TO_ITEM_ID_MAP[spell_id] then
jcallahan@306 2281 ClearKilledBossID()
jcallahan@306 2282 ClearLootToastContainerID()
jcallahan@306 2283
jcallahan@306 2284 private.loot_toast_container_id = private.LOOT_SPELL_ID_TO_ITEM_ID_MAP[spell_id]
jcallahan@306 2285 loot_toast_container_timer_handle = WDP:ScheduleTimer(ClearLootToastContainerID, 1) -- we need to assign a handle here to cancel it later
jcallahan@306 2286 end
jcallahan@306 2287
jcallahan@306 2288 if anvil_spell_ids[spell_id] then
jcallahan@306 2289 UpdateDBEntryLocation("objects", OBJECT_ID_ANVIL)
jcallahan@306 2290 elseif forge_spell_ids[spell_id] then
jcallahan@306 2291 UpdateDBEntryLocation("objects", OBJECT_ID_FORGE)
jcallahan@306 2292 elseif spell_name:match("^Harvest.+") then
jcallahan@306 2293 killed_npc_id = current_target_id
jcallahan@306 2294 private.harvesting = true
jcallahan@306 2295 end
jcallahan@306 2296 end
jcallahan@0 2297
jcallahan@90 2298
jcallahan@1 2299 function WDP:HandleSpellFailure(event_name, unit_id, spell_name, spell_rank, spell_line, spell_id)
jcallahan@1 2300 if unit_id ~= "player" then
jcallahan@1 2301 return
jcallahan@1 2302 end
jcallahan@0 2303
jcallahan@1 2304 if private.tracked_line == spell_line then
jcallahan@1 2305 private.tracked_line = nil
jcallahan@1 2306 end
jcallahan@147 2307 table.wipe(current_action)
jcallahan@0 2308 end
jcallahan@90 2309
jcallahan@90 2310
jcallahan@90 2311 do
jcallahan@90 2312 local function SetUnitField(field, required_type)
jcallahan@90 2313 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
jcallahan@90 2314
jcallahan@90 2315 if not unit_idnum or (required_type and unit_type ~= required_type) then
jcallahan@90 2316 return
jcallahan@90 2317 end
jcallahan@90 2318
jcallahan@171 2319 if UnitTypeIsNPC(unit_type) then
jcallahan@90 2320 NPCEntry(unit_idnum)[field] = true
jcallahan@90 2321 elseif unit_type == private.UNIT_TYPES.OBJECT then
jcallahan@90 2322 DBEntry("objects", unit_idnum)[field] = true
jcallahan@93 2323 UpdateDBEntryLocation("objects", unit_idnum)
jcallahan@90 2324 end
jcallahan@90 2325 end
jcallahan@90 2326
jcallahan@90 2327
jcallahan@90 2328 function WDP:AUCTION_HOUSE_SHOW(event_name)
jcallahan@90 2329 SetUnitField("auctioneer", private.UNIT_TYPES.NPC)
jcallahan@90 2330 end
jcallahan@90 2331
jcallahan@90 2332
jcallahan@90 2333 function WDP:BANKFRAME_OPENED(event_name)
jcallahan@90 2334 SetUnitField("banker", private.UNIT_TYPES.NPC)
jcallahan@90 2335 end
jcallahan@90 2336
jcallahan@90 2337
jcallahan@90 2338 function WDP:BATTLEFIELDS_SHOW(event_name)
jcallahan@90 2339 SetUnitField("battlemaster", private.UNIT_TYPES.NPC)
jcallahan@90 2340 end
jcallahan@90 2341
jcallahan@90 2342
jcallahan@92 2343 function WDP:FORGE_MASTER_OPENED(event_name)
jcallahan@90 2344 SetUnitField("arcane_reforger", private.UNIT_TYPES.NPC)
jcallahan@90 2345 end
jcallahan@90 2346
jcallahan@90 2347
jcallahan@92 2348 function WDP:GOSSIP_SHOW(event_name)
jcallahan@90 2349 local gossip_options = { _G.GetGossipOptions() }
jcallahan@90 2350
jcallahan@90 2351 for index = 2, #gossip_options, 2 do
jcallahan@90 2352 if gossip_options[index] == "binder" then
jcallahan@90 2353 SetUnitField("innkeeper", private.UNIT_TYPES.NPC)
jcallahan@90 2354 return
jcallahan@90 2355 end
jcallahan@90 2356 end
jcallahan@90 2357 end
jcallahan@90 2358
jcallahan@90 2359
jcallahan@93 2360 function WDP:GUILDBANKFRAME_OPENED(event_name)
jcallahan@93 2361 SetUnitField("guild_bank", private.UNIT_TYPES.OBJECT)
jcallahan@93 2362 end
jcallahan@93 2363
jcallahan@93 2364
jcallahan@189 2365 function WDP:ITEM_UPGRADE_MASTER_OPENED(event_name)
jcallahan@189 2366 SetUnitField("item_upgrade_master", private.UNIT_TYPES.NPC)
jcallahan@189 2367 end
jcallahan@189 2368
jcallahan@189 2369
jcallahan@90 2370 function WDP:TAXIMAP_OPENED(event_name)
jcallahan@90 2371 SetUnitField("flight_master", private.UNIT_TYPES.NPC)
jcallahan@90 2372 end
jcallahan@90 2373
jcallahan@90 2374
jcallahan@90 2375 function WDP:TRANSMOGRIFY_OPEN(event_name)
jcallahan@90 2376 SetUnitField("transmogrifier", private.UNIT_TYPES.NPC)
jcallahan@90 2377 end
jcallahan@90 2378
jcallahan@90 2379
jcallahan@90 2380 function WDP:VOID_STORAGE_OPEN(event_name)
jcallahan@90 2381 SetUnitField("void_storage", private.UNIT_TYPES.NPC)
jcallahan@90 2382 end
jcallahan@90 2383 end -- do-block