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