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