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)
|
catherton@470
|
1847 [224762] = true, -- Leyline Rift (summoned by players with Leyline Mastery in Suramar)
|
catherton@474
|
1848 [225832] = true, -- Nightglow Wisp (cast by players using Wisp in a Bottle toy)
|
MMOSimca@405
|
1849 }
|
MMOSimca@405
|
1850
|
jcallahan@23
|
1851 local function RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
|
MMOSimca@405
|
1852 if not spell_id or BLACKLISTED_SPELLS[spell_id] then
|
jcallahan@23
|
1853 return
|
jcallahan@23
|
1854 end
|
jcallahan@34
|
1855 local source_type, source_id = ParseGUID(source_guid)
|
jcallahan@23
|
1856
|
jcallahan@171
|
1857 if not source_id or not UnitTypeIsNPC(source_type) then
|
jcallahan@23
|
1858 return
|
jcallahan@23
|
1859 end
|
jcallahan@23
|
1860
|
jcallahan@23
|
1861 if bit.band(FLAGS_NPC_CONTROL, source_flags) == FLAGS_NPC_CONTROL and bit.band(FLAGS_NPC, source_flags) ~= 0 then
|
jcallahan@248
|
1862 local encounter_data = NPCEntry(source_id):EncounterData(InstanceDifficultyToken())
|
jcallahan@28
|
1863 encounter_data.spells = encounter_data.spells or {}
|
jcallahan@28
|
1864 encounter_data.spells[spell_id] = (encounter_data.spells[spell_id] or 0) + 1
|
jcallahan@23
|
1865 end
|
jcallahan@23
|
1866 end
|
jcallahan@23
|
1867
|
jcallahan@115
|
1868 local HEAL_BATTLE_PETS_SPELL_ID = 125801
|
jcallahan@115
|
1869
|
jcallahan@246
|
1870 local previous_combat_event = {}
|
jcallahan@246
|
1871
|
jcallahan@23
|
1872 local COMBAT_LOG_FUNCS = {
|
jcallahan@23
|
1873 SPELL_AURA_APPLIED = RecordNPCSpell,
|
jcallahan@23
|
1874 SPELL_CAST_START = RecordNPCSpell,
|
jcallahan@115
|
1875 SPELL_CAST_SUCCESS = function(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
|
jcallahan@115
|
1876 if spell_id == HEAL_BATTLE_PETS_SPELL_ID then
|
jcallahan@115
|
1877 local unit_type, unit_idnum = ParseGUID(source_guid)
|
jcallahan@115
|
1878
|
jcallahan@171
|
1879 if unit_idnum and UnitTypeIsNPC(unit_type) then
|
jcallahan@115
|
1880 NPCEntry(unit_idnum).stable_master = true
|
jcallahan@115
|
1881 end
|
jcallahan@115
|
1882 end
|
jcallahan@115
|
1883 RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
|
jcallahan@115
|
1884 end,
|
jcallahan@65
|
1885 UNIT_DIED = function(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id, spell_name)
|
jcallahan@65
|
1886 local unit_type, unit_idnum = ParseGUID(dest_guid)
|
jcallahan@65
|
1887
|
jcallahan@171
|
1888 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
jcallahan@245
|
1889 Debug("%s: %s is not an NPC, or has no ID.", sub_event, dest_name or _G.UNKNOWN)
|
jcallahan@177
|
1890 ClearKilledNPC()
|
jcallahan@98
|
1891 private.harvesting = nil
|
jcallahan@65
|
1892 return
|
jcallahan@65
|
1893 end
|
jcallahan@177
|
1894
|
jcallahan@246
|
1895 if source_guid == "" then
|
jcallahan@246
|
1896 source_guid = nil
|
jcallahan@246
|
1897 end
|
jcallahan@246
|
1898 local killer_guid = source_guid or previous_combat_event.source_guid
|
jcallahan@246
|
1899 local killer_name = source_name or previous_combat_event.source_name
|
jcallahan@246
|
1900
|
jcallahan@299
|
1901 if not previous_combat_event.party_damage then
|
jcallahan@312
|
1902 --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
|
1903 table.wipe(previous_combat_event)
|
jcallahan@217
|
1904 ClearKilledNPC()
|
jcallahan@306
|
1905 else
|
jcallahan@317
|
1906 --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
|
1907 end
|
jcallahan@177
|
1908 killed_npc_id = unit_idnum
|
MMOSimca@383
|
1909 C_Timer.After(0.1, ClearKilledNPC)
|
jcallahan@65
|
1910 end,
|
jcallahan@23
|
1911 }
|
jcallahan@23
|
1912
|
jcallahan@23
|
1913
|
jcallahan@246
|
1914 local NON_DAMAGE_EVENTS = {
|
jcallahan@246
|
1915 SPELL_AURA_APPLIED = true,
|
jcallahan@246
|
1916 SPELL_AURA_REMOVED = true,
|
jcallahan@246
|
1917 SPELL_AURA_REMOVED_DOSE = true,
|
jcallahan@246
|
1918 SPELL_CAST_FAILED = true,
|
jcallahan@246
|
1919 SWING_MISSED = true,
|
jcallahan@246
|
1920 }
|
jcallahan@246
|
1921
|
jcallahan@299
|
1922 local DAMAGE_EVENTS = {
|
jcallahan@299
|
1923 RANGE_DAMAGE = true,
|
jcallahan@299
|
1924 SPELL_BUILDING_DAMAGE = true,
|
jcallahan@299
|
1925 SPELL_DAMAGE = true,
|
jcallahan@299
|
1926 SPELL_PERIODIC_DAMAGE = true,
|
jcallahan@299
|
1927 SWING_DAMAGE = true,
|
jcallahan@299
|
1928 }
|
jcallahan@299
|
1929
|
jcallahan@246
|
1930
|
jcallahan@92
|
1931 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
|
1932 local combat_log_func = COMBAT_LOG_FUNCS[sub_event]
|
jcallahan@23
|
1933
|
jcallahan@23
|
1934 if not combat_log_func then
|
jcallahan@299
|
1935 if DAMAGE_EVENTS[sub_event] then
|
jcallahan@299
|
1936 table.wipe(previous_combat_event)
|
jcallahan@246
|
1937 previous_combat_event.source_name = source_name
|
jcallahan@299
|
1938
|
jcallahan@299
|
1939 if source_guid ~= dest_guid and (in_instance or group_member_guids[source_guid] or group_pet_guids[source_guid]) then
|
jcallahan@299
|
1940 previous_combat_event.party_damage = true
|
jcallahan@299
|
1941 end
|
jcallahan@246
|
1942 end
|
jcallahan@23
|
1943 return
|
jcallahan@23
|
1944 end
|
jcallahan@23
|
1945 combat_log_func(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, ...)
|
jcallahan@297
|
1946
|
jcallahan@297
|
1947 if NON_DAMAGE_EVENTS[sub_event] then
|
jcallahan@297
|
1948 table.wipe(previous_combat_event)
|
jcallahan@297
|
1949 end
|
jcallahan@23
|
1950 end
|
jcallahan@23
|
1951
|
catherton@465
|
1952
|
jcallahan@44
|
1953 local DIPLOMACY_SPELL_ID = 20599
|
jcallahan@44
|
1954 local MR_POP_RANK1_SPELL_ID = 78634
|
jcallahan@44
|
1955 local MR_POP_RANK2_SPELL_ID = 78635
|
MMOSimca@418
|
1956 local TRADING_PACT_SPELL_ID = 170200
|
jcallahan@44
|
1957
|
jcallahan@44
|
1958
|
jcallahan@92
|
1959 function WDP:COMBAT_TEXT_UPDATE(event_name, message_type, faction_name, amount)
|
jcallahan@177
|
1960 if message_type ~= "FACTION" or not killed_npc_id then
|
jcallahan@44
|
1961 return
|
jcallahan@44
|
1962 end
|
jcallahan@44
|
1963 UpdateFactionData()
|
jcallahan@44
|
1964
|
jcallahan@46
|
1965 if not faction_name or not faction_standings[faction_name] then
|
jcallahan@46
|
1966 return
|
jcallahan@46
|
1967 end
|
jcallahan@177
|
1968 local npc = NPCEntry(killed_npc_id)
|
jcallahan@177
|
1969 ClearKilledNPC()
|
jcallahan@46
|
1970
|
jcallahan@44
|
1971 if not npc then
|
jcallahan@98
|
1972 private.harvesting = nil
|
jcallahan@44
|
1973 return
|
jcallahan@44
|
1974 end
|
jcallahan@98
|
1975 npc.harvested = private.harvesting
|
jcallahan@98
|
1976 private.harvesting = nil
|
jcallahan@98
|
1977
|
jcallahan@44
|
1978 local modifier = 1
|
jcallahan@44
|
1979
|
MMOSimca@340
|
1980 -- Check for modifiers from known spells
|
jcallahan@44
|
1981 if _G.IsSpellKnown(DIPLOMACY_SPELL_ID) then
|
jcallahan@44
|
1982 modifier = modifier + 0.1
|
jcallahan@44
|
1983 end
|
jcallahan@44
|
1984 if _G.IsSpellKnown(MR_POP_RANK2_SPELL_ID) then
|
jcallahan@44
|
1985 modifier = modifier + 0.1
|
jcallahan@44
|
1986 elseif _G.IsSpellKnown(MR_POP_RANK1_SPELL_ID) then
|
jcallahan@44
|
1987 modifier = modifier + 0.05
|
jcallahan@44
|
1988 end
|
MMOSimca@418
|
1989 if _G.IsSpellKnown(TRADING_PACT_SPELL_ID) then
|
MMOSimca@418
|
1990 modifier = modifier + 0.2
|
MMOSimca@418
|
1991 end
|
jcallahan@44
|
1992
|
MMOSimca@340
|
1993 -- Determine faction ID
|
MMOSimca@340
|
1994 local faction_ID
|
MMOSimca@418
|
1995 for pseudo_faction_name, faction_data_table in pairs(private.FACTION_DATA) do
|
MMOSimca@418
|
1996 if faction_name == faction_data_table[3] then
|
MMOSimca@418
|
1997 -- Check ignore flag
|
MMOSimca@418
|
1998 if faction_data_table[2] then
|
MMOSimca@418
|
1999 return
|
MMOSimca@418
|
2000 end
|
MMOSimca@340
|
2001 faction_ID = faction_data_table[1]
|
MMOSimca@418
|
2002 break
|
MMOSimca@340
|
2003 end
|
MMOSimca@340
|
2004 end
|
MMOSimca@340
|
2005 if faction_ID and faction_ID > 0 then
|
MMOSimca@340
|
2006 -- Check for modifiers from Commendations (applied directly to the faction, account-wide)
|
MMOSimca@340
|
2007 local _, _, _, _, _, _, _, _, _, _, _, _, _, _, has_bonus_rep_gain = GetFactionInfoByID(faction_ID)
|
MMOSimca@340
|
2008 if has_bonus_rep_gain then
|
MMOSimca@340
|
2009 modifier = modifier + 1
|
MMOSimca@340
|
2010 end
|
MMOSimca@340
|
2011 end
|
MMOSimca@340
|
2012
|
MMOSimca@340
|
2013 -- Check for modifiers from buffs
|
MMOSimca@418
|
2014 for buff_name, buff_data_table in pairs(private.REP_BUFFS) do
|
jcallahan@44
|
2015 if _G.UnitBuff("player", buff_name) then
|
MMOSimca@340
|
2016 local modded_faction = buff_data_table.faction
|
jcallahan@44
|
2017
|
jcallahan@44
|
2018 if not modded_faction or faction_name == modded_faction then
|
MMOSimca@340
|
2019 if buff_data_table.ignore then
|
MMOSimca@340
|
2020 -- Some buffs from tabards convert all rep of other factions into rep for a specific faction.
|
MMOSimca@340
|
2021 -- We can't know what faction the rep was orginally from, so we must ignore the data entirely in these cases.
|
MMOSimca@340
|
2022 return
|
MMOSimca@340
|
2023 else
|
MMOSimca@340
|
2024 modifier = modifier + buff_data_table.modifier
|
MMOSimca@340
|
2025 end
|
jcallahan@44
|
2026 end
|
jcallahan@44
|
2027 end
|
jcallahan@44
|
2028 end
|
catherton@465
|
2029
|
jcallahan@65
|
2030 npc.reputations = npc.reputations or {}
|
jcallahan@65
|
2031 npc.reputations[("%s:%s"):format(faction_name, faction_standings[faction_name])] = math.floor(amount / modifier)
|
jcallahan@32
|
2032 end
|
jcallahan@44
|
2033 end -- do-block
|
jcallahan@18
|
2034
|
jcallahan@18
|
2035
|
jcallahan@140
|
2036 function WDP:CURSOR_UPDATE(event_name)
|
MMOSimca@355
|
2037 if current_action.fishing_target or _G.Minimap:IsMouseOver() then
|
jcallahan@140
|
2038 return
|
jcallahan@140
|
2039 end
|
jcallahan@140
|
2040 local text = _G["GameTooltipTextLeft1"]:GetText()
|
jcallahan@140
|
2041
|
MMOSimca@355
|
2042 -- Handle Fishing
|
MMOSimca@355
|
2043 if (current_action.spell_label == "FISHING") then
|
MMOSimca@355
|
2044 if not text or text == "Fishing Bobber" then
|
MMOSimca@355
|
2045 text = "NONE"
|
MMOSimca@355
|
2046 else
|
MMOSimca@355
|
2047 current_action.fishing_target = true
|
MMOSimca@355
|
2048 end
|
MMOSimca@355
|
2049 current_action.identifier = ("%s:%s"):format(current_action.spell_label, text)
|
MMOSimca@355
|
2050 -- Handle Garrison Cache
|
MMOSimca@355
|
2051 elseif private.GARRISON_CACHE_OBJECT_NAME_TO_OBJECT_ID_MAP[text] then
|
MMOSimca@355
|
2052 last_garrison_cache_object_id = private.GARRISON_CACHE_OBJECT_NAME_TO_OBJECT_ID_MAP[text]
|
jcallahan@140
|
2053 end
|
jcallahan@140
|
2054 end
|
jcallahan@140
|
2055
|
jcallahan@140
|
2056
|
jcallahan@92
|
2057 function WDP:ITEM_TEXT_BEGIN(event_name)
|
jcallahan@42
|
2058 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@42
|
2059
|
jcallahan@42
|
2060 if not unit_idnum or unit_type ~= private.UNIT_TYPES.OBJECT or _G.UnitName("npc") ~= _G.ItemTextGetItem() then
|
jcallahan@42
|
2061 return
|
jcallahan@42
|
2062 end
|
jcallahan@42
|
2063 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@42
|
2064 end
|
jcallahan@42
|
2065
|
jcallahan@42
|
2066
|
jcallahan@13
|
2067 do
|
MMOSimca@343
|
2068 local LOOT_OPENED_VERIFY_FUNCS = {
|
jcallahan@324
|
2069 -- 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
|
2070 [AF.ITEM] = function()
|
jcallahan@16
|
2071 local locked_item_id
|
jcallahan@16
|
2072
|
jcallahan@16
|
2073 for bag_index = 0, _G.NUM_BAG_FRAMES do
|
jcallahan@16
|
2074 for slot_index = 1, _G.GetContainerNumSlots(bag_index) do
|
jcallahan@324
|
2075 local _, _, is_locked, _, _, is_lootable = _G.GetContainerItemInfo(bag_index, slot_index)
|
jcallahan@324
|
2076
|
jcallahan@324
|
2077 if is_locked and is_lootable then
|
jcallahan@16
|
2078 locked_item_id = ItemLinkToID(_G.GetContainerItemLink(bag_index, slot_index))
|
jcallahan@165
|
2079 break
|
jcallahan@16
|
2080 end
|
jcallahan@16
|
2081 end
|
jcallahan@165
|
2082
|
jcallahan@165
|
2083 if locked_item_id then
|
jcallahan@165
|
2084 break
|
jcallahan@165
|
2085 end
|
jcallahan@16
|
2086 end
|
jcallahan@16
|
2087
|
MMOSimca@367
|
2088 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
|
2089 return false
|
jcallahan@16
|
2090 end
|
jcallahan@122
|
2091 current_action.identifier = locked_item_id
|
jcallahan@16
|
2092 return true
|
jcallahan@16
|
2093 end,
|
MMOSimca@401
|
2094 [AF.NPC] = function()
|
MMOSimca@401
|
2095 return not _G.IsFishingLoot()
|
MMOSimca@401
|
2096 end,
|
MMOSimca@401
|
2097 [AF.OBJECT] = function()
|
MMOSimca@401
|
2098 return not _G.IsFishingLoot()
|
MMOSimca@401
|
2099 end,
|
jcallahan@17
|
2100 [AF.ZONE] = function()
|
jcallahan@140
|
2101 current_action.zone_data = UpdateDBEntryLocation("zones", current_action.identifier)
|
jcallahan@210
|
2102 return _G.IsFishingLoot()
|
jcallahan@17
|
2103 end,
|
jcallahan@13
|
2104 }
|
jcallahan@13
|
2105
|
jcallahan@13
|
2106
|
MMOSimca@343
|
2107 local LOOT_OPENED_UPDATE_FUNCS = {
|
jcallahan@16
|
2108 [AF.ITEM] = function()
|
jcallahan@28
|
2109 GenericLootUpdate("items")
|
jcallahan@28
|
2110 end,
|
jcallahan@28
|
2111 [AF.NPC] = function()
|
jcallahan@75
|
2112 local difficulty_token = InstanceDifficultyToken()
|
jcallahan@312
|
2113 local loot_label = current_loot.label
|
jcallahan@77
|
2114 local source_list = {}
|
jcallahan@75
|
2115
|
jcallahan@131
|
2116 for source_guid, loot_data in pairs(current_loot.sources) do
|
jcallahan@331
|
2117 local _, source_id = ParseGUID(source_guid)
|
jcallahan@75
|
2118 local npc = NPCEntry(source_id)
|
jcallahan@75
|
2119
|
jcallahan@75
|
2120 if npc then
|
jcallahan@248
|
2121 local encounter_data = npc:EncounterData(difficulty_token)
|
jcallahan@312
|
2122 encounter_data[loot_label] = encounter_data[loot_label] or {}
|
jcallahan@75
|
2123
|
jcallahan@78
|
2124 if not source_list[source_guid] then
|
jcallahan@77
|
2125 encounter_data.loot_counts = encounter_data.loot_counts or {}
|
MMOSimca@426
|
2126 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
|
jcallahan@312
|
2127 source_list[source_guid] = true
|
jcallahan@77
|
2128 end
|
jcallahan@77
|
2129
|
jcallahan@309
|
2130 for loot_token, quantity in pairs(loot_data) do
|
mmosimca@496
|
2131 local loot_type, currency_id = (":"):split(loot_token)
|
mmosimca@496
|
2132
|
mmosimca@496
|
2133 if loot_type == "currency" and currency_id then
|
mmosimca@496
|
2134 -- Convert currency_id back into number from string
|
mmosimca@496
|
2135 currency_id = tonumber(currency_id) or 0
|
mmosimca@496
|
2136 if currency_id ~= 0 then
|
mmosimca@496
|
2137 table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
|
mmosimca@496
|
2138 end
|
jcallahan@309
|
2139 elseif loot_token == "money" then
|
jcallahan@312
|
2140 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
|
jcallahan@309
|
2141 else
|
jcallahan@312
|
2142 table.insert(encounter_data[loot_label], ("%d:%d"):format(loot_token, quantity))
|
jcallahan@309
|
2143 end
|
jcallahan@75
|
2144 end
|
jcallahan@75
|
2145 end
|
jcallahan@75
|
2146 end
|
jcallahan@16
|
2147 end,
|
jcallahan@13
|
2148 [AF.OBJECT] = function()
|
jcallahan@28
|
2149 GenericLootUpdate("objects", InstanceDifficultyToken())
|
jcallahan@17
|
2150 end,
|
jcallahan@17
|
2151 [AF.ZONE] = function()
|
MMOSimca@328
|
2152 if not (current_loot.map_level and current_loot.x and current_loot.y and current_loot.zone_data) then
|
MMOSimca@328
|
2153 return
|
MMOSimca@328
|
2154 end
|
jcallahan@141
|
2155 local location_token = ("%d:%d:%d"):format(current_loot.map_level, current_loot.x, current_loot.y)
|
jcallahan@41
|
2156
|
jcallahan@41
|
2157 -- This will start life as a boolean true.
|
jcallahan@131
|
2158 if _G.type(current_loot.zone_data[location_token]) ~= "table" then
|
jcallahan@131
|
2159 current_loot.zone_data[location_token] = {
|
jcallahan@41
|
2160 drops = {}
|
jcallahan@41
|
2161 }
|
jcallahan@41
|
2162 end
|
jcallahan@132
|
2163 local loot_count = ("%s_count"):format(current_loot.label)
|
jcallahan@131
|
2164 current_loot.zone_data[location_token][loot_count] = (current_loot.zone_data[location_token][loot_count] or 0) + 1
|
jcallahan@41
|
2165
|
jcallahan@131
|
2166 if current_loot.sources then
|
jcallahan@131
|
2167 for source_guid, loot_data in pairs(current_loot.sources) do
|
jcallahan@131
|
2168 for item_id, quantity in pairs(loot_data) do
|
jcallahan@131
|
2169 table.insert(current_loot.zone_data[location_token].drops, ("%d:%d"):format(item_id, quantity))
|
jcallahan@131
|
2170 end
|
jcallahan@131
|
2171 end
|
jcallahan@131
|
2172 end
|
jcallahan@131
|
2173
|
jcallahan@131
|
2174 if #current_loot.list <= 0 then
|
jcallahan@131
|
2175 return
|
jcallahan@131
|
2176 end
|
jcallahan@131
|
2177
|
jcallahan@131
|
2178 for index = 1, #current_loot.list do
|
MMOSimca@443
|
2179 table.insert(current_loot.zone_data[location_token].drops, current_loot.list[index])
|
jcallahan@41
|
2180 end
|
jcallahan@13
|
2181 end,
|
jcallahan@13
|
2182 }
|
jcallahan@13
|
2183
|
jcallahan@79
|
2184 -- Prevent opening the same loot window multiple times from recording data multiple times.
|
jcallahan@79
|
2185 local loot_guid_registry = {}
|
jcallahan@124
|
2186
|
jcallahan@124
|
2187
|
jcallahan@124
|
2188 function WDP:LOOT_CLOSED(event_name)
|
MMOSimca@398
|
2189 ClearChatLootData()
|
jcallahan@131
|
2190 current_loot = nil
|
jcallahan@131
|
2191 table.wipe(current_action)
|
jcallahan@124
|
2192 end
|
jcallahan@124
|
2193
|
jcallahan@13
|
2194
|
jcallahan@322
|
2195 local function ExtrapolatedCurrentActionFromLootData(event_name)
|
MMOSimca@402
|
2196 local log_source = event_name .. "- ExtrapolatedCurrentActionFromLootData"
|
MMOSimca@402
|
2197 local previous_spell_label = current_action.spell_label
|
jcallahan@322
|
2198 local extrapolated_guid_registry = {}
|
jcallahan@322
|
2199 local num_guids = 0
|
MMOSimca@402
|
2200 table.wipe(current_action)
|
MMOSimca@402
|
2201
|
MMOSimca@402
|
2202 if _G.IsFishingLoot() then
|
MMOSimca@402
|
2203 -- Set up a proper 'fishing' current_action table
|
MMOSimca@402
|
2204 local zone_name, area_id, x, y, map_level, instance_token = CurrentLocationData()
|
MMOSimca@402
|
2205 if not (zone_name and area_id and x and y and map_level) then
|
catherton@468
|
2206 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
|
2207 return
|
MMOSimca@402
|
2208 end
|
MMOSimca@402
|
2209 current_action.instance_token = instance_token
|
MMOSimca@402
|
2210 current_action.map_level = map_level
|
MMOSimca@402
|
2211 current_action.x = x
|
MMOSimca@402
|
2212 current_action.y = y
|
MMOSimca@402
|
2213 current_action.zone_data = ("%s:%d"):format(zone_name, area_id)
|
MMOSimca@402
|
2214 current_action.spell_label = "FISHING"
|
MMOSimca@402
|
2215 current_action.loot_label = "fishing"
|
MMOSimca@402
|
2216 current_action.identifier = "FISHING:NONE"
|
MMOSimca@402
|
2217 current_action.target_type = AF.ZONE
|
MMOSimca@402
|
2218
|
MMOSimca@402
|
2219 Debug("%s: Fishing loot detected.", log_source)
|
MMOSimca@402
|
2220 return true
|
MMOSimca@402
|
2221 end
|
jcallahan@322
|
2222
|
MMOSimca@344
|
2223 -- Loot extrapolation cannot handle objects that need special spell labels (like HERBALISM or MINING) (MIND_CONTROL is okay)
|
MMOSimca@402
|
2224 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
|
2225 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
|
2226 return false
|
MMOSimca@344
|
2227 end
|
MMOSimca@344
|
2228
|
jcallahan@322
|
2229 for loot_slot = 1, _G.GetNumLootItems() do
|
jcallahan@322
|
2230 local loot_info = {
|
jcallahan@322
|
2231 _G.GetLootSourceInfo(loot_slot)
|
jcallahan@322
|
2232 }
|
jcallahan@322
|
2233
|
jcallahan@322
|
2234 for loot_index = 1, #loot_info, 2 do
|
jcallahan@322
|
2235 local source_guid = loot_info[loot_index]
|
jcallahan@322
|
2236
|
jcallahan@322
|
2237 if not extrapolated_guid_registry[source_guid] then
|
jcallahan@322
|
2238 local unit_type, unit_idnum = ParseGUID(source_guid)
|
jcallahan@322
|
2239
|
jcallahan@322
|
2240 if unit_type and unit_idnum then
|
jcallahan@322
|
2241 extrapolated_guid_registry[source_guid] = {
|
jcallahan@322
|
2242 unit_type,
|
jcallahan@322
|
2243 unit_idnum
|
jcallahan@322
|
2244 }
|
jcallahan@322
|
2245
|
jcallahan@322
|
2246 num_guids = num_guids + 1
|
jcallahan@322
|
2247 end
|
jcallahan@322
|
2248 end
|
jcallahan@322
|
2249 end
|
jcallahan@322
|
2250 end
|
jcallahan@322
|
2251
|
jcallahan@322
|
2252 if num_guids == 0 then
|
jcallahan@322
|
2253 Debug("%s: No GUIDs found in loot. Blank loot window?", log_source)
|
jcallahan@322
|
2254 return false
|
jcallahan@322
|
2255 end
|
jcallahan@326
|
2256
|
jcallahan@322
|
2257 local num_npcs = 0
|
jcallahan@322
|
2258 local num_objects = 0
|
jcallahan@324
|
2259 local num_itemcontainers = 0
|
jcallahan@322
|
2260
|
jcallahan@322
|
2261 for source_guid, guid_data in pairs(extrapolated_guid_registry) do
|
jcallahan@322
|
2262 local unit_type = guid_data[1]
|
jcallahan@324
|
2263 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
|
2264
|
jcallahan@322
|
2265 if loot_label then
|
jcallahan@322
|
2266 local unit_idnum = guid_data[2]
|
jcallahan@322
|
2267
|
jcallahan@322
|
2268 if loot_guid_registry[loot_label] and loot_guid_registry[loot_label][source_guid] then
|
jcallahan@322
|
2269 Debug("%s: Previously scanned loot for unit with GUID %s and identifier %s.", log_source, source_guid, unit_idnum)
|
jcallahan@322
|
2270 elseif unit_type == private.UNIT_TYPES.OBJECT and unit_idnum ~= OBJECT_ID_FISHING_BOBBER then
|
jcallahan@322
|
2271 current_action.loot_label = loot_label
|
jcallahan@322
|
2272 current_action.spell_label = "OPENING"
|
jcallahan@322
|
2273 current_action.target_type = AF.OBJECT
|
jcallahan@322
|
2274 current_action.identifier = unit_idnum
|
jcallahan@322
|
2275 num_objects = num_objects + 1
|
jcallahan@322
|
2276 elseif UnitTypeIsNPC(unit_type) then
|
jcallahan@322
|
2277 current_action.loot_label = loot_label
|
jcallahan@322
|
2278 current_action.target_type = AF.NPC
|
jcallahan@322
|
2279 current_action.identifier = unit_idnum
|
jcallahan@322
|
2280 num_npcs = num_npcs + 1
|
jcallahan@324
|
2281 elseif unit_type == private.UNIT_TYPES.PLAYER then
|
jcallahan@331
|
2282 -- Item container GUIDs are currently of the 'PLAYER' type; this may be unintended and could change in the future.
|
jcallahan@324
|
2283 current_action.loot_label = loot_label
|
jcallahan@324
|
2284 current_action.target_type = AF.ITEM
|
jcallahan@324
|
2285 -- current_action.identifier assigned during loot verification.
|
jcallahan@324
|
2286 num_itemcontainers = num_itemcontainers + 1
|
jcallahan@322
|
2287 end
|
jcallahan@322
|
2288 else
|
jcallahan@322
|
2289 -- 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
|
2290 Debug("%s: Unit with GUID %s has unsupported type for looting.", log_source, source_guid)
|
jcallahan@322
|
2291 return false
|
jcallahan@322
|
2292 end
|
jcallahan@322
|
2293 end
|
jcallahan@322
|
2294
|
jcallahan@322
|
2295 if not current_action.target_type then
|
jcallahan@322
|
2296 Debug("%s: Failure to obtain target_type.", log_source)
|
jcallahan@322
|
2297 return false
|
jcallahan@322
|
2298 end
|
jcallahan@322
|
2299
|
jcallahan@322
|
2300 -- 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
|
2301 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
|
2302 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
|
2303 return false
|
jcallahan@322
|
2304 end
|
jcallahan@322
|
2305
|
jcallahan@322
|
2306 return true
|
jcallahan@322
|
2307 end
|
jcallahan@322
|
2308
|
jcallahan@322
|
2309
|
MMOSimca@343
|
2310 function WDP:LOOT_OPENED(event_name)
|
MMOSimca@398
|
2311 ClearChatLootData()
|
MMOSimca@387
|
2312
|
jcallahan@132
|
2313 if current_loot then
|
jcallahan@322
|
2314 current_loot = nil
|
jcallahan@322
|
2315 Debug("%s: Previous loot did not process in time for this event. Attempting to extrapolate current_action from loot data.", event_name)
|
jcallahan@322
|
2316
|
jcallahan@322
|
2317 if not ExtrapolatedCurrentActionFromLootData(event_name) then
|
jcallahan@322
|
2318 Debug("%s: Unable to extrapolate current_action. Aborting attempts to handle loot for now.", event_name)
|
jcallahan@322
|
2319 return
|
jcallahan@322
|
2320 end
|
jcallahan@18
|
2321 end
|
jcallahan@151
|
2322
|
jcallahan@151
|
2323 if not current_action.target_type then
|
jcallahan@322
|
2324 if not ExtrapolatedCurrentActionFromLootData(event_name) then
|
jcallahan@322
|
2325 Debug("%s: Unable to extrapolate current_action. Aborting attempts to handle loot for now.", event_name)
|
jcallahan@322
|
2326 return
|
jcallahan@322
|
2327 end
|
jcallahan@151
|
2328 end
|
MMOSimca@343
|
2329 local verify_func = LOOT_OPENED_VERIFY_FUNCS[current_action.target_type]
|
MMOSimca@343
|
2330 local update_func = LOOT_OPENED_UPDATE_FUNCS[current_action.target_type]
|
jcallahan@13
|
2331
|
jcallahan@14
|
2332 if not verify_func or not update_func then
|
jcallahan@322
|
2333 Debug("%s: The current action's target type is unsupported or nil.", event_name)
|
jcallahan@13
|
2334 return
|
jcallahan@13
|
2335 end
|
jcallahan@13
|
2336
|
jcallahan@14
|
2337 if _G.type(verify_func) == "function" and not verify_func() then
|
jcallahan@324
|
2338 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
|
2339 return
|
jcallahan@14
|
2340 end
|
jcallahan@80
|
2341 local guids_used = {}
|
jcallahan@132
|
2342
|
jcallahan@301
|
2343 InitializeCurrentLoot()
|
jcallahan@217
|
2344 loot_guid_registry[current_loot.label] = loot_guid_registry[current_loot.label] or {}
|
jcallahan@217
|
2345
|
jcallahan@55
|
2346 for loot_slot = 1, _G.GetNumLootItems() do
|
mmosimca@496
|
2347 local texture_filedata_id, item_text, slot_quantity, quality, locked = _G.GetLootSlotInfo(loot_slot)
|
jcallahan@55
|
2348 local slot_type = _G.GetLootSlotType(loot_slot)
|
catherton@463
|
2349 local loot_info = { _G.GetLootSourceInfo(loot_slot) }
|
catherton@464
|
2350 local loot_link = _G.GetLootSlotLink(loot_slot)
|
jcallahan@13
|
2351
|
jcallahan@237
|
2352 -- Odd index is GUID, even is count.
|
jcallahan@237
|
2353 for loot_index = 1, #loot_info, 2 do
|
jcallahan@237
|
2354 local source_guid = loot_info[loot_index]
|
jcallahan@75
|
2355
|
jcallahan@237
|
2356 if not loot_guid_registry[current_loot.label][source_guid] then
|
jcallahan@237
|
2357 local loot_quantity = loot_info[loot_index + 1]
|
jcallahan@324
|
2358 -- There is a new bug in 5.4.0 that causes GetLootSlotInfo() to (rarely) return nil values for slot_quantity.
|
jcallahan@324
|
2359 if slot_quantity then
|
jcallahan@324
|
2360 -- 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
|
2361 if slot_quantity > loot_quantity then
|
jcallahan@324
|
2362 loot_quantity = slot_quantity
|
jcallahan@324
|
2363 end
|
jcallahan@324
|
2364 local source_type, source_id = ParseGUID(source_guid)
|
MMOSimca@329
|
2365 local source_key = ("%s:%d"):format(source_type, source_id)
|
jcallahan@324
|
2366
|
MMOSimca@366
|
2367 if slot_type == LOOT_SLOT_ITEM then
|
catherton@464
|
2368 if loot_link then
|
catherton@464
|
2369 local item_id = ItemLinkToID(loot_link)
|
catherton@464
|
2370 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
|
2371 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
catherton@464
|
2372 current_loot.sources[source_guid][item_id] = (current_loot.sources[source_guid][item_id] or 0) + loot_quantity
|
catherton@464
|
2373 guids_used[source_guid] = true
|
catherton@463
|
2374 else
|
catherton@463
|
2375 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
|
2376 end
|
MMOSimca@366
|
2377 elseif slot_type == LOOT_SLOT_MONEY then
|
jcallahan@324
|
2378 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
|
2379 if current_loot.target_type == AF.ZONE then
|
jcallahan@324
|
2380 table.insert(current_loot.list, ("money:%d"):format(loot_quantity))
|
jcallahan@324
|
2381 else
|
jcallahan@324
|
2382 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
MMOSimca@367
|
2383 current_loot.sources[source_guid]["money"] = (current_loot.sources[source_guid]["money"] or 0) + loot_quantity
|
jcallahan@324
|
2384 guids_used[source_guid] = true
|
jcallahan@324
|
2385 end
|
MMOSimca@366
|
2386 elseif slot_type == LOOT_SLOT_CURRENCY then
|
jcallahan@324
|
2387 -- Same bug with GetLootSlotInfo() will screw up currency when it happens, so we won't process this slot's loot.
|
catherton@463
|
2388 if loot_link then
|
mmosimca@496
|
2389 local currency_id = CurrencyLinkToID(loot_link)
|
mmosimca@496
|
2390 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
|
2391 if current_loot.target_type == AF.ZONE then
|
mmosimca@496
|
2392 table.insert(current_loot.list, ("currency:%d:%d"):format(loot_quantity, currency_id))
|
jcallahan@324
|
2393 else
|
mmosimca@496
|
2394 local currency_token = ("currency:%d"):format(currency_id)
|
jcallahan@324
|
2395
|
jcallahan@324
|
2396 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
MMOSimca@367
|
2397 current_loot.sources[source_guid][currency_token] = (current_loot.sources[source_guid][currency_token] or 0) + loot_quantity
|
jcallahan@324
|
2398 guids_used[source_guid] = true
|
jcallahan@324
|
2399 end
|
jcallahan@324
|
2400 else
|
catherton@463
|
2401 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
|
2402 end
|
jcallahan@308
|
2403 end
|
jcallahan@324
|
2404 else
|
jcallahan@324
|
2405 -- 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
|
2406 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
|
2407 end
|
jcallahan@75
|
2408 end
|
jcallahan@13
|
2409 end
|
jcallahan@13
|
2410 end
|
jcallahan@80
|
2411
|
jcallahan@81
|
2412 for guid in pairs(guids_used) do
|
jcallahan@217
|
2413 loot_guid_registry[current_loot.label][guid] = true
|
jcallahan@80
|
2414 end
|
jcallahan@13
|
2415 update_func()
|
jcallahan@1
|
2416 end
|
jcallahan@13
|
2417 end -- do-block
|
jcallahan@0
|
2418
|
jcallahan@0
|
2419
|
jcallahan@89
|
2420 function WDP:MAIL_SHOW(event_name)
|
MMOSimca@436
|
2421 WDP:StopChatLootRecording(event_name)
|
jcallahan@89
|
2422 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@89
|
2423
|
jcallahan@89
|
2424 if not unit_idnum or unit_type ~= private.UNIT_TYPES.OBJECT then
|
jcallahan@89
|
2425 return
|
jcallahan@89
|
2426 end
|
jcallahan@89
|
2427 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@89
|
2428 end
|
jcallahan@89
|
2429
|
jcallahan@89
|
2430
|
jcallahan@44
|
2431 do
|
jcallahan@44
|
2432 local POINT_MATCH_PATTERNS = {
|
jcallahan@44
|
2433 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2434 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_3V3:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2435 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_5V5:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2436 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_BG:gsub("%%d", "(%%d+)")),
|
jcallahan@44
|
2437 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_3V3_BG:gsub("%%d", "(%%d+)")),
|
jcallahan@44
|
2438 }
|
jcallahan@5
|
2439
|
jcallahan@68
|
2440 local ITEM_REQ_REPUTATION_MATCH = "Requires (.-) %- (.*)"
|
jcallahan@87
|
2441 local ITEM_REQ_QUEST_MATCH1 = "Requires: .*"
|
jcallahan@87
|
2442 local ITEM_REQ_QUEST_MATCH2 = "Must have completed: .*"
|
jcallahan@68
|
2443
|
jcallahan@133
|
2444 local current_merchant
|
jcallahan@133
|
2445 local merchant_standing
|
jcallahan@133
|
2446
|
jcallahan@133
|
2447 function WDP:MERCHANT_CLOSED(event_name)
|
MMOSimca@436
|
2448 WDP:ResumeChatLootRecording(event_name)
|
jcallahan@133
|
2449 current_merchant = nil
|
jcallahan@133
|
2450 merchant_standing = nil
|
jcallahan@133
|
2451 end
|
jcallahan@133
|
2452
|
jcallahan@133
|
2453
|
jcallahan@89
|
2454 function WDP:UpdateMerchantItems(event_name)
|
jcallahan@144
|
2455 if not current_merchant or event_name == "MERCHANT_SHOW" then
|
MMOSimca@436
|
2456 WDP:StopChatLootRecording(event_name)
|
jcallahan@195
|
2457 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@4
|
2458
|
jcallahan@171
|
2459 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
jcallahan@133
|
2460 return
|
jcallahan@133
|
2461 end
|
jcallahan@331
|
2462 local _, faction_standing = UnitFactionStanding("npc")
|
jcallahan@331
|
2463 merchant_standing = faction_standing
|
jcallahan@133
|
2464 current_merchant = NPCEntry(unit_idnum)
|
jcallahan@133
|
2465 current_merchant.sells = current_merchant.sells or {}
|
jcallahan@44
|
2466 end
|
jcallahan@55
|
2467 local current_filters = _G.GetMerchantFilter()
|
jcallahan@57
|
2468 _G.SetMerchantFilter(_G.LE_LOOT_FILTER_ALL)
|
jcallahan@57
|
2469 _G.MerchantFrame_Update()
|
jcallahan@57
|
2470
|
jcallahan@150
|
2471 local num_items = _G.GetMerchantNumItems()
|
jcallahan@150
|
2472
|
jcallahan@44
|
2473 for item_index = 1, num_items do
|
jcallahan@44
|
2474 local _, _, copper_price, stack_size, num_available, _, extended_cost = _G.GetMerchantItemInfo(item_index)
|
jcallahan@44
|
2475 local item_id = ItemLinkToID(_G.GetMerchantItemLink(item_index))
|
jcallahan@5
|
2476
|
jcallahan@324
|
2477 DatamineTT:ClearLines()
|
jcallahan@324
|
2478 DatamineTT:SetMerchantItem(item_index)
|
jcallahan@324
|
2479
|
jcallahan@324
|
2480 if not item_id then
|
jcallahan@324
|
2481 local item_name, item_link = DatamineTT:GetItem()
|
jcallahan@324
|
2482 item_id = ItemLinkToID(item_link)
|
MMOSimca@354
|
2483 -- GetMerchantItemLink() still ocassionally fails as of Patch 6.0.2. It fails so badly that debug functions cause considerable slowdown.
|
jcallahan@324
|
2484 end
|
jcallahan@324
|
2485
|
jcallahan@44
|
2486 if item_id and item_id > 0 then
|
jcallahan@44
|
2487 local price_string = ActualCopperCost(copper_price, merchant_standing)
|
jcallahan@5
|
2488
|
jcallahan@68
|
2489 local num_lines = DatamineTT:NumLines()
|
jcallahan@68
|
2490
|
jcallahan@68
|
2491 for line_index = 1, num_lines do
|
jcallahan@68
|
2492 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@68
|
2493
|
jcallahan@68
|
2494 if not current_line then
|
jcallahan@68
|
2495 break
|
jcallahan@68
|
2496 end
|
jcallahan@68
|
2497 local faction, reputation = current_line:GetText():match(ITEM_REQ_REPUTATION_MATCH)
|
jcallahan@68
|
2498
|
jcallahan@68
|
2499 if faction or reputation then
|
jcallahan@68
|
2500 DBEntry("items", item_id).req_reputation = ("%s:%s"):format(faction:gsub("-", ""), reputation:upper())
|
jcallahan@68
|
2501 break
|
jcallahan@68
|
2502 end
|
jcallahan@68
|
2503 end
|
jcallahan@68
|
2504
|
jcallahan@87
|
2505 for line_index = 1, num_lines do
|
jcallahan@87
|
2506 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@87
|
2507
|
jcallahan@87
|
2508 if not current_line then
|
jcallahan@87
|
2509 break
|
jcallahan@87
|
2510 end
|
jcallahan@87
|
2511 local line_text = current_line:GetText()
|
jcallahan@87
|
2512 local quest_name = line_text:match(ITEM_REQ_QUEST_MATCH1) or line_text:match(ITEM_REQ_QUEST_MATCH2)
|
jcallahan@87
|
2513
|
jcallahan@87
|
2514 if quest_name then
|
jcallahan@87
|
2515 DBEntry("items", item_id).req_quest = ("%s"):format(quest_name:gsub("(.+): ", ""), quest_name)
|
jcallahan@87
|
2516 break
|
jcallahan@87
|
2517 end
|
jcallahan@87
|
2518 end
|
jcallahan@87
|
2519
|
jcallahan@44
|
2520 if extended_cost then
|
jcallahan@53
|
2521 local battleground_rating = 0
|
jcallahan@53
|
2522 local personal_rating = 0
|
jcallahan@53
|
2523 local required_season_amount
|
jcallahan@5
|
2524
|
jcallahan@68
|
2525 for line_index = 1, num_lines do
|
jcallahan@44
|
2526 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@5
|
2527
|
jcallahan@44
|
2528 if not current_line then
|
jcallahan@44
|
2529 break
|
jcallahan@44
|
2530 end
|
jcallahan@53
|
2531 required_season_amount = current_line:GetText():match("Requires earning a total of (%d+)\n(.-) for the season.")
|
jcallahan@5
|
2532
|
jcallahan@44
|
2533 for match_index = 1, #POINT_MATCH_PATTERNS do
|
jcallahan@44
|
2534 local match1, match2 = current_line:GetText():match(POINT_MATCH_PATTERNS[match_index])
|
jcallahan@53
|
2535 personal_rating = personal_rating + (match1 or 0)
|
jcallahan@53
|
2536 battleground_rating = battleground_rating + (match2 or 0)
|
jcallahan@5
|
2537
|
jcallahan@44
|
2538 if match1 or match2 then
|
jcallahan@44
|
2539 break
|
jcallahan@44
|
2540 end
|
jcallahan@44
|
2541 end
|
jcallahan@5
|
2542 end
|
jcallahan@44
|
2543 local currency_list = {}
|
jcallahan@44
|
2544 local item_count = _G.GetMerchantItemCostInfo(item_index)
|
jcallahan@50
|
2545
|
jcallahan@50
|
2546 -- Keeping this around in case Blizzard makes the two points diverge at some point.
|
jcallahan@53
|
2547 -- price_string = ("%s:%s:%s:%s"):format(price_string, battleground_rating, personal_rating, required_season_amount or 0)
|
jcallahan@53
|
2548 price_string = ("%s:%s:%s"):format(price_string, personal_rating, required_season_amount or 0)
|
jcallahan@5
|
2549
|
jcallahan@44
|
2550 for cost_index = 1, item_count do
|
jcallahan@324
|
2551 -- The third return (Blizz calls "currency_link") of GetMerchantItemCostItem only returns item links as of Patch 5.3.0.
|
mmosimca@496
|
2552 local texture_path, amount_required, item_link, name = _G.GetMerchantItemCostItem(item_index, cost_index)
|
mmosimca@496
|
2553
|
mmosimca@496
|
2554 -- Try to detect if this is actually a currency by looking for a nil item_link or item ID
|
mmosimca@496
|
2555 local is_item = item_link and ItemLinkToID(item_link)
|
mmosimca@496
|
2556
|
mmosimca@496
|
2557 if not is_item then
|
mmosimca@496
|
2558 local currency_id = CurrencyInfoToID(name, texture_path)
|
mmosimca@496
|
2559 currency_list[#currency_list + 1] = ("(%s:%d)"):format(amount_required, currency_id)
|
jcallahan@44
|
2560 end
|
jcallahan@44
|
2561 end
|
jcallahan@44
|
2562
|
jcallahan@44
|
2563 for currency_index = 1, #currency_list do
|
jcallahan@44
|
2564 price_string = ("%s:%s"):format(price_string, currency_list[currency_index])
|
jcallahan@5
|
2565 end
|
jcallahan@5
|
2566 end
|
jcallahan@133
|
2567 current_merchant.sells[item_id] = ("%s:%s:[%s]"):format(num_available, stack_size, price_string)
|
jcallahan@44
|
2568 end
|
jcallahan@44
|
2569 end
|
jcallahan@5
|
2570
|
jcallahan@44
|
2571 if _G.CanMerchantRepair() then
|
jcallahan@133
|
2572 current_merchant.can_repair = true
|
jcallahan@5
|
2573 end
|
jcallahan@57
|
2574 _G.SetMerchantFilter(current_filters)
|
jcallahan@57
|
2575 _G.MerchantFrame_Update()
|
jcallahan@4
|
2576 end
|
jcallahan@44
|
2577 end -- do-block
|
jcallahan@4
|
2578
|
jcallahan@89
|
2579
|
jcallahan@92
|
2580 function WDP:PET_BAR_UPDATE(event_name)
|
MMOSimca@336
|
2581 if not private.NON_LOOT_SPELL_LABELS[current_action.spell_label] then
|
jcallahan@25
|
2582 return
|
jcallahan@25
|
2583 end
|
jcallahan@34
|
2584 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("pet"))
|
jcallahan@25
|
2585
|
jcallahan@171
|
2586 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
jcallahan@25
|
2587 return
|
jcallahan@25
|
2588 end
|
jcallahan@29
|
2589 NPCEntry(unit_idnum).mind_control = true
|
jcallahan@122
|
2590 table.wipe(current_action)
|
jcallahan@25
|
2591 end
|
jcallahan@25
|
2592
|
jcallahan@25
|
2593
|
MMOSimca@368
|
2594 -- This function produces data currently unused by wowdb.com, and it causes unneeded bloat in the raw lua DB.
|
MMOSimca@442
|
2595 --[[local LPJ = LibStub("LibPetJournal-2.0")
|
MMOSimca@442
|
2596 function WDP:PET_JOURNAL_LIST_UPDATE(event_name)
|
MMOSimca@346
|
2597 if DEBUGGING then
|
jcallahan@309
|
2598 return
|
jcallahan@309
|
2599 end
|
jcallahan@309
|
2600
|
jcallahan@115
|
2601 local num_pets = LPJ:NumPets()
|
jcallahan@115
|
2602
|
jcallahan@115
|
2603 for index, pet_id in LPJ:IteratePetIDs() do
|
jcallahan@115
|
2604 local _, _, is_owned, _, level, _, _, name, icon, pet_type, npc_id, _, _, is_wild = _G.C_PetJournal.GetPetInfoByIndex(index)
|
jcallahan@115
|
2605
|
jcallahan@115
|
2606 if is_owned then
|
jcallahan@115
|
2607 local health, max_health, attack, speed, rarity = _G.C_PetJournal.GetPetStats(pet_id)
|
jcallahan@115
|
2608
|
jcallahan@139
|
2609 if rarity then
|
jcallahan@139
|
2610 local rarity_name = _G["BATTLE_PET_BREED_QUALITY" .. rarity]
|
jcallahan@139
|
2611 local npc = NPCEntry(npc_id)
|
jcallahan@139
|
2612 npc.wild_pet = is_wild or nil
|
jcallahan@139
|
2613 npc.battle_pet_data = npc.battle_pet_data or {}
|
jcallahan@139
|
2614 npc.battle_pet_data[rarity_name] = npc.battle_pet_data[rarity_name] or {}
|
jcallahan@139
|
2615 npc.battle_pet_data[rarity_name]["level_" .. level] = npc.battle_pet_data[rarity_name]["level_" .. level] or {}
|
jcallahan@139
|
2616
|
jcallahan@139
|
2617 local data = npc.battle_pet_data[rarity_name]["level_" .. level]
|
jcallahan@139
|
2618 data.max_health = max_health
|
jcallahan@139
|
2619 data.attack = attack
|
jcallahan@139
|
2620 data.speed = speed
|
jcallahan@139
|
2621 end
|
jcallahan@115
|
2622 end
|
jcallahan@115
|
2623 end
|
MMOSimca@368
|
2624 end]]--
|
jcallahan@115
|
2625
|
jcallahan@115
|
2626
|
jcallahan@156
|
2627 function WDP:PLAYER_REGEN_DISABLED(event_name)
|
jcallahan@156
|
2628 private.in_combat = true
|
jcallahan@156
|
2629 end
|
jcallahan@156
|
2630
|
jcallahan@156
|
2631
|
jcallahan@156
|
2632 function WDP:PLAYER_REGEN_ENABLED(event_name)
|
jcallahan@156
|
2633 private.in_combat = nil
|
jcallahan@156
|
2634 end
|
jcallahan@156
|
2635
|
jcallahan@156
|
2636
|
jcallahan@118
|
2637 function WDP:PLAYER_TARGET_CHANGED(event_name)
|
jcallahan@215
|
2638 if not TargetedNPC() then
|
jcallahan@118
|
2639 return
|
jcallahan@2
|
2640 end
|
jcallahan@151
|
2641 current_action.target_type = AF.NPC
|
jcallahan@118
|
2642 self:UpdateTargetLocation()
|
jcallahan@118
|
2643 end
|
jcallahan@2
|
2644
|
jcallahan@89
|
2645
|
jcallahan@12
|
2646 do
|
jcallahan@12
|
2647 local function UpdateQuestJuncture(point)
|
jcallahan@12
|
2648 local unit_name = _G.UnitName("questnpc")
|
jcallahan@9
|
2649
|
jcallahan@12
|
2650 if not unit_name then
|
jcallahan@12
|
2651 return
|
jcallahan@12
|
2652 end
|
jcallahan@34
|
2653 local unit_type, unit_id = ParseGUID(_G.UnitGUID("questnpc"))
|
MMOSimca@351
|
2654 Debug("UpdateQuestJuncture: Updating quest juncture for %s.", ("%s:%d"):format(private.UNIT_TYPE_NAMES[unit_type], unit_id))
|
jcallahan@12
|
2655 if unit_type == private.UNIT_TYPES.OBJECT then
|
jcallahan@38
|
2656 UpdateDBEntryLocation("objects", unit_id)
|
jcallahan@12
|
2657 end
|
jcallahan@19
|
2658 local quest = DBEntry("quests", _G.GetQuestID())
|
jcallahan@12
|
2659 quest[point] = quest[point] or {}
|
MMOSimca@329
|
2660 quest[point][("%s:%d"):format(private.UNIT_TYPE_NAMES[unit_type], unit_id)] = true
|
jcallahan@24
|
2661
|
jcallahan@24
|
2662 return quest
|
jcallahan@12
|
2663 end
|
jcallahan@10
|
2664
|
jcallahan@12
|
2665
|
jcallahan@92
|
2666 function WDP:QUEST_COMPLETE(event_name)
|
jcallahan@97
|
2667 local quest = UpdateQuestJuncture("end")
|
catherton@465
|
2668
|
MMOSimca@446
|
2669 if not quest then
|
MMOSimca@446
|
2670 return
|
MMOSimca@446
|
2671 end
|
jcallahan@97
|
2672
|
jcallahan@112
|
2673 if ALLOWED_LOCALES[CLIENT_LOCALE] then
|
jcallahan@112
|
2674 quest.reward_text = ReplaceKeywords(_G.GetRewardText())
|
jcallahan@112
|
2675 end
|
jcallahan@67
|
2676 -- Make sure the quest NPC isn't erroneously recorded as giving reputation for quests which award it.
|
jcallahan@177
|
2677 ClearKilledNPC()
|
jcallahan@10
|
2678 end
|
jcallahan@10
|
2679
|
jcallahan@12
|
2680
|
jcallahan@92
|
2681 function WDP:QUEST_DETAIL(event_name)
|
jcallahan@24
|
2682 local quest = UpdateQuestJuncture("begin")
|
jcallahan@24
|
2683
|
jcallahan@46
|
2684 if not quest then
|
jcallahan@46
|
2685 return
|
jcallahan@46
|
2686 end
|
jcallahan@24
|
2687 quest.classes = quest.classes or {}
|
jcallahan@27
|
2688 quest.classes[PLAYER_CLASS] = true
|
jcallahan@24
|
2689
|
jcallahan@24
|
2690 quest.races = quest.races or {}
|
jcallahan@100
|
2691 quest.races[(PLAYER_RACE == "Pandaren") and ("%s_%s"):format(PLAYER_RACE, PLAYER_FACTION or "Neutral") or PLAYER_RACE] = true
|
jcallahan@10
|
2692 end
|
jcallahan@12
|
2693 end -- do-block
|
jcallahan@9
|
2694
|
jcallahan@9
|
2695
|
jcallahan@92
|
2696 function WDP:QUEST_LOG_UPDATE(event_name)
|
jcallahan@38
|
2697 local selected_quest = _G.GetQuestLogSelection() -- Save current selection to be restored when we're done.
|
jcallahan@36
|
2698 local entry_index, processed_quests = 1, 0
|
jcallahan@36
|
2699 local _, num_quests = _G.GetNumQuestLogEntries()
|
jcallahan@36
|
2700
|
jcallahan@36
|
2701 while processed_quests <= num_quests do
|
MMOSimca@329
|
2702 local _, _, _, is_header, _, _, _, quest_id = _G.GetQuestLogTitle(entry_index)
|
jcallahan@36
|
2703
|
jcallahan@84
|
2704 if quest_id == 0 then
|
jcallahan@84
|
2705 processed_quests = processed_quests + 1
|
jcallahan@84
|
2706 elseif not is_header then
|
jcallahan@36
|
2707 _G.SelectQuestLogEntry(entry_index);
|
jcallahan@36
|
2708
|
jcallahan@36
|
2709 local quest = DBEntry("quests", quest_id)
|
jcallahan@36
|
2710 quest.timer = _G.GetQuestLogTimeLeft()
|
jcallahan@37
|
2711 quest.can_share = _G.GetQuestLogPushable() and true or nil
|
jcallahan@36
|
2712 processed_quests = processed_quests + 1
|
jcallahan@36
|
2713 end
|
jcallahan@36
|
2714 entry_index = entry_index + 1
|
jcallahan@36
|
2715 end
|
jcallahan@36
|
2716 _G.SelectQuestLogEntry(selected_quest)
|
jcallahan@4
|
2717 self:UnregisterEvent("QUEST_LOG_UPDATE")
|
jcallahan@4
|
2718 end
|
jcallahan@4
|
2719
|
jcallahan@4
|
2720
|
jcallahan@97
|
2721 function WDP:QUEST_PROGRESS(event_name)
|
jcallahan@112
|
2722 if not ALLOWED_LOCALES[CLIENT_LOCALE] then
|
jcallahan@112
|
2723 return
|
jcallahan@112
|
2724 end
|
jcallahan@97
|
2725 DBEntry("quests", _G.GetQuestID()).progress_text = ReplaceKeywords(_G.GetProgressText())
|
jcallahan@97
|
2726 end
|
jcallahan@97
|
2727
|
jcallahan@97
|
2728
|
jcallahan@92
|
2729 function WDP:UNIT_QUEST_LOG_CHANGED(event_name, unit_id)
|
jcallahan@4
|
2730 if unit_id ~= "player" then
|
jcallahan@4
|
2731 return
|
jcallahan@4
|
2732 end
|
jcallahan@4
|
2733 self:RegisterEvent("QUEST_LOG_UPDATE")
|
jcallahan@4
|
2734 end
|
jcallahan@4
|
2735
|
jcallahan@4
|
2736
|
jcallahan@92
|
2737 do
|
jcallahan@92
|
2738 local TRADESKILL_TOOLS = {
|
jcallahan@92
|
2739 Anvil = anvil_spell_ids,
|
jcallahan@92
|
2740 Forge = forge_spell_ids,
|
jcallahan@92
|
2741 }
|
jcallahan@92
|
2742
|
jcallahan@92
|
2743
|
jcallahan@167
|
2744 local function RegisterTools(tradeskill_name, tradeskill_index)
|
catherton@479
|
2745 local link = _G.C_TradeSkillUI.GetRecipeLink(tradeskill_index)
|
catherton@465
|
2746
|
MMOSimca@352
|
2747 if link then
|
MMOSimca@352
|
2748 local spell_id = tonumber(link:match("^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)"))
|
catherton@479
|
2749 local required_tool = _G.C_TradeSkillUI.GetRecipeTools(tradeskill_index)
|
MMOSimca@352
|
2750
|
MMOSimca@352
|
2751 if required_tool then
|
MMOSimca@352
|
2752 for tool_name, registry in pairs(TRADESKILL_TOOLS) do
|
MMOSimca@352
|
2753 if required_tool:find(tool_name) then
|
MMOSimca@352
|
2754 registry[spell_id] = true
|
MMOSimca@352
|
2755 end
|
jcallahan@167
|
2756 end
|
jcallahan@167
|
2757 end
|
jcallahan@167
|
2758 end
|
jcallahan@167
|
2759 end
|
jcallahan@167
|
2760
|
jcallahan@167
|
2761
|
jcallahan@92
|
2762 function WDP:TRADE_SKILL_SHOW(event_name)
|
catherton@479
|
2763 local profession_name, prof_level = _G.C_TradeSkillUI.GetTradeSkillLine()
|
jcallahan@92
|
2764
|
jcallahan@92
|
2765 if profession_name == _G.UNKNOWN then
|
jcallahan@92
|
2766 return
|
jcallahan@92
|
2767 end
|
jcallahan@167
|
2768 TradeSkillExecutePer(RegisterTools)
|
jcallahan@92
|
2769 end
|
jcallahan@92
|
2770 end -- do-block
|
jcallahan@92
|
2771
|
jcallahan@92
|
2772
|
jcallahan@167
|
2773 function WDP:TRAINER_CLOSED(event_name)
|
jcallahan@167
|
2774 private.trainer_shown = nil
|
jcallahan@167
|
2775 end
|
jcallahan@167
|
2776
|
jcallahan@167
|
2777
|
jcallahan@92
|
2778 function WDP:TRAINER_SHOW(event_name)
|
jcallahan@232
|
2779 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@164
|
2780 local trainer = NPCEntry(unit_idnum)
|
jcallahan@58
|
2781
|
jcallahan@164
|
2782 if not trainer then
|
jcallahan@58
|
2783 return
|
jcallahan@58
|
2784 end
|
jcallahan@331
|
2785 local _, trainer_standing = UnitFactionStanding("npc")
|
jcallahan@164
|
2786 trainer.teaches = trainer.teaches or {}
|
jcallahan@27
|
2787
|
jcallahan@167
|
2788 private.trainer_shown = true
|
jcallahan@167
|
2789
|
jcallahan@27
|
2790 -- Get the initial trainer filters
|
MMOSimca@344
|
2791 local available = _G.GetTrainerServiceTypeFilter("available") and 1 or 0
|
MMOSimca@344
|
2792 local unavailable = _G.GetTrainerServiceTypeFilter("unavailable") and 1 or 0
|
MMOSimca@344
|
2793 local used = _G.GetTrainerServiceTypeFilter("used") and 1 or 0
|
jcallahan@27
|
2794
|
jcallahan@27
|
2795 -- Clear the trainer filters
|
MMOSimca@344
|
2796 _G.SetTrainerServiceTypeFilter("available", 1)
|
MMOSimca@344
|
2797 _G.SetTrainerServiceTypeFilter("unavailable", 1)
|
MMOSimca@344
|
2798 _G.SetTrainerServiceTypeFilter("used", 1)
|
jcallahan@27
|
2799
|
jcallahan@27
|
2800 for index = 1, _G.GetNumTrainerServices(), 1 do
|
jcallahan@27
|
2801 local spell_name, rank_name, _, _, required_level = _G.GetTrainerServiceInfo(index)
|
jcallahan@27
|
2802
|
jcallahan@27
|
2803 if spell_name then
|
jcallahan@27
|
2804 DatamineTT:ClearLines()
|
jcallahan@27
|
2805 DatamineTT:SetTrainerService(index)
|
jcallahan@27
|
2806
|
jcallahan@27
|
2807 local _, _, spell_id = DatamineTT:GetSpell()
|
jcallahan@27
|
2808
|
jcallahan@43
|
2809 if spell_id then
|
jcallahan@164
|
2810 local class_professions = trainer.teaches[PLAYER_CLASS]
|
jcallahan@164
|
2811
|
jcallahan@164
|
2812 if not class_professions then
|
jcallahan@164
|
2813 trainer.teaches[PLAYER_CLASS] = {}
|
jcallahan@164
|
2814 class_professions = trainer.teaches[PLAYER_CLASS]
|
jcallahan@164
|
2815 end
|
jcallahan@43
|
2816 local profession, min_skill = _G.GetTrainerServiceSkillReq(index)
|
jcallahan@43
|
2817 profession = profession or "General"
|
jcallahan@43
|
2818
|
jcallahan@164
|
2819 local profession_skills = class_professions[profession]
|
jcallahan@43
|
2820
|
jcallahan@43
|
2821 if not profession_skills then
|
jcallahan@43
|
2822 class_professions[profession] = {}
|
jcallahan@43
|
2823 profession_skills = class_professions[profession]
|
jcallahan@43
|
2824 end
|
jcallahan@173
|
2825 profession_skills[spell_id] = ("%d:%d:%d"):format(required_level, min_skill, _G.GetTrainerServiceCost(index))
|
jcallahan@27
|
2826 end
|
jcallahan@27
|
2827 end
|
jcallahan@27
|
2828 end
|
jcallahan@27
|
2829 -- Reset the filters to what they were before
|
MMOSimca@344
|
2830 _G.SetTrainerServiceTypeFilter("available", available or 0)
|
MMOSimca@344
|
2831 _G.SetTrainerServiceTypeFilter("unavailable", unavailable or 0)
|
MMOSimca@344
|
2832 _G.SetTrainerServiceTypeFilter("used", used or 0)
|
jcallahan@27
|
2833 end
|
jcallahan@27
|
2834
|
jcallahan@27
|
2835
|
jcallahan@1
|
2836 function WDP:UNIT_SPELLCAST_SENT(event_name, unit_id, spell_name, spell_rank, target_name, spell_line)
|
jcallahan@1
|
2837 if private.tracked_line or unit_id ~= "player" then
|
jcallahan@1
|
2838 return
|
jcallahan@1
|
2839 end
|
jcallahan@1
|
2840 local spell_label = private.SPELL_LABELS_BY_NAME[spell_name]
|
jcallahan@1
|
2841
|
jcallahan@1
|
2842 if not spell_label then
|
jcallahan@1
|
2843 return
|
jcallahan@1
|
2844 end
|
jcallahan@306
|
2845
|
MMOSimca@343
|
2846 Debug("UNIT_SPELLCAST_SENT: %s was cast.", spell_name)
|
jcallahan@150
|
2847 local item_name, item_link = _G.GameTooltip:GetItem()
|
jcallahan@150
|
2848 local unit_name, unit_id = _G.GameTooltip:GetUnit()
|
jcallahan@1
|
2849
|
jcallahan@150
|
2850 if not unit_name and _G.UnitName("target") == target_name then
|
jcallahan@150
|
2851 unit_name = target_name
|
jcallahan@150
|
2852 unit_id = "target"
|
jcallahan@1
|
2853 end
|
jcallahan@1
|
2854 local spell_flags = private.SPELL_FLAGS_BY_LABEL[spell_label]
|
jcallahan@28
|
2855 local zone_name, area_id, x, y, map_level, instance_token = CurrentLocationData()
|
MMOSimca@328
|
2856 if not (zone_name and area_id and x and y and map_level) then
|
catherton@468
|
2857 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
|
2858 return
|
MMOSimca@328
|
2859 end
|
jcallahan@28
|
2860
|
jcallahan@205
|
2861 table.wipe(current_action)
|
jcallahan@122
|
2862 current_action.instance_token = instance_token
|
jcallahan@122
|
2863 current_action.map_level = map_level
|
jcallahan@122
|
2864 current_action.x = x
|
jcallahan@122
|
2865 current_action.y = y
|
jcallahan@122
|
2866 current_action.zone_data = ("%s:%d"):format(zone_name, area_id)
|
jcallahan@122
|
2867 current_action.spell_label = spell_label
|
jcallahan@105
|
2868
|
jcallahan@105
|
2869 if not private.NON_LOOT_SPELL_LABELS[spell_label] then
|
jcallahan@122
|
2870 current_action.loot_label = spell_label:lower()
|
jcallahan@105
|
2871 end
|
jcallahan@1
|
2872
|
jcallahan@151
|
2873 if unit_name and unit_name == target_name and not item_name then
|
jcallahan@16
|
2874 if bit.band(spell_flags, AF.NPC) == AF.NPC then
|
jcallahan@150
|
2875 if not unit_id or unit_name ~= target_name then
|
jcallahan@16
|
2876 return
|
jcallahan@16
|
2877 end
|
jcallahan@123
|
2878 current_action.target_type = AF.NPC
|
jcallahan@16
|
2879 end
|
jcallahan@16
|
2880 elseif bit.band(spell_flags, AF.ITEM) == AF.ITEM then
|
jcallahan@123
|
2881 current_action.target_type = AF.ITEM
|
jcallahan@16
|
2882
|
jcallahan@150
|
2883 if item_name and item_name == target_name then
|
jcallahan@150
|
2884 current_action.identifier = ItemLinkToID(item_link)
|
jcallahan@16
|
2885 elseif target_name and target_name ~= "" then
|
jcallahan@331
|
2886 local _, item_link = _G.GetItemInfo(target_name)
|
jcallahan@331
|
2887 current_action.identifier = ItemLinkToID(item_link)
|
jcallahan@16
|
2888 end
|
jcallahan@150
|
2889 elseif not item_name and not unit_name then
|
jcallahan@1
|
2890 if bit.band(spell_flags, AF.OBJECT) == AF.OBJECT then
|
jcallahan@17
|
2891 if target_name == "" then
|
jcallahan@17
|
2892 return
|
jcallahan@17
|
2893 end
|
jcallahan@122
|
2894 current_action.object_name = target_name
|
jcallahan@123
|
2895 current_action.target_type = AF.OBJECT
|
jcallahan@1
|
2896 elseif bit.band(spell_flags, AF.ZONE) == AF.ZONE then
|
jcallahan@123
|
2897 current_action.target_type = AF.ZONE
|
jcallahan@1
|
2898 end
|
jcallahan@1
|
2899 end
|
jcallahan@1
|
2900 private.tracked_line = spell_line
|
jcallahan@0
|
2901 end
|
jcallahan@0
|
2902
|
jcallahan@94
|
2903
|
MMOSimca@393
|
2904 -- Triggered by bonus roll prompts, disenchant prompts, and in a few other rare circumstances
|
jcallahan@312
|
2905 function WDP:SPELL_CONFIRMATION_PROMPT(event_name, spell_id, confirm_type, text, duration, currency_id_cost)
|
jcallahan@306
|
2906 if private.RAID_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id] then
|
jcallahan@306
|
2907 ClearKilledBossID()
|
jcallahan@306
|
2908 ClearLootToastContainerID()
|
MMOSimca@387
|
2909 raid_boss_id = private.RAID_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id]
|
jcallahan@306
|
2910 else
|
MMOSimca@336
|
2911 Debug("%s: Spell ID %d is not a known raid boss 'Bonus' spell.", event_name, spell_id)
|
jcallahan@306
|
2912 return
|
jcallahan@1
|
2913 end
|
jcallahan@306
|
2914
|
jcallahan@324
|
2915 -- Assign existing loot data to boss if it exists
|
jcallahan@307
|
2916 if loot_toast_data then
|
MMOSimca@427
|
2917 local npc = NPCEntry(raid_boss_id)
|
MMOSimca@427
|
2918 if npc then
|
MMOSimca@427
|
2919 -- Create needed npc fields if required
|
MMOSimca@427
|
2920 local loot_label = "drops"
|
MMOSimca@427
|
2921 local encounter_data = npc:EncounterData(InstanceDifficultyToken())
|
MMOSimca@427
|
2922 encounter_data[loot_label] = encounter_data[loot_label] or {}
|
MMOSimca@427
|
2923 encounter_data.loot_counts = encounter_data.loot_counts or {}
|
MMOSimca@427
|
2924
|
MMOSimca@427
|
2925 for index = 1, #loot_toast_data do
|
MMOSimca@427
|
2926 local data = loot_toast_data[index]
|
MMOSimca@427
|
2927 local loot_type = data[1]
|
MMOSimca@427
|
2928 local hyperlink = data[2]
|
MMOSimca@427
|
2929 local quantity = data[3]
|
MMOSimca@427
|
2930
|
MMOSimca@427
|
2931 if loot_type == "item" then
|
MMOSimca@427
|
2932 local item_id = ItemLinkToID(hyperlink)
|
MMOSimca@427
|
2933 Debug("%s: Assigned stored item loot data - %s - %d:%d", event_name, hyperlink, item_id, quantity)
|
MMOSimca@427
|
2934 table.insert(encounter_data[loot_label], ("%d:%d"):format(item_id, quantity))
|
MMOSimca@427
|
2935 elseif loot_type == "money" then
|
MMOSimca@427
|
2936 Debug("%s: Assigned stored money loot data - money:%d", event_name, quantity)
|
MMOSimca@427
|
2937 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
|
MMOSimca@427
|
2938 elseif loot_type == "currency" then
|
mmosimca@496
|
2939 local currency_id = CurrencyLinkToID(hyperlink)
|
mmosimca@496
|
2940 Debug("%s: Assigned stored currency loot data - %s - currency:%d (%d)", event_name, hyperlink, currency_id, quantity)
|
mmosimca@496
|
2941 table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
|
MMOSimca@427
|
2942 end
|
jcallahan@317
|
2943 end
|
jcallahan@317
|
2944
|
MMOSimca@427
|
2945 if not boss_loot_toasting[raid_boss_id] then
|
MMOSimca@427
|
2946 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
|
MMOSimca@427
|
2947 boss_loot_toasting[raid_boss_id] = true -- Do not count further loots until timer expires or another boss is killed
|
jcallahan@307
|
2948 end
|
MMOSimca@427
|
2949 else
|
MMOSimca@427
|
2950 Debug("%s: NPC is nil, but we have stored loot data...", event_name)
|
jcallahan@307
|
2951 end
|
jcallahan@307
|
2952 end
|
jcallahan@307
|
2953
|
jcallahan@307
|
2954 ClearLootToastData()
|
MMOSimca@427
|
2955 killed_boss_id_timer_handle = C_Timer.NewTimer(5, ClearKilledBossID)
|
jcallahan@306
|
2956 end
|
jcallahan@306
|
2957
|
jcallahan@306
|
2958
|
jcallahan@306
|
2959 function WDP:UNIT_SPELLCAST_SUCCEEDED(event_name, unit_id, spell_name, spell_rank, spell_line, spell_id)
|
jcallahan@306
|
2960 if unit_id ~= "player" then
|
jcallahan@306
|
2961 return
|
jcallahan@306
|
2962 end
|
jcallahan@306
|
2963 private.tracked_line = nil
|
jcallahan@306
|
2964 private.previous_spell_id = spell_id
|
jcallahan@306
|
2965
|
MMOSimca@393
|
2966 -- For spells cast when Logging
|
MMOSimca@345
|
2967 if private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[spell_id] then
|
MMOSimca@345
|
2968 last_timber_spell_id = spell_id
|
MMOSimca@351
|
2969 UpdateDBEntryLocation("objects", ("OPENING:%s"):format(private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[spell_id]))
|
MMOSimca@345
|
2970 return
|
MMOSimca@345
|
2971 end
|
MMOSimca@345
|
2972
|
MMOSimca@393
|
2973 -- For spells cast by items that always trigger loot toasts
|
MMOSimca@381
|
2974 if private.LOOT_TOAST_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id] then
|
jcallahan@306
|
2975 ClearKilledBossID()
|
jcallahan@306
|
2976 ClearLootToastContainerID()
|
jcallahan@307
|
2977 ClearLootToastData()
|
jcallahan@306
|
2978
|
MMOSimca@387
|
2979 loot_toast_container_id = private.LOOT_TOAST_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id]
|
MMOSimca@383
|
2980 loot_toast_container_timer_handle = C_Timer.NewTimer(1, ClearLootToastContainerID) -- we need to assign a handle here to cancel it later
|
MMOSimca@345
|
2981 return
|
jcallahan@306
|
2982 end
|
jcallahan@306
|
2983
|
MMOSimca@393
|
2984 -- For spells cast by items that don't usually trigger loot toasts
|
catherton@473
|
2985 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
|
2986 -- Set up timer
|
MMOSimca@393
|
2987 ClearChatLootData()
|
MMOSimca@393
|
2988 Debug("%s: Beginning chat-based loot timer for spellID %d", event_name, spell_id)
|
MMOSimca@411
|
2989 chat_loot_timer_handle = C_Timer.NewTimer(1.5, ClearChatLootData)
|
catherton@473
|
2990 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
|
2991 chat_loot_data.identifier = private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_BY_CLASS_ID_MAP[spell_id][PLAYER_CLASS_ID]
|
MMOSimca@454
|
2992 else
|
MMOSimca@454
|
2993 chat_loot_data.identifier = private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id]
|
MMOSimca@454
|
2994 end
|
MMOSimca@347
|
2995 return
|
MMOSimca@347
|
2996 end
|
MMOSimca@347
|
2997
|
jcallahan@306
|
2998 if anvil_spell_ids[spell_id] then
|
jcallahan@306
|
2999 UpdateDBEntryLocation("objects", OBJECT_ID_ANVIL)
|
jcallahan@306
|
3000 elseif forge_spell_ids[spell_id] then
|
jcallahan@306
|
3001 UpdateDBEntryLocation("objects", OBJECT_ID_FORGE)
|
jcallahan@306
|
3002 elseif spell_name:match("^Harvest.+") then
|
jcallahan@306
|
3003 killed_npc_id = current_target_id
|
MMOSimca@343
|
3004 private.harvesting = true -- Used to track which NPCs can be harvested (can we get this from CreatureCache instead?)
|
jcallahan@306
|
3005 end
|
jcallahan@306
|
3006 end
|
jcallahan@0
|
3007
|
jcallahan@90
|
3008
|
jcallahan@1
|
3009 function WDP:HandleSpellFailure(event_name, unit_id, spell_name, spell_rank, spell_line, spell_id)
|
jcallahan@1
|
3010 if unit_id ~= "player" then
|
jcallahan@1
|
3011 return
|
jcallahan@1
|
3012 end
|
jcallahan@0
|
3013
|
jcallahan@1
|
3014 if private.tracked_line == spell_line then
|
jcallahan@1
|
3015 private.tracked_line = nil
|
jcallahan@1
|
3016 end
|
jcallahan@147
|
3017 table.wipe(current_action)
|
jcallahan@0
|
3018 end
|
jcallahan@90
|
3019
|
jcallahan@90
|
3020
|
jcallahan@90
|
3021 do
|
jcallahan@90
|
3022 local function SetUnitField(field, required_type)
|
jcallahan@90
|
3023 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@90
|
3024
|
jcallahan@90
|
3025 if not unit_idnum or (required_type and unit_type ~= required_type) then
|
jcallahan@90
|
3026 return
|
jcallahan@90
|
3027 end
|
jcallahan@90
|
3028
|
jcallahan@171
|
3029 if UnitTypeIsNPC(unit_type) then
|
jcallahan@90
|
3030 NPCEntry(unit_idnum)[field] = true
|
jcallahan@90
|
3031 elseif unit_type == private.UNIT_TYPES.OBJECT then
|
jcallahan@90
|
3032 DBEntry("objects", unit_idnum)[field] = true
|
jcallahan@93
|
3033 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@90
|
3034 end
|
jcallahan@90
|
3035 end
|
jcallahan@90
|
3036
|
jcallahan@90
|
3037
|
jcallahan@90
|
3038 function WDP:AUCTION_HOUSE_SHOW(event_name)
|
MMOSimca@436
|
3039 WDP:StopChatLootRecording(event_name)
|
jcallahan@90
|
3040 SetUnitField("auctioneer", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3041 end
|
jcallahan@90
|
3042
|
jcallahan@90
|
3043
|
jcallahan@90
|
3044 function WDP:BANKFRAME_OPENED(event_name)
|
MMOSimca@436
|
3045 WDP:StopChatLootRecording(event_name)
|
jcallahan@90
|
3046 SetUnitField("banker", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3047 end
|
jcallahan@90
|
3048
|
jcallahan@90
|
3049
|
jcallahan@90
|
3050 function WDP:BATTLEFIELDS_SHOW(event_name)
|
jcallahan@90
|
3051 SetUnitField("battlemaster", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3052 end
|
jcallahan@90
|
3053
|
jcallahan@90
|
3054
|
jcallahan@92
|
3055 function WDP:FORGE_MASTER_OPENED(event_name)
|
jcallahan@90
|
3056 SetUnitField("arcane_reforger", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3057 end
|
jcallahan@90
|
3058
|
jcallahan@90
|
3059
|
jcallahan@323
|
3060 local GOSSIP_SHOW_FUNCS = {
|
jcallahan@323
|
3061 [private.UNIT_TYPES.NPC] = function(unit_idnum)
|
jcallahan@323
|
3062 local gossip_options = { _G.GetGossipOptions() }
|
jcallahan@323
|
3063
|
jcallahan@323
|
3064 for index = 2, #gossip_options, 2 do
|
jcallahan@323
|
3065 if gossip_options[index] == "binder" then
|
jcallahan@323
|
3066 SetUnitField("innkeeper", private.UNIT_TYPES.NPC)
|
jcallahan@323
|
3067 return
|
jcallahan@323
|
3068 end
|
jcallahan@323
|
3069 end
|
jcallahan@323
|
3070 end,
|
jcallahan@323
|
3071 [private.UNIT_TYPES.OBJECT] = function(unit_idnum)
|
jcallahan@323
|
3072 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@323
|
3073 end,
|
jcallahan@323
|
3074 }
|
jcallahan@323
|
3075
|
jcallahan@323
|
3076
|
jcallahan@92
|
3077 function WDP:GOSSIP_SHOW(event_name)
|
MMOSimca@436
|
3078 WDP:StopChatLootRecording(event_name)
|
jcallahan@323
|
3079 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@323
|
3080 if not unit_idnum then
|
jcallahan@323
|
3081 return
|
jcallahan@323
|
3082 end
|
jcallahan@323
|
3083
|
jcallahan@323
|
3084 if GOSSIP_SHOW_FUNCS[unit_type] then
|
jcallahan@323
|
3085 GOSSIP_SHOW_FUNCS[unit_type](unit_idnum)
|
jcallahan@90
|
3086 end
|
jcallahan@90
|
3087 end
|
jcallahan@90
|
3088
|
jcallahan@90
|
3089
|
jcallahan@93
|
3090 function WDP:GUILDBANKFRAME_OPENED(event_name)
|
MMOSimca@436
|
3091 WDP:StopChatLootRecording(event_name)
|
jcallahan@93
|
3092 SetUnitField("guild_bank", private.UNIT_TYPES.OBJECT)
|
jcallahan@93
|
3093 end
|
jcallahan@93
|
3094
|
jcallahan@93
|
3095
|
jcallahan@189
|
3096 function WDP:ITEM_UPGRADE_MASTER_OPENED(event_name)
|
jcallahan@189
|
3097 SetUnitField("item_upgrade_master", private.UNIT_TYPES.NPC)
|
jcallahan@189
|
3098 end
|
jcallahan@189
|
3099
|
jcallahan@189
|
3100
|
jcallahan@90
|
3101 function WDP:TAXIMAP_OPENED(event_name)
|
jcallahan@90
|
3102 SetUnitField("flight_master", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3103 end
|
jcallahan@90
|
3104
|
jcallahan@90
|
3105
|
jcallahan@90
|
3106 function WDP:TRANSMOGRIFY_OPEN(event_name)
|
jcallahan@90
|
3107 SetUnitField("transmogrifier", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3108 end
|
jcallahan@90
|
3109
|
jcallahan@90
|
3110
|
jcallahan@90
|
3111 function WDP:VOID_STORAGE_OPEN(event_name)
|
jcallahan@90
|
3112 SetUnitField("void_storage", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
3113 end
|
jcallahan@90
|
3114 end -- do-block
|