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