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