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