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