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