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