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