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@312
|
6 local tostring = _G.tostring
|
jcallahan@1
|
7 local tonumber = _G.tonumber
|
jcallahan@1
|
8
|
jcallahan@1
|
9 local bit = _G.bit
|
jcallahan@1
|
10 local math = _G.math
|
jcallahan@1
|
11 local table = _G.table
|
jcallahan@1
|
12
|
jcallahan@334
|
13 local next = _G.next
|
jcallahan@78
|
14 local select = _G.select
|
mmosimca@485
|
15 local type = _G.type
|
jcallahan@306
|
16 local unpack = _G.unpack
|
jcallahan@78
|
17
|
MMOSimca@383
|
18 local C_Timer = _G.C_Timer
|
mmosimca@496
|
19 local GetCurrencyInfo = _G.GetCurrencyInfo
|
MMOSimca@383
|
20
|
jcallahan@0
|
21
|
jcallahan@246
|
22 -- ADDON NAMESPACE ----------------------------------------------------
|
jcallahan@246
|
23
|
jcallahan@0
|
24 local ADDON_NAME, private = ...
|
jcallahan@0
|
25
|
jcallahan@0
|
26 local LibStub = _G.LibStub
|
MMOSimca@383
|
27 local WDP = LibStub("AceAddon-3.0"):NewAddon(ADDON_NAME, "AceConsole-3.0", "AceEvent-3.0")
|
jcallahan@0
|
28
|
jcallahan@48
|
29 local deformat = LibStub("LibDeformat-3.0")
|
catherton@465
|
30 local HereBeDragons = LibStub("HereBeDragons-1.0")
|
mmosimca@484
|
31 local LibRealmInfo = LibStub("LibRealmInfo")
|
jcallahan@48
|
32
|
jcallahan@4
|
33 local DatamineTT = _G.CreateFrame("GameTooltip", "WDPDatamineTT", _G.UIParent, "GameTooltipTemplate")
|
jcallahan@5
|
34 DatamineTT:SetOwner(_G.WorldFrame, "ANCHOR_NONE")
|
jcallahan@5
|
35
|
jcallahan@0
|
36
|
jcallahan@246
|
37 -- CONSTANTS ----------------------------------------------------------
|
jcallahan@246
|
38
|
jcallahan@246
|
39 local AF = private.ACTION_TYPE_FLAGS
|
jcallahan@246
|
40 local CLIENT_LOCALE = _G.GetLocale()
|
jcallahan@313
|
41 local DB_VERSION = 18
|
MMOSimca@346
|
42 local DEBUGGING = false
|
jcallahan@156
|
43 local EVENT_DEBUG = false
|
jcallahan@322
|
44
|
mmosimca@485
|
45 -- Timer durations in seconds
|
mmosimca@485
|
46 local DELAY_PROCESS_ITEMS = 30
|
mmosimca@485
|
47 local DELAY_PROCESS_WORLD_QUESTS = 60
|
mmosimca@485
|
48 local DELAY_UPDATE_TARGET_LOCATION = 0.5
|
mmosimca@485
|
49
|
MMOSimca@405
|
50 local ITEM_ID_TIMBER = 114781
|
MMOSimca@405
|
51
|
mmosimca@520
|
52 local LOOT_SLOT_CURRENCY = _G.LOOT_SLOT_CURRENCY
|
mmosimca@520
|
53 local LOOT_SLOT_ITEM = _G.LOOT_SLOT_ITEM
|
mmosimca@520
|
54 local LOOT_SLOT_MONEY = _G.LOOT_SLOT_MONEY
|
mmosimca@520
|
55
|
MMOSimca@422
|
56 local LOOT_SOURCE_ID_REDUNDANT = 3
|
MMOSimca@422
|
57 local LOOT_SOURCE_ID_GARRISON_CACHE = 10
|
MMOSimca@422
|
58
|
jcallahan@246
|
59 local OBJECT_ID_ANVIL = 192628
|
jcallahan@322
|
60 local OBJECT_ID_FISHING_BOBBER = 35591
|
jcallahan@246
|
61 local OBJECT_ID_FORGE = 1685
|
jcallahan@322
|
62
|
MMOSimca@454
|
63 local PLAYER_CLASS, PLAYER_CLASS_ID = _G.select(2, _G.UnitClass("player"))
|
jcallahan@246
|
64 local PLAYER_FACTION = _G.UnitFactionGroup("player")
|
jcallahan@300
|
65 local PLAYER_GUID
|
mmosimca@485
|
66 local PLAYER_LEVEL = _G.UnitLevel("player")
|
jcallahan@246
|
67 local PLAYER_NAME = _G.UnitName("player")
|
jcallahan@246
|
68 local PLAYER_RACE = _G.select(2, _G.UnitRace("player"))
|
jcallahan@246
|
69
|
mmosimca@520
|
70 local SPELL_ID_UPDATE_INTERACTIONS = 161006
|
MMOSimca@377
|
71
|
mmosimca@485
|
72 local WORLD_MAP_ID_BROKEN_ISLES = 1007
|
mmosimca@485
|
73
|
mmosimca@516
|
74 -- Removed in Patch 7.0.3; previously used to determine if a system message was a quest reward or not
|
mmosimca@517
|
75 local ERR_QUEST_REWARD_ITEM_MULT_IS = _G.ERR_QUEST_REWARD_ITEM_MULT_IS or "Received %d of item: %s."
|
mmosimca@517
|
76 local ERR_QUEST_REWARD_ITEM_S = _G.ERR_QUEST_REWARD_ITEM_S or "Received item: %s."
|
catherton@472
|
77
|
jcallahan@246
|
78 local ALLOWED_LOCALES = {
|
jcallahan@246
|
79 enUS = true,
|
jcallahan@246
|
80 enGB = true,
|
MMOSimca@336
|
81 enTW = true,
|
MMOSimca@336
|
82 enCN = true,
|
jcallahan@246
|
83 }
|
jcallahan@157
|
84
|
jcallahan@0
|
85 local DATABASE_DEFAULTS = {
|
jcallahan@128
|
86 char = {},
|
jcallahan@0
|
87 global = {
|
jcallahan@270
|
88 config = {
|
jcallahan@270
|
89 minimap_icon = {
|
jcallahan@270
|
90 hide = true,
|
jcallahan@270
|
91 },
|
jcallahan@270
|
92 },
|
jcallahan@0
|
93 items = {},
|
jcallahan@0
|
94 npcs = {},
|
jcallahan@0
|
95 objects = {},
|
jcallahan@0
|
96 quests = {},
|
jcallahan@167
|
97 spells = {},
|
jcallahan@17
|
98 zones = {},
|
jcallahan@0
|
99 }
|
jcallahan@0
|
100 }
|
jcallahan@0
|
101
|
jcallahan@1
|
102 local EVENT_MAPPING = {
|
MMOSimca@436
|
103 AUCTION_HOUSE_CLOSED = "ResumeChatLootRecording",
|
MMOSimca@436
|
104 AUCTION_HOUSE_SHOW = true, -- also triggers StopChatLootRecording
|
MMOSimca@436
|
105 BANKFRAME_CLOSED = "ResumeChatLootRecording",
|
MMOSimca@436
|
106 BANKFRAME_OPENED = true, -- also triggers StopChatLootRecording
|
jcallahan@90
|
107 BATTLEFIELDS_SHOW = true,
|
jcallahan@56
|
108 BLACK_MARKET_ITEM_UPDATE = true,
|
MMOSimca@408
|
109 BONUS_ROLL_RESULT = true,
|
MMOSimca@388
|
110 CHAT_MSG_CURRENCY = true,
|
jcallahan@48
|
111 CHAT_MSG_LOOT = true,
|
jcallahan@95
|
112 CHAT_MSG_MONSTER_SAY = "RecordQuote",
|
jcallahan@95
|
113 CHAT_MSG_MONSTER_WHISPER = "RecordQuote",
|
jcallahan@95
|
114 CHAT_MSG_MONSTER_YELL = "RecordQuote",
|
jcallahan@40
|
115 CHAT_MSG_SYSTEM = true,
|
jcallahan@23
|
116 COMBAT_LOG_EVENT_UNFILTERED = true,
|
jcallahan@18
|
117 COMBAT_TEXT_UPDATE = true,
|
jcallahan@140
|
118 CURSOR_UPDATE = true,
|
jcallahan@90
|
119 FORGE_MASTER_OPENED = true,
|
MMOSimca@436
|
120 GARRISON_MISSION_NPC_CLOSED = "ResumeChatLootRecording",
|
MMOSimca@436
|
121 GARRISON_MISSION_NPC_OPENED = "StopChatLootRecording",
|
MMOSimca@450
|
122 GARRISON_SHIPYARD_NPC_CLOSED = "ResumeChatLootRecording",
|
MMOSimca@450
|
123 GARRISON_SHIPYARD_NPC_OPENED = "StopChatLootRecording",
|
MMOSimca@436
|
124 GOSSIP_CLOSED = "ResumeChatLootRecording",
|
MMOSimca@436
|
125 GOSSIP_SHOW = true, -- also triggers StopChatLootRecording
|
jcallahan@290
|
126 GROUP_ROSTER_UPDATE = true,
|
MMOSimca@436
|
127 GUILDBANKFRAME_CLOSED = "ResumeChatLootRecording",
|
MMOSimca@436
|
128 GUILDBANKFRAME_OPENED = true, -- also triggers StopChatLootRecording
|
jcallahan@42
|
129 ITEM_TEXT_BEGIN = true,
|
jcallahan@189
|
130 ITEM_UPGRADE_MASTER_OPENED = true,
|
jcallahan@124
|
131 LOOT_CLOSED = true,
|
MMOSimca@343
|
132 LOOT_OPENED = true,
|
MMOSimca@412
|
133 LOOT_SLOT_CLEARED = "HandleBadChatLootData",
|
MMOSimca@436
|
134 MAIL_CLOSED = "ResumeChatLootRecording",
|
MMOSimca@436
|
135 MAIL_SHOW = true, -- also triggers StopChatLootRecording
|
MMOSimca@436
|
136 MERCHANT_CLOSED = true, -- also triggers ResumeChatLootRecording
|
MMOSimca@436
|
137 MERCHANT_SHOW = "UpdateMerchantItems", -- also triggers StopChatLootRecording
|
jcallahan@61
|
138 MERCHANT_UPDATE = "UpdateMerchantItems",
|
jcallahan@25
|
139 PET_BAR_UPDATE = true,
|
MMOSimca@368
|
140 --PET_JOURNAL_LIST_UPDATE = true,
|
jcallahan@156
|
141 PLAYER_REGEN_DISABLED = true,
|
jcallahan@156
|
142 PLAYER_REGEN_ENABLED = true,
|
jcallahan@2
|
143 PLAYER_TARGET_CHANGED = true,
|
jcallahan@9
|
144 QUEST_COMPLETE = true,
|
jcallahan@9
|
145 QUEST_DETAIL = true,
|
jcallahan@9
|
146 QUEST_LOG_UPDATE = true,
|
jcallahan@97
|
147 QUEST_PROGRESS = true,
|
jcallahan@178
|
148 SHOW_LOOT_TOAST = true,
|
jcallahan@306
|
149 SPELL_CONFIRMATION_PROMPT = true,
|
jcallahan@88
|
150 TAXIMAP_OPENED = true,
|
MMOSimca@437
|
151 TRADE_CLOSED = "ResumeChatLootRecording",
|
MMOSimca@437
|
152 TRADE_SHOW = "StopChatLootRecording",
|
jcallahan@92
|
153 TRADE_SKILL_SHOW = true,
|
jcallahan@167
|
154 TRAINER_CLOSED = true,
|
jcallahan@27
|
155 TRAINER_SHOW = true,
|
jcallahan@90
|
156 TRANSMOGRIFY_OPEN = true,
|
jcallahan@246
|
157 UNIT_PET = true,
|
jcallahan@4
|
158 UNIT_QUEST_LOG_CHANGED = true,
|
jcallahan@1
|
159 UNIT_SPELLCAST_FAILED = "HandleSpellFailure",
|
jcallahan@1
|
160 UNIT_SPELLCAST_FAILED_QUIET = "HandleSpellFailure",
|
jcallahan@1
|
161 UNIT_SPELLCAST_INTERRUPTED = "HandleSpellFailure",
|
jcallahan@1
|
162 UNIT_SPELLCAST_SENT = true,
|
jcallahan@1
|
163 UNIT_SPELLCAST_SUCCEEDED = true,
|
jcallahan@90
|
164 VOID_STORAGE_OPEN = true,
|
jcallahan@0
|
165 }
|
jcallahan@0
|
166
|
jcallahan@4
|
167
|
jcallahan@246
|
168 -- VARIABLES ----------------------------------------------------------
|
jcallahan@246
|
169
|
jcallahan@92
|
170 local anvil_spell_ids = {}
|
jcallahan@92
|
171 local currently_drunk
|
jcallahan@128
|
172 local char_db
|
jcallahan@128
|
173 local global_db
|
jcallahan@299
|
174 local group_member_guids = {}
|
jcallahan@246
|
175 local group_owner_guids_to_pet_guids = {}
|
jcallahan@246
|
176 local group_pet_guids = {}
|
jcallahan@299
|
177 local in_instance
|
jcallahan@187
|
178 local item_process_timer_handle
|
jcallahan@92
|
179 local faction_standings = {}
|
jcallahan@92
|
180 local forge_spell_ids = {}
|
jcallahan@95
|
181 local languages_known = {}
|
jcallahan@317
|
182 local boss_loot_toasting = {}
|
MMOSimca@387
|
183 local container_loot_toasting
|
MMOSimca@387
|
184 local loot_toast_container_id
|
MMOSimca@387
|
185 local raid_boss_id
|
jcallahan@306
|
186 local loot_toast_container_timer_handle
|
jcallahan@307
|
187 local loot_toast_data
|
jcallahan@307
|
188 local loot_toast_data_timer_handle
|
jcallahan@95
|
189 local name_to_id_map = {}
|
jcallahan@306
|
190 local killed_boss_id_timer_handle
|
jcallahan@177
|
191 local killed_npc_id
|
jcallahan@2
|
192 local target_location_timer_handle
|
MMOSimca@345
|
193 local last_timber_spell_id
|
MMOSimca@355
|
194 local last_garrison_cache_object_id
|
MMOSimca@436
|
195 local block_chat_loot_data
|
MMOSimca@435
|
196 local chat_loot_data = {}
|
MMOSimca@347
|
197 local chat_loot_timer_handle
|
mmosimca@485
|
198 local world_quest_timer_handle
|
mmosimca@485
|
199 local world_quest_event_timestamp = 0
|
jcallahan@86
|
200 local current_target_id
|
jcallahan@131
|
201 local current_loot
|
jcallahan@1
|
202
|
jcallahan@312
|
203
|
jcallahan@121
|
204 -- Data for our current action. Including possible values as a reference.
|
jcallahan@122
|
205 local current_action = {
|
jcallahan@121
|
206 identifier = nil,
|
jcallahan@121
|
207 loot_label = nil,
|
jcallahan@121
|
208 loot_list = nil,
|
jcallahan@121
|
209 loot_sources = nil,
|
jcallahan@121
|
210 map_level = nil,
|
jcallahan@121
|
211 spell_label = nil,
|
jcallahan@123
|
212 target_type = nil,
|
jcallahan@121
|
213 x = nil,
|
jcallahan@121
|
214 y = nil,
|
jcallahan@121
|
215 zone_data = nil,
|
jcallahan@121
|
216 }
|
jcallahan@92
|
217
|
jcallahan@246
|
218
|
MMOSimca@393
|
219 -- Timer prototypes
|
MMOSimca@393
|
220 local ClearKilledNPC, ClearKilledBossID, ClearLootToastContainerID, ClearLootToastData, ClearChatLootData
|
MMOSimca@393
|
221
|
MMOSimca@393
|
222
|
jcallahan@246
|
223 -- HELPERS ------------------------------------------------------------
|
jcallahan@246
|
224
|
jcallahan@245
|
225 local function Debug(message, ...)
|
MMOSimca@350
|
226 if not DEBUGGING or not message then
|
jcallahan@151
|
227 return
|
jcallahan@151
|
228 end
|
catherton@465
|
229
|
MMOSimca@350
|
230 if ... then
|
MMOSimca@350
|
231 local args = { ... }
|
MMOSimca@350
|
232
|
MMOSimca@350
|
233 for index = 1, #args do
|
MMOSimca@377
|
234 args[index] = tostring(args[index])
|
jcallahan@306
|
235 end
|
MMOSimca@350
|
236 _G.print(message:format(unpack(args)))
|
MMOSimca@350
|
237 else
|
MMOSimca@350
|
238 _G.print(message)
|
jcallahan@306
|
239 end
|
jcallahan@151
|
240 end
|
jcallahan@151
|
241
|
jcallahan@151
|
242
|
MMOSimca@393
|
243 local function InitializeCurrentLoot()
|
MMOSimca@393
|
244 current_loot = {
|
MMOSimca@393
|
245 list = {},
|
MMOSimca@393
|
246 sources = {},
|
MMOSimca@393
|
247 identifier = current_action.identifier,
|
MMOSimca@393
|
248 label = current_action.loot_label or "drops",
|
MMOSimca@393
|
249 map_level = current_action.map_level,
|
MMOSimca@393
|
250 object_name = current_action.object_name,
|
MMOSimca@393
|
251 spell_label = current_action.spell_label,
|
MMOSimca@393
|
252 target_type = current_action.target_type,
|
MMOSimca@393
|
253 x = current_action.x,
|
MMOSimca@393
|
254 y = current_action.y,
|
MMOSimca@393
|
255 zone_data = current_action.zone_data,
|
MMOSimca@393
|
256 }
|
MMOSimca@393
|
257
|
MMOSimca@393
|
258 table.wipe(current_action)
|
MMOSimca@393
|
259 end
|
MMOSimca@393
|
260
|
MMOSimca@393
|
261
|
jcallahan@169
|
262 local TradeSkillExecutePer
|
jcallahan@169
|
263 do
|
jcallahan@169
|
264 local header_list = {}
|
jcallahan@169
|
265
|
jcallahan@169
|
266 function TradeSkillExecutePer(iter_func)
|
jcallahan@169
|
267 if not _G.TradeSkillFrame or not _G.TradeSkillFrame:IsVisible() then
|
jcallahan@169
|
268 return
|
jcallahan@169
|
269 end
|
catherton@465
|
270
|
catherton@479
|
271 local recipes = _G.C_TradeSkillUI.GetAllRecipeIDs()
|
catherton@479
|
272
|
catherton@479
|
273 if recipes and (#recipes > 0) then
|
catherton@479
|
274 for i = 1, #recipes do
|
catherton@479
|
275 if iter_func(_G.C_TradeSkillUI.GetRecipeInfo(recipes[i]).name, recipes[i]) then
|
catherton@465
|
276 break
|
catherton@465
|
277 end
|
catherton@465
|
278 end
|
catherton@465
|
279 end
|
jcallahan@167
|
280 end
|
jcallahan@169
|
281 end -- do-block
|
jcallahan@167
|
282
|
jcallahan@167
|
283
|
jcallahan@39
|
284 local ActualCopperCost
|
jcallahan@39
|
285 do
|
jcallahan@39
|
286 local BARTERING_SPELL_ID = 83964
|
jcallahan@39
|
287
|
jcallahan@39
|
288 local STANDING_DISCOUNTS = {
|
jcallahan@39
|
289 HATED = 0,
|
jcallahan@39
|
290 HOSTILE = 0,
|
jcallahan@39
|
291 UNFRIENDLY = 0,
|
jcallahan@39
|
292 NEUTRAL = 0,
|
jcallahan@39
|
293 FRIENDLY = 0.05,
|
jcallahan@39
|
294 HONORED = 0.1,
|
jcallahan@39
|
295 REVERED = 0.15,
|
jcallahan@39
|
296 EXALTED = 0.2,
|
jcallahan@39
|
297 }
|
jcallahan@39
|
298
|
jcallahan@39
|
299
|
jcallahan@39
|
300 function ActualCopperCost(copper_cost, rep_standing)
|
jcallahan@39
|
301 if not copper_cost or copper_cost == 0 then
|
jcallahan@39
|
302 return 0
|
jcallahan@39
|
303 end
|
jcallahan@39
|
304 local modifier = 1
|
jcallahan@39
|
305
|
jcallahan@39
|
306 if _G.IsSpellKnown(BARTERING_SPELL_ID) then
|
jcallahan@39
|
307 modifier = modifier - 0.1
|
jcallahan@39
|
308 end
|
jcallahan@39
|
309
|
jcallahan@39
|
310 if rep_standing then
|
jcallahan@39
|
311 if PLAYER_RACE == "Goblin" then
|
jcallahan@39
|
312 modifier = modifier - STANDING_DISCOUNTS["EXALTED"]
|
jcallahan@39
|
313 elseif STANDING_DISCOUNTS[rep_standing] then
|
jcallahan@39
|
314 modifier = modifier - STANDING_DISCOUNTS[rep_standing]
|
jcallahan@39
|
315 end
|
jcallahan@39
|
316 end
|
jcallahan@39
|
317 return math.floor(copper_cost / modifier)
|
jcallahan@39
|
318 end
|
jcallahan@39
|
319 end -- do-block
|
jcallahan@39
|
320
|
jcallahan@39
|
321
|
mmosimca@496
|
322 local CurrencyInfoToID
|
mmosimca@496
|
323 local PopulateCurrencyInfoLookup
|
mmosimca@496
|
324 do
|
mmosimca@496
|
325 local MAX_CURRENCY_ID_GAP = 800
|
mmosimca@496
|
326
|
mmosimca@496
|
327 local currency_info_lookup = {}
|
mmosimca@496
|
328
|
mmosimca@496
|
329
|
mmosimca@496
|
330 function CurrencyInfoToID(name, texture)
|
mmosimca@501
|
331 if not name or not texture then return nil end
|
mmosimca@496
|
332 return currency_info_lookup[("%s:%s"):format(name, texture)]
|
mmosimca@496
|
333 end
|
mmosimca@496
|
334
|
mmosimca@496
|
335
|
mmosimca@496
|
336 function PopulateCurrencyInfoLookup()
|
mmosimca@496
|
337 local currency_index = 1
|
mmosimca@496
|
338 local gap_since_last_currency = 0
|
mmosimca@496
|
339 repeat
|
mmosimca@496
|
340 -- Store ID by info (name and texture combined)
|
mmosimca@496
|
341 local name, _, texture = GetCurrencyInfo(currency_index)
|
mmosimca@496
|
342 currency_info_lookup[("%s:%s"):format(name, texture)] = currency_index
|
mmosimca@496
|
343
|
mmosimca@496
|
344 -- If we found nothing, increment gap
|
mmosimca@496
|
345 if not name or not texture or (name == "" and texture == "") then
|
mmosimca@496
|
346 gap_since_last_currency = gap_since_last_currency + 1
|
mmosimca@496
|
347 else
|
mmosimca@496
|
348 gap_since_last_currency = 0
|
mmosimca@496
|
349 end
|
mmosimca@496
|
350
|
mmosimca@496
|
351 -- Increment loop counter
|
mmosimca@496
|
352 currency_index = currency_index + 1
|
mmosimca@496
|
353
|
mmosimca@496
|
354 until (gap_since_last_currency > MAX_CURRENCY_ID_GAP)
|
mmosimca@496
|
355 end
|
mmosimca@496
|
356 end
|
mmosimca@496
|
357
|
mmosimca@496
|
358
|
jcallahan@29
|
359 local function InstanceDifficultyToken()
|
MMOSimca@440
|
360 -- Sometimes, instance information is returned when not in an instance. This check protects against that.
|
MMOSimca@440
|
361 if _G.IsInInstance() then
|
MMOSimca@440
|
362 local _, instance_type, instance_difficulty, _, _, _, is_dynamic = _G.GetInstanceInfo()
|
MMOSimca@440
|
363
|
MMOSimca@440
|
364 if not instance_type or instance_type == "" then
|
MMOSimca@440
|
365 instance_type = "NONE"
|
MMOSimca@440
|
366 end
|
MMOSimca@440
|
367 return ("%s:%d:%s"):format(instance_type:upper(), instance_difficulty, tostring(is_dynamic))
|
jcallahan@59
|
368 end
|
MMOSimca@440
|
369 return "NONE:0:false"
|
jcallahan@29
|
370 end
|
jcallahan@29
|
371
|
jcallahan@29
|
372
|
jcallahan@1
|
373 local function CurrentLocationData()
|
mmosimca@488
|
374 local x, y, current_area_id, map_level, map_file, is_micro_dungeon = HereBeDragons:GetPlayerZonePosition(false)
|
catherton@468
|
375 local zone_name = _G.GetRealZoneText()
|
catherton@465
|
376
|
mmosimca@488
|
377 -- Remove micro-dungeon-ness by translating back to the parent world map (at floor 0) if possible
|
mmosimca@488
|
378 if (is_micro_dungeon and x and y and current_area_id and map_level and map_level > 0) then
|
mmosimca@488
|
379 x, y = HereBeDragons:TranslateZoneCoordinates(x, y, current_area_id, map_level, current_area_id, 0, false)
|
mmosimca@488
|
380 map_level = 0
|
mmosimca@488
|
381 end
|
mmosimca@488
|
382
|
catherton@465
|
383 -- Put coordinates into expected format (as integers, they don't get a billion decimals output in the SavedVariables)
|
catherton@468
|
384 local x_int = nil
|
catherton@468
|
385 if (x and type(x) == "number") then
|
catherton@468
|
386 x_int = _G.floor(x * 1000)
|
mmosimca@485
|
387
|
mmosimca@482
|
388 -- Limit precision to 0.2
|
catherton@468
|
389 if x_int % 2 ~= 0 then
|
catherton@468
|
390 x_int = x_int + 1
|
catherton@468
|
391 end
|
mmosimca@485
|
392
|
mmosimca@482
|
393 -- Prevent out of bounds coordinates
|
mmosimca@482
|
394 if (x_int < 0 or x_int > 1000) then
|
mmosimca@482
|
395 x_int = nil
|
mmosimca@482
|
396 end
|
jcallahan@145
|
397 end
|
catherton@468
|
398 local y_int = nil
|
catherton@468
|
399 if (y and type(y) == "number") then
|
catherton@468
|
400 y_int = _G.floor(y * 1000)
|
mmosimca@485
|
401
|
mmosimca@482
|
402 -- Limit precision to 0.2
|
catherton@468
|
403 if y_int % 2 ~= 0 then
|
catherton@468
|
404 y_int = y_int + 1
|
catherton@468
|
405 end
|
mmosimca@485
|
406
|
mmosimca@482
|
407 -- Prevent out of bounds coordinates
|
mmosimca@482
|
408 if (y_int < 0 or y_int > 1000) then
|
mmosimca@482
|
409 y_int = nil
|
mmosimca@482
|
410 end
|
jcallahan@1
|
411 end
|
jcallahan@1
|
412
|
catherton@468
|
413 return zone_name, current_area_id, x_int, y_int, map_level, InstanceDifficultyToken()
|
jcallahan@1
|
414 end
|
jcallahan@1
|
415
|
jcallahan@1
|
416
|
MMOSimca@441
|
417 local function DBEntry(data_type, unit_id)
|
MMOSimca@441
|
418 if not data_type or not unit_id then
|
jcallahan@312
|
419 return
|
jcallahan@312
|
420 end
|
MMOSimca@441
|
421 local category = global_db[data_type]
|
MMOSimca@441
|
422
|
MMOSimca@441
|
423 if not category then
|
MMOSimca@441
|
424 category = {}
|
MMOSimca@441
|
425 global_db[data_type] = category
|
MMOSimca@441
|
426 end
|
MMOSimca@441
|
427 local unit = category[unit_id]
|
MMOSimca@441
|
428
|
MMOSimca@441
|
429 if not unit then
|
MMOSimca@441
|
430 unit = {}
|
MMOSimca@441
|
431 category[unit_id] = unit
|
MMOSimca@441
|
432 end
|
MMOSimca@441
|
433 return unit
|
jcallahan@312
|
434 end
|
jcallahan@312
|
435
|
MMOSimca@441
|
436 private.DBEntry = DBEntry
|
MMOSimca@441
|
437
|
MMOSimca@441
|
438 local NPCEntry
|
MMOSimca@441
|
439 do
|
MMOSimca@441
|
440 local npc_prototype = {}
|
MMOSimca@441
|
441 local npc_meta = {
|
MMOSimca@441
|
442 __index = npc_prototype
|
MMOSimca@441
|
443 }
|
MMOSimca@441
|
444
|
MMOSimca@441
|
445 function NPCEntry(identifier)
|
MMOSimca@441
|
446 local npc = DBEntry("npcs", identifier)
|
MMOSimca@441
|
447 return npc and _G.setmetatable(npc, npc_meta) or nil
|
jcallahan@1
|
448 end
|
MMOSimca@441
|
449
|
MMOSimca@441
|
450 function npc_prototype:EncounterData(difficulty_token)
|
MMOSimca@441
|
451 self.encounter_data = self.encounter_data or {}
|
MMOSimca@441
|
452 self.encounter_data[difficulty_token] = self.encounter_data[difficulty_token] or {}
|
MMOSimca@441
|
453 self.encounter_data[difficulty_token].stats = self.encounter_data[difficulty_token].stats or {}
|
MMOSimca@441
|
454
|
MMOSimca@441
|
455 return self.encounter_data[difficulty_token]
|
MMOSimca@441
|
456 end
|
jcallahan@1
|
457 end
|
jcallahan@270
|
458
|
jcallahan@4
|
459
|
jcallahan@141
|
460 local UpdateDBEntryLocation
|
jcallahan@141
|
461 do
|
jcallahan@141
|
462 -- Fishing node coordinate code based on code in GatherMate2 with permission from Kagaro.
|
jcallahan@141
|
463 local function FishingCoordinates(x, y, yard_width, yard_height)
|
jcallahan@141
|
464 local facing = _G.GetPlayerFacing()
|
jcallahan@141
|
465
|
jcallahan@141
|
466 if not facing then
|
jcallahan@141
|
467 return x, y
|
jcallahan@141
|
468 end
|
jcallahan@246
|
469 local rad = facing + math.pi
|
jcallahan@141
|
470 return x + math.sin(rad) * 15 / yard_width, y + math.cos(rad) * 15 / yard_height
|
jcallahan@10
|
471 end
|
jcallahan@10
|
472
|
jcallahan@24
|
473
|
jcallahan@141
|
474 function UpdateDBEntryLocation(entry_type, identifier)
|
jcallahan@141
|
475 if not identifier then
|
jcallahan@141
|
476 return
|
jcallahan@141
|
477 end
|
jcallahan@141
|
478 local zone_name, area_id, x, y, map_level, difficulty_token = CurrentLocationData()
|
MMOSimca@328
|
479 if not (zone_name and area_id and x and y and map_level) then
|
mmosimca@508
|
480 if not (_G.IsInInstance()) then
|
mmosimca@508
|
481 Debug("UpdateDBEntryLocation: Missing current location data - %s, %s, %s, %s, %s.", tostring(zone_name), tostring(area_id), tostring(x), tostring(y), tostring(map_level))
|
mmosimca@508
|
482 end
|
MMOSimca@328
|
483 return
|
MMOSimca@328
|
484 end
|
jcallahan@141
|
485 local entry = DBEntry(entry_type, identifier)
|
jcallahan@141
|
486 entry[difficulty_token] = entry[difficulty_token] or {}
|
jcallahan@141
|
487 entry[difficulty_token].locations = entry[difficulty_token].locations or {}
|
jcallahan@141
|
488
|
jcallahan@141
|
489 local zone_token = ("%s:%d"):format(zone_name, area_id)
|
jcallahan@141
|
490 local zone_data = entry[difficulty_token].locations[zone_token]
|
jcallahan@141
|
491
|
jcallahan@141
|
492 if not zone_data then
|
jcallahan@141
|
493 zone_data = {}
|
jcallahan@141
|
494 entry[difficulty_token].locations[zone_token] = zone_data
|
jcallahan@141
|
495 end
|
jcallahan@141
|
496
|
jcallahan@141
|
497 -- Special case for Fishing.
|
jcallahan@141
|
498 if current_action.spell_label == "FISHING" then
|
MMOSimca@441
|
499 local _, qx, qy = _G.GetWorldLocFromMapPos(0, 0)
|
MMOSimca@441
|
500 local _, wx, wy = _G.GetWorldLocFromMapPos(1, 1)
|
MMOSimca@441
|
501 local yard_width, yard_height = qy - wy, qx - wx
|
jcallahan@141
|
502
|
jcallahan@141
|
503 if yard_width > 0 and yard_height > 0 then
|
jcallahan@141
|
504 x, y = FishingCoordinates(x, y, yard_width, yard_height)
|
jcallahan@141
|
505 current_action.x = x
|
jcallahan@141
|
506 current_action.y = y
|
jcallahan@141
|
507 end
|
jcallahan@141
|
508 end
|
jcallahan@141
|
509 local location_token = ("%d:%d:%d"):format(map_level, x, y)
|
jcallahan@141
|
510
|
jcallahan@141
|
511 zone_data[location_token] = zone_data[location_token] or true
|
jcallahan@141
|
512 return zone_data
|
jcallahan@10
|
513 end
|
jcallahan@141
|
514 end -- do-block
|
jcallahan@10
|
515
|
jcallahan@10
|
516
|
mmosimca@496
|
517 local function CurrencyLinkToID(currency_link)
|
MMOSimca@441
|
518 if not currency_link then
|
mmosimca@496
|
519 return nil
|
MMOSimca@441
|
520 end
|
mmosimca@496
|
521 return tonumber(currency_link:match("currency:(%d+)")) or 0
|
mmosimca@496
|
522 --texture_path:match("[^\\]+$"):lower()
|
MMOSimca@441
|
523 end
|
MMOSimca@441
|
524
|
MMOSimca@441
|
525
|
MMOSimca@441
|
526 local function ItemLinkToID(item_link)
|
MMOSimca@441
|
527 if not item_link then
|
MMOSimca@441
|
528 return
|
MMOSimca@441
|
529 end
|
MMOSimca@441
|
530 return tonumber(tostring(item_link):match("item:(%d+)"))
|
MMOSimca@441
|
531 end
|
MMOSimca@441
|
532
|
MMOSimca@441
|
533 private.ItemLinkToID = ItemLinkToID
|
MMOSimca@441
|
534
|
MMOSimca@441
|
535 local function UnitTypeIsNPC(unit_type)
|
MMOSimca@441
|
536 return unit_type == private.UNIT_TYPES.NPC or unit_type == private.UNIT_TYPES.VEHICLE
|
MMOSimca@441
|
537 end
|
MMOSimca@441
|
538
|
MMOSimca@441
|
539
|
MMOSimca@441
|
540 local ParseGUID
|
MMOSimca@441
|
541 do
|
MMOSimca@441
|
542 local UNIT_TYPES = private.UNIT_TYPES
|
MMOSimca@441
|
543
|
MMOSimca@441
|
544 local NPC_ID_MAPPING = {
|
MMOSimca@441
|
545 [62164] = 63191, -- Garalon
|
MMOSimca@441
|
546 }
|
MMOSimca@441
|
547
|
MMOSimca@441
|
548
|
MMOSimca@441
|
549 local function MatchUnitTypes(unit_type_name)
|
MMOSimca@441
|
550 if not unit_type_name then
|
MMOSimca@441
|
551 return UNIT_TYPES.UNKNOWN
|
MMOSimca@441
|
552 end
|
MMOSimca@441
|
553
|
MMOSimca@441
|
554 for def, text in next, UNIT_TYPES do
|
MMOSimca@441
|
555 if unit_type_name == text then
|
MMOSimca@441
|
556 return UNIT_TYPES[def]
|
MMOSimca@441
|
557 end
|
MMOSimca@441
|
558 end
|
MMOSimca@441
|
559 return UNIT_TYPES.UNKNOWN
|
MMOSimca@441
|
560 end
|
MMOSimca@441
|
561
|
MMOSimca@441
|
562
|
MMOSimca@441
|
563 function ParseGUID(guid)
|
MMOSimca@441
|
564 if not guid then
|
MMOSimca@441
|
565 return
|
MMOSimca@441
|
566 end
|
MMOSimca@441
|
567
|
MMOSimca@441
|
568 -- We might want to use some of this new information later, but leaving the returns alone for now
|
mmosimca@497
|
569 local guid_pieces = { ("-"):split(guid) }
|
mmosimca@497
|
570 local unit_type_name, unk_field, server_id, instance_id, zone_uid, unit_id, spawn_uid, player_uid = guid_pieces[1]
|
MMOSimca@441
|
571
|
MMOSimca@441
|
572 local unit_type = MatchUnitTypes(unit_type_name)
|
mmosimca@518
|
573
|
mmosimca@497
|
574 -- Creatures, GameObjects, Vehicles, and Vignettes
|
MMOSimca@441
|
575 if unit_type ~= UNIT_TYPES.PLAYER and unit_type ~= UNIT_TYPES.PET and unit_type ~= UNIT_TYPES.ITEM then
|
mmosimca@497
|
576 unk_field, server_id, instance_id, zone_uid, unit_id, spawn_uid = guid_pieces[2], guid_pieces[3], guid_pieces[4], guid_pieces[5], guid_pieces[6], guid_pieces[7]
|
mmosimca@497
|
577
|
mmosimca@497
|
578 local id_mapping = NPC_ID_MAPPING[unit_id]
|
MMOSimca@441
|
579
|
MMOSimca@441
|
580 if id_mapping and UnitTypeIsNPC(unit_type) then
|
mmosimca@497
|
581 unit_id = id_mapping
|
MMOSimca@441
|
582 end
|
mmosimca@497
|
583
|
mmosimca@497
|
584 -- Players
|
mmosimca@497
|
585 elseif unit_type == UNIT_TYPES.PLAYER then
|
mmosimca@497
|
586 server_id, player_uid = guid_pieces[2], guid_pieces[3]
|
mmosimca@497
|
587
|
mmosimca@497
|
588 -- Items
|
mmosimca@497
|
589 elseif unit_type == UNIT_TYPES.ITEM then
|
mmosimca@497
|
590 server_id, unk_field, spawn_uid = guid_pieces[2], guid_pieces[3], guid_pieces[4]
|
MMOSimca@441
|
591 end
|
mmosimca@518
|
592
|
mmosimca@497
|
593 -- Pets and other (i.e. do nothing)
|
mmosimca@497
|
594 return unit_type, unit_id
|
MMOSimca@441
|
595 end
|
MMOSimca@441
|
596
|
MMOSimca@441
|
597 private.ParseGUID = ParseGUID
|
MMOSimca@441
|
598 end -- do-block
|
MMOSimca@441
|
599
|
MMOSimca@441
|
600
|
jcallahan@19
|
601 local function HandleItemUse(item_link, bag_index, slot_index)
|
jcallahan@19
|
602 if not item_link then
|
jcallahan@19
|
603 return
|
jcallahan@19
|
604 end
|
jcallahan@19
|
605 local item_id = ItemLinkToID(item_link)
|
jcallahan@19
|
606
|
jcallahan@19
|
607 if not bag_index or not slot_index then
|
jcallahan@19
|
608 for new_bag_index = 0, _G.NUM_BAG_FRAMES do
|
jcallahan@19
|
609 for new_slot_index = 1, _G.GetContainerNumSlots(new_bag_index) do
|
jcallahan@19
|
610 if item_id == ItemLinkToID(_G.GetContainerItemLink(new_bag_index, new_slot_index)) then
|
jcallahan@19
|
611 bag_index = new_bag_index
|
jcallahan@19
|
612 slot_index = new_slot_index
|
jcallahan@19
|
613 break
|
jcallahan@19
|
614 end
|
jcallahan@19
|
615 end
|
jcallahan@19
|
616 end
|
jcallahan@19
|
617 end
|
jcallahan@19
|
618
|
MMOSimca@410
|
619 local any_loot = false
|
MMOSimca@410
|
620
|
MMOSimca@411
|
621 -- Check if Blizzard has marked this item as officially having a chance of containing loot
|
MMOSimca@410
|
622 if bag_index and slot_index then
|
MMOSimca@410
|
623 local _, _, _, _, _, is_lootable = _G.GetContainerItemInfo(bag_index, slot_index)
|
MMOSimca@410
|
624 if is_lootable then
|
MMOSimca@410
|
625 any_loot = true
|
MMOSimca@410
|
626 end
|
jcallahan@19
|
627 end
|
catherton@465
|
628
|
MMOSimca@410
|
629 -- Check if we've marked this item as one Blizzard provides bad is_lootable data for
|
MMOSimca@410
|
630 if private.CONTAINER_ITEM_ID_LIST[item_id] ~= nil then
|
MMOSimca@410
|
631 any_loot = true
|
jcallahan@19
|
632 end
|
MMOSimca@368
|
633
|
MMOSimca@436
|
634 -- Going to block 'chat-loot data' at this level for now because I don't think we actually want normal item containers being recorded in these scenarios either.
|
MMOSimca@436
|
635 if any_loot and not block_chat_loot_data then
|
MMOSimca@414
|
636 -- For item containers that open instantly with no spell cast
|
MMOSimca@410
|
637 if (private.CONTAINER_ITEM_ID_LIST[item_id] == true) and ((not _G.GetNumLootItems()) or (_G.GetNumLootItems() == 0)) then
|
MMOSimca@410
|
638 ClearChatLootData()
|
MMOSimca@410
|
639 Debug("HandleItemUse: Beginning chat-based loot timer for item with ID %d.", item_id)
|
MMOSimca@423
|
640 chat_loot_timer_handle = C_Timer.NewTimer(1.5, ClearChatLootData)
|
MMOSimca@414
|
641 chat_loot_data.identifier = item_id
|
MMOSimca@414
|
642 -- For normal item containers
|
MMOSimca@414
|
643 else
|
MMOSimca@414
|
644 table.wipe(current_action)
|
MMOSimca@414
|
645 current_loot = nil
|
MMOSimca@414
|
646 current_action.target_type = AF.ITEM
|
MMOSimca@414
|
647 current_action.identifier = item_id
|
MMOSimca@414
|
648 current_action.loot_label = "contains"
|
MMOSimca@410
|
649 end
|
MMOSimca@393
|
650 end
|
jcallahan@19
|
651 end
|
jcallahan@19
|
652
|
jcallahan@19
|
653
|
jcallahan@39
|
654 local UnitFactionStanding
|
jcallahan@32
|
655 local UpdateFactionData
|
jcallahan@32
|
656 do
|
jcallahan@32
|
657 local MAX_FACTION_INDEX = 1000
|
jcallahan@20
|
658
|
jcallahan@32
|
659 local STANDING_NAMES = {
|
jcallahan@32
|
660 "HATED",
|
jcallahan@32
|
661 "HOSTILE",
|
jcallahan@32
|
662 "UNFRIENDLY",
|
jcallahan@32
|
663 "NEUTRAL",
|
jcallahan@32
|
664 "FRIENDLY",
|
jcallahan@32
|
665 "HONORED",
|
jcallahan@32
|
666 "REVERED",
|
jcallahan@32
|
667 "EXALTED",
|
jcallahan@32
|
668 }
|
jcallahan@32
|
669
|
jcallahan@39
|
670
|
jcallahan@39
|
671 function UnitFactionStanding(unit)
|
jcallahan@135
|
672 local unit_name = _G.UnitName(unit)
|
jcallahan@39
|
673 UpdateFactionData()
|
jcallahan@39
|
674 DatamineTT:ClearLines()
|
jcallahan@39
|
675 DatamineTT:SetUnit(unit)
|
jcallahan@39
|
676
|
jcallahan@39
|
677 for line_index = 1, DatamineTT:NumLines() do
|
jcallahan@64
|
678 local faction_name = _G["WDPDatamineTTTextLeft" .. line_index]:GetText():trim()
|
jcallahan@39
|
679
|
jcallahan@135
|
680 if faction_name and faction_name ~= unit_name and faction_standings[faction_name] then
|
jcallahan@39
|
681 return faction_name, faction_standings[faction_name]
|
jcallahan@39
|
682 end
|
jcallahan@39
|
683 end
|
jcallahan@39
|
684 end
|
jcallahan@39
|
685
|
jcallahan@39
|
686
|
jcallahan@32
|
687 function UpdateFactionData()
|
jcallahan@32
|
688 for faction_index = 1, MAX_FACTION_INDEX do
|
jcallahan@32
|
689 local faction_name, _, current_standing, _, _, _, _, _, is_header = _G.GetFactionInfo(faction_index)
|
jcallahan@32
|
690
|
jcallahan@86
|
691 if faction_name then
|
jcallahan@32
|
692 faction_standings[faction_name] = STANDING_NAMES[current_standing]
|
jcallahan@32
|
693 elseif not faction_name then
|
jcallahan@32
|
694 break
|
jcallahan@32
|
695 end
|
jcallahan@20
|
696 end
|
jcallahan@20
|
697 end
|
jcallahan@32
|
698 end -- do-block
|
jcallahan@20
|
699
|
jcallahan@48
|
700
|
MMOSimca@429
|
701 local GenericLootUpdate, LootTable
|
jcallahan@75
|
702 do
|
MMOSimca@429
|
703 function LootTable(entry, loot_type, top_field)
|
jcallahan@75
|
704 if top_field then
|
jcallahan@75
|
705 entry[top_field] = entry[top_field] or {}
|
jcallahan@75
|
706 entry[top_field][loot_type] = entry[top_field][loot_type] or {}
|
jcallahan@75
|
707 return entry[top_field][loot_type]
|
jcallahan@75
|
708 end
|
jcallahan@48
|
709 entry[loot_type] = entry[loot_type] or {}
|
jcallahan@75
|
710 return entry[loot_type]
|
jcallahan@48
|
711 end
|
jcallahan@48
|
712
|
jcallahan@75
|
713 function GenericLootUpdate(data_type, top_field)
|
jcallahan@132
|
714 local loot_type = current_loot.label
|
jcallahan@75
|
715 local loot_count = ("%s_count"):format(loot_type)
|
jcallahan@77
|
716 local source_list = {}
|
jcallahan@75
|
717
|
jcallahan@131
|
718 if current_loot.sources then
|
jcallahan@131
|
719 for source_guid, loot_data in pairs(current_loot.sources) do
|
jcallahan@304
|
720 local source_id
|
jcallahan@78
|
721
|
jcallahan@131
|
722 if current_loot.target_type == AF.ITEM then
|
jcallahan@119
|
723 -- Items return the player as the source, so we need to use the item's ID (disenchant, milling, etc)
|
jcallahan@131
|
724 source_id = current_loot.identifier
|
jcallahan@119
|
725 else
|
jcallahan@331
|
726 local _, unit_ID = ParseGUID(source_guid)
|
MMOSimca@328
|
727 if unit_ID then
|
MMOSimca@328
|
728 if current_loot.target_type == AF.OBJECT then
|
MMOSimca@328
|
729 source_id = ("%s:%s"):format(current_loot.spell_label, unit_ID)
|
MMOSimca@328
|
730 else
|
MMOSimca@328
|
731 source_id = unit_ID
|
MMOSimca@328
|
732 end
|
MMOSimca@328
|
733 end
|
jcallahan@119
|
734 end
|
jcallahan@304
|
735 local entry = DBEntry(data_type, source_id)
|
jcallahan@75
|
736
|
jcallahan@119
|
737 if entry then
|
jcallahan@119
|
738 local loot_table = LootTable(entry, loot_type, top_field)
|
jcallahan@77
|
739
|
jcallahan@304
|
740 if not source_list[source_id] then
|
jcallahan@119
|
741 if top_field then
|
jcallahan@119
|
742 entry[top_field][loot_count] = (entry[top_field][loot_count] or 0) + 1
|
MMOSimca@387
|
743 elseif not container_loot_toasting then
|
jcallahan@119
|
744 entry[loot_count] = (entry[loot_count] or 0) + 1
|
jcallahan@119
|
745 end
|
jcallahan@304
|
746 source_list[source_id] = true
|
jcallahan@77
|
747 end
|
jcallahan@119
|
748 UpdateDBEntryLocation(data_type, source_id)
|
jcallahan@75
|
749
|
jcallahan@309
|
750 if current_loot.target_type == AF.ZONE then
|
jcallahan@309
|
751 for item_id, quantity in pairs(loot_data) do
|
jcallahan@309
|
752 table.insert(loot_table, ("%d:%d"):format(item_id, quantity))
|
jcallahan@309
|
753 end
|
jcallahan@309
|
754 else
|
jcallahan@308
|
755 for loot_token, quantity in pairs(loot_data) do
|
mmosimca@496
|
756 local label, currency_id = (":"):split(loot_token)
|
mmosimca@496
|
757
|
mmosimca@496
|
758 if label == "currency" and currency_id then
|
mmosimca@496
|
759 -- Convert currency_id back into number from string
|
mmosimca@496
|
760 currency_id = tonumber(currency_id) or 0
|
mmosimca@496
|
761 if currency_id ~= 0 then
|
mmosimca@496
|
762 table.insert(loot_table, ("currency:%d:%d"):format(quantity, currency_id))
|
mmosimca@496
|
763 end
|
jcallahan@308
|
764 elseif loot_token == "money" then
|
jcallahan@308
|
765 table.insert(loot_table, ("money:%d"):format(quantity))
|
jcallahan@308
|
766 else
|
jcallahan@308
|
767 table.insert(loot_table, ("%d:%d"):format(loot_token, quantity))
|
jcallahan@308
|
768 end
|
jcallahan@308
|
769 end
|
jcallahan@119
|
770 end
|
jcallahan@75
|
771 end
|
jcallahan@75
|
772 end
|
jcallahan@75
|
773 end
|
jcallahan@121
|
774
|
jcallahan@121
|
775 -- This is used for Gas Extractions.
|
jcallahan@131
|
776 if #current_loot.list <= 0 then
|
jcallahan@78
|
777 return
|
jcallahan@78
|
778 end
|
jcallahan@82
|
779 local entry
|
jcallahan@82
|
780
|
jcallahan@82
|
781 -- At this point we only have a name if it's an object.
|
MMOSimca@388
|
782 -- (As of 5.x, the above statement is almost never true, but there are a few cases, like gas extractions.)
|
jcallahan@131
|
783 if current_loot.target_type == AF.OBJECT then
|
jcallahan@131
|
784 entry = DBEntry(data_type, ("%s:%s"):format(current_loot.spell_label, current_loot.object_name))
|
jcallahan@82
|
785 else
|
jcallahan@131
|
786 entry = DBEntry(data_type, current_loot.identifier)
|
jcallahan@82
|
787 end
|
jcallahan@75
|
788
|
jcallahan@75
|
789 if not entry then
|
jcallahan@75
|
790 return
|
jcallahan@75
|
791 end
|
jcallahan@77
|
792 local loot_table = LootTable(entry, loot_type, top_field)
|
jcallahan@77
|
793
|
jcallahan@307
|
794 if current_loot.identifier then
|
jcallahan@307
|
795 if not source_list[current_loot.identifier] then
|
jcallahan@307
|
796 if top_field then
|
jcallahan@307
|
797 entry[top_field][loot_count] = (entry[top_field][loot_count] or 0) + 1
|
jcallahan@307
|
798 else
|
jcallahan@307
|
799 entry[loot_count] = (entry[loot_count] or 0) + 1
|
jcallahan@307
|
800 end
|
jcallahan@307
|
801 source_list[current_loot.identifier] = true
|
jcallahan@77
|
802 end
|
jcallahan@77
|
803 end
|
jcallahan@75
|
804
|
jcallahan@131
|
805 for index = 1, #current_loot.list do
|
jcallahan@131
|
806 table.insert(loot_table, current_loot.list[index])
|
jcallahan@75
|
807 end
|
jcallahan@48
|
808 end
|
jcallahan@75
|
809 end -- do-block
|
jcallahan@48
|
810
|
jcallahan@97
|
811
|
jcallahan@97
|
812 local ReplaceKeywords
|
jcallahan@97
|
813 do
|
jcallahan@97
|
814 local KEYWORD_SUBSTITUTIONS = {
|
jcallahan@97
|
815 class = PLAYER_CLASS,
|
jcallahan@97
|
816 name = PLAYER_NAME,
|
jcallahan@97
|
817 race = PLAYER_RACE,
|
jcallahan@97
|
818 }
|
jcallahan@97
|
819
|
jcallahan@97
|
820
|
jcallahan@97
|
821 function ReplaceKeywords(text)
|
jcallahan@97
|
822 if not text or text == "" then
|
jcallahan@97
|
823 return ""
|
jcallahan@97
|
824 end
|
jcallahan@97
|
825
|
jcallahan@97
|
826 for category, lookup in pairs(KEYWORD_SUBSTITUTIONS) do
|
jcallahan@97
|
827 local category_format = ("<%s>"):format(category)
|
jcallahan@97
|
828 text = text:gsub(lookup, category_format):gsub(lookup:lower(), category_format)
|
jcallahan@97
|
829 end
|
jcallahan@97
|
830 return text
|
jcallahan@97
|
831 end
|
jcallahan@97
|
832 end -- do-block
|
jcallahan@97
|
833
|
jcallahan@97
|
834
|
MMOSimca@347
|
835 -- TIMERS -------------------------------------------------------------
|
MMOSimca@347
|
836
|
MMOSimca@393
|
837 function ClearKilledNPC()
|
MMOSimca@347
|
838 killed_npc_id = nil
|
MMOSimca@347
|
839 end
|
MMOSimca@347
|
840
|
MMOSimca@347
|
841
|
MMOSimca@393
|
842 function ClearKilledBossID()
|
MMOSimca@347
|
843 if killed_boss_id_timer_handle then
|
MMOSimca@383
|
844 killed_boss_id_timer_handle:Cancel()
|
MMOSimca@347
|
845 killed_boss_id_timer_handle = nil
|
MMOSimca@347
|
846 end
|
MMOSimca@347
|
847
|
MMOSimca@347
|
848 table.wipe(boss_loot_toasting)
|
MMOSimca@387
|
849 raid_boss_id = nil
|
MMOSimca@347
|
850 end
|
MMOSimca@347
|
851
|
MMOSimca@347
|
852
|
MMOSimca@393
|
853 function ClearLootToastContainerID()
|
MMOSimca@347
|
854 if loot_toast_container_timer_handle then
|
MMOSimca@383
|
855 loot_toast_container_timer_handle:Cancel()
|
MMOSimca@347
|
856 loot_toast_container_timer_handle = nil
|
MMOSimca@347
|
857 end
|
MMOSimca@347
|
858
|
MMOSimca@387
|
859 container_loot_toasting = false
|
MMOSimca@387
|
860 loot_toast_container_id = nil
|
MMOSimca@347
|
861 end
|
MMOSimca@347
|
862
|
MMOSimca@347
|
863
|
MMOSimca@393
|
864 function ClearLootToastData()
|
MMOSimca@347
|
865 if loot_toast_data_timer_handle then
|
MMOSimca@383
|
866 loot_toast_data_timer_handle:Cancel()
|
MMOSimca@347
|
867 loot_toast_data_timer_handle = nil
|
MMOSimca@347
|
868 end
|
MMOSimca@347
|
869
|
MMOSimca@347
|
870 if loot_toast_data then
|
MMOSimca@347
|
871 table.wipe(loot_toast_data)
|
MMOSimca@347
|
872 end
|
MMOSimca@347
|
873 end
|
MMOSimca@347
|
874
|
MMOSimca@347
|
875
|
MMOSimca@393
|
876 function ClearChatLootData()
|
MMOSimca@398
|
877 if not chat_loot_timer_handle then
|
MMOSimca@435
|
878 table.wipe(chat_loot_data)
|
MMOSimca@398
|
879 return
|
MMOSimca@398
|
880 end
|
MMOSimca@398
|
881 Debug("ClearChatLootData: Ending chat-based loot timer.")
|
MMOSimca@398
|
882 chat_loot_timer_handle:Cancel()
|
MMOSimca@398
|
883 chat_loot_timer_handle = nil
|
MMOSimca@398
|
884
|
MMOSimca@435
|
885 if chat_loot_data.identifier and (private.CONTAINER_ITEM_ID_LIST[chat_loot_data.identifier] ~= nil) and chat_loot_data.loot then
|
MMOSimca@414
|
886 -- A slimmed down (and more importantly, separate) version of GenericLootUpdate, specifically for AF.ITEM and chat_loot_data
|
MMOSimca@414
|
887 local entry = DBEntry("items", chat_loot_data.identifier)
|
MMOSimca@414
|
888
|
MMOSimca@414
|
889 if entry then
|
MMOSimca@414
|
890 local loot_table = LootTable(entry, "contains")
|
MMOSimca@414
|
891 entry["contains_count"] = (entry["contains_count"] or 0) + 1
|
MMOSimca@414
|
892
|
MMOSimca@435
|
893 for loot_token, quantity in pairs(chat_loot_data.loot) do
|
mmosimca@496
|
894 local label, currency_id = (":"):split(loot_token)
|
mmosimca@496
|
895
|
mmosimca@496
|
896 if label == "currency" and currency_id then
|
mmosimca@496
|
897 -- Convert currency_id back into number from string
|
mmosimca@496
|
898 currency_id = tonumber(currency_id) or 0
|
mmosimca@496
|
899 if currency_id ~= 0 then
|
mmosimca@496
|
900 table.insert(loot_table, ("currency:%d:%d"):format(quantity, currency_id))
|
mmosimca@496
|
901 end
|
MMOSimca@414
|
902 elseif loot_token == "money" then
|
MMOSimca@414
|
903 table.insert(loot_table, ("money:%d"):format(quantity))
|
MMOSimca@414
|
904 else
|
MMOSimca@414
|
905 table.insert(loot_table, ("%d:%d"):format(loot_token, quantity))
|
MMOSimca@414
|
906 end
|
MMOSimca@414
|
907 end
|
MMOSimca@414
|
908 end
|
MMOSimca@347
|
909 end
|
MMOSimca@435
|
910 table.wipe(chat_loot_data)
|
MMOSimca@347
|
911 end
|
MMOSimca@347
|
912
|
MMOSimca@347
|
913
|
jcallahan@246
|
914 -- METHODS ------------------------------------------------------------
|
jcallahan@246
|
915
|
jcallahan@0
|
916 function WDP:OnInitialize()
|
jcallahan@128
|
917 local db = LibStub("AceDB-3.0"):New("WoWDBProfilerData", DATABASE_DEFAULTS, "Default")
|
jcallahan@270
|
918 private.db = db
|
jcallahan@128
|
919 global_db = db.global
|
jcallahan@128
|
920 char_db = db.char
|
jcallahan@14
|
921
|
jcallahan@270
|
922 local raw_db = _G.WoWDBProfilerData
|
jcallahan@18
|
923 local build_num = tonumber(private.build_num)
|
mmosimca@485
|
924
|
mmosimca@484
|
925 -- Get current region from LibRealmInfo (and account for the fact that PTR and Beta return nil)
|
mmosimca@484
|
926 local current_region = LibRealmInfo:GetCurrentRegion() or "XX"
|
mmosimca@484
|
927
|
mmosimca@484
|
928 -- Wipe all data if DB version or build number changed
|
jcallahan@136
|
929 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
|
930 for entry in pairs(DATABASE_DEFAULTS.global) do
|
jcallahan@128
|
931 global_db[entry] = {}
|
jcallahan@74
|
932 end
|
jcallahan@74
|
933 end
|
mmosimca@485
|
934 -- Wipe World Quest data if region changed
|
mmosimca@485
|
935 if raw_db.region and raw_db.region ~= current_region and global_db["world_quests"] then
|
mmosimca@485
|
936 global_db["world_quests"] = {}
|
mmosimca@485
|
937 end
|
mmosimca@485
|
938
|
jcallahan@35
|
939 raw_db.build_num = build_num
|
mmosimca@484
|
940 raw_db.region = current_region
|
jcallahan@63
|
941 raw_db.version = DB_VERSION
|
jcallahan@249
|
942
|
jcallahan@312
|
943 private.InitializeCommentSystem()
|
jcallahan@312
|
944 self:RegisterChatCommand("comment", private.ProcessCommentCommand)
|
jcallahan@0
|
945 end
|
jcallahan@0
|
946
|
jcallahan@0
|
947
|
jcallahan@153
|
948 function WDP:EventDispatcher(...)
|
jcallahan@153
|
949 local event_name = ...
|
jcallahan@153
|
950
|
MMOSimca@346
|
951 if DEBUGGING then
|
jcallahan@154
|
952 if event_name == "COMBAT_LOG_EVENT_UNFILTERED" then
|
jcallahan@154
|
953 Debug(event_name)
|
jcallahan@154
|
954 else
|
jcallahan@154
|
955 Debug(...)
|
jcallahan@153
|
956 end
|
jcallahan@153
|
957 end
|
jcallahan@153
|
958 local func = EVENT_MAPPING[event_name]
|
jcallahan@153
|
959
|
mmosimca@522
|
960 if type(func) == "boolean" then
|
jcallahan@153
|
961 self[event_name](self, ...)
|
mmosimca@522
|
962 elseif type(func) == "function" then
|
jcallahan@159
|
963 self[func](self, ...)
|
jcallahan@153
|
964 end
|
jcallahan@153
|
965 end
|
jcallahan@153
|
966
|
jcallahan@153
|
967
|
jcallahan@0
|
968 function WDP:OnEnable()
|
jcallahan@300
|
969 PLAYER_GUID = _G.UnitGUID("player")
|
jcallahan@300
|
970
|
jcallahan@0
|
971 for event_name, mapping in pairs(EVENT_MAPPING) do
|
jcallahan@156
|
972 if EVENT_DEBUG then
|
jcallahan@153
|
973 self:RegisterEvent(event_name, "EventDispatcher")
|
jcallahan@153
|
974 else
|
mmosimca@522
|
975 self:RegisterEvent(event_name, (type(mapping) ~= "boolean") and mapping or nil)
|
jcallahan@153
|
976 end
|
jcallahan@0
|
977 end
|
jcallahan@95
|
978
|
mmosimca@496
|
979 -- Gather known languages
|
jcallahan@95
|
980 for index = 1, _G.GetNumLanguages() do
|
jcallahan@95
|
981 languages_known[_G.GetLanguageByIndex(index)] = true
|
jcallahan@95
|
982 end
|
mmosimca@518
|
983
|
mmosimca@496
|
984 -- Populate currency data from known currency information
|
mmosimca@496
|
985 PopulateCurrencyInfoLookup()
|
MMOSimca@383
|
986
|
mmosimca@485
|
987 -- These timers loop indefinitely using Lua's infinity constant
|
mmosimca@485
|
988 item_process_timer_handle = C_Timer.NewTicker(DELAY_PROCESS_ITEMS, WDP.ProcessItems, math.huge)
|
mmosimca@485
|
989 target_location_timer_handle = C_Timer.NewTicker(DELAY_UPDATE_TARGET_LOCATION, WDP.UpdateTargetLocation, math.huge)
|
mmosimca@485
|
990 world_quest_timer_handle = C_Timer.NewTicker(DELAY_PROCESS_WORLD_QUESTS, WDP.ProcessWorldQuests, math.huge)
|
jcallahan@19
|
991
|
jcallahan@19
|
992 _G.hooksecurefunc("UseContainerItem", function(bag_index, slot_index, target_unit)
|
jcallahan@19
|
993 if target_unit then
|
jcallahan@19
|
994 return
|
jcallahan@19
|
995 end
|
jcallahan@19
|
996 HandleItemUse(_G.GetContainerItemLink(bag_index, slot_index), bag_index, slot_index)
|
jcallahan@19
|
997 end)
|
jcallahan@19
|
998
|
jcallahan@19
|
999 _G.hooksecurefunc("UseItemByName", function(identifier, target_unit)
|
jcallahan@19
|
1000 if target_unit then
|
jcallahan@19
|
1001 return
|
jcallahan@19
|
1002 end
|
jcallahan@19
|
1003 local _, item_link = _G.GetItemInfo(identifier)
|
jcallahan@19
|
1004 HandleItemUse(item_link)
|
jcallahan@19
|
1005 end)
|
jcallahan@263
|
1006
|
jcallahan@290
|
1007 self:GROUP_ROSTER_UPDATE()
|
jcallahan@0
|
1008 end
|
jcallahan@0
|
1009
|
jcallahan@0
|
1010
|
mmosimca@485
|
1011 -- Record data for a specific quest ID; reward data must be available or nothing will be recorded
|
mmosimca@485
|
1012 -- When we reach this point, we've already checked for a valid mapID, questID, quest data, and worldQuestType
|
mmosimca@485
|
1013 local function RecordWorldQuestData(world_map_id, quest_id, api_data_table)
|
mmosimca@485
|
1014
|
mmosimca@485
|
1015 -- Ensure we have location data and rewards (barely readable so putting it on multiple lines)
|
mmosimca@487
|
1016 -- (Honor is built in to the quest; it is not a sign rewards have been loaded)
|
mmosimca@485
|
1017 if not api_data_table.x or not api_data_table.y or not api_data_table.floor or not
|
mmosimca@485
|
1018 (_G.GetQuestLogRewardXP(quest_id) > 0 or _G.GetNumQuestLogRewardCurrencies(quest_id) > 0
|
mmosimca@485
|
1019 or _G.GetNumQuestLogRewards(quest_id) > 0 or _G.GetQuestLogRewardMoney(quest_id) > 0
|
mmosimca@487
|
1020 or _G.GetQuestLogRewardArtifactXP(quest_id) > 0) then
|
mmosimca@485
|
1021 return
|
mmosimca@485
|
1022 end
|
mmosimca@485
|
1023
|
mmosimca@485
|
1024 local entry = DBEntry("world_quests", quest_id)
|
mmosimca@485
|
1025
|
mmosimca@485
|
1026 if entry then
|
mmosimca@485
|
1027
|
mmosimca@485
|
1028 -- Record location
|
mmosimca@485
|
1029 entry["location"] = {}
|
mmosimca@485
|
1030 entry["location"]["world_map_id"] = world_map_id
|
mmosimca@485
|
1031 entry["location"]["x"] = (tonumber(api_data_table.x) or 0) * 100
|
mmosimca@485
|
1032 entry["location"]["y"] = (tonumber(api_data_table.y) or 0) * 100
|
mmosimca@485
|
1033 entry["location"]["floor"] = tonumber(api_data_table.floor) or 0
|
mmosimca@485
|
1034
|
mmosimca@485
|
1035 -- Record simple rewards (XP, money, artifact XP, honor)
|
mmosimca@485
|
1036 entry["rewards"] = {}
|
mmosimca@485
|
1037 entry["rewards"]["xp"] = tonumber(_G.GetQuestLogRewardXP(quest_id)) or 0
|
mmosimca@485
|
1038 entry["rewards"]["money"] = tonumber(_G.GetQuestLogRewardMoney(quest_id)) or 0
|
mmosimca@485
|
1039 local actualXP, scaling = _G.GetQuestLogRewardArtifactXP(quest_id)
|
mmosimca@485
|
1040 entry["rewards"]["artifact_xp"] = ("%d:%d"):format(tonumber(actualXP) or 0, tonumber(scaling) or 0)
|
mmosimca@485
|
1041 entry["rewards"]["honor"] = tonumber(_G.GetQuestLogRewardHonor(quest_id)) or 0
|
mmosimca@485
|
1042
|
mmosimca@485
|
1043 -- Record currencies
|
mmosimca@485
|
1044 entry["rewards"]["currency_count"] = tonumber(_G.GetNumQuestLogRewardCurrencies(quest_id)) or 0
|
mmosimca@485
|
1045
|
mmosimca@496
|
1046 -- Create currency rewards sub-table and fill
|
mmosimca@485
|
1047 if entry["rewards"]["currency_count"] > 0 then
|
mmosimca@485
|
1048 entry["rewards"]["currencies"] = {}
|
mmosimca@485
|
1049 for i = 1, entry["rewards"]["currency_count"] do
|
mmosimca@503
|
1050 local name, texture_path, quantity, currency_id = _G.GetQuestLogRewardCurrencyInfo(i, quest_id)
|
mmosimca@503
|
1051 table.insert(entry["rewards"]["currencies"], ("%d:%d"):format(quantity, currency_id))
|
mmosimca@485
|
1052 end
|
mmosimca@485
|
1053 end
|
mmosimca@485
|
1054
|
mmosimca@485
|
1055 -- Record items
|
mmosimca@485
|
1056 entry["rewards"]["item_count"] = tonumber(_G.GetNumQuestLogRewards(quest_id)) or 0
|
mmosimca@485
|
1057
|
mmosimca@496
|
1058 -- Create item rewards sub-table and fill
|
mmosimca@485
|
1059 if entry["rewards"]["item_count"] > 0 then
|
mmosimca@485
|
1060 entry["rewards"]["items"] = {}
|
mmosimca@485
|
1061 for i = 1, entry["rewards"]["item_count"] do
|
mmosimca@485
|
1062 local item_name, item_texture, quantity, quality, is_usable, item_id = _G.GetQuestLogRewardInfo(i, quest_id)
|
mmosimca@485
|
1063 table.insert(entry["rewards"]["items"], ("%d:%d"):format(item_id, quantity))
|
mmosimca@485
|
1064 end
|
mmosimca@485
|
1065 end
|
mmosimca@485
|
1066
|
mmosimca@485
|
1067 -- Record time remaining
|
mmosimca@485
|
1068 entry["estimated_end_time"] = _G.GetServerTime() + ((_G.C_TaskQuest.GetQuestTimeLeftMinutes(quest_id) or 0) * 60)
|
mmosimca@485
|
1069 end
|
mmosimca@485
|
1070 end
|
mmosimca@485
|
1071
|
mmosimca@485
|
1072
|
mmosimca@485
|
1073 function WDP:ProcessWorldQuests()
|
mmosimca@485
|
1074 -- Ignore if player is low level
|
mmosimca@485
|
1075 if _G.UnitLevel("player") ~= 110 then return end
|
mmosimca@485
|
1076
|
mmosimca@485
|
1077 local current_world_map_id = _G.GetCurrentMapAreaID()
|
mmosimca@485
|
1078
|
mmosimca@485
|
1079 -- Iterate over known World Quest maps
|
mmosimca@485
|
1080 for i = 1, #private.WORLD_QUEST_MAP_IDS do
|
mmosimca@485
|
1081 local world_map_id = private.WORLD_QUEST_MAP_IDS[i]
|
mmosimca@485
|
1082
|
mmosimca@485
|
1083 -- Only bother checking the API if the world map in question is currently displayed OR its continent is currently displayed
|
mmosimca@485
|
1084 if current_world_map_id == WORLD_MAP_ID_BROKEN_ISLES or current_world_map_id == world_map_id then
|
mmosimca@485
|
1085
|
mmosimca@485
|
1086 -- Get data for World Quests on map
|
mmosimca@485
|
1087 local api_data = _G.C_TaskQuest.GetQuestsForPlayerByMapID(world_map_id)
|
mmosimca@485
|
1088
|
mmosimca@485
|
1089 -- Iterate over the questIDs for each map, doing preload reward requests and creating SavedVariables entries
|
mmosimca@485
|
1090 if api_data and type(api_data) == "table" and #api_data > 0 then
|
mmosimca@485
|
1091 for j = 1, #api_data do
|
mmosimca@485
|
1092 local current_data = api_data[j]
|
mmosimca@485
|
1093
|
mmosimca@485
|
1094 -- Check if we had a valid API table returned to us
|
mmosimca@485
|
1095 if current_data and type(current_data) == "table" and current_data["questId"] then
|
mmosimca@485
|
1096 local quest_id = tonumber(current_data["questId"]) or 0
|
mmosimca@485
|
1097
|
mmosimca@485
|
1098 -- Check if we have quest data
|
mmosimca@485
|
1099 if _G.HaveQuestData(quest_id) then
|
mmosimca@485
|
1100 local tag_id, tag_name, world_quest_type, rarity, is_elite, tradeskill_line_index = _G.GetQuestTagInfo(quest_id)
|
mmosimca@485
|
1101
|
mmosimca@485
|
1102 -- Check for valid questID and whether or not it is a World Quest
|
mmosimca@485
|
1103 if quest_id > 0 and world_quest_type ~= nil then
|
mmosimca@485
|
1104 _G.C_TaskQuest.RequestPreloadRewardData(quest_id)
|
mmosimca@485
|
1105 RecordWorldQuestData(world_map_id, quest_id, current_data)
|
mmosimca@485
|
1106 end
|
mmosimca@485
|
1107 end
|
mmosimca@485
|
1108 end
|
mmosimca@485
|
1109 end
|
mmosimca@485
|
1110 end
|
mmosimca@485
|
1111 end
|
mmosimca@485
|
1112 end
|
mmosimca@485
|
1113 end
|
mmosimca@485
|
1114
|
mmosimca@485
|
1115
|
MMOSimca@340
|
1116 local function RecordItemData(item_id, item_link, process_bonus_ids, durability)
|
jcallahan@331
|
1117 local _, _, item_string = item_link:find("^|%x+|H(.+)|h%[.+%]")
|
jcallahan@219
|
1118 local item
|
jcallahan@0
|
1119
|
jcallahan@191
|
1120 if item_string then
|
MMOSimca@338
|
1121 local item_results = { (":"):split(item_string) }
|
MMOSimca@338
|
1122
|
MMOSimca@460
|
1123 local suffix_id = tonumber(item_results[8]) or 0
|
MMOSimca@462
|
1124 local unique_id = tonumber(item_results[9]) or 0
|
MMOSimca@447
|
1125 --local level = tonumber(item_results[10])
|
MMOSimca@460
|
1126 --local specialization_id = tonumber(item_results[11])
|
catherton@469
|
1127 --local upgrade_type_id = tonumber(item_results[12])
|
MMOSimca@460
|
1128 local instance_difficulty_id = tonumber(item_results[13]) or 0
|
MMOSimca@460
|
1129 local num_bonus_ids = tonumber(item_results[14]) or 0
|
catherton@471
|
1130 -- upgrade_value is optional in 6.2! can be detected using upgrade_type_id, but it's just as easy to check like this
|
catherton@469
|
1131 local upgrade_value = tonumber(item_results[15 + num_bonus_ids]) or 0
|
catherton@465
|
1132
|
mmosimca@484
|
1133 local unk_item_field_1 = tonumber(item_results[16 + num_bonus_ids]) or 0
|
mmosimca@484
|
1134 local unk_item_field_2 = tonumber(item_results[17 + num_bonus_ids]) or 0
|
mmosimca@484
|
1135 --if unk_item_field_1 > 0 then Debug("unk_item_field_1 for %s is non-zero, specifically %d.", item_link, unk_item_field_1) end
|
mmosimca@484
|
1136 --if unk_item_field_2 > 0 then Debug("unk_item_field_2 for %s is non-zero, specifically %d.", item_link, unk_item_field_2) end
|
MMOSimca@460
|
1137
|
MMOSimca@460
|
1138 -- If there is anything special (non-zero) for this item then we need to make note of everything
|
catherton@471
|
1139 if math.max(suffix_id, instance_difficulty_id, num_bonus_ids, upgrade_value) ~= 0 then
|
MMOSimca@460
|
1140 item = DBEntry("items", item_id)
|
MMOSimca@460
|
1141 item.suffix_id = suffix_id
|
MMOSimca@460
|
1142 item.unique_id = bit.band(unique_id, 0xFFFF)
|
MMOSimca@460
|
1143 item.instance_difficulty_id = instance_difficulty_id
|
catherton@471
|
1144 item.upgrade_value = upgrade_value
|
MMOSimca@460
|
1145
|
MMOSimca@460
|
1146 if process_bonus_ids then
|
MMOSimca@460
|
1147
|
MMOSimca@460
|
1148 -- Get ready for bonus IDs
|
MMOSimca@384
|
1149 if not item.seen_bonuses then
|
MMOSimca@384
|
1150 item.seen_bonuses = {}
|
MMOSimca@372
|
1151 end
|
catherton@465
|
1152
|
MMOSimca@460
|
1153 if num_bonus_ids > 0 then
|
MMOSimca@460
|
1154 -- We want the bonus ID combo output to be in the form ["bonusID1:bonusID2:bonusID3"] = true
|
MMOSimca@460
|
1155 -- And sorted numerically with the smallest bonusID first
|
MMOSimca@460
|
1156 local sorted_bonus_string = ""
|
MMOSimca@460
|
1157 local min_bonus_id_array = {}
|
MMOSimca@460
|
1158 for iterations = 1, num_bonus_ids do
|
MMOSimca@460
|
1159 -- Find minimum of this iteration
|
MMOSimca@460
|
1160 local min_bonus_id = 100000
|
MMOSimca@460
|
1161 for bonus_index = 1, num_bonus_ids do
|
MMOSimca@460
|
1162 local temp_bonus_id = tonumber(item_results[14 + bonus_index])
|
MMOSimca@460
|
1163 if temp_bonus_id and (not min_bonus_id_array[temp_bonus_id]) and (temp_bonus_id < min_bonus_id) then
|
MMOSimca@460
|
1164 min_bonus_id = temp_bonus_id
|
MMOSimca@460
|
1165 end
|
MMOSimca@460
|
1166 end
|
MMOSimca@460
|
1167
|
MMOSimca@460
|
1168 -- Keep track of already processed IDs
|
MMOSimca@460
|
1169 min_bonus_id_array[min_bonus_id] = true
|
MMOSimca@460
|
1170
|
MMOSimca@460
|
1171 -- Build string
|
MMOSimca@460
|
1172 if iterations == 1 then
|
MMOSimca@460
|
1173 sorted_bonus_string = sorted_bonus_string .. tostring(min_bonus_id)
|
MMOSimca@460
|
1174 else
|
MMOSimca@460
|
1175 sorted_bonus_string = sorted_bonus_string .. ":" .. tostring(min_bonus_id)
|
MMOSimca@460
|
1176 end
|
MMOSimca@384
|
1177 end
|
MMOSimca@460
|
1178
|
MMOSimca@460
|
1179 item.seen_bonuses[sorted_bonus_string] = true
|
MMOSimca@460
|
1180 Debug("RecordItemData: Recorded bonus IDs %s for item %d.", sorted_bonus_string, item_id)
|
MMOSimca@384
|
1181 else
|
MMOSimca@460
|
1182 item.seen_bonuses["0"] = true
|
MMOSimca@384
|
1183 end
|
MMOSimca@329
|
1184 end
|
jcallahan@191
|
1185 end
|
jcallahan@0
|
1186 end
|
jcallahan@212
|
1187
|
jcallahan@212
|
1188 if durability and durability > 0 then
|
jcallahan@219
|
1189 item = item or DBEntry("items", item_id)
|
jcallahan@212
|
1190 item.durability = durability
|
jcallahan@212
|
1191 end
|
jcallahan@0
|
1192 end
|
jcallahan@0
|
1193
|
jcallahan@0
|
1194
|
jcallahan@187
|
1195 function WDP:ProcessItems()
|
jcallahan@187
|
1196 for slot_index = _G.INVSLOT_FIRST_EQUIPPED, _G.INVSLOT_LAST_EQUIPPED do
|
jcallahan@1
|
1197 local item_id = _G.GetInventoryItemID("player", slot_index)
|
jcallahan@0
|
1198
|
jcallahan@0
|
1199 if item_id and item_id > 0 then
|
jcallahan@1
|
1200 local _, max_durability = _G.GetInventoryItemDurability(slot_index)
|
MMOSimca@340
|
1201 RecordItemData(item_id, _G.GetInventoryItemLink("player", slot_index), false, max_durability)
|
jcallahan@0
|
1202 end
|
jcallahan@0
|
1203 end
|
jcallahan@0
|
1204
|
jcallahan@0
|
1205 for bag_index = 0, _G.NUM_BAG_SLOTS do
|
jcallahan@0
|
1206 for slot_index = 1, _G.GetContainerNumSlots(bag_index) do
|
jcallahan@1
|
1207 local item_id = _G.GetContainerItemID(bag_index, slot_index)
|
jcallahan@0
|
1208
|
jcallahan@0
|
1209 if item_id and item_id > 0 then
|
jcallahan@1
|
1210 local _, max_durability = _G.GetContainerItemDurability(bag_index, slot_index)
|
MMOSimca@340
|
1211 RecordItemData(item_id, _G.GetContainerItemLink(bag_index, slot_index), false, max_durability)
|
jcallahan@0
|
1212 end
|
jcallahan@0
|
1213 end
|
jcallahan@0
|
1214 end
|
jcallahan@0
|
1215 end
|
jcallahan@0
|
1216
|
jcallahan@118
|
1217
|
jcallahan@215
|
1218 local TargetedNPC
|
jcallahan@118
|
1219 do
|
jcallahan@118
|
1220 local GENDER_NAMES = {
|
jcallahan@118
|
1221 "UNKNOWN",
|
jcallahan@118
|
1222 "MALE",
|
jcallahan@118
|
1223 "FEMALE",
|
jcallahan@118
|
1224 }
|
jcallahan@118
|
1225
|
jcallahan@118
|
1226
|
jcallahan@118
|
1227 local REACTION_NAMES = {
|
jcallahan@118
|
1228 "HATED",
|
jcallahan@118
|
1229 "HOSTILE",
|
jcallahan@118
|
1230 "UNFRIENDLY",
|
jcallahan@118
|
1231 "NEUTRAL",
|
jcallahan@118
|
1232 "FRIENDLY",
|
jcallahan@118
|
1233 "HONORED",
|
jcallahan@118
|
1234 "REVERED",
|
jcallahan@118
|
1235 "EXALTED",
|
jcallahan@118
|
1236 }
|
jcallahan@118
|
1237
|
jcallahan@118
|
1238
|
mmosimca@496
|
1239 -- We should just use IDs here someday; WoWDB site knows all about different power types
|
jcallahan@118
|
1240 local POWER_TYPE_NAMES = {
|
jcallahan@118
|
1241 ["0"] = "MANA",
|
jcallahan@118
|
1242 ["1"] = "RAGE",
|
jcallahan@118
|
1243 ["2"] = "FOCUS",
|
jcallahan@118
|
1244 ["3"] = "ENERGY",
|
jcallahan@118
|
1245 ["6"] = "RUNIC_POWER",
|
jcallahan@118
|
1246 }
|
jcallahan@118
|
1247
|
jcallahan@118
|
1248
|
jcallahan@215
|
1249 function TargetedNPC()
|
jcallahan@118
|
1250 if not _G.UnitExists("target") or _G.UnitPlayerControlled("target") or currently_drunk then
|
jcallahan@118
|
1251 current_target_id = nil
|
jcallahan@118
|
1252 return
|
jcallahan@118
|
1253 end
|
jcallahan@118
|
1254 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("target"))
|
jcallahan@118
|
1255
|
jcallahan@171
|
1256 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
jcallahan@118
|
1257 return
|
jcallahan@118
|
1258 end
|
jcallahan@118
|
1259 current_target_id = unit_idnum
|
jcallahan@118
|
1260
|
jcallahan@118
|
1261 local npc = NPCEntry(unit_idnum)
|
jcallahan@118
|
1262 local _, class_token = _G.UnitClass("target")
|
jcallahan@118
|
1263 npc.class = class_token
|
jcallahan@118
|
1264 npc.faction = UnitFactionStanding("target")
|
jcallahan@118
|
1265 npc.genders = npc.genders or {}
|
jcallahan@118
|
1266 npc.genders[GENDER_NAMES[_G.UnitSex("target")] or "UNDEFINED"] = true
|
jcallahan@118
|
1267 npc.is_pvp = _G.UnitIsPVP("target") and true or nil
|
jcallahan@118
|
1268 npc.reaction = ("%s:%s:%s"):format(_G.UnitLevel("player"), _G.UnitFactionGroup("player"), REACTION_NAMES[_G.UnitReaction("player", "target")])
|
jcallahan@118
|
1269
|
jcallahan@248
|
1270 local encounter_data = npc:EncounterData(InstanceDifficultyToken()).stats
|
jcallahan@118
|
1271 local npc_level = ("level_%d"):format(_G.UnitLevel("target"))
|
jcallahan@250
|
1272 local level_data = encounter_data[npc_level]
|
jcallahan@250
|
1273
|
jcallahan@250
|
1274 if not level_data then
|
jcallahan@250
|
1275 level_data = {}
|
jcallahan@250
|
1276 encounter_data[npc_level] = level_data
|
jcallahan@250
|
1277 end
|
jcallahan@257
|
1278 level_data.max_health = level_data.max_health or _G.UnitHealthMax("target")
|
jcallahan@257
|
1279
|
mmosimca@496
|
1280 -- May not capture as much data as it could, since the API changed in Legion to report multiple types of power
|
jcallahan@257
|
1281 if not level_data.power then
|
MMOSimca@337
|
1282 local max_power = _G.UnitPowerMax("target")
|
jcallahan@257
|
1283
|
jcallahan@257
|
1284 if max_power > 0 then
|
jcallahan@257
|
1285 local power_type = _G.UnitPowerType("target")
|
jcallahan@312
|
1286 level_data.power = ("%s:%d"):format(POWER_TYPE_NAMES[tostring(power_type)] or power_type, max_power)
|
jcallahan@257
|
1287 end
|
jcallahan@118
|
1288 end
|
jcallahan@118
|
1289 name_to_id_map[_G.UnitName("target")] = unit_idnum
|
jcallahan@118
|
1290 return npc, unit_idnum
|
jcallahan@118
|
1291 end
|
jcallahan@118
|
1292 end -- do-block
|
jcallahan@118
|
1293
|
jcallahan@118
|
1294
|
jcallahan@113
|
1295 do
|
jcallahan@113
|
1296 local COORD_MAX = 5
|
jcallahan@0
|
1297
|
jcallahan@113
|
1298 function WDP:UpdateTargetLocation()
|
catherton@480
|
1299 if currently_drunk or not _G.UnitExists("target") or _G.UnitPlayerControlled("target") or (_G.UnitIsTapDenied("target") and not _G.UnitIsDead("target")) then
|
jcallahan@2
|
1300 return
|
jcallahan@2
|
1301 end
|
jcallahan@113
|
1302
|
jcallahan@113
|
1303 for index = 1, 4 do
|
jcallahan@113
|
1304 if not _G.CheckInteractDistance("target", index) then
|
jcallahan@113
|
1305 return
|
jcallahan@113
|
1306 end
|
jcallahan@113
|
1307 end
|
jcallahan@215
|
1308 local npc = TargetedNPC()
|
jcallahan@113
|
1309
|
jcallahan@113
|
1310 if not npc then
|
jcallahan@113
|
1311 return
|
jcallahan@113
|
1312 end
|
jcallahan@113
|
1313 local zone_name, area_id, x, y, map_level, difficulty_token = CurrentLocationData()
|
MMOSimca@328
|
1314 if not (zone_name and area_id and x and y and map_level) then
|
mmosimca@508
|
1315 if not (_G.IsInInstance()) then
|
mmosimca@508
|
1316 Debug("UpdateTargetLocation: Missing current location data - %s, %s, %s, %s, %s.", tostring(zone_name), tostring(area_id), tostring(x), tostring(y), tostring(map_level))
|
mmosimca@508
|
1317 end
|
MMOSimca@328
|
1318 return
|
MMOSimca@328
|
1319 end
|
jcallahan@248
|
1320 local npc_data = npc:EncounterData(difficulty_token).stats[("level_%d"):format(_G.UnitLevel("target"))]
|
jcallahan@113
|
1321 local zone_token = ("%s:%d"):format(zone_name, area_id)
|
jcallahan@118
|
1322 npc_data.locations = npc_data.locations or {} -- TODO: Fix this. It is broken. Possibly something to do with the timed updates.
|
jcallahan@113
|
1323
|
jcallahan@113
|
1324 local zone_data = npc_data.locations[zone_token]
|
jcallahan@113
|
1325
|
jcallahan@113
|
1326 if not zone_data then
|
jcallahan@113
|
1327 zone_data = {}
|
jcallahan@113
|
1328 npc_data.locations[zone_token] = zone_data
|
jcallahan@113
|
1329 end
|
jcallahan@113
|
1330
|
jcallahan@113
|
1331 for location_token in pairs(zone_data) do
|
jcallahan@113
|
1332 local loc_level, loc_x, loc_y = (":"):split(location_token)
|
jcallahan@113
|
1333 loc_level = tonumber(loc_level)
|
jcallahan@113
|
1334
|
jcallahan@113
|
1335 if map_level == loc_level and math.abs(x - loc_x) <= COORD_MAX and math.abs(y - loc_y) <= COORD_MAX then
|
jcallahan@113
|
1336 return
|
jcallahan@113
|
1337 end
|
jcallahan@113
|
1338 end
|
jcallahan@141
|
1339 zone_data[("%d:%d:%d"):format(map_level, x, y)] = true
|
jcallahan@2
|
1340 end
|
jcallahan@113
|
1341 end -- do-block
|
jcallahan@2
|
1342
|
jcallahan@118
|
1343
|
MMOSimca@412
|
1344 function WDP:HandleBadChatLootData(...)
|
MMOSimca@398
|
1345 ClearChatLootData()
|
MMOSimca@398
|
1346 end
|
MMOSimca@398
|
1347
|
MMOSimca@398
|
1348
|
MMOSimca@420
|
1349 -- EVENT HANDLERS -----------------------------------------------------
|
MMOSimca@420
|
1350
|
MMOSimca@436
|
1351 -- This function (and the following function) are to stop 'HandleItemUse' from triggering when you put an item that would normally be opened into the bank, guild bank, etc.
|
MMOSimca@436
|
1352 function WDP:StopChatLootRecording(event_name)
|
MMOSimca@436
|
1353 if not block_chat_loot_data then
|
MMOSimca@439
|
1354 Debug("%s: Pausing chat-based loot recording.", event_name)
|
MMOSimca@436
|
1355 ClearChatLootData()
|
MMOSimca@436
|
1356 block_chat_loot_data = true
|
MMOSimca@436
|
1357 end
|
MMOSimca@436
|
1358 end
|
MMOSimca@436
|
1359
|
MMOSimca@436
|
1360
|
MMOSimca@436
|
1361 function WDP:ResumeChatLootRecording(event_name)
|
MMOSimca@436
|
1362 if block_chat_loot_data then
|
MMOSimca@439
|
1363 Debug("%s: Resuming chat-based loot recording.", event_name)
|
MMOSimca@436
|
1364 block_chat_loot_data = false
|
MMOSimca@436
|
1365 end
|
MMOSimca@436
|
1366 end
|
MMOSimca@436
|
1367
|
MMOSimca@436
|
1368
|
mmosimca@485
|
1369 -- Process world quests if the map is moved to the Broken Isles continent world map (this provides us an opportunity to get data for all zones on the continent without moving the map)
|
mmosimca@485
|
1370 function WDP:WORLD_MAP_UPATE(event_name)
|
mmosimca@485
|
1371 if _G.GetCurrentMapAreaID() == WORLD_MAP_ID_BROKEN_ISLES and _G.GetServerTime() > (world_quest_event_timestamp + DELAY_PROCESS_WORLD_QUESTS) then
|
mmosimca@485
|
1372 world_quest_event_timestamp = _G.GetServerTime()
|
mmosimca@485
|
1373 WDP:ProcessWorldQuests()
|
mmosimca@485
|
1374 end
|
mmosimca@485
|
1375 end
|
mmosimca@485
|
1376
|
mmosimca@485
|
1377
|
MMOSimca@408
|
1378 -- For now, bonus roll data only pollutes the true drop percentages. We still want to capture the data from SPELL_CONFIRMATION_PROMPT because of legendary quest items though.
|
MMOSimca@408
|
1379 function WDP:BONUS_ROLL_RESULT(event_name)
|
MMOSimca@408
|
1380 Debug("%s: Bonus roll detected; stopping loot recording for this boss to avoid recording bonus loot.", event_name)
|
MMOSimca@408
|
1381 ClearKilledBossID()
|
MMOSimca@408
|
1382 ClearLootToastContainerID()
|
MMOSimca@408
|
1383 end
|
MMOSimca@408
|
1384
|
MMOSimca@408
|
1385
|
jcallahan@90
|
1386 function WDP:BLACK_MARKET_ITEM_UPDATE(event_name)
|
jcallahan@243
|
1387 if not ALLOWED_LOCALES[CLIENT_LOCALE] then
|
jcallahan@243
|
1388 return
|
jcallahan@243
|
1389 end
|
jcallahan@282
|
1390 local num_items = _G.C_BlackMarket.GetNumItems() or 0
|
jcallahan@56
|
1391
|
jcallahan@56
|
1392 for index = 1, num_items do
|
jcallahan@56
|
1393 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
|
1394
|
jcallahan@56
|
1395 if item_link then
|
jcallahan@56
|
1396 DBEntry("items", ItemLinkToID(item_link)).black_market = seller_name or "UNKNOWN"
|
jcallahan@56
|
1397 end
|
jcallahan@56
|
1398 end
|
jcallahan@56
|
1399 end
|
jcallahan@56
|
1400
|
jcallahan@56
|
1401
|
jcallahan@298
|
1402 local function UpdateUnitPet(unit_guid, unit_id)
|
jcallahan@246
|
1403 local current_pet_guid = group_owner_guids_to_pet_guids[unit_guid]
|
jcallahan@246
|
1404
|
jcallahan@246
|
1405 if current_pet_guid then
|
jcallahan@246
|
1406 group_owner_guids_to_pet_guids[unit_guid] = nil
|
jcallahan@246
|
1407 group_pet_guids[current_pet_guid] = nil
|
jcallahan@246
|
1408 end
|
jcallahan@246
|
1409 local pet_guid = _G.UnitGUID(unit_id .. "pet")
|
jcallahan@246
|
1410
|
jcallahan@246
|
1411 if pet_guid then
|
jcallahan@296
|
1412 group_owner_guids_to_pet_guids[unit_guid] = pet_guid
|
jcallahan@246
|
1413 group_pet_guids[pet_guid] = true
|
jcallahan@246
|
1414 end
|
jcallahan@246
|
1415 end
|
jcallahan@246
|
1416
|
jcallahan@246
|
1417
|
jcallahan@298
|
1418 function WDP:GROUP_ROSTER_UPDATE(event_name)
|
jcallahan@298
|
1419 local is_raid = _G.IsInRaid()
|
jcallahan@298
|
1420 local unit_type = is_raid and "raid" or "party"
|
jcallahan@298
|
1421 local group_size = is_raid and _G.GetNumGroupMembers() or _G.GetNumSubgroupMembers()
|
jcallahan@298
|
1422
|
jcallahan@299
|
1423 table.wipe(group_member_guids)
|
jcallahan@298
|
1424
|
jcallahan@298
|
1425 for index = 1, group_size do
|
jcallahan@298
|
1426 local unit_id = unit_type .. index
|
jcallahan@298
|
1427 local unit_guid = _G.UnitGUID(unit_id)
|
jcallahan@298
|
1428
|
jcallahan@299
|
1429 group_member_guids[unit_guid] = true
|
jcallahan@298
|
1430 UpdateUnitPet(unit_guid, unit_id)
|
jcallahan@298
|
1431 end
|
jcallahan@299
|
1432 group_member_guids[PLAYER_GUID] = true
|
jcallahan@298
|
1433 end
|
jcallahan@298
|
1434
|
jcallahan@298
|
1435
|
jcallahan@298
|
1436 function WDP:UNIT_PET(event_name, unit_id)
|
jcallahan@298
|
1437 UpdateUnitPet(_G.UnitGUID(unit_id), unit_id)
|
jcallahan@298
|
1438 end
|
jcallahan@298
|
1439
|
jcallahan@298
|
1440
|
MMOSimca@375
|
1441 function WDP:SHOW_LOOT_TOAST(event_name, loot_type, item_link, quantity, spec_ID, sex_ID, is_personal, loot_source)
|
jcallahan@312
|
1442 if not loot_type or (loot_type ~= "item" and loot_type ~= "money" and loot_type ~= "currency") then
|
jcallahan@306
|
1443 Debug("%s: loot_type is %s. Item link is %s, and quantity is %d.", event_name, loot_type, item_link, quantity)
|
jcallahan@306
|
1444 return
|
jcallahan@306
|
1445 end
|
MMOSimca@372
|
1446
|
MMOSimca@372
|
1447 -- Need information on the most recent args, so using this complete debug statement for now
|
MMOSimca@375
|
1448 Debug("%s: loot_type: %s, item_link: %s, quantity: %s, spec_ID: %s, sex_ID: %s, is_personal: %s, loot_source: %s", event_name, loot_type, item_link, quantity, spec_ID, sex_ID, is_personal, loot_source)
|
MMOSimca@372
|
1449
|
MMOSimca@355
|
1450 -- Handle Garrison cache specially
|
MMOSimca@422
|
1451 if loot_source and (loot_source == LOOT_SOURCE_ID_GARRISON_CACHE) and last_garrison_cache_object_id then
|
MMOSimca@355
|
1452 -- Record location data for cache
|
MMOSimca@355
|
1453 UpdateDBEntryLocation("objects", ("OPENING:%d"):format(last_garrison_cache_object_id))
|
MMOSimca@355
|
1454
|
MMOSimca@355
|
1455 -- Add drop data
|
mmosimca@496
|
1456 local currency_id = CurrencyLinkToID(item_link)
|
mmosimca@496
|
1457 if currency_id and currency_id ~= 0 then
|
MMOSimca@355
|
1458 -- Check for top level object data
|
MMOSimca@355
|
1459 local object_entry = DBEntry("objects", ("OPENING:%d"):format(last_garrison_cache_object_id))
|
MMOSimca@355
|
1460 local difficulty_token = InstanceDifficultyToken()
|
MMOSimca@355
|
1461 if object_entry[difficulty_token] then
|
MMOSimca@355
|
1462 -- Increment loot count
|
MMOSimca@355
|
1463 object_entry[difficulty_token]["opening_count"] = (object_entry[difficulty_token]["opening_count"] or 0) + 1
|
MMOSimca@355
|
1464
|
mmosimca@496
|
1465 Debug("%s: %d X %d", event_name, currency_id, quantity)
|
MMOSimca@355
|
1466 object_entry[difficulty_token]["opening"] = object_entry[difficulty_token]["opening"] or {}
|
mmosimca@496
|
1467 table.insert(object_entry[difficulty_token]["opening"], ("currency:%d:%d"):format(quantity, currency_id))
|
MMOSimca@355
|
1468 else
|
MMOSimca@355
|
1469 Debug("%s: When handling the Garrison cache, the top level loot data was missing for objectID %d.", event_name, last_garrison_cache_object_id)
|
MMOSimca@355
|
1470 end
|
MMOSimca@355
|
1471 else
|
mmosimca@496
|
1472 Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
|
MMOSimca@355
|
1473 end
|
catherton@465
|
1474
|
MMOSimca@431
|
1475 -- Wipe object ID until future mouseover
|
MMOSimca@431
|
1476 last_garrison_cache_object_id = nil
|
MMOSimca@387
|
1477 elseif raid_boss_id then
|
MMOSimca@427
|
1478 local npc = NPCEntry(raid_boss_id)
|
MMOSimca@427
|
1479 if npc then
|
MMOSimca@427
|
1480 local loot_label = "drops"
|
MMOSimca@427
|
1481 local encounter_data = npc:EncounterData(InstanceDifficultyToken())
|
MMOSimca@427
|
1482 encounter_data[loot_label] = encounter_data[loot_label] or {}
|
MMOSimca@427
|
1483 encounter_data.loot_counts = encounter_data.loot_counts or {}
|
MMOSimca@427
|
1484
|
MMOSimca@427
|
1485 if loot_type == "item" then
|
MMOSimca@427
|
1486 local item_id = ItemLinkToID(item_link)
|
MMOSimca@427
|
1487 if item_id then
|
MMOSimca@427
|
1488 Debug("%s: %s X %d (%d)", event_name, item_link, quantity, item_id)
|
MMOSimca@427
|
1489 RecordItemData(item_id, item_link, true)
|
MMOSimca@427
|
1490 table.insert(encounter_data[loot_label], ("%d:%d"):format(item_id, quantity))
|
MMOSimca@427
|
1491 else
|
MMOSimca@427
|
1492 Debug("%s: ItemID is nil, from item link %s", event_name, item_link)
|
MMOSimca@427
|
1493 return
|
MMOSimca@427
|
1494 end
|
MMOSimca@427
|
1495 elseif loot_type == "money" then
|
MMOSimca@427
|
1496 Debug("%s: money X %d", event_name, quantity)
|
MMOSimca@427
|
1497 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
|
MMOSimca@427
|
1498 elseif loot_type == "currency" then
|
mmosimca@496
|
1499 local currency_id = CurrencyLinkToID(item_link)
|
mmosimca@496
|
1500 if currency_id and currency_id ~= 0 then
|
mmosimca@496
|
1501 Debug("%s: %d X %d", event_name, currency_id, quantity)
|
mmosimca@496
|
1502 table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
|
MMOSimca@427
|
1503 else
|
mmosimca@496
|
1504 Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
|
MMOSimca@427
|
1505 return
|
MMOSimca@427
|
1506 end
|
jcallahan@312
|
1507 end
|
jcallahan@317
|
1508
|
MMOSimca@427
|
1509 if not boss_loot_toasting[raid_boss_id] then
|
MMOSimca@427
|
1510 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
|
MMOSimca@427
|
1511 boss_loot_toasting[raid_boss_id] = true -- Do not count further loots until timer expires or another boss is killed
|
jcallahan@312
|
1512 end
|
jcallahan@312
|
1513 end
|
MMOSimca@387
|
1514 elseif loot_toast_container_id then
|
jcallahan@305
|
1515 InitializeCurrentLoot()
|
jcallahan@305
|
1516
|
jcallahan@306
|
1517 -- Fake the loot characteristics to match that of an actual container item
|
MMOSimca@387
|
1518 current_loot.identifier = loot_toast_container_id
|
jcallahan@306
|
1519 current_loot.label = "contains"
|
jcallahan@306
|
1520 current_loot.target_type = AF.ITEM
|
jcallahan@306
|
1521
|
MMOSimca@387
|
1522 current_loot.sources[loot_toast_container_id] = current_loot.sources[loot_toast_container_id] or {}
|
jcallahan@312
|
1523
|
jcallahan@301
|
1524 if loot_type == "item" then
|
jcallahan@312
|
1525 local item_id = ItemLinkToID(item_link)
|
jcallahan@312
|
1526 if item_id then
|
jcallahan@312
|
1527 Debug("%s: %s X %d (%d)", event_name, item_link, quantity, item_id)
|
MMOSimca@340
|
1528 RecordItemData(item_id, item_link, true)
|
MMOSimca@387
|
1529 current_loot.sources[loot_toast_container_id][item_id] = (current_loot.sources[loot_toast_container_id][item_id] or 0) + quantity
|
jcallahan@312
|
1530 else
|
jcallahan@301
|
1531 Debug("%s: ItemID is nil, from item link %s", event_name, item_link)
|
jcallahan@312
|
1532 current_loot = nil
|
jcallahan@301
|
1533 return
|
jcallahan@301
|
1534 end
|
jcallahan@301
|
1535 elseif loot_type == "money" then
|
jcallahan@312
|
1536 Debug("%s: money X %d", event_name, quantity)
|
MMOSimca@387
|
1537 current_loot.sources[loot_toast_container_id]["money"] = (current_loot.sources[loot_toast_container_id]["money"] or 0) + quantity
|
jcallahan@312
|
1538 elseif loot_type == "currency" then
|
mmosimca@496
|
1539 local currency_id = CurrencyLinkToID(item_link)
|
mmosimca@496
|
1540 if currency_id and currency_id ~= 0 then
|
mmosimca@496
|
1541 Debug("%s: %d X %d", event_name, currency_id, quantity)
|
mmosimca@496
|
1542 local currency_token = ("currency:%d"):format(currency_id)
|
MMOSimca@387
|
1543 current_loot.sources[loot_toast_container_id][currency_token] = (current_loot.sources[loot_toast_container_id][currency_token] or 0) + quantity
|
jcallahan@312
|
1544 else
|
mmosimca@496
|
1545 Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
|
jcallahan@312
|
1546 current_loot = nil
|
jcallahan@312
|
1547 return
|
jcallahan@312
|
1548 end
|
jcallahan@301
|
1549 end
|
jcallahan@312
|
1550
|
jcallahan@301
|
1551 GenericLootUpdate("items")
|
jcallahan@301
|
1552 current_loot = nil
|
MMOSimca@387
|
1553 container_loot_toasting = true -- Do not count further loots until timer expires or another container is opened
|
MMOSimca@444
|
1554 elseif loot_source and (loot_source == LOOT_SOURCE_ID_REDUNDANT) and chat_loot_timer_handle then
|
MMOSimca@444
|
1555 -- Handle currency loot toasts for chat-based loot (we do this instead of reading currency chat messages because the chat messages are very delayed)
|
MMOSimca@444
|
1556 if loot_type == "currency" then
|
mmosimca@496
|
1557 local currency_id = CurrencyLinkToID(item_link)
|
mmosimca@496
|
1558 if currency_id and currency_id ~= 0 then
|
MMOSimca@444
|
1559 -- Verify that we're still assigning data to the right items
|
MMOSimca@444
|
1560 if chat_loot_data.identifier and (private.CONTAINER_ITEM_ID_LIST[chat_loot_data.identifier] ~= nil) then
|
mmosimca@496
|
1561 Debug("%s: Captured currency for chat-based loot recording. %d X %d", event_name, currency_id, quantity)
|
mmosimca@496
|
1562 local currency_token = ("currency:%d"):format(currency_id)
|
MMOSimca@444
|
1563 chat_loot_data.loot = chat_loot_data.loot or {}
|
MMOSimca@444
|
1564 chat_loot_data.loot[currency_token] = (chat_loot_data.loot[currency_token] or 0) + quantity
|
MMOSimca@444
|
1565 else -- If not, cancel the timer and wipe the loot table early
|
MMOSimca@444
|
1566 Debug("%s: Canceled chat-based loot recording because we would have assigned the wrong loot!", event_name)
|
MMOSimca@444
|
1567 ClearChatLootData()
|
MMOSimca@444
|
1568 end
|
MMOSimca@444
|
1569 else
|
mmosimca@496
|
1570 Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
|
MMOSimca@444
|
1571 end
|
MMOSimca@444
|
1572 -- Handle money loot toasts for chat-based loot (we do this instead of reading money chat messages because the chat messages are very delayed)
|
MMOSimca@444
|
1573 elseif loot_type == "money" then
|
MMOSimca@424
|
1574 -- Verify that we're still assigning data to the right items
|
MMOSimca@435
|
1575 if chat_loot_data.identifier and (private.CONTAINER_ITEM_ID_LIST[chat_loot_data.identifier] ~= nil) then
|
MMOSimca@444
|
1576 Debug("%s: Captured money for chat-based loot recording. money X %d", event_name, quantity)
|
MMOSimca@435
|
1577 chat_loot_data.loot = chat_loot_data.loot or {}
|
MMOSimca@444
|
1578 chat_loot_data.loot["money"] = (chat_loot_data.loot["money"] or 0) + quantity
|
MMOSimca@424
|
1579 else -- If not, cancel the timer and wipe the loot table early
|
MMOSimca@424
|
1580 Debug("%s: Canceled chat-based loot recording because we would have assigned the wrong loot!", event_name)
|
MMOSimca@424
|
1581 ClearChatLootData()
|
MMOSimca@424
|
1582 end
|
MMOSimca@424
|
1583 end
|
jcallahan@301
|
1584 else
|
jcallahan@307
|
1585 Debug("%s: NPC and Container are nil, storing loot toast data for 5 seconds.", event_name)
|
jcallahan@307
|
1586
|
jcallahan@307
|
1587 loot_toast_data = loot_toast_data or {}
|
jcallahan@312
|
1588 loot_toast_data[#loot_toast_data + 1] = { loot_type, item_link, quantity }
|
jcallahan@307
|
1589
|
MMOSimca@340
|
1590 local item_id = ItemLinkToID(item_link)
|
MMOSimca@340
|
1591 if item_id then
|
MMOSimca@340
|
1592 RecordItemData(item_id, item_link, true)
|
MMOSimca@340
|
1593 end
|
MMOSimca@340
|
1594
|
MMOSimca@383
|
1595 loot_toast_data_timer_handle = C_Timer.NewTimer(5, ClearLootToastData)
|
jcallahan@178
|
1596 end
|
jcallahan@178
|
1597 end
|
jcallahan@178
|
1598
|
jcallahan@178
|
1599
|
jcallahan@179
|
1600 do
|
MMOSimca@388
|
1601 local CHAT_MSG_CURRENCY_UPDATE_FUNCS = {
|
mmosimca@496
|
1602 [AF.NPC] = function(currency_id, quantity)
|
mmosimca@496
|
1603 Debug("CHAT_MSG_CURRENCY: AF.NPC currency:%d (%d)", currency_id, quantity)
|
MMOSimca@388
|
1604 end,
|
mmosimca@496
|
1605 [AF.ZONE] = function(currency_id, quantity)
|
mmosimca@496
|
1606 Debug("CHAT_MSG_CURRENCY: AF.ZONE currency:%d (%d)", currency_id, quantity)
|
MMOSimca@388
|
1607 InitializeCurrentLoot()
|
mmosimca@496
|
1608 current_loot.list[1] = ("currency:%d:%d"):format(quantity, currency_id)
|
MMOSimca@388
|
1609 GenericLootUpdate("zones")
|
MMOSimca@388
|
1610 current_loot = nil
|
MMOSimca@388
|
1611 end,
|
MMOSimca@388
|
1612 }
|
MMOSimca@388
|
1613
|
MMOSimca@388
|
1614
|
MMOSimca@388
|
1615 function WDP:CHAT_MSG_CURRENCY(event_name, message)
|
MMOSimca@388
|
1616 local category
|
MMOSimca@388
|
1617
|
MMOSimca@388
|
1618 local currency_link, quantity = deformat(message, _G.CURRENCY_GAINED_MULTIPLE)
|
MMOSimca@388
|
1619 if not currency_link then
|
MMOSimca@388
|
1620 quantity, currency_link = 1, deformat(message, _G.CURRENCY_GAINED)
|
MMOSimca@388
|
1621 end
|
mmosimca@496
|
1622 local currency_id = CurrencyLinkToID(currency_link)
|
mmosimca@496
|
1623
|
mmosimca@496
|
1624 if not currency_id or currency_id == 0 then
|
MMOSimca@388
|
1625 return
|
MMOSimca@388
|
1626 end
|
MMOSimca@388
|
1627
|
MMOSimca@388
|
1628 -- Set update category
|
MMOSimca@388
|
1629 if current_action.spell_label == "FISHING" then
|
MMOSimca@388
|
1630 category = AF.ZONE
|
MMOSimca@388
|
1631 elseif raid_boss_id then
|
MMOSimca@388
|
1632 category = AF.NPC
|
MMOSimca@388
|
1633 end
|
MMOSimca@388
|
1634
|
MMOSimca@388
|
1635 -- Take action based on update category
|
MMOSimca@388
|
1636 local update_func = CHAT_MSG_CURRENCY_UPDATE_FUNCS[category]
|
MMOSimca@388
|
1637 if not category or not update_func then
|
MMOSimca@388
|
1638 return
|
MMOSimca@388
|
1639 end
|
mmosimca@496
|
1640 update_func(currency_id, quantity)
|
MMOSimca@388
|
1641 end
|
MMOSimca@388
|
1642
|
MMOSimca@388
|
1643
|
MMOSimca@412
|
1644 local BLACKLISTED_ITEMS = {
|
MMOSimca@412
|
1645 [114116] = true,
|
MMOSimca@412
|
1646 [114119] = true,
|
MMOSimca@412
|
1647 [114120] = true,
|
MMOSimca@412
|
1648 [116980] = true,
|
MMOSimca@412
|
1649 [120319] = true,
|
MMOSimca@412
|
1650 [120320] = true,
|
catherton@475
|
1651 [139593] = true,
|
catherton@475
|
1652 [139594] = true,
|
catherton@475
|
1653 [140590] = true,
|
MMOSimca@412
|
1654 }
|
MMOSimca@412
|
1655
|
MMOSimca@412
|
1656
|
jcallahan@179
|
1657 local CHAT_MSG_LOOT_UPDATE_FUNCS = {
|
MMOSimca@347
|
1658 [AF.ITEM] = function(item_id, quantity)
|
MMOSimca@347
|
1659 -- Verify that we're still assigning data to the right items
|
MMOSimca@435
|
1660 if chat_loot_data.identifier and (private.CONTAINER_ITEM_ID_LIST[chat_loot_data.identifier] ~= nil) then
|
MMOSimca@347
|
1661 Debug("CHAT_MSG_LOOT: AF.ITEM %d (%d)", item_id, quantity)
|
MMOSimca@435
|
1662 chat_loot_data.loot = chat_loot_data.loot or {}
|
MMOSimca@435
|
1663 chat_loot_data.loot[item_id] = (chat_loot_data.loot[item_id] or 0) + quantity
|
MMOSimca@347
|
1664 else -- If not, cancel the timer and wipe the loot table early
|
MMOSimca@387
|
1665 Debug("CHAT_MSG_LOOT: We would have assigned the wrong loot!")
|
MMOSimca@387
|
1666 ClearChatLootData()
|
MMOSimca@347
|
1667 end
|
MMOSimca@347
|
1668 end,
|
jcallahan@179
|
1669 [AF.NPC] = function(item_id, quantity)
|
MMOSimca@345
|
1670 Debug("CHAT_MSG_LOOT: AF.NPC %d (%d)", item_id, quantity)
|
MMOSimca@345
|
1671 end,
|
MMOSimca@345
|
1672 [AF.OBJECT] = function(item_id, quantity)
|
MMOSimca@345
|
1673 Debug("CHAT_MSG_LOOT: AF.OBJECT %d (%d)", item_id, quantity)
|
MMOSimca@381
|
1674 -- Check for top level object data
|
MMOSimca@381
|
1675 local object_entry = DBEntry("objects", ("OPENING:%s"):format(private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[last_timber_spell_id]))
|
MMOSimca@381
|
1676 local difficulty_token = InstanceDifficultyToken()
|
MMOSimca@381
|
1677 if object_entry[difficulty_token] then
|
MMOSimca@381
|
1678 -- Increment loot count
|
MMOSimca@381
|
1679 object_entry[difficulty_token]["opening_count"] = (object_entry[difficulty_token]["opening_count"] or 0) + 1
|
MMOSimca@381
|
1680
|
MMOSimca@381
|
1681 -- Add drop data
|
MMOSimca@381
|
1682 object_entry[difficulty_token]["opening"] = object_entry[difficulty_token]["opening"] or {}
|
MMOSimca@381
|
1683 table.insert(object_entry[difficulty_token]["opening"], ("%d:%d"):format(item_id, quantity))
|
MMOSimca@381
|
1684 else
|
MMOSimca@381
|
1685 Debug("CHAT_MSG_LOOT: When handling timber, the top level data was missing for objectID %s.", private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[last_timber_spell_id])
|
MMOSimca@381
|
1686 end
|
jcallahan@179
|
1687 end,
|
jcallahan@179
|
1688 [AF.ZONE] = function(item_id, quantity)
|
MMOSimca@345
|
1689 Debug("CHAT_MSG_LOOT: AF.ZONE %d (%d)", item_id, quantity)
|
jcallahan@312
|
1690 InitializeCurrentLoot()
|
jcallahan@312
|
1691 current_loot.list[1] = ("%d:%d"):format(item_id, quantity)
|
jcallahan@179
|
1692 GenericLootUpdate("zones")
|
jcallahan@312
|
1693 current_loot = nil
|
jcallahan@179
|
1694 end,
|
jcallahan@179
|
1695 }
|
jcallahan@177
|
1696
|
jcallahan@177
|
1697
|
MMOSimca@388
|
1698 function WDP:CHAT_MSG_LOOT(event_name, message)
|
jcallahan@179
|
1699 local category
|
jcallahan@177
|
1700
|
MMOSimca@345
|
1701 local item_link, quantity = deformat(message, _G.LOOT_ITEM_PUSHED_SELF_MULTIPLE)
|
MMOSimca@345
|
1702 if not item_link then
|
MMOSimca@345
|
1703 quantity, item_link = 1, deformat(message, _G.LOOT_ITEM_PUSHED_SELF)
|
MMOSimca@345
|
1704 end
|
MMOSimca@345
|
1705 local item_id = ItemLinkToID(item_link)
|
MMOSimca@345
|
1706
|
MMOSimca@345
|
1707 if not item_id then
|
MMOSimca@345
|
1708 return
|
MMOSimca@345
|
1709 end
|
MMOSimca@345
|
1710
|
MMOSimca@345
|
1711 -- Set update category
|
MMOSimca@405
|
1712 if last_timber_spell_id and item_id == ITEM_ID_TIMBER then
|
MMOSimca@345
|
1713 category = AF.OBJECT
|
MMOSimca@345
|
1714 -- Recently changed from ~= "EXTRACT_GAS" because of some occassional bad data, and, as far as I know, no benefit.
|
MMOSimca@345
|
1715 elseif current_action.spell_label == "FISHING" then
|
jcallahan@179
|
1716 category = AF.ZONE
|
MMOSimca@388
|
1717 elseif raid_boss_id then
|
jcallahan@179
|
1718 category = AF.NPC
|
MMOSimca@347
|
1719 elseif chat_loot_timer_handle then
|
MMOSimca@347
|
1720 category = AF.ITEM
|
jcallahan@179
|
1721 end
|
MMOSimca@345
|
1722
|
MMOSimca@395
|
1723 -- We still want to record the item's data, even if it doesn't need its drop location recorded
|
MMOSimca@395
|
1724 RecordItemData(item_id, item_link, true)
|
MMOSimca@395
|
1725
|
MMOSimca@345
|
1726 -- Take action based on update category
|
jcallahan@179
|
1727 local update_func = CHAT_MSG_LOOT_UPDATE_FUNCS[category]
|
MMOSimca@412
|
1728 if not category or not update_func or BLACKLISTED_ITEMS[item_id] then
|
MMOSimca@340
|
1729 return
|
MMOSimca@340
|
1730 end
|
jcallahan@179
|
1731 update_func(item_id, quantity)
|
jcallahan@177
|
1732 end
|
MMOSimca@388
|
1733 end
|
MMOSimca@388
|
1734
|
MMOSimca@388
|
1735
|
jcallahan@97
|
1736 function WDP:RecordQuote(event_name, message, source_name, language_name)
|
jcallahan@112
|
1737 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
|
1738 return
|
jcallahan@95
|
1739 end
|
jcallahan@97
|
1740 local npc = NPCEntry(name_to_id_map[source_name])
|
jcallahan@97
|
1741 npc.quotes = npc.quotes or {}
|
jcallahan@97
|
1742 npc.quotes[event_name] = npc.quotes[event_name] or {}
|
jcallahan@97
|
1743 npc.quotes[event_name][ReplaceKeywords(message)] = true
|
jcallahan@97
|
1744 end
|
jcallahan@95
|
1745
|
jcallahan@95
|
1746
|
jcallahan@95
|
1747 do
|
jcallahan@40
|
1748 local SOBER_MATCH = _G.DRUNK_MESSAGE_ITEM_SELF1:gsub("%%s", ".+")
|
jcallahan@40
|
1749
|
jcallahan@40
|
1750 local DRUNK_COMPARES = {
|
jcallahan@40
|
1751 _G.DRUNK_MESSAGE_SELF2,
|
jcallahan@40
|
1752 _G.DRUNK_MESSAGE_SELF3,
|
jcallahan@40
|
1753 _G.DRUNK_MESSAGE_SELF4,
|
jcallahan@40
|
1754 }
|
jcallahan@40
|
1755
|
jcallahan@40
|
1756 local DRUNK_MATCHES = {
|
jcallahan@254
|
1757 (_G.DRUNK_MESSAGE_SELF2:gsub("%%s", ".+")),
|
jcallahan@254
|
1758 (_G.DRUNK_MESSAGE_SELF3:gsub("%%s", ".+")),
|
jcallahan@254
|
1759 (_G.DRUNK_MESSAGE_SELF4:gsub("%%s", ".+")),
|
jcallahan@40
|
1760 }
|
jcallahan@40
|
1761
|
jcallahan@167
|
1762 local RECIPE_MATCH = _G.ERR_LEARN_RECIPE_S:gsub("%%s", "(.*)")
|
jcallahan@167
|
1763
|
jcallahan@167
|
1764
|
jcallahan@167
|
1765 local function RecordDiscovery(tradeskill_name, tradeskill_index)
|
jcallahan@167
|
1766 if tradeskill_name == private.discovered_recipe_name then
|
catherton@479
|
1767 DBEntry("spells", tonumber(_G.C_TradeSkillUI.GetRecipeLink(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
|
1768
|
jcallahan@167
|
1769 private.discovered_recipe_name = nil
|
jcallahan@167
|
1770 private.profession_level = nil
|
jcallahan@167
|
1771 private.previous_spell_id = nil
|
jcallahan@169
|
1772
|
jcallahan@169
|
1773 return true
|
jcallahan@167
|
1774 end
|
jcallahan@167
|
1775 end
|
jcallahan@167
|
1776
|
jcallahan@167
|
1777
|
jcallahan@167
|
1778 local function IterativeRecordDiscovery()
|
jcallahan@167
|
1779 TradeSkillExecutePer(RecordDiscovery)
|
jcallahan@167
|
1780 end
|
jcallahan@167
|
1781
|
jcallahan@167
|
1782
|
jcallahan@92
|
1783 function WDP:CHAT_MSG_SYSTEM(event_name, message)
|
mmosimca@514
|
1784 -- This code no longer works, as of Patch 7.0.3, because Blizzard unified the text from quest rewards and loot to match (and now there is no way to distinguish between them)
|
catherton@472
|
1785 local item_link, quantity = deformat(message, ERR_QUEST_REWARD_ITEM_MULT_IS)
|
MMOSimca@400
|
1786 if not item_link then
|
catherton@472
|
1787 quantity, item_link = 1, deformat(message, ERR_QUEST_REWARD_ITEM_S)
|
MMOSimca@400
|
1788 end
|
MMOSimca@400
|
1789 local item_id = ItemLinkToID(item_link)
|
MMOSimca@400
|
1790
|
mmosimca@514
|
1791 if item_id then
|
mmosimca@514
|
1792 -- If it was a quest message (that we can decode), parse its link
|
mmosimca@514
|
1793 RecordItemData(item_id, item_link, true)
|
mmosimca@514
|
1794 else
|
mmosimca@514
|
1795 -- If it isn't a quest message, check the other uses of system messages
|
MMOSimca@400
|
1796 if not private.trainer_shown then
|
MMOSimca@400
|
1797 local recipe_name = message:match(RECIPE_MATCH)
|
MMOSimca@400
|
1798
|
MMOSimca@400
|
1799 if recipe_name and private.previous_spell_id then
|
catherton@479
|
1800 local profession_name, prof_level = _G.C_TradeSkillUI.GetTradeSkillLine()
|
MMOSimca@400
|
1801
|
MMOSimca@400
|
1802 if profession_name == _G.UNKNOWN then
|
MMOSimca@400
|
1803 return
|
MMOSimca@400
|
1804 end
|
MMOSimca@400
|
1805 private.discovered_recipe_name = recipe_name
|
MMOSimca@400
|
1806 private.profession_level = prof_level
|
MMOSimca@400
|
1807
|
MMOSimca@400
|
1808 C_Timer.After(0.2, IterativeRecordDiscovery)
|
jcallahan@167
|
1809 end
|
jcallahan@167
|
1810 end
|
MMOSimca@400
|
1811
|
MMOSimca@400
|
1812 if currently_drunk then
|
MMOSimca@400
|
1813 if message == _G.DRUNK_MESSAGE_SELF1 or message:match(SOBER_MATCH) then
|
MMOSimca@400
|
1814 currently_drunk = nil
|
MMOSimca@400
|
1815 end
|
MMOSimca@400
|
1816 return
|
MMOSimca@400
|
1817 end
|
MMOSimca@400
|
1818
|
MMOSimca@400
|
1819 for index = 1, #DRUNK_MATCHES do
|
MMOSimca@400
|
1820 if message == DRUNK_COMPARES[index] or message:match(DRUNK_MATCHES[index]) then
|
MMOSimca@400
|
1821 currently_drunk = true
|
MMOSimca@400
|
1822 break
|
MMOSimca@400
|
1823 end
|
jcallahan@40
|
1824 end
|
jcallahan@40
|
1825 end
|
jcallahan@40
|
1826 end
|
jcallahan@40
|
1827 end
|
jcallahan@40
|
1828
|
jcallahan@307
|
1829
|
jcallahan@331
|
1830 do
|
jcallahan@23
|
1831 local FLAGS_NPC = bit.bor(_G.COMBATLOG_OBJECT_TYPE_GUARDIAN, _G.COMBATLOG_OBJECT_CONTROL_NPC)
|
jcallahan@23
|
1832 local FLAGS_NPC_CONTROL = bit.bor(_G.COMBATLOG_OBJECT_AFFILIATION_OUTSIDER, _G.COMBATLOG_OBJECT_CONTROL_NPC)
|
jcallahan@23
|
1833
|
MMOSimca@458
|
1834 -- Spells that are cast by players/NPCs that are mistakely assigned as being cast by the target; must be blacklisted
|
MMOSimca@405
|
1835 local BLACKLISTED_SPELLS = {
|
MMOSimca@458
|
1836 [117526] = true, -- Binding Shot (cast by Hunters)
|
MMOSimca@458
|
1837 [121308] = true, -- Disguise (cast by Rogues)
|
MMOSimca@458
|
1838 [132464] = true, -- Chi Wave (cast by Monks)
|
MMOSimca@458
|
1839 [132467] = true, -- Chi Wave (cast by Monks)
|
MMOSimca@460
|
1840 [167432] = true, -- Savagery (cast by Warsong Commander)
|
MMOSimca@460
|
1841 [175077] = true, -- Fearsome Battle Standard (cast by Fearsome Battle Standard item)
|
MMOSimca@458
|
1842 [176813] = true, -- Itchy Spores (cast by Marsh Creatures in Ashran)
|
MMOSimca@458
|
1843 [183901] = true, -- Stolen Strength (cast by Felblood NPCs in Tanaan Jungle)
|
MMOSimca@458
|
1844 [183904] = true, -- Stolen Speed (cast by Felblood NPCs in Tanaan Jungle)
|
MMOSimca@458
|
1845 [183907] = true, -- Stolen Fervor (cast by Felblood NPCs in Tanaan Jungle)
|
mmosimca@495
|
1846 [195802] = true, -- Moonkin Feather (applied by Moonfeather Statue; first stage buff)
|
mmosimca@495
|
1847 [195805] = true, -- Moonkin Molting (applied by Moonfeather Statue; second stage buff)
|
mmosimca@495
|
1848 [195810] = true, -- Feeling Moonkin (applied by Moonfeather Statue; third stage buff)
|
mmosimca@495
|
1849 [195816] = true, -- Owlvercome wth the Fever (applied by Moonfeather Statue; final stage buff)
|
catherton@474
|
1850 [213738] = true, -- Taste of Blood (applied by Fate and Fortune, Combat Rogue artifacts)
|
mmosimca@483
|
1851 [213877] = true, -- Vampiric Aura (used by Nathrezim Invasion bosses and transformed players)
|
catherton@474
|
1852 [215377] = true, -- The Maw Must Feed (applied by Maw of the Damned, Blood Death Knight artifact)
|
mmosimca@499
|
1853 [218136] = true, -- Arcane Invigoration (cast by Duskwatch Rune Scribes in The Arcway)
|
catherton@470
|
1854 [224762] = true, -- Leyline Rift (summoned by players with Leyline Mastery in Suramar)
|
catherton@474
|
1855 [225832] = true, -- Nightglow Wisp (cast by players using Wisp in a Bottle toy)
|
MMOSimca@405
|
1856 }
|
MMOSimca@405
|
1857
|
jcallahan@23
|
1858 local function RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
|
MMOSimca@405
|
1859 if not spell_id or BLACKLISTED_SPELLS[spell_id] then
|
jcallahan@23
|
1860 return
|
jcallahan@23
|
1861 end
|
jcallahan@34
|
1862 local source_type, source_id = ParseGUID(source_guid)
|
jcallahan@23
|
1863
|
jcallahan@171
|
1864 if not source_id or not UnitTypeIsNPC(source_type) then
|
jcallahan@23
|
1865 return
|
jcallahan@23
|
1866 end
|
jcallahan@23
|
1867
|
jcallahan@23
|
1868 if bit.band(FLAGS_NPC_CONTROL, source_flags) == FLAGS_NPC_CONTROL and bit.band(FLAGS_NPC, source_flags) ~= 0 then
|
jcallahan@248
|
1869 local encounter_data = NPCEntry(source_id):EncounterData(InstanceDifficultyToken())
|
jcallahan@28
|
1870 encounter_data.spells = encounter_data.spells or {}
|
jcallahan@28
|
1871 encounter_data.spells[spell_id] = (encounter_data.spells[spell_id] or 0) + 1
|
jcallahan@23
|
1872 end
|
jcallahan@23
|
1873 end
|
jcallahan@23
|
1874
|
jcallahan@115
|
1875 local HEAL_BATTLE_PETS_SPELL_ID = 125801
|
jcallahan@115
|
1876
|
jcallahan@246
|
1877 local previous_combat_event = {}
|
jcallahan@246
|
1878
|
jcallahan@23
|
1879 local COMBAT_LOG_FUNCS = {
|
jcallahan@23
|
1880 SPELL_AURA_APPLIED = RecordNPCSpell,
|
jcallahan@23
|
1881 SPELL_CAST_START = RecordNPCSpell,
|
jcallahan@115
|
1882 SPELL_CAST_SUCCESS = function(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
|
jcallahan@115
|
1883 if spell_id == HEAL_BATTLE_PETS_SPELL_ID then
|
jcallahan@115
|
1884 local unit_type, unit_idnum = ParseGUID(source_guid)
|
jcallahan@115
|
1885
|
jcallahan@171
|
1886 if unit_idnum and UnitTypeIsNPC(unit_type) then
|
jcallahan@115
|
1887 NPCEntry(unit_idnum).stable_master = true
|
jcallahan@115
|
1888 end
|
jcallahan@115
|
1889 end
|
jcallahan@115
|
1890 RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
|
jcallahan@115
|
1891 end,
|
jcallahan@65
|
1892 UNIT_DIED = function(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
|
jcallahan@65
|
1893 local unit_type, unit_idnum = ParseGUID(dest_guid)
|
jcallahan@65
|
1894
|
jcallahan@171
|
1895 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
mmosimca@515
|
1896 --Debug("%s: %s is not an NPC, or has no ID.", sub_event, dest_name or _G.UNKNOWN) -- we really don't need to know this
|
jcallahan@177
|
1897 ClearKilledNPC()
|
jcallahan@98
|
1898 private.harvesting = nil
|
jcallahan@65
|
1899 return
|
jcallahan@65
|
1900 end
|
jcallahan@177
|
1901
|
jcallahan@246
|
1902 if source_guid == "" then
|
jcallahan@246
|
1903 source_guid = nil
|
jcallahan@246
|
1904 end
|
jcallahan@246
|
1905 local killer_guid = source_guid or previous_combat_event.source_guid
|
jcallahan@246
|
1906 local killer_name = source_name or previous_combat_event.source_name
|
jcallahan@246
|
1907
|
jcallahan@299
|
1908 if not previous_combat_event.party_damage then
|
jcallahan@312
|
1909 --Debug("%s: %s was killed by %s (not group member or pet).", sub_event, dest_name or _G.UNKNOWN, killer_name or _G.UNKNOWN) -- broken in Patch 5.4
|
jcallahan@299
|
1910 table.wipe(previous_combat_event)
|
jcallahan@217
|
1911 ClearKilledNPC()
|
jcallahan@306
|
1912 else
|
jcallahan@317
|
1913 --Debug("%s: %s was killed by %s.", sub_event, dest_name or _G.UNKNOWN, killer_name or _G.UNKNOWN) -- broken in Patch 5.4
|
jcallahan@177
|
1914 end
|
jcallahan@177
|
1915 killed_npc_id = unit_idnum
|
MMOSimca@383
|
1916 C_Timer.After(0.1, ClearKilledNPC)
|
jcallahan@65
|
1917 end,
|
jcallahan@23
|
1918 }
|
jcallahan@23
|
1919
|
jcallahan@23
|
1920
|
jcallahan@246
|
1921 local NON_DAMAGE_EVENTS = {
|
jcallahan@246
|
1922 SPELL_AURA_APPLIED = true,
|
jcallahan@246
|
1923 SPELL_AURA_REMOVED = true,
|
jcallahan@246
|
1924 SPELL_AURA_REMOVED_DOSE = true,
|
jcallahan@246
|
1925 SPELL_CAST_FAILED = true,
|
jcallahan@246
|
1926 SWING_MISSED = true,
|
jcallahan@246
|
1927 }
|
jcallahan@246
|
1928
|
jcallahan@299
|
1929 local DAMAGE_EVENTS = {
|
jcallahan@299
|
1930 RANGE_DAMAGE = true,
|
jcallahan@299
|
1931 SPELL_BUILDING_DAMAGE = true,
|
jcallahan@299
|
1932 SPELL_DAMAGE = true,
|
jcallahan@299
|
1933 SPELL_PERIODIC_DAMAGE = true,
|
jcallahan@299
|
1934 SWING_DAMAGE = true,
|
jcallahan@299
|
1935 }
|
jcallahan@299
|
1936
|
jcallahan@246
|
1937
|
jcallahan@92
|
1938 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
|
1939 local combat_log_func = COMBAT_LOG_FUNCS[sub_event]
|
jcallahan@23
|
1940
|
jcallahan@23
|
1941 if not combat_log_func then
|
jcallahan@299
|
1942 if DAMAGE_EVENTS[sub_event] then
|
jcallahan@299
|
1943 table.wipe(previous_combat_event)
|
jcallahan@246
|
1944 previous_combat_event.source_name = source_name
|
jcallahan@299
|
1945
|
jcallahan@299
|
1946 if source_guid ~= dest_guid and (in_instance or group_member_guids[source_guid] or group_pet_guids[source_guid]) then
|
jcallahan@299
|
1947 previous_combat_event.party_damage = true
|
jcallahan@299
|
1948 end
|
jcallahan@246
|
1949 end
|
jcallahan@23
|
1950 return
|
jcallahan@23
|
1951 end
|
jcallahan@23
|
1952 combat_log_func(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, ...)
|
jcallahan@297
|
1953
|
jcallahan@297
|
1954 if NON_DAMAGE_EVENTS[sub_event] then
|
jcallahan@297
|
1955 table.wipe(previous_combat_event)
|
jcallahan@297
|
1956 end
|
jcallahan@23
|
1957 end
|
jcallahan@23
|
1958
|
catherton@465
|
1959
|
jcallahan@44
|
1960 local DIPLOMACY_SPELL_ID = 20599
|
jcallahan@44
|
1961 local MR_POP_RANK1_SPELL_ID = 78634
|
jcallahan@44
|
1962 local MR_POP_RANK2_SPELL_ID = 78635
|
MMOSimca@418
|
1963 local TRADING_PACT_SPELL_ID = 170200
|
jcallahan@44
|
1964
|
jcallahan@44
|
1965
|
jcallahan@92
|
1966 function WDP:COMBAT_TEXT_UPDATE(event_name, message_type, faction_name, amount)
|
jcallahan@177
|
1967 if message_type ~= "FACTION" or not killed_npc_id then
|
jcallahan@44
|
1968 return
|
jcallahan@44
|
1969 end
|
jcallahan@44
|
1970 UpdateFactionData()
|
jcallahan@44
|
1971
|
jcallahan@46
|
1972 if not faction_name or not faction_standings[faction_name] then
|
jcallahan@46
|
1973 return
|
jcallahan@46
|
1974 end
|
jcallahan@177
|
1975 local npc = NPCEntry(killed_npc_id)
|
jcallahan@177
|
1976 ClearKilledNPC()
|
jcallahan@46
|
1977
|
jcallahan@44
|
1978 if not npc then
|
jcallahan@98
|
1979 private.harvesting = nil
|
jcallahan@44
|
1980 return
|
jcallahan@44
|
1981 end
|
jcallahan@98
|
1982 npc.harvested = private.harvesting
|
jcallahan@98
|
1983 private.harvesting = nil
|
jcallahan@98
|
1984
|
jcallahan@44
|
1985 local modifier = 1
|
jcallahan@44
|
1986
|
MMOSimca@340
|
1987 -- Check for modifiers from known spells
|
jcallahan@44
|
1988 if _G.IsSpellKnown(DIPLOMACY_SPELL_ID) then
|
jcallahan@44
|
1989 modifier = modifier + 0.1
|
jcallahan@44
|
1990 end
|
jcallahan@44
|
1991 if _G.IsSpellKnown(MR_POP_RANK2_SPELL_ID) then
|
jcallahan@44
|
1992 modifier = modifier + 0.1
|
jcallahan@44
|
1993 elseif _G.IsSpellKnown(MR_POP_RANK1_SPELL_ID) then
|
jcallahan@44
|
1994 modifier = modifier + 0.05
|
jcallahan@44
|
1995 end
|
MMOSimca@418
|
1996 if _G.IsSpellKnown(TRADING_PACT_SPELL_ID) then
|
MMOSimca@418
|
1997 modifier = modifier + 0.2
|
MMOSimca@418
|
1998 end
|
jcallahan@44
|
1999
|
MMOSimca@340
|
2000 -- Determine faction ID
|
MMOSimca@340
|
2001 local faction_ID
|
MMOSimca@418
|
2002 for pseudo_faction_name, faction_data_table in pairs(private.FACTION_DATA) do
|
MMOSimca@418
|
2003 if faction_name == faction_data_table[3] then
|
MMOSimca@418
|
2004 -- Check ignore flag
|
MMOSimca@418
|
2005 if faction_data_table[2] then
|
MMOSimca@418
|
2006 return
|
MMOSimca@418
|
2007 end
|
MMOSimca@340
|
2008 faction_ID = faction_data_table[1]
|
MMOSimca@418
|
2009 break
|
MMOSimca@340
|
2010 end
|
MMOSimca@340
|
2011 end
|
MMOSimca@340
|
2012 if faction_ID and faction_ID > 0 then
|
MMOSimca@340
|
2013 -- Check for modifiers from Commendations (applied directly to the faction, account-wide)
|
MMOSimca@340
|
2014 local _, _, _, _, _, _, _, _, _, _, _, _, _, _, has_bonus_rep_gain = GetFactionInfoByID(faction_ID)
|
MMOSimca@340
|
2015 if has_bonus_rep_gain then
|
MMOSimca@340
|
2016 modifier = modifier + 1
|
MMOSimca@340
|
2017 end
|
MMOSimca@340
|
2018 end
|
MMOSimca@340
|
2019
|
MMOSimca@340
|
2020 -- Check for modifiers from buffs
|
MMOSimca@418
|
2021 for buff_name, buff_data_table in pairs(private.REP_BUFFS) do
|
jcallahan@44
|
2022 if _G.UnitBuff("player", buff_name) then
|
MMOSimca@340
|
2023 local modded_faction = buff_data_table.faction
|
jcallahan@44
|
2024
|
jcallahan@44
|
2025 if not modded_faction or faction_name == modded_faction then
|
MMOSimca@340
|
2026 if buff_data_table.ignore then
|
MMOSimca@340
|
2027 -- Some buffs from tabards convert all rep of other factions into rep for a specific faction.
|
MMOSimca@340
|
2028 -- We can't know what faction the rep was orginally from, so we must ignore the data entirely in these cases.
|
MMOSimca@340
|
2029 return
|
MMOSimca@340
|
2030 else
|
MMOSimca@340
|
2031 modifier = modifier + buff_data_table.modifier
|
MMOSimca@340
|
2032 end
|
jcallahan@44
|
2033 end
|
jcallahan@44
|
2034 end
|
jcallahan@44
|
2035 end
|
catherton@465
|
2036
|
jcallahan@65
|
2037 npc.reputations = npc.reputations or {}
|
jcallahan@65
|
2038 npc.reputations[("%s:%s"):format(faction_name, faction_standings[faction_name])] = math.floor(amount / modifier)
|
jcallahan@32
|
2039 end
|
jcallahan@44
|
2040 end -- do-block
|
jcallahan@18
|
2041
|
jcallahan@18
|
2042
|
jcallahan@140
|
2043 function WDP:CURSOR_UPDATE(event_name)
|
MMOSimca@355
|
2044 if current_action.fishing_target or _G.Minimap:IsMouseOver() then
|
jcallahan@140
|
2045 return
|
jcallahan@140
|
2046 end
|
jcallahan@140
|
2047 local text = _G["GameTooltipTextLeft1"]:GetText()
|
jcallahan@140
|
2048
|
MMOSimca@355
|
2049 -- Handle Fishing
|
MMOSimca@355
|
2050 if (current_action.spell_label == "FISHING") then
|
MMOSimca@355
|
2051 if not text or text == "Fishing Bobber" then
|
MMOSimca@355
|
2052 text = "NONE"
|
MMOSimca@355
|
2053 else
|
MMOSimca@355
|
2054 current_action.fishing_target = true
|
MMOSimca@355
|
2055 end
|
MMOSimca@355
|
2056 current_action.identifier = ("%s:%s"):format(current_action.spell_label, text)
|
MMOSimca@355
|
2057 -- Handle Garrison Cache
|
MMOSimca@355
|
2058 elseif private.GARRISON_CACHE_OBJECT_NAME_TO_OBJECT_ID_MAP[text] then
|
MMOSimca@355
|
2059 last_garrison_cache_object_id = private.GARRISON_CACHE_OBJECT_NAME_TO_OBJECT_ID_MAP[text]
|
jcallahan@140
|
2060 end
|
jcallahan@140
|
2061 end
|
jcallahan@140
|
2062
|
jcallahan@140
|
2063
|
jcallahan@92
|
2064 function WDP:ITEM_TEXT_BEGIN(event_name)
|
jcallahan@42
|
2065 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@42
|
2066
|
jcallahan@42
|
2067 if not unit_idnum or unit_type ~= private.UNIT_TYPES.OBJECT or _G.UnitName("npc") ~= _G.ItemTextGetItem() then
|
jcallahan@42
|
2068 return
|
jcallahan@42
|
2069 end
|
jcallahan@42
|
2070 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@42
|
2071 end
|
jcallahan@42
|
2072
|
jcallahan@42
|
2073
|
jcallahan@13
|
2074 do
|
MMOSimca@343
|
2075 local LOOT_OPENED_VERIFY_FUNCS = {
|
jcallahan@324
|
2076 -- Item containers can be AOE-looted in Patch 5.4.2 if the user clicks fast enough, but this verification still works as long as they both have loot.
|
jcallahan@16
|
2077 [AF.ITEM] = function()
|
jcallahan@16
|
2078 local locked_item_id
|
jcallahan@16
|
2079
|
jcallahan@16
|
2080 for bag_index = 0, _G.NUM_BAG_FRAMES do
|
jcallahan@16
|
2081 for slot_index = 1, _G.GetContainerNumSlots(bag_index) do
|
jcallahan@324
|
2082 local _, _, is_locked, _, _, is_lootable = _G.GetContainerItemInfo(bag_index, slot_index)
|
jcallahan@324
|
2083
|
jcallahan@324
|
2084 if is_locked and is_lootable then
|
jcallahan@16
|
2085 locked_item_id = ItemLinkToID(_G.GetContainerItemLink(bag_index, slot_index))
|
jcallahan@165
|
2086 break
|
jcallahan@16
|
2087 end
|
jcallahan@16
|
2088 end
|
jcallahan@165
|
2089
|
jcallahan@165
|
2090 if locked_item_id then
|
jcallahan@165
|
2091 break
|
jcallahan@165
|
2092 end
|
jcallahan@16
|
2093 end
|
jcallahan@16
|
2094
|
MMOSimca@367
|
2095 if (not current_action.spell_label == "DISENCHANT") and (not locked_item_id or (current_action.identifier and current_action.identifier ~= locked_item_id)) then
|
jcallahan@16
|
2096 return false
|
jcallahan@16
|
2097 end
|
jcallahan@122
|
2098 current_action.identifier = locked_item_id
|
jcallahan@16
|
2099 return true
|
jcallahan@16
|
2100 end,
|
MMOSimca@401
|
2101 [AF.NPC] = function()
|
MMOSimca@401
|
2102 return not _G.IsFishingLoot()
|
MMOSimca@401
|
2103 end,
|
MMOSimca@401
|
2104 [AF.OBJECT] = function()
|
MMOSimca@401
|
2105 return not _G.IsFishingLoot()
|
MMOSimca@401
|
2106 end,
|
jcallahan@17
|
2107 [AF.ZONE] = function()
|
jcallahan@140
|
2108 current_action.zone_data = UpdateDBEntryLocation("zones", current_action.identifier)
|
jcallahan@210
|
2109 return _G.IsFishingLoot()
|
jcallahan@17
|
2110 end,
|
jcallahan@13
|
2111 }
|
jcallahan@13
|
2112
|
jcallahan@13
|
2113
|
MMOSimca@343
|
2114 local LOOT_OPENED_UPDATE_FUNCS = {
|
jcallahan@16
|
2115 [AF.ITEM] = function()
|
jcallahan@28
|
2116 GenericLootUpdate("items")
|
jcallahan@28
|
2117 end,
|
jcallahan@28
|
2118 [AF.NPC] = function()
|
jcallahan@75
|
2119 local difficulty_token = InstanceDifficultyToken()
|
jcallahan@312
|
2120 local loot_label = current_loot.label
|
jcallahan@77
|
2121 local source_list = {}
|
jcallahan@75
|
2122
|
jcallahan@131
|
2123 for source_guid, loot_data in pairs(current_loot.sources) do
|
jcallahan@331
|
2124 local _, source_id = ParseGUID(source_guid)
|
jcallahan@75
|
2125 local npc = NPCEntry(source_id)
|
jcallahan@75
|
2126
|
jcallahan@75
|
2127 if npc then
|
jcallahan@248
|
2128 local encounter_data = npc:EncounterData(difficulty_token)
|
jcallahan@312
|
2129 encounter_data[loot_label] = encounter_data[loot_label] or {}
|
jcallahan@75
|
2130
|
jcallahan@78
|
2131 if not source_list[source_guid] then
|
jcallahan@77
|
2132 encounter_data.loot_counts = encounter_data.loot_counts or {}
|
MMOSimca@426
|
2133 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
|
jcallahan@312
|
2134 source_list[source_guid] = true
|
jcallahan@77
|
2135 end
|
jcallahan@77
|
2136
|
jcallahan@309
|
2137 for loot_token, quantity in pairs(loot_data) do
|
mmosimca@496
|
2138 local loot_type, currency_id = (":"):split(loot_token)
|
mmosimca@496
|
2139
|
mmosimca@496
|
2140 if loot_type == "currency" and currency_id then
|
mmosimca@496
|
2141 -- Convert currency_id back into number from string
|
mmosimca@496
|
2142 currency_id = tonumber(currency_id) or 0
|
mmosimca@496
|
2143 if currency_id ~= 0 then
|
mmosimca@496
|
2144 table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
|
mmosimca@496
|
2145 end
|
jcallahan@309
|
2146 elseif loot_token == "money" then
|
jcallahan@312
|
2147 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
|
jcallahan@309
|
2148 else
|
jcallahan@312
|
2149 table.insert(encounter_data[loot_label], ("%d:%d"):format(loot_token, quantity))
|
jcallahan@309
|
2150 end
|
jcallahan@75
|
2151 end
|
jcallahan@75
|
2152 end
|
jcallahan@75
|
2153 end
|
jcallahan@16
|
2154 end,
|
jcallahan@13
|
2155 [AF.OBJECT] = function()
|
jcallahan@28
|
2156 GenericLootUpdate("objects", InstanceDifficultyToken())
|
jcallahan@17
|
2157 end,
|
jcallahan@17
|
2158 [AF.ZONE] = function()
|
MMOSimca@328
|
2159 if not (current_loot.map_level and current_loot.x and current_loot.y and current_loot.zone_data) then
|
MMOSimca@328
|
2160 return
|
MMOSimca@328
|
2161 end
|
jcallahan@141
|
2162 local location_token = ("%d:%d:%d"):format(current_loot.map_level, current_loot.x, current_loot.y)
|
jcallahan@41
|
2163
|
jcallahan@41
|
2164 -- This will start life as a boolean true.
|
mmosimca@522
|
2165 if type(current_loot.zone_data[location_token]) ~= "table" then
|
jcallahan@131
|
2166 current_loot.zone_data[location_token] = {
|
jcallahan@41
|
2167 drops = {}
|
jcallahan@41
|
2168 }
|
jcallahan@41
|
2169 end
|
jcallahan@132
|
2170 local loot_count = ("%s_count"):format(current_loot.label)
|
jcallahan@131
|
2171 current_loot.zone_data[location_token][loot_count] = (current_loot.zone_data[location_token][loot_count] or 0) + 1
|
jcallahan@41
|
2172
|
jcallahan@131
|
2173 if current_loot.sources then
|
jcallahan@131
|
2174 for source_guid, loot_data in pairs(current_loot.sources) do
|
jcallahan@131
|
2175 for item_id, quantity in pairs(loot_data) do
|
jcallahan@131
|
2176 table.insert(current_loot.zone_data[location_token].drops, ("%d:%d"):format(item_id, quantity))
|
jcallahan@131
|
2177 end
|
jcallahan@131
|
2178 end
|
jcallahan@131
|
2179 end
|
jcallahan@131
|
2180
|
jcallahan@131
|
2181 if #current_loot.list <= 0 then
|
jcallahan@131
|
2182 return
|
jcallahan@131
|
2183 end
|
jcallahan@131
|
2184
|
jcallahan@131
|
2185 for index = 1, #current_loot.list do
|
MMOSimca@443
|
2186 table.insert(current_loot.zone_data[location_token].drops, current_loot.list[index])
|
jcallahan@41
|
2187 end
|
jcallahan@13
|
2188 end,
|
jcallahan@13
|
2189 }
|
jcallahan@13
|
2190
|
jcallahan@79
|
2191 -- Prevent opening the same loot window multiple times from recording data multiple times.
|
jcallahan@79
|
2192 local loot_guid_registry = {}
|
jcallahan@124
|
2193
|
jcallahan@124
|
2194
|
jcallahan@124
|
2195 function WDP:LOOT_CLOSED(event_name)
|
MMOSimca@398
|
2196 ClearChatLootData()
|
jcallahan@131
|
2197 current_loot = nil
|
jcallahan@131
|
2198 table.wipe(current_action)
|
jcallahan@124
|
2199 end
|
jcallahan@124
|
2200
|
jcallahan@13
|
2201
|
jcallahan@322
|
2202 local function ExtrapolatedCurrentActionFromLootData(event_name)
|
MMOSimca@402
|
2203 local log_source = event_name .. "- ExtrapolatedCurrentActionFromLootData"
|
MMOSimca@402
|
2204 local previous_spell_label = current_action.spell_label
|
jcallahan@322
|
2205 local extrapolated_guid_registry = {}
|
jcallahan@322
|
2206 local num_guids = 0
|
MMOSimca@402
|
2207 table.wipe(current_action)
|
MMOSimca@402
|
2208
|
MMOSimca@402
|
2209 if _G.IsFishingLoot() then
|
MMOSimca@402
|
2210 -- Set up a proper 'fishing' current_action table
|
MMOSimca@402
|
2211 local zone_name, area_id, x, y, map_level, instance_token = CurrentLocationData()
|
MMOSimca@402
|
2212 if not (zone_name and area_id and x and y and map_level) then
|
mmosimca@508
|
2213 if not (_G.IsInInstance()) then
|
mmosimca@508
|
2214 Debug("%s: Missing current location data - %s, %s, %s, %s, %s.", log_source, tostring(zone_name), tostring(area_id), tostring(x), tostring(y), tostring(map_level))
|
mmosimca@508
|
2215 end
|
MMOSimca@402
|
2216 return
|
MMOSimca@402
|
2217 end
|
MMOSimca@402
|
2218 current_action.instance_token = instance_token
|
MMOSimca@402
|
2219 current_action.map_level = map_level
|
MMOSimca@402
|
2220 current_action.x = x
|
MMOSimca@402
|
2221 current_action.y = y
|
MMOSimca@402
|
2222 current_action.zone_data = ("%s:%d"):format(zone_name, area_id)
|
MMOSimca@402
|
2223 current_action.spell_label = "FISHING"
|
MMOSimca@402
|
2224 current_action.loot_label = "fishing"
|
MMOSimca@402
|
2225 current_action.identifier = "FISHING:NONE"
|
MMOSimca@402
|
2226 current_action.target_type = AF.ZONE
|
MMOSimca@402
|
2227
|
MMOSimca@402
|
2228 Debug("%s: Fishing loot detected.", log_source)
|
MMOSimca@402
|
2229 return true
|
MMOSimca@402
|
2230 end
|
jcallahan@322
|
2231
|
MMOSimca@344
|
2232 -- Loot extrapolation cannot handle objects that need special spell labels (like HERBALISM or MINING) (MIND_CONTROL is okay)
|
MMOSimca@402
|
2233 if previous_spell_label and private.SPELL_FLAGS_BY_LABEL[previous_spell_label] and not private.NON_LOOT_SPELL_LABELS[previous_spell_label] then
|
MMOSimca@344
|
2234 Debug("%s: Problematic spell label %s found. Loot extrapolation for this set of loot would have run an increased risk of introducing bad data into the system.", log_source, private.previous_spell_id)
|
MMOSimca@344
|
2235 return false
|
MMOSimca@344
|
2236 end
|
MMOSimca@344
|
2237
|
jcallahan@322
|
2238 for loot_slot = 1, _G.GetNumLootItems() do
|
jcallahan@322
|
2239 local loot_info = {
|
jcallahan@322
|
2240 _G.GetLootSourceInfo(loot_slot)
|
jcallahan@322
|
2241 }
|
jcallahan@322
|
2242
|
jcallahan@322
|
2243 for loot_index = 1, #loot_info, 2 do
|
jcallahan@322
|
2244 local source_guid = loot_info[loot_index]
|
jcallahan@322
|
2245
|
jcallahan@322
|
2246 if not extrapolated_guid_registry[source_guid] then
|
jcallahan@322
|
2247 local unit_type, unit_idnum = ParseGUID(source_guid)
|
jcallahan@322
|
2248
|
jcallahan@322
|
2249 if unit_type and unit_idnum then
|
jcallahan@322
|
2250 extrapolated_guid_registry[source_guid] = {
|
jcallahan@322
|
2251 unit_type,
|
jcallahan@322
|
2252 unit_idnum
|
jcallahan@322
|
2253 }
|
jcallahan@322
|
2254
|
jcallahan@322
|
2255 num_guids = num_guids + 1
|
jcallahan@322
|
2256 end
|
jcallahan@322
|
2257 end
|
jcallahan@322
|
2258 end
|
jcallahan@322
|
2259 end
|
jcallahan@322
|
2260
|
jcallahan@322
|
2261 if num_guids == 0 then
|
jcallahan@322
|
2262 Debug("%s: No GUIDs found in loot. Blank loot window?", log_source)
|
jcallahan@322
|
2263 return false
|
jcallahan@322
|
2264 end
|
jcallahan@326
|
2265
|
jcallahan@322
|
2266 local num_npcs = 0
|
jcallahan@322
|
2267 local num_objects = 0
|
jcallahan@324
|
2268 local num_itemcontainers = 0
|
jcallahan@322
|
2269
|
jcallahan@322
|
2270 for source_guid, guid_data in pairs(extrapolated_guid_registry) do
|
jcallahan@322
|
2271 local unit_type = guid_data[1]
|
mmosimca@516
|
2272 local loot_label = (unit_type == private.UNIT_TYPES.OBJECT) and "opening" or (UnitTypeIsNPC(unit_type) and "drops") or ((unit_type == private.UNIT_TYPES.ITEM) and "contains")
|
jcallahan@322
|
2273
|
jcallahan@322
|
2274 if loot_label then
|
jcallahan@322
|
2275 local unit_idnum = guid_data[2]
|
jcallahan@322
|
2276
|
jcallahan@322
|
2277 if loot_guid_registry[loot_label] and loot_guid_registry[loot_label][source_guid] then
|
jcallahan@322
|
2278 Debug("%s: Previously scanned loot for unit with GUID %s and identifier %s.", log_source, source_guid, unit_idnum)
|
jcallahan@322
|
2279 elseif unit_type == private.UNIT_TYPES.OBJECT and unit_idnum ~= OBJECT_ID_FISHING_BOBBER then
|
jcallahan@322
|
2280 current_action.loot_label = loot_label
|
jcallahan@322
|
2281 current_action.spell_label = "OPENING"
|
jcallahan@322
|
2282 current_action.target_type = AF.OBJECT
|
jcallahan@322
|
2283 current_action.identifier = unit_idnum
|
jcallahan@322
|
2284 num_objects = num_objects + 1
|
jcallahan@322
|
2285 elseif UnitTypeIsNPC(unit_type) then
|
jcallahan@322
|
2286 current_action.loot_label = loot_label
|
jcallahan@322
|
2287 current_action.target_type = AF.NPC
|
jcallahan@322
|
2288 current_action.identifier = unit_idnum
|
jcallahan@322
|
2289 num_npcs = num_npcs + 1
|
mmosimca@516
|
2290 elseif unit_type == private.UNIT_TYPES.ITEM then
|
jcallahan@324
|
2291 current_action.loot_label = loot_label
|
jcallahan@324
|
2292 current_action.target_type = AF.ITEM
|
jcallahan@324
|
2293 -- current_action.identifier assigned during loot verification.
|
jcallahan@324
|
2294 num_itemcontainers = num_itemcontainers + 1
|
jcallahan@322
|
2295 end
|
jcallahan@322
|
2296 else
|
jcallahan@322
|
2297 -- Bail here; not only do we not know what this unit is, but we don't want to attribute loot to something that doesn't actually drop it.
|
jcallahan@322
|
2298 Debug("%s: Unit with GUID %s has unsupported type for looting.", log_source, source_guid)
|
jcallahan@322
|
2299 return false
|
jcallahan@322
|
2300 end
|
jcallahan@322
|
2301 end
|
jcallahan@322
|
2302
|
jcallahan@322
|
2303 if not current_action.target_type then
|
jcallahan@322
|
2304 Debug("%s: Failure to obtain target_type.", log_source)
|
jcallahan@322
|
2305 return false
|
jcallahan@322
|
2306 end
|
jcallahan@322
|
2307
|
jcallahan@322
|
2308 -- We can't figure out what dropped the loot. This shouldn't ever happen, but hey - Blizzard does some awesome stuff on occasion.
|
jcallahan@324
|
2309 if (num_npcs > 0 and num_objects + num_itemcontainers > 0) or (num_objects > 0 and num_npcs + num_itemcontainers > 0) or (num_itemcontainers > 0 and num_npcs + num_objects > 0) then
|
jcallahan@324
|
2310 Debug("%s: Mixed target types are not supported. NPCs - %d, Objects - %d, Item Containers - %d.", log_source, num_npcs, num_objects, num_itemcontainers)
|
jcallahan@322
|
2311 return false
|
jcallahan@322
|
2312 end
|
jcallahan@322
|
2313
|
jcallahan@322
|
2314 return true
|
jcallahan@322
|
2315 end
|
jcallahan@322
|
2316
|
jcallahan@322
|
2317
|
MMOSimca@343
|
2318 function WDP:LOOT_OPENED(event_name)
|
MMOSimca@398
|
2319 ClearChatLootData()
|
MMOSimca@387
|
2320
|
jcallahan@132
|
2321 if current_loot then
|
jcallahan@322
|
2322 current_loot = nil
|
jcallahan@322
|
2323 Debug("%s: Previous loot did not process in time for this event. Attempting to extrapolate current_action from loot data.", event_name)
|
jcallahan@322
|
2324
|
jcallahan@322
|
2325 if not ExtrapolatedCurrentActionFromLootData(event_name) then
|
jcallahan@322
|
2326 Debug("%s: Unable to extrapolate current_action. Aborting attempts to handle loot for now.", event_name)
|
jcallahan@322
|
2327 return
|
jcallahan@322
|
2328 end
|
jcallahan@18
|
2329 end
|
jcallahan@151
|
2330
|
jcallahan@151
|
2331 if not current_action.target_type then
|
jcallahan@322
|
2332 if not ExtrapolatedCurrentActionFromLootData(event_name) then
|
jcallahan@322
|
2333 Debug("%s: Unable to extrapolate current_action. Aborting attempts to handle loot for now.", event_name)
|
jcallahan@322
|
2334 return
|
jcallahan@322
|
2335 end
|
jcallahan@151
|
2336 end
|
MMOSimca@343
|
2337 local verify_func = LOOT_OPENED_VERIFY_FUNCS[current_action.target_type]
|
MMOSimca@343
|
2338 local update_func = LOOT_OPENED_UPDATE_FUNCS[current_action.target_type]
|
jcallahan@13
|
2339
|
jcallahan@14
|
2340 if not verify_func or not update_func then
|
jcallahan@322
|
2341 Debug("%s: The current action's target type is unsupported or nil.", event_name)
|
jcallahan@13
|
2342 return
|
jcallahan@13
|
2343 end
|
jcallahan@13
|
2344
|
mmosimca@522
|
2345 if type(verify_func) == "function" and not verify_func() then
|
jcallahan@324
|
2346 Debug("%s: The current action type, %s, is supported but has failed loot verification.", event_name, private.ACTION_TYPE_NAMES[current_action.target_type])
|
jcallahan@14
|
2347 return
|
jcallahan@14
|
2348 end
|
jcallahan@80
|
2349 local guids_used = {}
|
jcallahan@132
|
2350
|
jcallahan@301
|
2351 InitializeCurrentLoot()
|
jcallahan@217
|
2352 loot_guid_registry[current_loot.label] = loot_guid_registry[current_loot.label] or {}
|
jcallahan@217
|
2353
|
jcallahan@55
|
2354 for loot_slot = 1, _G.GetNumLootItems() do
|
mmosimca@496
|
2355 local texture_filedata_id, item_text, slot_quantity, quality, locked = _G.GetLootSlotInfo(loot_slot)
|
jcallahan@55
|
2356 local slot_type = _G.GetLootSlotType(loot_slot)
|
catherton@463
|
2357 local loot_info = { _G.GetLootSourceInfo(loot_slot) }
|
catherton@464
|
2358 local loot_link = _G.GetLootSlotLink(loot_slot)
|
jcallahan@13
|
2359
|
jcallahan@237
|
2360 -- Odd index is GUID, even is count.
|
jcallahan@237
|
2361 for loot_index = 1, #loot_info, 2 do
|
jcallahan@237
|
2362 local source_guid = loot_info[loot_index]
|
jcallahan@75
|
2363
|
jcallahan@237
|
2364 if not loot_guid_registry[current_loot.label][source_guid] then
|
jcallahan@237
|
2365 local loot_quantity = loot_info[loot_index + 1]
|
jcallahan@324
|
2366 -- There is a new bug in 5.4.0 that causes GetLootSlotInfo() to (rarely) return nil values for slot_quantity.
|
jcallahan@324
|
2367 if slot_quantity then
|
jcallahan@324
|
2368 -- We need slot_quantity to account for an old bug where loot_quantity is sometimes '1' for stacks of items, such as cloth.
|
jcallahan@324
|
2369 if slot_quantity > loot_quantity then
|
jcallahan@324
|
2370 loot_quantity = slot_quantity
|
jcallahan@324
|
2371 end
|
jcallahan@324
|
2372 local source_type, source_id = ParseGUID(source_guid)
|
MMOSimca@329
|
2373 local source_key = ("%s:%d"):format(source_type, source_id)
|
jcallahan@324
|
2374
|
MMOSimca@366
|
2375 if slot_type == LOOT_SLOT_ITEM then
|
catherton@464
|
2376 if loot_link then
|
catherton@464
|
2377 local item_id = ItemLinkToID(loot_link)
|
catherton@464
|
2378 Debug("GUID: %s - Type:ID: %s - ItemID: %d - Amount: %d (%d)", loot_info[loot_index], source_key, item_id, loot_info[loot_index + 1], slot_quantity)
|
catherton@464
|
2379 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
catherton@464
|
2380 current_loot.sources[source_guid][item_id] = (current_loot.sources[source_guid][item_id] or 0) + loot_quantity
|
catherton@464
|
2381 guids_used[source_guid] = true
|
catherton@463
|
2382 else
|
catherton@463
|
2383 Debug("%s: Loot link is nil for loot slot %d of the entity with GUID %s and Type:ID: %s.", event_name, loot_slot, loot_info[loot_index], source_key)
|
catherton@463
|
2384 end
|
MMOSimca@366
|
2385 elseif slot_type == LOOT_SLOT_MONEY then
|
jcallahan@324
|
2386 Debug("GUID: %s - Type:ID: %s - Money - Amount: %d (%d)", loot_info[loot_index], source_key, loot_info[loot_index + 1], slot_quantity)
|
jcallahan@324
|
2387 if current_loot.target_type == AF.ZONE then
|
jcallahan@324
|
2388 table.insert(current_loot.list, ("money:%d"):format(loot_quantity))
|
jcallahan@324
|
2389 else
|
jcallahan@324
|
2390 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
MMOSimca@367
|
2391 current_loot.sources[source_guid]["money"] = (current_loot.sources[source_guid]["money"] or 0) + loot_quantity
|
jcallahan@324
|
2392 guids_used[source_guid] = true
|
jcallahan@324
|
2393 end
|
MMOSimca@366
|
2394 elseif slot_type == LOOT_SLOT_CURRENCY then
|
jcallahan@324
|
2395 -- Same bug with GetLootSlotInfo() will screw up currency when it happens, so we won't process this slot's loot.
|
catherton@463
|
2396 if loot_link then
|
mmosimca@496
|
2397 local currency_id = CurrencyLinkToID(loot_link)
|
mmosimca@496
|
2398 Debug("GUID: %s - Type:ID: %s - Currency: %d - Amount: %d (%d)", loot_info[loot_index], source_key, currency_id, loot_info[loot_index + 1], slot_quantity)
|
jcallahan@324
|
2399 if current_loot.target_type == AF.ZONE then
|
mmosimca@496
|
2400 table.insert(current_loot.list, ("currency:%d:%d"):format(loot_quantity, currency_id))
|
jcallahan@324
|
2401 else
|
mmosimca@496
|
2402 local currency_token = ("currency:%d"):format(currency_id)
|
jcallahan@324
|
2403
|
jcallahan@324
|
2404 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
MMOSimca@367
|
2405 current_loot.sources[source_guid][currency_token] = (current_loot.sources[source_guid][currency_token] or 0) + loot_quantity
|
jcallahan@324
|
2406 guids_used[source_guid] = true
|
jcallahan@324
|
2407 end
|
jcallahan@324
|
2408 else
|
catherton@463
|
2409 Debug("%s: Loot link is nil for loot slot %d of the entity with GUID %s and Type:ID: %s.", event_name, loot_slot, loot_info[loot_index], source_key)
|
jcallahan@324
|
2410 end
|
jcallahan@308
|
2411 end
|
jcallahan@324
|
2412 else
|
jcallahan@324
|
2413 -- If this is nil, then the item's quantity could be wrong if loot_quantity is wrong, so we won't process this slot's loot.
|
catherton@463
|
2414 Debug("%s: Slot quantity is nil for loot slot %d of the entity with GUID %s and Type:ID: %s.", event_name, loot_slot, loot_info[loot_index], source_key)
|
jcallahan@79
|
2415 end
|
jcallahan@75
|
2416 end
|
jcallahan@13
|
2417 end
|
jcallahan@13
|
2418 end
|
jcallahan@80
|
2419
|
jcallahan@81
|
2420 for guid in pairs(guids_used) do
|
jcallahan@217
|
2421 loot_guid_registry[current_loot.label][guid] = true
|
jcallahan@80
|
2422 end
|
jcallahan@13
|
2423 update_func()
|
jcallahan@1
|
2424 end
|
jcallahan@13
|
2425 end -- do-block
|
jcallahan@0
|
2426
|
jcallahan@0
|
2427
|
jcallahan@89
|
2428 function WDP:MAIL_SHOW(event_name)
|
MMOSimca@436
|
2429 WDP:StopChatLootRecording(event_name)
|
jcallahan@89
|
2430 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@89
|
2431
|
jcallahan@89
|
2432 if not unit_idnum or unit_type ~= private.UNIT_TYPES.OBJECT then
|
jcallahan@89
|
2433 return
|
jcallahan@89
|
2434 end
|
jcallahan@89
|
2435 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@89
|
2436 end
|
jcallahan@89
|
2437
|
jcallahan@89
|
2438
|
jcallahan@44
|
2439 do
|
jcallahan@44
|
2440 local POINT_MATCH_PATTERNS = {
|
jcallahan@44
|
2441 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2442 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_3V3:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2443 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_5V5:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2444 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_BG:gsub("%%d", "(%%d+)")),
|
jcallahan@44
|
2445 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_3V3_BG:gsub("%%d", "(%%d+)")),
|
jcallahan@44
|
2446 }
|
jcallahan@5
|
2447
|
jcallahan@68
|
2448 local ITEM_REQ_REPUTATION_MATCH = "Requires (.-) %- (.*)"
|
jcallahan@87
|
2449 local ITEM_REQ_QUEST_MATCH1 = "Requires: .*"
|
jcallahan@87
|
2450 local ITEM_REQ_QUEST_MATCH2 = "Must have completed: .*"
|
jcallahan@68
|
2451
|
jcallahan@133
|
2452 local current_merchant
|
jcallahan@133
|
2453 local merchant_standing
|
jcallahan@133
|
2454
|
jcallahan@133
|
2455 function WDP:MERCHANT_CLOSED(event_name)
|
MMOSimca@436
|
2456 WDP:ResumeChatLootRecording(event_name)
|
jcallahan@133
|
2457 current_merchant = nil
|
jcallahan@133
|
2458 merchant_standing = nil
|
jcallahan@133
|
2459 end
|
jcallahan@133
|
2460
|
jcallahan@133
|
2461
|
jcallahan@89
|
2462 function WDP:UpdateMerchantItems(event_name)
|
jcallahan@144
|
2463 if not current_merchant or event_name == "MERCHANT_SHOW" then
|
MMOSimca@436
|
2464 WDP:StopChatLootRecording(event_name)
|
jcallahan@195
|
2465 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@4
|
2466
|
jcallahan@171
|
2467 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
jcallahan@133
|
2468 return
|
jcallahan@133
|
2469 end
|
jcallahan@331
|
2470 local _, faction_standing = UnitFactionStanding("npc")
|
jcallahan@331
|
2471 merchant_standing = faction_standing
|
jcallahan@133
|
2472 current_merchant = NPCEntry(unit_idnum)
|
jcallahan@133
|
2473 current_merchant.sells = current_merchant.sells or {}
|
jcallahan@44
|
2474 end
|
jcallahan@55
|
2475 local current_filters = _G.GetMerchantFilter()
|
jcallahan@57
|
2476 _G.SetMerchantFilter(_G.LE_LOOT_FILTER_ALL)
|
jcallahan@57
|
2477 _G.MerchantFrame_Update()
|
jcallahan@57
|
2478
|
jcallahan@150
|
2479 local num_items = _G.GetMerchantNumItems()
|
jcallahan@150
|
2480
|
jcallahan@44
|
2481 for item_index = 1, num_items do
|
jcallahan@44
|
2482 local _, _, copper_price, stack_size, num_available, _, extended_cost = _G.GetMerchantItemInfo(item_index)
|
jcallahan@44
|
2483 local item_id = ItemLinkToID(_G.GetMerchantItemLink(item_index))
|
jcallahan@5
|
2484
|
jcallahan@324
|
2485 DatamineTT:ClearLines()
|
jcallahan@324
|
2486 DatamineTT:SetMerchantItem(item_index)
|
jcallahan@324
|
2487
|
jcallahan@324
|
2488 if not item_id then
|
jcallahan@324
|
2489 local item_name, item_link = DatamineTT:GetItem()
|
jcallahan@324
|
2490 item_id = ItemLinkToID(item_link)
|
MMOSimca@354
|
2491 -- GetMerchantItemLink() still ocassionally fails as of Patch 6.0.2. It fails so badly that debug functions cause considerable slowdown.
|
jcallahan@324
|
2492 end
|
jcallahan@324
|
2493
|
jcallahan@44
|
2494 if item_id and item_id > 0 then
|
jcallahan@44
|
2495 local price_string = ActualCopperCost(copper_price, merchant_standing)
|
jcallahan@5
|
2496
|
jcallahan@68
|
2497 local num_lines = DatamineTT:NumLines()
|
jcallahan@68
|
2498
|
jcallahan@68
|
2499 for line_index = 1, num_lines do
|
jcallahan@68
|
2500 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@68
|
2501
|
jcallahan@68
|
2502 if not current_line then
|
jcallahan@68
|
2503 break
|
jcallahan@68
|
2504 end
|
jcallahan@68
|
2505 local faction, reputation = current_line:GetText():match(ITEM_REQ_REPUTATION_MATCH)
|
jcallahan@68
|
2506
|
jcallahan@68
|
2507 if faction or reputation then
|
jcallahan@68
|
2508 DBEntry("items", item_id).req_reputation = ("%s:%s"):format(faction:gsub("-", ""), reputation:upper())
|
jcallahan@68
|
2509 break
|
jcallahan@68
|
2510 end
|
jcallahan@68
|
2511 end
|
jcallahan@68
|
2512
|
jcallahan@87
|
2513 for line_index = 1, num_lines do
|
jcallahan@87
|
2514 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@87
|
2515
|
jcallahan@87
|
2516 if not current_line then
|
jcallahan@87
|
2517 break
|
jcallahan@87
|
2518 end
|
jcallahan@87
|
2519 local line_text = current_line:GetText()
|
jcallahan@87
|
2520 local quest_name = line_text:match(ITEM_REQ_QUEST_MATCH1) or line_text:match(ITEM_REQ_QUEST_MATCH2)
|
jcallahan@87
|
2521
|
jcallahan@87
|
2522 if quest_name then
|
jcallahan@87
|
2523 DBEntry("items", item_id).req_quest = ("%s"):format(quest_name:gsub("(.+): ", ""), quest_name)
|
jcallahan@87
|
2524 break
|
jcallahan@87
|
2525 end
|
jcallahan@87
|
2526 end
|
jcallahan@87
|
2527
|
jcallahan@44
|
2528 if extended_cost then
|
jcallahan@53
|
2529 local battleground_rating = 0
|
jcallahan@53
|
2530 local personal_rating = 0
|
jcallahan@53
|
2531 local required_season_amount
|
jcallahan@5
|
2532
|
jcallahan@68
|
2533 for line_index = 1, num_lines do
|
jcallahan@44
|
2534 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@5
|
2535
|
jcallahan@44
|
2536 if not current_line then
|
jcallahan@44
|
2537 break
|
jcallahan@44
|
2538 end
|
jcallahan@53
|
2539 required_season_amount = current_line:GetText():match("Requires earning a total of (%d+)\n(.-) for the season.")
|
jcallahan@5
|
2540
|
jcallahan@44
|
2541 for match_index = 1, #POINT_MATCH_PATTERNS do
|
jcallahan@44
|
2542 local match1, match2 = current_line:GetText():match(POINT_MATCH_PATTERNS[match_index])
|
jcallahan@53
|
2543 personal_rating = personal_rating + (match1 or 0)
|
jcallahan@53
|
2544 battleground_rating = battleground_rating + (match2 or 0)
|
jcallahan@5
|
2545
|
jcallahan@44
|
2546 if match1 or match2 then
|
jcallahan@44
|
2547 break
|
jcallahan@44
|
2548 end
|
jcallahan@44
|
2549 end
|
jcallahan@5
|
2550 end
|
jcallahan@44
|
2551 local currency_list = {}
|
jcallahan@44
|
2552 local item_count = _G.GetMerchantItemCostInfo(item_index)
|
jcallahan@50
|
2553
|
mmosimca@518
|
2554 -- Keeping this around in case Blizzard makes the two ratings (personal and battleground) diverge at some point
|
mmosimca@518
|
2555 --price_string = ("%s:%s:%s:%s"):format(price_string, battleground_rating, personal_rating, required_season_amount or 0)
|
jcallahan@53
|
2556 price_string = ("%s:%s:%s"):format(price_string, personal_rating, required_season_amount or 0)
|
jcallahan@5
|
2557
|
jcallahan@44
|
2558 for cost_index = 1, item_count do
|
jcallahan@324
|
2559 -- The third return (Blizz calls "currency_link") of GetMerchantItemCostItem only returns item links as of Patch 5.3.0.
|
mmosimca@496
|
2560 local texture_path, amount_required, item_link, name = _G.GetMerchantItemCostItem(item_index, cost_index)
|
mmosimca@496
|
2561
|
mmosimca@519
|
2562 -- Try to get item ID
|
mmosimca@519
|
2563 local item_id = ItemLinkToID(item_link)
|
mmosimca@519
|
2564
|
mmosimca@519
|
2565 -- FUTURE: At some point, we should make the output from these two cases (item_id vs currency_id) slightly different, so that WoWDB doesn't have to guess if it is a currency or item
|
mmosimca@519
|
2566 -- Handle cases when the additional cost is another item
|
mmosimca@519
|
2567 if item_id and item_id > 0 then
|
mmosimca@519
|
2568 currency_list[#currency_list + 1] = ("(%s:%d)"):format(amount_required, item_id)
|
mmosimca@519
|
2569 -- Handle cases when the additional cost is another currency
|
mmosimca@519
|
2570 else
|
mmosimca@496
|
2571 local currency_id = CurrencyInfoToID(name, texture_path)
|
mmosimca@519
|
2572 if currency_id and currency_id > 0 then
|
mmosimca@501
|
2573 currency_list[#currency_list + 1] = ("(%s:%d)"):format(amount_required, currency_id)
|
mmosimca@501
|
2574 end
|
jcallahan@44
|
2575 end
|
jcallahan@44
|
2576 end
|
jcallahan@44
|
2577
|
jcallahan@44
|
2578 for currency_index = 1, #currency_list do
|
jcallahan@44
|
2579 price_string = ("%s:%s"):format(price_string, currency_list[currency_index])
|
jcallahan@5
|
2580 end
|
jcallahan@5
|
2581 end
|
jcallahan@133
|
2582 current_merchant.sells[item_id] = ("%s:%s:[%s]"):format(num_available, stack_size, price_string)
|
jcallahan@44
|
2583 end
|
jcallahan@44
|
2584 end
|
jcallahan@5
|
2585
|
jcallahan@44
|
2586 if _G.CanMerchantRepair() then
|
jcallahan@133
|
2587 current_merchant.can_repair = true
|
jcallahan@5
|
2588 end
|
jcallahan@57
|
2589 _G.SetMerchantFilter(current_filters)
|
jcallahan@57
|
2590 _G.MerchantFrame_Update()
|
jcallahan@4
|
2591 end
|
jcallahan@44
|
2592 end -- do-block
|
jcallahan@4
|
2593
|
jcallahan@89
|
2594
|
jcallahan@92
|
2595 function WDP:PET_BAR_UPDATE(event_name)
|
MMOSimca@336
|
2596 if not private.NON_LOOT_SPELL_LABELS[current_action.spell_label] then
|
jcallahan@25
|
2597 return
|
jcallahan@25
|
2598 end
|
jcallahan@34
|
2599 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("pet"))
|
jcallahan@25
|
2600
|
jcallahan@171
|
2601 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
jcallahan@25
|
2602 return
|
jcallahan@25
|
2603 end
|
jcallahan@29
|
2604 NPCEntry(unit_idnum).mind_control = true
|
jcallahan@122
|
2605 table.wipe(current_action)
|
jcallahan@25
|
2606 end
|
jcallahan@25
|
2607
|
jcallahan@25
|
2608
|
MMOSimca@368
|
2609 -- This function produces data currently unused by wowdb.com, and it causes unneeded bloat in the raw lua DB.
|
MMOSimca@442
|
2610 --[[local LPJ = LibStub("LibPetJournal-2.0")
|
MMOSimca@442
|
2611 function WDP:PET_JOURNAL_LIST_UPDATE(event_name)
|
MMOSimca@346
|
2612 if DEBUGGING then
|
jcallahan@309
|
2613 return
|
jcallahan@309
|
2614 end
|
jcallahan@309
|
2615
|
jcallahan@115
|
2616 local num_pets = LPJ:NumPets()
|
jcallahan@115
|
2617
|
jcallahan@115
|
2618 for index, pet_id in LPJ:IteratePetIDs() do
|
jcallahan@115
|
2619 local _, _, is_owned, _, level, _, _, name, icon, pet_type, npc_id, _, _, is_wild = _G.C_PetJournal.GetPetInfoByIndex(index)
|
jcallahan@115
|
2620
|
jcallahan@115
|
2621 if is_owned then
|
jcallahan@115
|
2622 local health, max_health, attack, speed, rarity = _G.C_PetJournal.GetPetStats(pet_id)
|
jcallahan@115
|
2623
|
jcallahan@139
|
2624 if rarity then
|
jcallahan@139
|
2625 local rarity_name = _G["BATTLE_PET_BREED_QUALITY" .. rarity]
|
jcallahan@139
|
2626 local npc = NPCEntry(npc_id)
|
jcallahan@139
|
2627 npc.wild_pet = is_wild or nil
|
jcallahan@139
|
2628 npc.battle_pet_data = npc.battle_pet_data or {}
|
jcallahan@139
|
2629 npc.battle_pet_data[rarity_name] = npc.battle_pet_data[rarity_name] or {}
|
jcallahan@139
|
2630 npc.battle_pet_data[rarity_name]["level_" .. level] = npc.battle_pet_data[rarity_name]["level_" .. level] or {}
|
jcallahan@139
|
2631
|
jcallahan@139
|
2632 local data = npc.battle_pet_data[rarity_name]["level_" .. level]
|
jcallahan@139
|
2633 data.max_health = max_health
|
jcallahan@139
|
2634 data.attack = attack
|
jcallahan@139
|
2635 data.speed = speed
|
jcallahan@139
|
2636 end
|
jcallahan@115
|
2637 end
|
jcallahan@115
|
2638 end
|
MMOSimca@368
|
2639 end]]--
|
jcallahan@115
|
2640
|
jcallahan@115
|
2641
|
jcallahan@156
|
2642 function WDP:PLAYER_REGEN_DISABLED(event_name)
|
jcallahan@156
|
2643 private.in_combat = true
|
jcallahan@156
|
2644 end
|
jcallahan@156
|
2645
|
jcallahan@156
|
2646
|
jcallahan@156
|
2647 function WDP:PLAYER_REGEN_ENABLED(event_name)
|
jcallahan@156
|
2648 private.in_combat = nil
|
jcallahan@156
|
2649 end
|
jcallahan@156
|
2650
|
jcallahan@156
|
2651
|
jcallahan@118
|
2652 function WDP:PLAYER_TARGET_CHANGED(event_name)
|
jcallahan@215
|
2653 if not TargetedNPC() then
|
jcallahan@118
|
2654 return
|
jcallahan@2
|
2655 end
|
jcallahan@151
|
2656 current_action.target_type = AF.NPC
|
jcallahan@118
|
2657 self:UpdateTargetLocation()
|
jcallahan@118
|
2658 end
|
jcallahan@2
|
2659
|
jcallahan@89
|
2660
|
jcallahan@12
|
2661 do
|
jcallahan@12
|
2662 local function UpdateQuestJuncture(point)
|
jcallahan@12
|
2663 local unit_name = _G.UnitName("questnpc")
|
jcallahan@9
|
2664
|
jcallahan@12
|
2665 if not unit_name then
|
jcallahan@12
|
2666 return
|
jcallahan@12
|
2667 end
|
jcallahan@34
|
2668 local unit_type, unit_id = ParseGUID(_G.UnitGUID("questnpc"))
|
MMOSimca@351
|
2669 Debug("UpdateQuestJuncture: Updating quest juncture for %s.", ("%s:%d"):format(private.UNIT_TYPE_NAMES[unit_type], unit_id))
|
jcallahan@12
|
2670 if unit_type == private.UNIT_TYPES.OBJECT then
|
jcallahan@38
|
2671 UpdateDBEntryLocation("objects", unit_id)
|
jcallahan@12
|
2672 end
|
jcallahan@19
|
2673 local quest = DBEntry("quests", _G.GetQuestID())
|
jcallahan@12
|
2674 quest[point] = quest[point] or {}
|
MMOSimca@329
|
2675 quest[point][("%s:%d"):format(private.UNIT_TYPE_NAMES[unit_type], unit_id)] = true
|
jcallahan@24
|
2676
|
jcallahan@24
|
2677 return quest
|
jcallahan@12
|
2678 end
|
jcallahan@10
|
2679
|
jcallahan@12
|
2680
|
jcallahan@92
|
2681 function WDP:QUEST_COMPLETE(event_name)
|
jcallahan@97
|
2682 local quest = UpdateQuestJuncture("end")
|
catherton@465
|
2683
|
MMOSimca@446
|
2684 if not quest then
|
MMOSimca@446
|
2685 return
|
MMOSimca@446
|
2686 end
|
jcallahan@97
|
2687
|
jcallahan@112
|
2688 if ALLOWED_LOCALES[CLIENT_LOCALE] then
|
jcallahan@112
|
2689 quest.reward_text = ReplaceKeywords(_G.GetRewardText())
|
jcallahan@112
|
2690 end
|
jcallahan@67
|
2691 -- Make sure the quest NPC isn't erroneously recorded as giving reputation for quests which award it.
|
jcallahan@177
|
2692 ClearKilledNPC()
|
jcallahan@10
|
2693 end
|
jcallahan@10
|
2694
|
jcallahan@12
|
2695
|
jcallahan@92
|
2696 function WDP:QUEST_DETAIL(event_name)
|
jcallahan@24
|
2697 local quest = UpdateQuestJuncture("begin")
|
jcallahan@24
|
2698
|
jcallahan@46
|
2699 if not quest then
|
jcallahan@46
|
2700 return
|
jcallahan@46
|
2701 end
|
jcallahan@24
|
2702 quest.classes = quest.classes or {}
|
jcallahan@27
|
2703 quest.classes[PLAYER_CLASS] = true
|
jcallahan@24
|
2704
|
jcallahan@24
|
2705 quest.races = quest.races or {}
|
jcallahan@100
|
2706 quest.races[(PLAYER_RACE == "Pandaren") and ("%s_%s"):format(PLAYER_RACE, PLAYER_FACTION or "Neutral") or PLAYER_RACE] = true
|
jcallahan@10
|
2707 end
|
jcallahan@12
|
2708 end -- do-block
|
jcallahan@9
|
2709
|
jcallahan@9
|
2710
|
jcallahan@92
|
2711 function WDP:QUEST_LOG_UPDATE(event_name)
|
jcallahan@38
|
2712 local selected_quest = _G.GetQuestLogSelection() -- Save current selection to be restored when we're done.
|
jcallahan@36
|
2713 local entry_index, processed_quests = 1, 0
|
jcallahan@36
|
2714 local _, num_quests = _G.GetNumQuestLogEntries()
|
jcallahan@36
|
2715
|
jcallahan@36
|
2716 while processed_quests <= num_quests do
|
MMOSimca@329
|
2717 local _, _, _, is_header, _, _, _, quest_id = _G.GetQuestLogTitle(entry_index)
|
jcallahan@36
|
2718
|
jcallahan@84
|
2719 if quest_id == 0 then
|
jcallahan@84
|
2720 processed_quests = processed_quests + 1
|
jcallahan@84
|
2721 elseif not is_header then
|
jcallahan@36
|
2722 _G.SelectQuestLogEntry(entry_index);
|
jcallahan@36
|
2723
|
jcallahan@36
|
2724 local quest = DBEntry("quests", quest_id)
|
jcallahan@36
|
2725 quest.timer = _G.GetQuestLogTimeLeft()
|
jcallahan@37
|
2726 quest.can_share = _G.GetQuestLogPushable() and true or nil
|
jcallahan@36
|
2727 processed_quests = processed_quests + 1
|
jcallahan@36
|
2728 end
|
jcallahan@36
|
2729 entry_index = entry_index + 1
|
jcallahan@36
|
2730 end
|
jcallahan@36
|
2731 _G.SelectQuestLogEntry(selected_quest)
|
jcallahan@4
|
2732 self:UnregisterEvent("QUEST_LOG_UPDATE")
|
jcallahan@4
|
2733 end
|
jcallahan@4
|
2734
|
jcallahan@4
|
2735
|
jcallahan@97
|
2736 function WDP:QUEST_PROGRESS(event_name)
|
jcallahan@112
|
2737 if not ALLOWED_LOCALES[CLIENT_LOCALE] then
|
jcallahan@112
|
2738 return
|
jcallahan@112
|
2739 end
|
jcallahan@97
|
2740 DBEntry("quests", _G.GetQuestID()).progress_text = ReplaceKeywords(_G.GetProgressText())
|
jcallahan@97
|
2741 end
|
jcallahan@97
|
2742
|
jcallahan@97
|
2743
|
jcallahan@92
|
2744 function WDP:UNIT_QUEST_LOG_CHANGED(event_name, unit_id)
|
jcallahan@4
|
2745 if unit_id ~= "player" then
|
jcallahan@4
|
2746 return
|
jcallahan@4
|
2747 end
|
jcallahan@4
|
2748 self:RegisterEvent("QUEST_LOG_UPDATE")
|
jcallahan@4
|
2749 end
|
jcallahan@4
|
2750
|
jcallahan@4
|
2751
|
jcallahan@92
|
2752 do
|
jcallahan@92
|
2753 local TRADESKILL_TOOLS = {
|
jcallahan@92
|
2754 Anvil = anvil_spell_ids,
|
jcallahan@92
|
2755 Forge = forge_spell_ids,
|
jcallahan@92
|
2756 }
|
jcallahan@92
|
2757
|
jcallahan@92
|
2758
|
jcallahan@167
|
2759 local function RegisterTools(tradeskill_name, tradeskill_index)
|
catherton@479
|
2760 local link = _G.C_TradeSkillUI.GetRecipeLink(tradeskill_index)
|
catherton@465
|
2761
|
MMOSimca@352
|
2762 if link then
|
MMOSimca@352
|
2763 local spell_id = tonumber(link:match("^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)"))
|
catherton@479
|
2764 local required_tool = _G.C_TradeSkillUI.GetRecipeTools(tradeskill_index)
|
MMOSimca@352
|
2765
|
MMOSimca@352
|
2766 if required_tool then
|
MMOSimca@352
|
2767 for tool_name, registry in pairs(TRADESKILL_TOOLS) do
|
MMOSimca@352
|
2768 if required_tool:find(tool_name) then
|
MMOSimca@352
|
2769 registry[spell_id] = true
|
MMOSimca@352
|
2770 end
|
jcallahan@167
|
2771 end
|
jcallahan@167
|
2772 end
|
jcallahan@167
|
2773 end
|
jcallahan@167
|
2774 end
|
jcallahan@167
|
2775
|
jcallahan@167
|
2776
|
jcallahan@92
|
2777 function WDP:TRADE_SKILL_SHOW(event_name)
|
catherton@479
|
2778 local profession_name, prof_level = _G.C_TradeSkillUI.GetTradeSkillLine()
|
jcallahan@92
|
2779
|
jcallahan@92
|
2780 if profession_name == _G.UNKNOWN then
|
jcallahan@92
|
2781 return
|
jcallahan@92
|
2782 end
|
jcallahan@167
|
2783 TradeSkillExecutePer(RegisterTools)
|
jcallahan@92
|
2784 end
|
jcallahan@92
|
2785 end -- do-block
|
jcallahan@92
|
2786
|
jcallahan@92
|
2787
|
jcallahan@167
|
2788 function WDP:TRAINER_CLOSED(event_name)
|
jcallahan@167
|
2789 private.trainer_shown = nil
|
jcallahan@167
|
2790 end
|
jcallahan@167
|
2791
|
jcallahan@167
|
2792
|
jcallahan@92
|
2793 function WDP:TRAINER_SHOW(event_name)
|
jcallahan@232
|
2794 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@164
|
2795 local trainer = NPCEntry(unit_idnum)
|
jcallahan@58
|
2796
|
jcallahan@164
|
2797 if not trainer then
|
jcallahan@58
|
2798 return
|
jcallahan@58
|
2799 end
|
jcallahan@331
|
2800 local _, trainer_standing = UnitFactionStanding("npc")
|
jcallahan@164
|
2801 trainer.teaches = trainer.teaches or {}
|
jcallahan@27
|
2802
|
jcallahan@167
|
2803 private.trainer_shown = true
|
jcallahan@167
|
2804
|
jcallahan@27
|
2805 -- Get the initial trainer filters
|
MMOSimca@344
|
2806 local available = _G.GetTrainerServiceTypeFilter("available") and 1 or 0
|
MMOSimca@344
|
2807 local unavailable = _G.GetTrainerServiceTypeFilter("unavailable") and 1 or 0
|
MMOSimca@344
|
2808 local used = _G.GetTrainerServiceTypeFilter("used") and 1 or 0
|
jcallahan@27
|
2809
|
jcallahan@27
|
2810 -- Clear the trainer filters
|
MMOSimca@344
|
2811 _G.SetTrainerServiceTypeFilter("available", 1)
|
MMOSimca@344
|
2812 _G.SetTrainerServiceTypeFilter("unavailable", 1)
|
MMOSimca@344
|
2813 _G.SetTrainerServiceTypeFilter("used", 1)
|
jcallahan@27
|
2814
|
jcallahan@27
|
2815 for index = 1, _G.GetNumTrainerServices(), 1 do
|
jcallahan@27
|
2816 local spell_name, rank_name, _, _, required_level = _G.GetTrainerServiceInfo(index)
|
jcallahan@27
|
2817
|
jcallahan@27
|
2818 if spell_name then
|
jcallahan@27
|
2819 DatamineTT:ClearLines()
|
jcallahan@27
|
2820 DatamineTT:SetTrainerService(index)
|
jcallahan@27
|
2821
|
jcallahan@27
|
2822 local _, _, spell_id = DatamineTT:GetSpell()
|
jcallahan@27
|
2823
|
jcallahan@43
|
2824 if spell_id then
|
jcallahan@164
|
2825 local class_professions = trainer.teaches[PLAYER_CLASS]
|
jcallahan@164
|
2826
|
jcallahan@164
|
2827 if not class_professions then
|
jcallahan@164
|
2828 trainer.teaches[PLAYER_CLASS] = {}
|
jcallahan@164
|
2829 class_professions = trainer.teaches[PLAYER_CLASS]
|
jcallahan@164
|
2830 end
|
jcallahan@43
|
2831 local profession, min_skill = _G.GetTrainerServiceSkillReq(index)
|
jcallahan@43
|
2832 profession = profession or "General"
|
jcallahan@43
|
2833
|
jcallahan@164
|
2834 local profession_skills = class_professions[profession]
|
jcallahan@43
|
2835
|
jcallahan@43
|
2836 if not profession_skills then
|
jcallahan@43
|
2837 class_professions[profession] = {}
|
jcallahan@43
|
2838 profession_skills = class_professions[profession]
|
jcallahan@43
|
2839 end
|
jcallahan@173
|
2840 profession_skills[spell_id] = ("%d:%d:%d"):format(required_level, min_skill, _G.GetTrainerServiceCost(index))
|
jcallahan@27
|
2841 end
|
jcallahan@27
|
2842 end
|
jcallahan@27
|
2843 end
|
jcallahan@27
|
2844 -- Reset the filters to what they were before
|
MMOSimca@344
|
2845 _G.SetTrainerServiceTypeFilter("available", available or 0)
|
MMOSimca@344
|
2846 _G.SetTrainerServiceTypeFilter("unavailable", unavailable or 0)
|
MMOSimca@344
|
2847 _G.SetTrainerServiceTypeFilter("used", used or 0)
|
jcallahan@27
|
2848 end
|
jcallahan@27
|
2849
|
jcallahan@27
|
2850
|
jcallahan@1
|
2851 function WDP:UNIT_SPELLCAST_SENT(event_name, unit_id, spell_name, spell_rank, target_name, spell_line)
|
jcallahan@1
|
2852 if private.tracked_line or unit_id ~= "player" then
|
jcallahan@1
|
2853 return
|
jcallahan@1
|
2854 end
|
jcallahan@1
|
2855 local spell_label = private.SPELL_LABELS_BY_NAME[spell_name]
|
jcallahan@1
|
2856
|
jcallahan@1
|
2857 if not spell_label then
|
jcallahan@1
|
2858 return
|
jcallahan@1
|
2859 end
|
jcallahan@306
|
2860
|
MMOSimca@343
|
2861 Debug("UNIT_SPELLCAST_SENT: %s was cast.", spell_name)
|
jcallahan@150
|
2862 local item_name, item_link = _G.GameTooltip:GetItem()
|
jcallahan@150
|
2863 local unit_name, unit_id = _G.GameTooltip:GetUnit()
|
jcallahan@1
|
2864
|
jcallahan@150
|
2865 if not unit_name and _G.UnitName("target") == target_name then
|
jcallahan@150
|
2866 unit_name = target_name
|
jcallahan@150
|
2867 unit_id = "target"
|
jcallahan@1
|
2868 end
|
jcallahan@1
|
2869 local spell_flags = private.SPELL_FLAGS_BY_LABEL[spell_label]
|
jcallahan@28
|
2870 local zone_name, area_id, x, y, map_level, instance_token = CurrentLocationData()
|
MMOSimca@328
|
2871 if not (zone_name and area_id and x and y and map_level) then
|
mmosimca@508
|
2872 if not (_G.IsInInstance()) then
|
mmosimca@508
|
2873 Debug("%s: Missing current location data - %s, %s, %s, %s, %s.", event_name, tostring(zone_name), tostring(area_id), tostring(x), tostring(y), tostring(map_level))
|
mmosimca@508
|
2874 end
|
MMOSimca@328
|
2875 return
|
MMOSimca@328
|
2876 end
|
jcallahan@28
|
2877
|
jcallahan@205
|
2878 table.wipe(current_action)
|
jcallahan@122
|
2879 current_action.instance_token = instance_token
|
jcallahan@122
|
2880 current_action.map_level = map_level
|
jcallahan@122
|
2881 current_action.x = x
|
jcallahan@122
|
2882 current_action.y = y
|
jcallahan@122
|
2883 current_action.zone_data = ("%s:%d"):format(zone_name, area_id)
|
jcallahan@122
|
2884 current_action.spell_label = spell_label
|
jcallahan@105
|
2885
|
jcallahan@105
|
2886 if not private.NON_LOOT_SPELL_LABELS[spell_label] then
|
jcallahan@122
|
2887 current_action.loot_label = spell_label:lower()
|
jcallahan@105
|
2888 end
|
jcallahan@1
|
2889
|
jcallahan@151
|
2890 if unit_name and unit_name == target_name and not item_name then
|
jcallahan@16
|
2891 if bit.band(spell_flags, AF.NPC) == AF.NPC then
|
jcallahan@150
|
2892 if not unit_id or unit_name ~= target_name then
|
jcallahan@16
|
2893 return
|
jcallahan@16
|
2894 end
|
jcallahan@123
|
2895 current_action.target_type = AF.NPC
|
jcallahan@16
|
2896 end
|
jcallahan@16
|
2897 elseif bit.band(spell_flags, AF.ITEM) == AF.ITEM then
|
jcallahan@123
|
2898 current_action.target_type = AF.ITEM
|
jcallahan@16
|
2899
|
jcallahan@150
|
2900 if item_name and item_name == target_name then
|
jcallahan@150
|
2901 current_action.identifier = ItemLinkToID(item_link)
|
jcallahan@16
|
2902 elseif target_name and target_name ~= "" then
|
jcallahan@331
|
2903 local _, item_link = _G.GetItemInfo(target_name)
|
jcallahan@331
|
2904 current_action.identifier = ItemLinkToID(item_link)
|
jcallahan@16
|
2905 end
|
jcallahan@150
|
2906 elseif not item_name and not unit_name then
|
jcallahan@1
|
2907 if bit.band(spell_flags, AF.OBJECT) == AF.OBJECT then
|
jcallahan@17
|
2908 if target_name == "" then
|
jcallahan@17
|
2909 return
|
jcallahan@17
|
2910 end
|
jcallahan@122
|
2911 current_action.object_name = target_name
|
jcallahan@123
|
2912 current_action.target_type = AF.OBJECT
|
jcallahan@1
|
2913 elseif bit.band(spell_flags, AF.ZONE) == AF.ZONE then
|
jcallahan@123
|
2914 current_action.target_type = AF.ZONE
|
jcallahan@1
|
2915 end
|
jcallahan@1
|
2916 end
|
jcallahan@1
|
2917 private.tracked_line = spell_line
|
jcallahan@0
|
2918 end
|
jcallahan@0
|
2919
|
jcallahan@94
|
2920
|
MMOSimca@393
|
2921 -- Triggered by bonus roll prompts, disenchant prompts, and in a few other rare circumstances
|
jcallahan@312
|
2922 function WDP:SPELL_CONFIRMATION_PROMPT(event_name, spell_id, confirm_type, text, duration, currency_id_cost)
|
jcallahan@306
|
2923 if private.RAID_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id] then
|
jcallahan@306
|
2924 ClearKilledBossID()
|
jcallahan@306
|
2925 ClearLootToastContainerID()
|
MMOSimca@387
|
2926 raid_boss_id = private.RAID_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id]
|
jcallahan@306
|
2927 else
|
MMOSimca@336
|
2928 Debug("%s: Spell ID %d is not a known raid boss 'Bonus' spell.", event_name, spell_id)
|
jcallahan@306
|
2929 return
|
jcallahan@1
|
2930 end
|
jcallahan@306
|
2931
|
jcallahan@324
|
2932 -- Assign existing loot data to boss if it exists
|
jcallahan@307
|
2933 if loot_toast_data then
|
MMOSimca@427
|
2934 local npc = NPCEntry(raid_boss_id)
|
MMOSimca@427
|
2935 if npc then
|
MMOSimca@427
|
2936 -- Create needed npc fields if required
|
MMOSimca@427
|
2937 local loot_label = "drops"
|
MMOSimca@427
|
2938 local encounter_data = npc:EncounterData(InstanceDifficultyToken())
|
MMOSimca@427
|
2939 encounter_data[loot_label] = encounter_data[loot_label] or {}
|
MMOSimca@427
|
2940 encounter_data.loot_counts = encounter_data.loot_counts or {}
|
MMOSimca@427
|
2941
|
MMOSimca@427
|
2942 for index = 1, #loot_toast_data do
|
MMOSimca@427
|
2943 local data = loot_toast_data[index]
|
MMOSimca@427
|
2944 local loot_type = data[1]
|
MMOSimca@427
|
2945 local hyperlink = data[2]
|
MMOSimca@427
|
2946 local quantity = data[3]
|
MMOSimca@427
|
2947
|
MMOSimca@427
|
2948 if loot_type == "item" then
|
MMOSimca@427
|
2949 local item_id = ItemLinkToID(hyperlink)
|
MMOSimca@427
|
2950 Debug("%s: Assigned stored item loot data - %s - %d:%d", event_name, hyperlink, item_id, quantity)
|
MMOSimca@427
|
2951 table.insert(encounter_data[loot_label], ("%d:%d"):format(item_id, quantity))
|
MMOSimca@427
|
2952 elseif loot_type == "money" then
|
MMOSimca@427
|
2953 Debug("%s: Assigned stored money loot data - money:%d", event_name, quantity)
|
MMOSimca@427
|
2954 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
|
MMOSimca@427
|
2955 elseif loot_type == "currency" then
|
mmosimca@496
|
2956 local currency_id = CurrencyLinkToID(hyperlink)
|
mmosimca@496
|
2957 Debug("%s: Assigned stored currency loot data - %s - currency:%d (%d)", event_name, hyperlink, currency_id, quantity)
|
mmosimca@496
|
2958 table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
|
MMOSimca@427
|
2959 end
|
jcallahan@317
|
2960 end
|
jcallahan@317
|
2961
|
MMOSimca@427
|
2962 if not boss_loot_toasting[raid_boss_id] then
|
MMOSimca@427
|
2963 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
|
MMOSimca@427
|
2964 boss_loot_toasting[raid_boss_id] = true -- Do not count further loots until timer expires or another boss is killed
|
jcallahan@307
|
2965 end
|
MMOSimca@427
|
2966 else
|
MMOSimca@427
|
2967 Debug("%s: NPC is nil, but we have stored loot data...", event_name)
|
jcallahan@307
|
2968 end
|
jcallahan@307
|
2969 end
|
jcallahan@307
|
2970
|
jcallahan@307
|
2971 ClearLootToastData()
|
MMOSimca@427
|
2972 killed_boss_id_timer_handle = C_Timer.NewTimer(5, ClearKilledBossID)
|
jcallahan@306
|
2973 end
|
jcallahan@306
|
2974
|
jcallahan@306
|
2975
|
jcallahan@306
|
2976 function WDP:UNIT_SPELLCAST_SUCCEEDED(event_name, unit_id, spell_name, spell_rank, spell_line, spell_id)
|
jcallahan@306
|
2977 if unit_id ~= "player" then
|
jcallahan@306
|
2978 return
|
jcallahan@306
|
2979 end
|
jcallahan@306
|
2980 private.tracked_line = nil
|
jcallahan@306
|
2981 private.previous_spell_id = spell_id
|
jcallahan@306
|
2982
|
MMOSimca@393
|
2983 -- For spells cast when Logging
|
MMOSimca@345
|
2984 if private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[spell_id] then
|
MMOSimca@345
|
2985 last_timber_spell_id = spell_id
|
MMOSimca@351
|
2986 UpdateDBEntryLocation("objects", ("OPENING:%s"):format(private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[spell_id]))
|
MMOSimca@345
|
2987 return
|
MMOSimca@345
|
2988 end
|
MMOSimca@345
|
2989
|
MMOSimca@393
|
2990 -- For spells cast by items that always trigger loot toasts
|
MMOSimca@381
|
2991 if private.LOOT_TOAST_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id] then
|
jcallahan@306
|
2992 ClearKilledBossID()
|
jcallahan@306
|
2993 ClearLootToastContainerID()
|
jcallahan@307
|
2994 ClearLootToastData()
|
jcallahan@306
|
2995
|
MMOSimca@387
|
2996 loot_toast_container_id = private.LOOT_TOAST_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id]
|
MMOSimca@383
|
2997 loot_toast_container_timer_handle = C_Timer.NewTimer(1, ClearLootToastContainerID) -- we need to assign a handle here to cancel it later
|
MMOSimca@345
|
2998 return
|
jcallahan@306
|
2999 end
|
jcallahan@306
|
3000
|
MMOSimca@393
|
3001 -- For spells cast by items that don't usually trigger loot toasts
|
catherton@473
|
3002 if not block_chat_loot_data and (private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id] or (private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_BY_CLASS_ID_MAP[spell_id] and private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_BY_CLASS_ID_MAP[spell_id][PLAYER_CLASS_ID])) then
|
MMOSimca@347
|
3003 -- Set up timer
|
MMOSimca@393
|
3004 ClearChatLootData()
|
MMOSimca@393
|
3005 Debug("%s: Beginning chat-based loot timer for spellID %d", event_name, spell_id)
|
MMOSimca@411
|
3006 chat_loot_timer_handle = C_Timer.NewTimer(1.5, ClearChatLootData)
|
catherton@473
|
3007 if (private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_BY_CLASS_ID_MAP[spell_id] and private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_BY_CLASS_ID_MAP[spell_id][PLAYER_CLASS_ID]) then
|
catherton@473
|
3008 chat_loot_data.identifier = private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_BY_CLASS_ID_MAP[spell_id][PLAYER_CLASS_ID]
|
MMOSimca@454
|
3009 else
|
MMOSimca@454
|
3010 chat_loot_data.identifier = private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id]
|
MMOSimca@454
|
3011 end
|
MMOSimca@347
|
3012 return
|
MMOSimca@347
|
3013 end
|
MMOSimca@347
|
3014
|
mmosimca@520
|
3015 -- For Ephemeral Crystals (uses a combination of mouseover text and a 'Update Interactions' spell cast to detect the object - this is incredibly hacky but there is no alternative)
|
mmosimca@520
|
3016 local text = _G["GameTooltipTextLeft1"] and _G["GameTooltipTextLeft1"]:GetText() or nil
|
mmosimca@520
|
3017 if spell_id == SPELL_ID_UPDATE_INTERACTIONS and text and text == "Ephemeral Crystal" then
|
mmosimca@522
|
3018 Debug("%s: Detected location for an Ephemeral Crystal.", event_name)
|
mmosimca@520
|
3019 for index = 1, #private.EPHEMERAL_CRYSTAL_OBJECT_IDS do
|
mmosimca@520
|
3020 UpdateDBEntryLocation("objects", private.EPHEMERAL_CRYSTAL_OBJECT_IDS[index])
|
mmosimca@520
|
3021 end
|
mmosimca@520
|
3022 end
|
mmosimca@520
|
3023
|
jcallahan@306
|
3024 if anvil_spell_ids[spell_id] then
|
jcallahan@306
|
3025 UpdateDBEntryLocation("objects", OBJECT_ID_ANVIL)
|
jcallahan@306
|
3026 elseif forge_spell_ids[spell_id] then
|
jcallahan@306
|
3027 UpdateDBEntryLocation("objects", OBJECT_ID_FORGE)
|
jcallahan@306
|
3028 elseif spell_name:match("^Harvest.+") then
|
jcallahan@306
|
3029 killed_npc_id = current_target_id
|
MMOSimca@343
|
3030 private.harvesting = true -- Used to track which NPCs can be harvested (can we get this from CreatureCache instead?)
|
jcallahan@306
|
3031 end
|
jcallahan@306
|
3032 end
|
jcallahan@0
|
3033
|
jcallahan@90
|
3034
|
jcallahan@1
|
3035 function WDP:HandleSpellFailure(event_name, unit_id, spell_name, spell_rank, spell_line, spell_id)
|
jcallahan@1
|
3036 if unit_id ~= "player" then
|
jcallahan@1
|
3037 return
|
jcallahan@1
|
3038 end
|
jcallahan@0
|
3039
|
jcallahan@1
|
3040 if private.tracked_line == spell_line then
|
jcallahan@1
|
3041 private.tracked_line = nil
|
jcallahan@1
|
3042 end
|
jcallahan@147
|
3043 table.wipe(current_action)
|
jcallahan@0
|
3044 end
|
jcallahan@90
|
3045
|
jcallahan@90
|
3046
|
jcallahan@90
|
3047 do
|
jcallahan@90
|
3048 local function SetUnitField(field, required_type)
|
jcallahan@90
|
3049 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@90
|
3050
|
jcallahan@90
|
3051 if not unit_idnum or (required_type and unit_type ~= required_type) then
|
jcallahan@90
|
3052 return
|
jcallahan@90
|
3053 end
|
jcallahan@90
|
3054
|
jcallahan@171
|
3055 if UnitTypeIsNPC(unit_type) then
|
jcallahan@90
|
3056 NPCEntry(unit_idnum)[field] = true
|
jcallahan@90
|
3057 elseif unit_type == private.UNIT_TYPES.OBJECT then
|
jcallahan@90
|
3058 DBEntry("objects", unit_idnum)[field] = true
|
jcallahan@93
|
3059 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@90
|
3060 end
|
jcallahan@90
|
3061 end
|
jcallahan@90
|
3062
|
jcallahan@90
|
3063
|
jcallahan@90
|
3064 function WDP:AUCTION_HOUSE_SHOW(event_name)
|
MMOSimca@436
|
3065 WDP:StopChatLootRecording(event_name)
|
jcallahan@90
|
3066 SetUnitField("auctioneer", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3067 end
|
jcallahan@90
|
3068
|
jcallahan@90
|
3069
|
jcallahan@90
|
3070 function WDP:BANKFRAME_OPENED(event_name)
|
MMOSimca@436
|
3071 WDP:StopChatLootRecording(event_name)
|
jcallahan@90
|
3072 SetUnitField("banker", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3073 end
|
jcallahan@90
|
3074
|
jcallahan@90
|
3075
|
jcallahan@90
|
3076 function WDP:BATTLEFIELDS_SHOW(event_name)
|
jcallahan@90
|
3077 SetUnitField("battlemaster", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3078 end
|
jcallahan@90
|
3079
|
jcallahan@90
|
3080
|
jcallahan@92
|
3081 function WDP:FORGE_MASTER_OPENED(event_name)
|
jcallahan@90
|
3082 SetUnitField("arcane_reforger", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3083 end
|
jcallahan@90
|
3084
|
jcallahan@90
|
3085
|
jcallahan@323
|
3086 local GOSSIP_SHOW_FUNCS = {
|
jcallahan@323
|
3087 [private.UNIT_TYPES.NPC] = function(unit_idnum)
|
jcallahan@323
|
3088 local gossip_options = { _G.GetGossipOptions() }
|
jcallahan@323
|
3089
|
jcallahan@323
|
3090 for index = 2, #gossip_options, 2 do
|
jcallahan@323
|
3091 if gossip_options[index] == "binder" then
|
jcallahan@323
|
3092 SetUnitField("innkeeper", private.UNIT_TYPES.NPC)
|
jcallahan@323
|
3093 return
|
jcallahan@323
|
3094 end
|
jcallahan@323
|
3095 end
|
jcallahan@323
|
3096 end,
|
jcallahan@323
|
3097 [private.UNIT_TYPES.OBJECT] = function(unit_idnum)
|
jcallahan@323
|
3098 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@323
|
3099 end,
|
jcallahan@323
|
3100 }
|
jcallahan@323
|
3101
|
jcallahan@323
|
3102
|
jcallahan@92
|
3103 function WDP:GOSSIP_SHOW(event_name)
|
MMOSimca@436
|
3104 WDP:StopChatLootRecording(event_name)
|
jcallahan@323
|
3105 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@323
|
3106 if not unit_idnum then
|
jcallahan@323
|
3107 return
|
jcallahan@323
|
3108 end
|
jcallahan@323
|
3109
|
jcallahan@323
|
3110 if GOSSIP_SHOW_FUNCS[unit_type] then
|
jcallahan@323
|
3111 GOSSIP_SHOW_FUNCS[unit_type](unit_idnum)
|
jcallahan@90
|
3112 end
|
jcallahan@90
|
3113 end
|
jcallahan@90
|
3114
|
jcallahan@90
|
3115
|
jcallahan@93
|
3116 function WDP:GUILDBANKFRAME_OPENED(event_name)
|
MMOSimca@436
|
3117 WDP:StopChatLootRecording(event_name)
|
jcallahan@93
|
3118 SetUnitField("guild_bank", private.UNIT_TYPES.OBJECT)
|
jcallahan@93
|
3119 end
|
jcallahan@93
|
3120
|
jcallahan@93
|
3121
|
jcallahan@189
|
3122 function WDP:ITEM_UPGRADE_MASTER_OPENED(event_name)
|
jcallahan@189
|
3123 SetUnitField("item_upgrade_master", private.UNIT_TYPES.NPC)
|
jcallahan@189
|
3124 end
|
jcallahan@189
|
3125
|
jcallahan@189
|
3126
|
jcallahan@90
|
3127 function WDP:TAXIMAP_OPENED(event_name)
|
jcallahan@90
|
3128 SetUnitField("flight_master", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3129 end
|
jcallahan@90
|
3130
|
jcallahan@90
|
3131
|
jcallahan@90
|
3132 function WDP:TRANSMOGRIFY_OPEN(event_name)
|
jcallahan@90
|
3133 SetUnitField("transmogrifier", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3134 end
|
jcallahan@90
|
3135
|
jcallahan@90
|
3136
|
jcallahan@90
|
3137 function WDP:VOID_STORAGE_OPEN(event_name)
|
jcallahan@90
|
3138 SetUnitField("void_storage", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3139 end
|
jcallahan@90
|
3140 end -- do-block
|