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