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@565
|
40 local DB_VERSION = 19
|
MMOSimca@346
|
41 local DEBUGGING = false
|
jcallahan@156
|
42 local EVENT_DEBUG = false
|
jcallahan@322
|
43
|
mmosimca@485
|
44 -- Timer durations in seconds
|
mmosimca@485
|
45 local DELAY_PROCESS_ITEMS = 30
|
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
|
atcaleb@561
|
444 local _, q_vector = _G.C_Map.GetWorldPosFromMapPos(area_id, _G.CreateVector2D(0,0))
|
atcaleb@561
|
445 local _, w_vector = _G.C_Map.GetWorldPosFromMapPos(area_id, _G.CreateVector2D(1,1))
|
atcaleb@561
|
446 local yard_width, yard_height = q_vector.y - w_vector.y, q_vector.x - w_vector.x
|
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
|
atcaleb@562
|
929 item_process_timer_handle = C_Timer.NewTicker(DELAY_PROCESS_ITEMS, WDP.ProcessItems, nil)
|
atcaleb@562
|
930 target_location_timer_handle = C_Timer.NewTicker(DELAY_UPDATE_TARGET_LOCATION, WDP.UpdateTargetLocation, nil)
|
atcaleb@562
|
931 world_quest_timer_handle = C_Timer.NewTicker(DELAY_PROCESS_WORLD_QUESTS, WDP.ProcessWorldQuests, nil)
|
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
|
atcaleb@562
|
954 local function RecordWorldQuestData(quest_id, api_data_table)
|
mmosimca@485
|
955 -- Ensure we have location data and rewards (barely readable so putting it on multiple lines)
|
mmosimca@487
|
956 -- (Honor is built in to the quest; it is not a sign rewards have been loaded)
|
atcaleb@562
|
957 if not api_data_table or not api_data_table.x or not api_data_table.y or not api_data_table.mapID or not
|
mmosimca@485
|
958 (_G.GetQuestLogRewardXP(quest_id) > 0 or _G.GetNumQuestLogRewardCurrencies(quest_id) > 0
|
atcaleb@562
|
959 or _G.GetNumQuestLogRewards(quest_id) > 0 or _G.GetQuestLogRewardMoney(quest_id) > 0) then
|
atcaleb@562
|
960 --or _G.GetQuestLogRewardArtifactXP(quest_id) > 0)
|
mmosimca@485
|
961 return
|
mmosimca@485
|
962 end
|
mmosimca@485
|
963
|
mmosimca@485
|
964 local entry = DBEntry("world_quests", quest_id)
|
mmosimca@485
|
965 if entry then
|
mmosimca@485
|
966
|
mmosimca@485
|
967 -- Record location
|
mmosimca@485
|
968 entry["location"] = {}
|
atcaleb@562
|
969 entry["location"]["world_map_id"] = api_data_table.mapID
|
atcaleb@562
|
970 entry["location"]["x"] = api_data_table.x * 100
|
atcaleb@562
|
971 entry["location"]["y"] = api_data_table.y * 100
|
mmosimca@485
|
972
|
mmosimca@485
|
973 -- Record simple rewards (XP, money, artifact XP, honor)
|
mmosimca@485
|
974 entry["rewards"] = {}
|
mmosimca@485
|
975 entry["rewards"]["xp"] = tonumber(_G.GetQuestLogRewardXP(quest_id)) or 0
|
mmosimca@485
|
976 entry["rewards"]["money"] = tonumber(_G.GetQuestLogRewardMoney(quest_id)) or 0
|
atcaleb@562
|
977 --local actualXP, scaling = _G.GetQuestLogRewardArtifactXP(quest_id)
|
atcaleb@562
|
978 --entry["rewards"]["artifact_xp"] = ("%d:%d"):format(tonumber(actualXP) or 0, tonumber(scaling) or 0)
|
mmosimca@485
|
979 entry["rewards"]["honor"] = tonumber(_G.GetQuestLogRewardHonor(quest_id)) or 0
|
mmosimca@485
|
980
|
mmosimca@485
|
981 -- Record currencies
|
mmosimca@485
|
982 entry["rewards"]["currency_count"] = tonumber(_G.GetNumQuestLogRewardCurrencies(quest_id)) or 0
|
mmosimca@485
|
983
|
mmosimca@496
|
984 -- Create currency rewards sub-table and fill
|
mmosimca@485
|
985 if entry["rewards"]["currency_count"] > 0 then
|
mmosimca@485
|
986 entry["rewards"]["currencies"] = {}
|
mmosimca@485
|
987 for i = 1, entry["rewards"]["currency_count"] do
|
mmosimca@503
|
988 local name, texture_path, quantity, currency_id = _G.GetQuestLogRewardCurrencyInfo(i, quest_id)
|
mmosimca@503
|
989 table.insert(entry["rewards"]["currencies"], ("%d:%d"):format(quantity, currency_id))
|
mmosimca@485
|
990 end
|
mmosimca@485
|
991 end
|
mmosimca@485
|
992
|
mmosimca@485
|
993 -- Record items
|
mmosimca@485
|
994 entry["rewards"]["item_count"] = tonumber(_G.GetNumQuestLogRewards(quest_id)) or 0
|
mmosimca@485
|
995
|
mmosimca@496
|
996 -- Create item rewards sub-table and fill
|
mmosimca@485
|
997 if entry["rewards"]["item_count"] > 0 then
|
mmosimca@485
|
998 entry["rewards"]["items"] = {}
|
mmosimca@485
|
999 for i = 1, entry["rewards"]["item_count"] do
|
mmosimca@485
|
1000 local item_name, item_texture, quantity, quality, is_usable, item_id = _G.GetQuestLogRewardInfo(i, quest_id)
|
mmosimca@485
|
1001 table.insert(entry["rewards"]["items"], ("%d:%d"):format(item_id, quantity))
|
mmosimca@485
|
1002 end
|
mmosimca@485
|
1003 end
|
mmosimca@485
|
1004
|
mmosimca@485
|
1005 -- Record time remaining
|
mmosimca@485
|
1006 entry["estimated_end_time"] = _G.GetServerTime() + ((_G.C_TaskQuest.GetQuestTimeLeftMinutes(quest_id) or 0) * 60)
|
mmosimca@485
|
1007 end
|
mmosimca@485
|
1008 end
|
mmosimca@485
|
1009
|
mmosimca@485
|
1010
|
mmosimca@485
|
1011 function WDP:ProcessWorldQuests()
|
MMOSimca@532
|
1012 -- Ignore if player is low level (there are some world quests before max level now, but we can collect enough data from 110s alone still)
|
atcaleb@562
|
1013 if _G.UnitLevel("player") < 110 then return end
|
atcaleb@559
|
1014
|
atcaleb@559
|
1015 local current_ui_map_id = C_Map.GetBestMapForUnit("player")
|
atcaleb@559
|
1016 local bounty_maps = MapUtil.GetRelatedBountyZoneMaps(current_ui_map_id)
|
MMOSimca@535
|
1017
|
MMOSimca@535
|
1018 -- Iterate over zones in continent
|
atcaleb@559
|
1019 for i = 1, #bounty_maps do
|
MMOSimca@535
|
1020
|
MMOSimca@535
|
1021 -- Get data for World Quests
|
atcaleb@559
|
1022 local api_data = C_TaskQuest.GetQuestsForPlayerByMapID(bounty_maps[i]);
|
atcaleb@559
|
1023 local continent_ui_map_id = MapUtil.GetMapParentInfo(bounty_maps[i], _G.Enum.UIMapType.Continent)
|
MMOSimca@535
|
1024
|
MMOSimca@535
|
1025 -- Iterate over the questIDs for each map, doing preload reward requests and creating SavedVariables entries
|
MMOSimca@535
|
1026 if api_data and type(api_data) == "table" and #api_data > 0 then
|
atcaleb@562
|
1027 for j = 1, #api_data do
|
MMOSimca@535
|
1028
|
MMOSimca@535
|
1029 -- Check if we had a valid API table returned to us
|
atcaleb@562
|
1030 if api_data[j] and type(api_data[j]) == "table" and api_data[j].questId then
|
atcaleb@562
|
1031 local quest_id = tonumber(api_data[j].questId) or 0
|
MMOSimca@535
|
1032
|
MMOSimca@535
|
1033 -- Check if we have quest data
|
atcaleb@562
|
1034 if quest_id > 0 and _G.HaveQuestData(quest_id) and QuestUtils_IsQuestWorldQuest(quest_id) and api_data[j].mapID == bounty_maps[i] then
|
atcaleb@559
|
1035 _G.C_TaskQuest.RequestPreloadRewardData(quest_id)
|
atcaleb@562
|
1036 RecordWorldQuestData(quest_id, api_data[j])
|
mmosimca@485
|
1037 end
|
mmosimca@485
|
1038 end
|
mmosimca@485
|
1039 end
|
mmosimca@485
|
1040 end
|
mmosimca@485
|
1041 end
|
mmosimca@485
|
1042 end
|
mmosimca@485
|
1043
|
mmosimca@485
|
1044
|
MMOSimca@340
|
1045 local function RecordItemData(item_id, item_link, process_bonus_ids, durability)
|
jcallahan@331
|
1046 local _, _, item_string = item_link:find("^|%x+|H(.+)|h%[.+%]")
|
jcallahan@219
|
1047 local item
|
jcallahan@0
|
1048
|
jcallahan@191
|
1049 if item_string then
|
MMOSimca@338
|
1050 local item_results = { (":"):split(item_string) }
|
MMOSimca@338
|
1051
|
MMOSimca@460
|
1052 local suffix_id = tonumber(item_results[8]) or 0
|
MMOSimca@462
|
1053 local unique_id = tonumber(item_results[9]) or 0
|
MMOSimca@447
|
1054 --local level = tonumber(item_results[10])
|
MMOSimca@460
|
1055 --local specialization_id = tonumber(item_results[11])
|
catherton@469
|
1056 --local upgrade_type_id = tonumber(item_results[12])
|
MMOSimca@460
|
1057 local instance_difficulty_id = tonumber(item_results[13]) or 0
|
MMOSimca@460
|
1058 local num_bonus_ids = tonumber(item_results[14]) or 0
|
catherton@471
|
1059 -- 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
|
1060 local upgrade_value = tonumber(item_results[15 + num_bonus_ids]) or 0
|
catherton@465
|
1061
|
mmosimca@484
|
1062 local unk_item_field_1 = tonumber(item_results[16 + num_bonus_ids]) or 0
|
mmosimca@484
|
1063 local unk_item_field_2 = tonumber(item_results[17 + num_bonus_ids]) or 0
|
mmosimca@484
|
1064 --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
|
1065 --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
|
1066
|
MMOSimca@460
|
1067 -- If there is anything special (non-zero) for this item then we need to make note of everything
|
catherton@471
|
1068 if math.max(suffix_id, instance_difficulty_id, num_bonus_ids, upgrade_value) ~= 0 then
|
MMOSimca@460
|
1069 item = DBEntry("items", item_id)
|
MMOSimca@460
|
1070 item.suffix_id = suffix_id
|
MMOSimca@460
|
1071 item.unique_id = bit.band(unique_id, 0xFFFF)
|
MMOSimca@460
|
1072 item.instance_difficulty_id = instance_difficulty_id
|
catherton@471
|
1073 item.upgrade_value = upgrade_value
|
MMOSimca@460
|
1074
|
MMOSimca@460
|
1075 if process_bonus_ids then
|
MMOSimca@460
|
1076
|
MMOSimca@460
|
1077 -- Get ready for bonus IDs
|
MMOSimca@384
|
1078 if not item.seen_bonuses then
|
MMOSimca@384
|
1079 item.seen_bonuses = {}
|
MMOSimca@372
|
1080 end
|
catherton@465
|
1081
|
MMOSimca@460
|
1082 if num_bonus_ids > 0 then
|
MMOSimca@460
|
1083 -- We want the bonus ID combo output to be in the form ["bonusID1:bonusID2:bonusID3"] = true
|
MMOSimca@460
|
1084 -- And sorted numerically with the smallest bonusID first
|
MMOSimca@460
|
1085 local sorted_bonus_string = ""
|
MMOSimca@460
|
1086 local min_bonus_id_array = {}
|
MMOSimca@460
|
1087 for iterations = 1, num_bonus_ids do
|
MMOSimca@460
|
1088 -- Find minimum of this iteration
|
MMOSimca@460
|
1089 local min_bonus_id = 100000
|
MMOSimca@460
|
1090 for bonus_index = 1, num_bonus_ids do
|
MMOSimca@460
|
1091 local temp_bonus_id = tonumber(item_results[14 + bonus_index])
|
MMOSimca@460
|
1092 if temp_bonus_id and (not min_bonus_id_array[temp_bonus_id]) and (temp_bonus_id < min_bonus_id) then
|
MMOSimca@460
|
1093 min_bonus_id = temp_bonus_id
|
MMOSimca@460
|
1094 end
|
MMOSimca@460
|
1095 end
|
MMOSimca@460
|
1096
|
MMOSimca@460
|
1097 -- Keep track of already processed IDs
|
MMOSimca@460
|
1098 min_bonus_id_array[min_bonus_id] = true
|
MMOSimca@460
|
1099
|
MMOSimca@460
|
1100 -- Build string
|
MMOSimca@460
|
1101 if iterations == 1 then
|
MMOSimca@460
|
1102 sorted_bonus_string = sorted_bonus_string .. tostring(min_bonus_id)
|
MMOSimca@460
|
1103 else
|
MMOSimca@460
|
1104 sorted_bonus_string = sorted_bonus_string .. ":" .. tostring(min_bonus_id)
|
MMOSimca@460
|
1105 end
|
MMOSimca@384
|
1106 end
|
MMOSimca@460
|
1107
|
MMOSimca@460
|
1108 item.seen_bonuses[sorted_bonus_string] = true
|
MMOSimca@460
|
1109 Debug("RecordItemData: Recorded bonus IDs %s for item %d.", sorted_bonus_string, item_id)
|
MMOSimca@384
|
1110 else
|
MMOSimca@460
|
1111 item.seen_bonuses["0"] = true
|
MMOSimca@384
|
1112 end
|
MMOSimca@329
|
1113 end
|
jcallahan@191
|
1114 end
|
jcallahan@0
|
1115 end
|
jcallahan@212
|
1116
|
jcallahan@212
|
1117 if durability and durability > 0 then
|
jcallahan@219
|
1118 item = item or DBEntry("items", item_id)
|
jcallahan@212
|
1119 item.durability = durability
|
jcallahan@212
|
1120 end
|
jcallahan@0
|
1121 end
|
jcallahan@0
|
1122
|
jcallahan@0
|
1123
|
jcallahan@187
|
1124 function WDP:ProcessItems()
|
jcallahan@187
|
1125 for slot_index = _G.INVSLOT_FIRST_EQUIPPED, _G.INVSLOT_LAST_EQUIPPED do
|
jcallahan@1
|
1126 local item_id = _G.GetInventoryItemID("player", slot_index)
|
jcallahan@0
|
1127
|
jcallahan@0
|
1128 if item_id and item_id > 0 then
|
jcallahan@1
|
1129 local _, max_durability = _G.GetInventoryItemDurability(slot_index)
|
MMOSimca@340
|
1130 RecordItemData(item_id, _G.GetInventoryItemLink("player", slot_index), false, max_durability)
|
jcallahan@0
|
1131 end
|
jcallahan@0
|
1132 end
|
jcallahan@0
|
1133
|
jcallahan@0
|
1134 for bag_index = 0, _G.NUM_BAG_SLOTS do
|
jcallahan@0
|
1135 for slot_index = 1, _G.GetContainerNumSlots(bag_index) do
|
jcallahan@1
|
1136 local item_id = _G.GetContainerItemID(bag_index, slot_index)
|
jcallahan@0
|
1137
|
jcallahan@0
|
1138 if item_id and item_id > 0 then
|
jcallahan@1
|
1139 local _, max_durability = _G.GetContainerItemDurability(bag_index, slot_index)
|
MMOSimca@340
|
1140 RecordItemData(item_id, _G.GetContainerItemLink(bag_index, slot_index), false, max_durability)
|
jcallahan@0
|
1141 end
|
jcallahan@0
|
1142 end
|
jcallahan@0
|
1143 end
|
jcallahan@0
|
1144 end
|
jcallahan@0
|
1145
|
jcallahan@118
|
1146
|
atcaleb@558
|
1147 local function TargetedNPC()
|
atcaleb@558
|
1148 if not _G.UnitExists("target") or _G.UnitPlayerControlled("target") or currently_drunk then
|
atcaleb@558
|
1149 current_target_id = nil
|
atcaleb@558
|
1150 return
|
atcaleb@558
|
1151 end
|
atcaleb@558
|
1152 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("target"))
|
atcaleb@558
|
1153
|
atcaleb@558
|
1154 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
atcaleb@558
|
1155 return
|
atcaleb@558
|
1156 end
|
atcaleb@558
|
1157 current_target_id = unit_idnum
|
atcaleb@558
|
1158
|
atcaleb@558
|
1159 local npc = NPCEntry(unit_idnum)
|
atcaleb@558
|
1160 local _, class_token = _G.UnitClass("target")
|
atcaleb@558
|
1161 npc.class = class_token
|
atcaleb@558
|
1162 npc.faction = UnitFactionStanding("target")
|
atcaleb@558
|
1163 npc.genders = npc.genders or {}
|
atcaleb@558
|
1164 npc.genders[private.GENDER_NAMES[_G.UnitSex("target")] or "UNDEFINED"] = true
|
atcaleb@558
|
1165 npc.is_pvp = _G.UnitIsPVP("target") and true or nil
|
atcaleb@558
|
1166 npc.reaction = ("%s:%s:%s"):format(_G.UnitLevel("player"), _G.UnitFactionGroup("player"), private.REACTION_NAMES[_G.UnitReaction("player", "target")])
|
atcaleb@558
|
1167
|
atcaleb@558
|
1168 local encounter_data = npc:EncounterData(InstanceDifficultyToken()).stats
|
atcaleb@558
|
1169 local npc_level = ("level_%d"):format(_G.UnitLevel("target"))
|
atcaleb@558
|
1170 local level_data = encounter_data[npc_level]
|
atcaleb@558
|
1171
|
atcaleb@558
|
1172 if not level_data then
|
atcaleb@558
|
1173 level_data = {}
|
atcaleb@558
|
1174 encounter_data[npc_level] = level_data
|
atcaleb@558
|
1175 end
|
atcaleb@558
|
1176 level_data.max_health = level_data.max_health or _G.UnitHealthMax("target")
|
atcaleb@558
|
1177
|
atcaleb@558
|
1178 -- May not capture as much data as it could, since the API changed in Legion to report multiple types of power
|
atcaleb@558
|
1179 if not level_data.power then
|
atcaleb@558
|
1180 local max_power = _G.UnitPowerMax("target")
|
atcaleb@558
|
1181
|
atcaleb@558
|
1182 if max_power > 0 then
|
atcaleb@558
|
1183 local power_type = _G.UnitPowerType("target")
|
atcaleb@558
|
1184 level_data.power = ("%s:%d"):format(private.POWER_TYPE_NAMES[tostring(power_type)] or power_type, max_power)
|
jcallahan@118
|
1185 end
|
jcallahan@118
|
1186 end
|
atcaleb@558
|
1187 name_to_id_map[_G.UnitName("target")] = unit_idnum
|
atcaleb@558
|
1188 return npc, unit_idnum
|
atcaleb@558
|
1189 end
|
jcallahan@118
|
1190
|
jcallahan@118
|
1191
|
jcallahan@113
|
1192 do
|
jcallahan@113
|
1193 local COORD_MAX = 5
|
jcallahan@0
|
1194
|
jcallahan@113
|
1195 function WDP:UpdateTargetLocation()
|
catherton@480
|
1196 if currently_drunk or not _G.UnitExists("target") or _G.UnitPlayerControlled("target") or (_G.UnitIsTapDenied("target") and not _G.UnitIsDead("target")) then
|
jcallahan@2
|
1197 return
|
jcallahan@2
|
1198 end
|
jcallahan@113
|
1199
|
jcallahan@113
|
1200 for index = 1, 4 do
|
jcallahan@113
|
1201 if not _G.CheckInteractDistance("target", index) then
|
jcallahan@113
|
1202 return
|
jcallahan@113
|
1203 end
|
jcallahan@113
|
1204 end
|
jcallahan@215
|
1205 local npc = TargetedNPC()
|
jcallahan@113
|
1206
|
jcallahan@113
|
1207 if not npc then
|
jcallahan@113
|
1208 return
|
jcallahan@113
|
1209 end
|
jcallahan@113
|
1210 local zone_name, area_id, x, y, map_level, difficulty_token = CurrentLocationData()
|
MMOSimca@328
|
1211 if not (zone_name and area_id and x and y and map_level) then
|
mmosimca@508
|
1212 if not (_G.IsInInstance()) then
|
mmosimca@508
|
1213 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
|
1214 end
|
MMOSimca@328
|
1215 return
|
MMOSimca@328
|
1216 end
|
jcallahan@248
|
1217 local npc_data = npc:EncounterData(difficulty_token).stats[("level_%d"):format(_G.UnitLevel("target"))]
|
jcallahan@113
|
1218 local zone_token = ("%s:%d"):format(zone_name, area_id)
|
jcallahan@118
|
1219 npc_data.locations = npc_data.locations or {} -- TODO: Fix this. It is broken. Possibly something to do with the timed updates.
|
jcallahan@113
|
1220
|
jcallahan@113
|
1221 local zone_data = npc_data.locations[zone_token]
|
jcallahan@113
|
1222
|
jcallahan@113
|
1223 if not zone_data then
|
jcallahan@113
|
1224 zone_data = {}
|
jcallahan@113
|
1225 npc_data.locations[zone_token] = zone_data
|
jcallahan@113
|
1226 end
|
jcallahan@113
|
1227
|
jcallahan@113
|
1228 for location_token in pairs(zone_data) do
|
jcallahan@113
|
1229 local loc_level, loc_x, loc_y = (":"):split(location_token)
|
jcallahan@113
|
1230 loc_level = tonumber(loc_level)
|
jcallahan@113
|
1231
|
jcallahan@113
|
1232 if map_level == loc_level and math.abs(x - loc_x) <= COORD_MAX and math.abs(y - loc_y) <= COORD_MAX then
|
jcallahan@113
|
1233 return
|
jcallahan@113
|
1234 end
|
jcallahan@113
|
1235 end
|
jcallahan@141
|
1236 zone_data[("%d:%d:%d"):format(map_level, x, y)] = true
|
jcallahan@2
|
1237 end
|
jcallahan@113
|
1238 end -- do-block
|
jcallahan@2
|
1239
|
jcallahan@118
|
1240
|
MMOSimca@412
|
1241 function WDP:HandleBadChatLootData(...)
|
MMOSimca@398
|
1242 ClearChatLootData()
|
MMOSimca@398
|
1243 end
|
MMOSimca@398
|
1244
|
MMOSimca@398
|
1245
|
MMOSimca@420
|
1246 -- EVENT HANDLERS -----------------------------------------------------
|
MMOSimca@420
|
1247
|
MMOSimca@436
|
1248 -- 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
|
1249 function WDP:StopChatLootRecording(event_name)
|
MMOSimca@436
|
1250 if not block_chat_loot_data then
|
MMOSimca@439
|
1251 Debug("%s: Pausing chat-based loot recording.", event_name)
|
MMOSimca@436
|
1252 ClearChatLootData()
|
MMOSimca@436
|
1253 block_chat_loot_data = true
|
MMOSimca@436
|
1254 end
|
MMOSimca@436
|
1255 end
|
MMOSimca@436
|
1256
|
MMOSimca@436
|
1257
|
MMOSimca@436
|
1258 function WDP:ResumeChatLootRecording(event_name)
|
MMOSimca@436
|
1259 if block_chat_loot_data then
|
MMOSimca@439
|
1260 Debug("%s: Resuming chat-based loot recording.", event_name)
|
MMOSimca@436
|
1261 block_chat_loot_data = false
|
MMOSimca@436
|
1262 end
|
MMOSimca@436
|
1263 end
|
MMOSimca@436
|
1264
|
MMOSimca@436
|
1265
|
MMOSimca@408
|
1266 -- 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
|
1267 function WDP:BONUS_ROLL_RESULT(event_name)
|
MMOSimca@408
|
1268 Debug("%s: Bonus roll detected; stopping loot recording for this boss to avoid recording bonus loot.", event_name)
|
MMOSimca@408
|
1269 ClearKilledBossID()
|
MMOSimca@408
|
1270 ClearLootToastContainerID()
|
MMOSimca@408
|
1271 end
|
MMOSimca@408
|
1272
|
MMOSimca@408
|
1273
|
jcallahan@90
|
1274 function WDP:BLACK_MARKET_ITEM_UPDATE(event_name)
|
jcallahan@243
|
1275 if not ALLOWED_LOCALES[CLIENT_LOCALE] then
|
jcallahan@243
|
1276 return
|
jcallahan@243
|
1277 end
|
jcallahan@282
|
1278 local num_items = _G.C_BlackMarket.GetNumItems() or 0
|
jcallahan@56
|
1279
|
jcallahan@56
|
1280 for index = 1, num_items do
|
jcallahan@56
|
1281 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
|
1282
|
jcallahan@56
|
1283 if item_link then
|
jcallahan@56
|
1284 DBEntry("items", ItemLinkToID(item_link)).black_market = seller_name or "UNKNOWN"
|
jcallahan@56
|
1285 end
|
jcallahan@56
|
1286 end
|
jcallahan@56
|
1287 end
|
jcallahan@56
|
1288
|
jcallahan@56
|
1289
|
jcallahan@298
|
1290 local function UpdateUnitPet(unit_guid, unit_id)
|
jcallahan@246
|
1291 local current_pet_guid = group_owner_guids_to_pet_guids[unit_guid]
|
jcallahan@246
|
1292
|
jcallahan@246
|
1293 if current_pet_guid then
|
jcallahan@246
|
1294 group_owner_guids_to_pet_guids[unit_guid] = nil
|
jcallahan@246
|
1295 group_pet_guids[current_pet_guid] = nil
|
jcallahan@246
|
1296 end
|
jcallahan@246
|
1297 local pet_guid = _G.UnitGUID(unit_id .. "pet")
|
jcallahan@246
|
1298
|
jcallahan@246
|
1299 if pet_guid then
|
jcallahan@296
|
1300 group_owner_guids_to_pet_guids[unit_guid] = pet_guid
|
jcallahan@246
|
1301 group_pet_guids[pet_guid] = true
|
jcallahan@246
|
1302 end
|
jcallahan@246
|
1303 end
|
jcallahan@246
|
1304
|
jcallahan@246
|
1305
|
jcallahan@298
|
1306 function WDP:GROUP_ROSTER_UPDATE(event_name)
|
jcallahan@298
|
1307 local is_raid = _G.IsInRaid()
|
jcallahan@298
|
1308 local unit_type = is_raid and "raid" or "party"
|
jcallahan@298
|
1309 local group_size = is_raid and _G.GetNumGroupMembers() or _G.GetNumSubgroupMembers()
|
jcallahan@298
|
1310
|
jcallahan@299
|
1311 table.wipe(group_member_guids)
|
jcallahan@298
|
1312
|
jcallahan@298
|
1313 for index = 1, group_size do
|
jcallahan@298
|
1314 local unit_id = unit_type .. index
|
jcallahan@298
|
1315 local unit_guid = _G.UnitGUID(unit_id)
|
jcallahan@298
|
1316
|
jcallahan@299
|
1317 group_member_guids[unit_guid] = true
|
jcallahan@298
|
1318 UpdateUnitPet(unit_guid, unit_id)
|
jcallahan@298
|
1319 end
|
jcallahan@299
|
1320 group_member_guids[PLAYER_GUID] = true
|
jcallahan@298
|
1321 end
|
jcallahan@298
|
1322
|
jcallahan@298
|
1323
|
jcallahan@298
|
1324 function WDP:UNIT_PET(event_name, unit_id)
|
jcallahan@298
|
1325 UpdateUnitPet(_G.UnitGUID(unit_id), unit_id)
|
jcallahan@298
|
1326 end
|
jcallahan@298
|
1327
|
jcallahan@298
|
1328
|
MMOSimca@375
|
1329 function WDP:SHOW_LOOT_TOAST(event_name, loot_type, item_link, quantity, spec_ID, sex_ID, is_personal, loot_source)
|
jcallahan@312
|
1330 if not loot_type or (loot_type ~= "item" and loot_type ~= "money" and loot_type ~= "currency") then
|
jcallahan@306
|
1331 Debug("%s: loot_type is %s. Item link is %s, and quantity is %d.", event_name, loot_type, item_link, quantity)
|
jcallahan@306
|
1332 return
|
jcallahan@306
|
1333 end
|
MMOSimca@372
|
1334
|
MMOSimca@372
|
1335 -- Need information on the most recent args, so using this complete debug statement for now
|
MMOSimca@375
|
1336 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
|
1337
|
MMOSimca@355
|
1338 -- Handle Garrison cache specially
|
MMOSimca@422
|
1339 if loot_source and (loot_source == LOOT_SOURCE_ID_GARRISON_CACHE) and last_garrison_cache_object_id then
|
MMOSimca@355
|
1340 -- Record location data for cache
|
MMOSimca@355
|
1341 UpdateDBEntryLocation("objects", ("OPENING:%d"):format(last_garrison_cache_object_id))
|
MMOSimca@355
|
1342
|
MMOSimca@355
|
1343 -- Add drop data
|
mmosimca@496
|
1344 local currency_id = CurrencyLinkToID(item_link)
|
mmosimca@496
|
1345 if currency_id and currency_id ~= 0 then
|
MMOSimca@355
|
1346 -- Check for top level object data
|
MMOSimca@355
|
1347 local object_entry = DBEntry("objects", ("OPENING:%d"):format(last_garrison_cache_object_id))
|
MMOSimca@355
|
1348 local difficulty_token = InstanceDifficultyToken()
|
MMOSimca@355
|
1349 if object_entry[difficulty_token] then
|
MMOSimca@355
|
1350 -- Increment loot count
|
MMOSimca@355
|
1351 object_entry[difficulty_token]["opening_count"] = (object_entry[difficulty_token]["opening_count"] or 0) + 1
|
MMOSimca@355
|
1352
|
mmosimca@496
|
1353 Debug("%s: %d X %d", event_name, currency_id, quantity)
|
MMOSimca@355
|
1354 object_entry[difficulty_token]["opening"] = object_entry[difficulty_token]["opening"] or {}
|
mmosimca@496
|
1355 table.insert(object_entry[difficulty_token]["opening"], ("currency:%d:%d"):format(quantity, currency_id))
|
MMOSimca@355
|
1356 else
|
MMOSimca@355
|
1357 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
|
1358 end
|
MMOSimca@355
|
1359 else
|
mmosimca@496
|
1360 Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
|
MMOSimca@355
|
1361 end
|
catherton@465
|
1362
|
MMOSimca@431
|
1363 -- Wipe object ID until future mouseover
|
MMOSimca@431
|
1364 last_garrison_cache_object_id = nil
|
MMOSimca@387
|
1365 elseif raid_boss_id then
|
MMOSimca@427
|
1366 local npc = NPCEntry(raid_boss_id)
|
MMOSimca@427
|
1367 if npc then
|
MMOSimca@427
|
1368 local loot_label = "drops"
|
MMOSimca@427
|
1369 local encounter_data = npc:EncounterData(InstanceDifficultyToken())
|
MMOSimca@427
|
1370 encounter_data[loot_label] = encounter_data[loot_label] or {}
|
MMOSimca@427
|
1371 encounter_data.loot_counts = encounter_data.loot_counts or {}
|
MMOSimca@427
|
1372
|
MMOSimca@427
|
1373 if loot_type == "item" then
|
MMOSimca@427
|
1374 local item_id = ItemLinkToID(item_link)
|
MMOSimca@427
|
1375 if item_id then
|
MMOSimca@427
|
1376 Debug("%s: %s X %d (%d)", event_name, item_link, quantity, item_id)
|
MMOSimca@427
|
1377 RecordItemData(item_id, item_link, true)
|
MMOSimca@427
|
1378 table.insert(encounter_data[loot_label], ("%d:%d"):format(item_id, quantity))
|
MMOSimca@427
|
1379 else
|
MMOSimca@427
|
1380 Debug("%s: ItemID is nil, from item link %s", event_name, item_link)
|
MMOSimca@427
|
1381 return
|
MMOSimca@427
|
1382 end
|
MMOSimca@427
|
1383 elseif loot_type == "money" then
|
MMOSimca@427
|
1384 Debug("%s: money X %d", event_name, quantity)
|
MMOSimca@427
|
1385 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
|
MMOSimca@427
|
1386 elseif loot_type == "currency" then
|
mmosimca@496
|
1387 local currency_id = CurrencyLinkToID(item_link)
|
mmosimca@496
|
1388 if currency_id and currency_id ~= 0 then
|
mmosimca@496
|
1389 Debug("%s: %d X %d", event_name, currency_id, quantity)
|
mmosimca@496
|
1390 table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
|
MMOSimca@427
|
1391 else
|
mmosimca@496
|
1392 Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
|
MMOSimca@427
|
1393 return
|
MMOSimca@427
|
1394 end
|
jcallahan@312
|
1395 end
|
jcallahan@317
|
1396
|
MMOSimca@427
|
1397 if not boss_loot_toasting[raid_boss_id] then
|
MMOSimca@427
|
1398 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
|
MMOSimca@427
|
1399 boss_loot_toasting[raid_boss_id] = true -- Do not count further loots until timer expires or another boss is killed
|
jcallahan@312
|
1400 end
|
jcallahan@312
|
1401 end
|
MMOSimca@387
|
1402 elseif loot_toast_container_id then
|
jcallahan@305
|
1403 InitializeCurrentLoot()
|
jcallahan@305
|
1404
|
jcallahan@306
|
1405 -- Fake the loot characteristics to match that of an actual container item
|
MMOSimca@387
|
1406 current_loot.identifier = loot_toast_container_id
|
jcallahan@306
|
1407 current_loot.label = "contains"
|
jcallahan@306
|
1408 current_loot.target_type = AF.ITEM
|
jcallahan@306
|
1409
|
MMOSimca@387
|
1410 current_loot.sources[loot_toast_container_id] = current_loot.sources[loot_toast_container_id] or {}
|
jcallahan@312
|
1411
|
jcallahan@301
|
1412 if loot_type == "item" then
|
jcallahan@312
|
1413 local item_id = ItemLinkToID(item_link)
|
jcallahan@312
|
1414 if item_id then
|
jcallahan@312
|
1415 Debug("%s: %s X %d (%d)", event_name, item_link, quantity, item_id)
|
MMOSimca@340
|
1416 RecordItemData(item_id, item_link, true)
|
MMOSimca@387
|
1417 current_loot.sources[loot_toast_container_id][item_id] = (current_loot.sources[loot_toast_container_id][item_id] or 0) + quantity
|
jcallahan@312
|
1418 else
|
jcallahan@301
|
1419 Debug("%s: ItemID is nil, from item link %s", event_name, item_link)
|
jcallahan@312
|
1420 current_loot = nil
|
jcallahan@301
|
1421 return
|
jcallahan@301
|
1422 end
|
jcallahan@301
|
1423 elseif loot_type == "money" then
|
jcallahan@312
|
1424 Debug("%s: money X %d", event_name, quantity)
|
MMOSimca@387
|
1425 current_loot.sources[loot_toast_container_id]["money"] = (current_loot.sources[loot_toast_container_id]["money"] or 0) + quantity
|
jcallahan@312
|
1426 elseif loot_type == "currency" then
|
mmosimca@496
|
1427 local currency_id = CurrencyLinkToID(item_link)
|
mmosimca@496
|
1428 if currency_id and currency_id ~= 0 then
|
mmosimca@496
|
1429 Debug("%s: %d X %d", event_name, currency_id, quantity)
|
mmosimca@496
|
1430 local currency_token = ("currency:%d"):format(currency_id)
|
MMOSimca@387
|
1431 current_loot.sources[loot_toast_container_id][currency_token] = (current_loot.sources[loot_toast_container_id][currency_token] or 0) + quantity
|
jcallahan@312
|
1432 else
|
mmosimca@496
|
1433 Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
|
jcallahan@312
|
1434 current_loot = nil
|
jcallahan@312
|
1435 return
|
jcallahan@312
|
1436 end
|
jcallahan@301
|
1437 end
|
jcallahan@312
|
1438
|
jcallahan@301
|
1439 GenericLootUpdate("items")
|
jcallahan@301
|
1440 current_loot = nil
|
MMOSimca@387
|
1441 container_loot_toasting = true -- Do not count further loots until timer expires or another container is opened
|
MMOSimca@539
|
1442 elseif loot_source and chat_loot_timer_handle then
|
MMOSimca@444
|
1443 -- 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
|
1444 if loot_type == "currency" then
|
mmosimca@496
|
1445 local currency_id = CurrencyLinkToID(item_link)
|
mmosimca@496
|
1446 if currency_id and currency_id ~= 0 then
|
MMOSimca@444
|
1447 -- Verify that we're still assigning data to the right items
|
MMOSimca@444
|
1448 if chat_loot_data.identifier and (private.CONTAINER_ITEM_ID_LIST[chat_loot_data.identifier] ~= nil) then
|
mmosimca@496
|
1449 Debug("%s: Captured currency for chat-based loot recording. %d X %d", event_name, currency_id, quantity)
|
mmosimca@496
|
1450 local currency_token = ("currency:%d"):format(currency_id)
|
MMOSimca@444
|
1451 chat_loot_data.loot = chat_loot_data.loot or {}
|
MMOSimca@444
|
1452 chat_loot_data.loot[currency_token] = (chat_loot_data.loot[currency_token] or 0) + quantity
|
MMOSimca@444
|
1453 else -- If not, cancel the timer and wipe the loot table early
|
MMOSimca@444
|
1454 Debug("%s: Canceled chat-based loot recording because we would have assigned the wrong loot!", event_name)
|
MMOSimca@444
|
1455 ClearChatLootData()
|
MMOSimca@444
|
1456 end
|
MMOSimca@444
|
1457 else
|
mmosimca@496
|
1458 Debug("%s: Currency ID is nil or 0, from currency link %s", event_name, item_link)
|
MMOSimca@444
|
1459 end
|
MMOSimca@444
|
1460 -- 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
|
1461 elseif loot_type == "money" then
|
MMOSimca@424
|
1462 -- Verify that we're still assigning data to the right items
|
MMOSimca@435
|
1463 if chat_loot_data.identifier and (private.CONTAINER_ITEM_ID_LIST[chat_loot_data.identifier] ~= nil) then
|
MMOSimca@444
|
1464 Debug("%s: Captured money for chat-based loot recording. money X %d", event_name, quantity)
|
MMOSimca@435
|
1465 chat_loot_data.loot = chat_loot_data.loot or {}
|
MMOSimca@444
|
1466 chat_loot_data.loot["money"] = (chat_loot_data.loot["money"] or 0) + quantity
|
MMOSimca@424
|
1467 else -- If not, cancel the timer and wipe the loot table early
|
MMOSimca@424
|
1468 Debug("%s: Canceled chat-based loot recording because we would have assigned the wrong loot!", event_name)
|
MMOSimca@424
|
1469 ClearChatLootData()
|
MMOSimca@424
|
1470 end
|
MMOSimca@424
|
1471 end
|
jcallahan@301
|
1472 else
|
jcallahan@307
|
1473 Debug("%s: NPC and Container are nil, storing loot toast data for 5 seconds.", event_name)
|
jcallahan@307
|
1474
|
jcallahan@307
|
1475 loot_toast_data = loot_toast_data or {}
|
jcallahan@312
|
1476 loot_toast_data[#loot_toast_data + 1] = { loot_type, item_link, quantity }
|
jcallahan@307
|
1477
|
MMOSimca@340
|
1478 local item_id = ItemLinkToID(item_link)
|
MMOSimca@340
|
1479 if item_id then
|
MMOSimca@340
|
1480 RecordItemData(item_id, item_link, true)
|
MMOSimca@340
|
1481 end
|
MMOSimca@340
|
1482
|
MMOSimca@383
|
1483 loot_toast_data_timer_handle = C_Timer.NewTimer(5, ClearLootToastData)
|
jcallahan@178
|
1484 end
|
jcallahan@178
|
1485 end
|
jcallahan@178
|
1486
|
jcallahan@178
|
1487
|
jcallahan@179
|
1488 do
|
MMOSimca@388
|
1489 local CHAT_MSG_CURRENCY_UPDATE_FUNCS = {
|
mmosimca@496
|
1490 [AF.NPC] = function(currency_id, quantity)
|
mmosimca@496
|
1491 Debug("CHAT_MSG_CURRENCY: AF.NPC currency:%d (%d)", currency_id, quantity)
|
MMOSimca@388
|
1492 end,
|
mmosimca@496
|
1493 [AF.ZONE] = function(currency_id, quantity)
|
mmosimca@496
|
1494 Debug("CHAT_MSG_CURRENCY: AF.ZONE currency:%d (%d)", currency_id, quantity)
|
MMOSimca@388
|
1495 InitializeCurrentLoot()
|
mmosimca@496
|
1496 current_loot.list[1] = ("currency:%d:%d"):format(quantity, currency_id)
|
MMOSimca@388
|
1497 GenericLootUpdate("zones")
|
MMOSimca@388
|
1498 current_loot = nil
|
MMOSimca@388
|
1499 end,
|
MMOSimca@388
|
1500 }
|
MMOSimca@388
|
1501
|
MMOSimca@388
|
1502
|
MMOSimca@388
|
1503 function WDP:CHAT_MSG_CURRENCY(event_name, message)
|
MMOSimca@388
|
1504 local category
|
MMOSimca@388
|
1505
|
MMOSimca@388
|
1506 local currency_link, quantity = deformat(message, _G.CURRENCY_GAINED_MULTIPLE)
|
MMOSimca@388
|
1507 if not currency_link then
|
MMOSimca@388
|
1508 quantity, currency_link = 1, deformat(message, _G.CURRENCY_GAINED)
|
MMOSimca@388
|
1509 end
|
mmosimca@496
|
1510 local currency_id = CurrencyLinkToID(currency_link)
|
mmosimca@496
|
1511
|
mmosimca@496
|
1512 if not currency_id or currency_id == 0 then
|
MMOSimca@388
|
1513 return
|
MMOSimca@388
|
1514 end
|
MMOSimca@388
|
1515
|
MMOSimca@388
|
1516 -- Set update category
|
MMOSimca@388
|
1517 if current_action.spell_label == "FISHING" then
|
MMOSimca@388
|
1518 category = AF.ZONE
|
MMOSimca@388
|
1519 elseif raid_boss_id then
|
MMOSimca@388
|
1520 category = AF.NPC
|
MMOSimca@388
|
1521 end
|
MMOSimca@388
|
1522
|
MMOSimca@388
|
1523 -- Take action based on update category
|
MMOSimca@388
|
1524 local update_func = CHAT_MSG_CURRENCY_UPDATE_FUNCS[category]
|
MMOSimca@388
|
1525 if not category or not update_func then
|
MMOSimca@388
|
1526 return
|
MMOSimca@388
|
1527 end
|
mmosimca@496
|
1528 update_func(currency_id, quantity)
|
MMOSimca@388
|
1529 end
|
MMOSimca@388
|
1530
|
MMOSimca@388
|
1531
|
jcallahan@179
|
1532 local CHAT_MSG_LOOT_UPDATE_FUNCS = {
|
MMOSimca@347
|
1533 [AF.ITEM] = function(item_id, quantity)
|
MMOSimca@347
|
1534 -- Verify that we're still assigning data to the right items
|
MMOSimca@435
|
1535 if chat_loot_data.identifier and (private.CONTAINER_ITEM_ID_LIST[chat_loot_data.identifier] ~= nil) then
|
MMOSimca@347
|
1536 Debug("CHAT_MSG_LOOT: AF.ITEM %d (%d)", item_id, quantity)
|
MMOSimca@435
|
1537 chat_loot_data.loot = chat_loot_data.loot or {}
|
MMOSimca@435
|
1538 chat_loot_data.loot[item_id] = (chat_loot_data.loot[item_id] or 0) + quantity
|
MMOSimca@347
|
1539 else -- If not, cancel the timer and wipe the loot table early
|
MMOSimca@387
|
1540 Debug("CHAT_MSG_LOOT: We would have assigned the wrong loot!")
|
MMOSimca@387
|
1541 ClearChatLootData()
|
MMOSimca@347
|
1542 end
|
MMOSimca@347
|
1543 end,
|
jcallahan@179
|
1544 [AF.NPC] = function(item_id, quantity)
|
MMOSimca@345
|
1545 Debug("CHAT_MSG_LOOT: AF.NPC %d (%d)", item_id, quantity)
|
MMOSimca@345
|
1546 end,
|
MMOSimca@345
|
1547 [AF.OBJECT] = function(item_id, quantity)
|
MMOSimca@345
|
1548 Debug("CHAT_MSG_LOOT: AF.OBJECT %d (%d)", item_id, quantity)
|
MMOSimca@381
|
1549 -- Check for top level object data
|
MMOSimca@381
|
1550 local object_entry = DBEntry("objects", ("OPENING:%s"):format(private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[last_timber_spell_id]))
|
MMOSimca@381
|
1551 local difficulty_token = InstanceDifficultyToken()
|
MMOSimca@381
|
1552 if object_entry[difficulty_token] then
|
MMOSimca@381
|
1553 -- Increment loot count
|
MMOSimca@381
|
1554 object_entry[difficulty_token]["opening_count"] = (object_entry[difficulty_token]["opening_count"] or 0) + 1
|
MMOSimca@381
|
1555
|
MMOSimca@381
|
1556 -- Add drop data
|
MMOSimca@381
|
1557 object_entry[difficulty_token]["opening"] = object_entry[difficulty_token]["opening"] or {}
|
MMOSimca@381
|
1558 table.insert(object_entry[difficulty_token]["opening"], ("%d:%d"):format(item_id, quantity))
|
MMOSimca@381
|
1559 else
|
MMOSimca@381
|
1560 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
|
1561 end
|
jcallahan@179
|
1562 end,
|
jcallahan@179
|
1563 [AF.ZONE] = function(item_id, quantity)
|
MMOSimca@345
|
1564 Debug("CHAT_MSG_LOOT: AF.ZONE %d (%d)", item_id, quantity)
|
jcallahan@312
|
1565 InitializeCurrentLoot()
|
jcallahan@312
|
1566 current_loot.list[1] = ("%d:%d"):format(item_id, quantity)
|
jcallahan@179
|
1567 GenericLootUpdate("zones")
|
jcallahan@312
|
1568 current_loot = nil
|
jcallahan@179
|
1569 end,
|
jcallahan@179
|
1570 }
|
jcallahan@177
|
1571
|
jcallahan@177
|
1572
|
MMOSimca@388
|
1573 function WDP:CHAT_MSG_LOOT(event_name, message)
|
jcallahan@179
|
1574 local category
|
jcallahan@177
|
1575
|
MMOSimca@345
|
1576 local item_link, quantity = deformat(message, _G.LOOT_ITEM_PUSHED_SELF_MULTIPLE)
|
MMOSimca@345
|
1577 if not item_link then
|
MMOSimca@345
|
1578 quantity, item_link = 1, deformat(message, _G.LOOT_ITEM_PUSHED_SELF)
|
MMOSimca@345
|
1579 end
|
MMOSimca@345
|
1580 local item_id = ItemLinkToID(item_link)
|
MMOSimca@345
|
1581
|
MMOSimca@345
|
1582 if not item_id then
|
MMOSimca@345
|
1583 return
|
MMOSimca@345
|
1584 end
|
MMOSimca@345
|
1585
|
MMOSimca@345
|
1586 -- Set update category
|
MMOSimca@405
|
1587 if last_timber_spell_id and item_id == ITEM_ID_TIMBER then
|
MMOSimca@345
|
1588 category = AF.OBJECT
|
MMOSimca@345
|
1589 -- Recently changed from ~= "EXTRACT_GAS" because of some occassional bad data, and, as far as I know, no benefit.
|
MMOSimca@345
|
1590 elseif current_action.spell_label == "FISHING" then
|
jcallahan@179
|
1591 category = AF.ZONE
|
MMOSimca@388
|
1592 elseif raid_boss_id then
|
jcallahan@179
|
1593 category = AF.NPC
|
MMOSimca@347
|
1594 elseif chat_loot_timer_handle then
|
MMOSimca@347
|
1595 category = AF.ITEM
|
jcallahan@179
|
1596 end
|
MMOSimca@345
|
1597
|
MMOSimca@395
|
1598 -- We still want to record the item's data, even if it doesn't need its drop location recorded
|
MMOSimca@395
|
1599 RecordItemData(item_id, item_link, true)
|
MMOSimca@395
|
1600
|
MMOSimca@345
|
1601 -- Take action based on update category
|
jcallahan@179
|
1602 local update_func = CHAT_MSG_LOOT_UPDATE_FUNCS[category]
|
atcaleb@558
|
1603 if not category or not update_func or private.BLACKLISTED_ITEMS[item_id] then
|
MMOSimca@340
|
1604 return
|
MMOSimca@340
|
1605 end
|
jcallahan@179
|
1606 update_func(item_id, quantity)
|
jcallahan@177
|
1607 end
|
MMOSimca@388
|
1608 end
|
MMOSimca@388
|
1609
|
MMOSimca@388
|
1610
|
jcallahan@97
|
1611 function WDP:RecordQuote(event_name, message, source_name, language_name)
|
jcallahan@112
|
1612 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
|
1613 return
|
jcallahan@95
|
1614 end
|
jcallahan@97
|
1615 local npc = NPCEntry(name_to_id_map[source_name])
|
jcallahan@97
|
1616 npc.quotes = npc.quotes or {}
|
jcallahan@97
|
1617 npc.quotes[event_name] = npc.quotes[event_name] or {}
|
jcallahan@97
|
1618 npc.quotes[event_name][ReplaceKeywords(message)] = true
|
jcallahan@97
|
1619 end
|
jcallahan@95
|
1620
|
jcallahan@95
|
1621
|
jcallahan@95
|
1622 do
|
jcallahan@40
|
1623 local SOBER_MATCH = _G.DRUNK_MESSAGE_ITEM_SELF1:gsub("%%s", ".+")
|
jcallahan@40
|
1624
|
jcallahan@40
|
1625 local DRUNK_COMPARES = {
|
jcallahan@40
|
1626 _G.DRUNK_MESSAGE_SELF2,
|
jcallahan@40
|
1627 _G.DRUNK_MESSAGE_SELF3,
|
jcallahan@40
|
1628 _G.DRUNK_MESSAGE_SELF4,
|
jcallahan@40
|
1629 }
|
jcallahan@40
|
1630
|
jcallahan@40
|
1631 local DRUNK_MATCHES = {
|
jcallahan@254
|
1632 (_G.DRUNK_MESSAGE_SELF2:gsub("%%s", ".+")),
|
jcallahan@254
|
1633 (_G.DRUNK_MESSAGE_SELF3:gsub("%%s", ".+")),
|
jcallahan@254
|
1634 (_G.DRUNK_MESSAGE_SELF4:gsub("%%s", ".+")),
|
jcallahan@40
|
1635 }
|
jcallahan@40
|
1636
|
jcallahan@167
|
1637 local RECIPE_MATCH = _G.ERR_LEARN_RECIPE_S:gsub("%%s", "(.*)")
|
jcallahan@167
|
1638
|
jcallahan@167
|
1639
|
jcallahan@167
|
1640 local function RecordDiscovery(tradeskill_name, tradeskill_index)
|
jcallahan@167
|
1641 if tradeskill_name == private.discovered_recipe_name then
|
catherton@479
|
1642 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
|
1643
|
jcallahan@167
|
1644 private.discovered_recipe_name = nil
|
jcallahan@167
|
1645 private.profession_level = nil
|
jcallahan@167
|
1646 private.previous_spell_id = nil
|
jcallahan@169
|
1647
|
jcallahan@169
|
1648 return true
|
jcallahan@167
|
1649 end
|
jcallahan@167
|
1650 end
|
jcallahan@167
|
1651
|
jcallahan@167
|
1652
|
jcallahan@167
|
1653 local function IterativeRecordDiscovery()
|
jcallahan@167
|
1654 TradeSkillExecutePer(RecordDiscovery)
|
jcallahan@167
|
1655 end
|
jcallahan@167
|
1656
|
jcallahan@167
|
1657
|
jcallahan@92
|
1658 function WDP:CHAT_MSG_SYSTEM(event_name, message)
|
mmosimca@514
|
1659 -- 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
|
1660 --[[
|
MMOSimca@532
|
1661 -- Removed in Patch 7.0.3; previously used to determine if a system message was a quest reward or not
|
MMOSimca@532
|
1662 local ERR_QUEST_REWARD_ITEM_MULT_IS = _G.ERR_QUEST_REWARD_ITEM_MULT_IS or "Received %d of item: %s."
|
MMOSimca@532
|
1663 local ERR_QUEST_REWARD_ITEM_S = _G.ERR_QUEST_REWARD_ITEM_S or "Received item: %s."
|
MMOSimca@532
|
1664
|
catherton@472
|
1665 local item_link, quantity = deformat(message, ERR_QUEST_REWARD_ITEM_MULT_IS)
|
MMOSimca@400
|
1666 if not item_link then
|
catherton@472
|
1667 quantity, item_link = 1, deformat(message, ERR_QUEST_REWARD_ITEM_S)
|
MMOSimca@400
|
1668 end
|
MMOSimca@400
|
1669 local item_id = ItemLinkToID(item_link)
|
MMOSimca@400
|
1670
|
mmosimca@514
|
1671 if item_id then
|
mmosimca@514
|
1672 -- If it was a quest message (that we can decode), parse its link
|
mmosimca@514
|
1673 RecordItemData(item_id, item_link, true)
|
mmosimca@514
|
1674 else
|
mmosimca@514
|
1675 -- If it isn't a quest message, check the other uses of system messages
|
MMOSimca@532
|
1676 end
|
MMOSimca@532
|
1677 ]]--
|
MMOSimca@532
|
1678
|
MMOSimca@532
|
1679 if not private.trainer_shown then
|
MMOSimca@532
|
1680 local recipe_name = message:match(RECIPE_MATCH)
|
MMOSimca@532
|
1681
|
MMOSimca@532
|
1682 if recipe_name and private.previous_spell_id then
|
MMOSimca@532
|
1683 local profession_name, prof_level = _G.C_TradeSkillUI.GetTradeSkillLine()
|
MMOSimca@532
|
1684
|
MMOSimca@532
|
1685 if profession_name == _G.UNKNOWN then
|
MMOSimca@532
|
1686 return
|
jcallahan@167
|
1687 end
|
MMOSimca@532
|
1688 private.discovered_recipe_name = recipe_name
|
MMOSimca@532
|
1689 private.profession_level = prof_level
|
MMOSimca@532
|
1690
|
MMOSimca@532
|
1691 C_Timer.After(0.2, IterativeRecordDiscovery)
|
jcallahan@167
|
1692 end
|
MMOSimca@532
|
1693 end
|
MMOSimca@532
|
1694
|
MMOSimca@532
|
1695 if currently_drunk then
|
MMOSimca@532
|
1696 if message == _G.DRUNK_MESSAGE_SELF1 or message:match(SOBER_MATCH) then
|
MMOSimca@532
|
1697 currently_drunk = nil
|
MMOSimca@400
|
1698 end
|
MMOSimca@532
|
1699 return
|
MMOSimca@532
|
1700 end
|
MMOSimca@532
|
1701
|
MMOSimca@532
|
1702 for index = 1, #DRUNK_MATCHES do
|
MMOSimca@532
|
1703 if message == DRUNK_COMPARES[index] or message:match(DRUNK_MATCHES[index]) then
|
MMOSimca@532
|
1704 currently_drunk = true
|
MMOSimca@532
|
1705 break
|
jcallahan@40
|
1706 end
|
jcallahan@40
|
1707 end
|
jcallahan@40
|
1708 end
|
jcallahan@40
|
1709 end
|
jcallahan@40
|
1710
|
jcallahan@307
|
1711
|
jcallahan@331
|
1712 do
|
jcallahan@23
|
1713 local FLAGS_NPC = bit.bor(_G.COMBATLOG_OBJECT_TYPE_GUARDIAN, _G.COMBATLOG_OBJECT_CONTROL_NPC)
|
jcallahan@23
|
1714 local FLAGS_NPC_CONTROL = bit.bor(_G.COMBATLOG_OBJECT_AFFILIATION_OUTSIDER, _G.COMBATLOG_OBJECT_CONTROL_NPC)
|
jcallahan@23
|
1715
|
atcaleb@552
|
1716 local function RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id)
|
atcaleb@558
|
1717 if not spell_id or private.BLACKLISTED_SPELLS[spell_id] then
|
jcallahan@23
|
1718 return
|
jcallahan@23
|
1719 end
|
jcallahan@34
|
1720 local source_type, source_id = ParseGUID(source_guid)
|
jcallahan@23
|
1721
|
jcallahan@171
|
1722 if not source_id or not UnitTypeIsNPC(source_type) then
|
jcallahan@23
|
1723 return
|
jcallahan@23
|
1724 end
|
jcallahan@23
|
1725
|
jcallahan@23
|
1726 if bit.band(FLAGS_NPC_CONTROL, source_flags) == FLAGS_NPC_CONTROL and bit.band(FLAGS_NPC, source_flags) ~= 0 then
|
jcallahan@248
|
1727 local encounter_data = NPCEntry(source_id):EncounterData(InstanceDifficultyToken())
|
jcallahan@28
|
1728 encounter_data.spells = encounter_data.spells or {}
|
jcallahan@28
|
1729 encounter_data.spells[spell_id] = (encounter_data.spells[spell_id] or 0) + 1
|
jcallahan@23
|
1730 end
|
jcallahan@23
|
1731 end
|
jcallahan@23
|
1732
|
jcallahan@115
|
1733 local HEAL_BATTLE_PETS_SPELL_ID = 125801
|
jcallahan@115
|
1734
|
jcallahan@246
|
1735 local previous_combat_event = {}
|
jcallahan@246
|
1736
|
jcallahan@23
|
1737 local COMBAT_LOG_FUNCS = {
|
jcallahan@23
|
1738 SPELL_AURA_APPLIED = RecordNPCSpell,
|
jcallahan@23
|
1739 SPELL_CAST_START = RecordNPCSpell,
|
atcaleb@552
|
1740 SPELL_CAST_SUCCESS = function(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id)
|
jcallahan@115
|
1741 if spell_id == HEAL_BATTLE_PETS_SPELL_ID then
|
jcallahan@115
|
1742 local unit_type, unit_idnum = ParseGUID(source_guid)
|
jcallahan@115
|
1743
|
jcallahan@171
|
1744 if unit_idnum and UnitTypeIsNPC(unit_type) then
|
jcallahan@115
|
1745 NPCEntry(unit_idnum).stable_master = true
|
jcallahan@115
|
1746 end
|
jcallahan@115
|
1747 end
|
atcaleb@552
|
1748 RecordNPCSpell(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id)
|
jcallahan@115
|
1749 end,
|
atcaleb@552
|
1750 UNIT_DIED = function(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id)
|
jcallahan@65
|
1751 local unit_type, unit_idnum = ParseGUID(dest_guid)
|
jcallahan@65
|
1752
|
jcallahan@171
|
1753 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
mmosimca@515
|
1754 --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
|
1755 ClearKilledNPC()
|
jcallahan@98
|
1756 private.harvesting = nil
|
jcallahan@65
|
1757 return
|
jcallahan@65
|
1758 end
|
jcallahan@177
|
1759
|
jcallahan@246
|
1760 if source_guid == "" then
|
jcallahan@246
|
1761 source_guid = nil
|
jcallahan@246
|
1762 end
|
jcallahan@246
|
1763 local killer_guid = source_guid or previous_combat_event.source_guid
|
jcallahan@246
|
1764 local killer_name = source_name or previous_combat_event.source_name
|
jcallahan@246
|
1765
|
jcallahan@299
|
1766 if not previous_combat_event.party_damage then
|
jcallahan@312
|
1767 --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
|
1768 table.wipe(previous_combat_event)
|
jcallahan@217
|
1769 ClearKilledNPC()
|
jcallahan@306
|
1770 else
|
jcallahan@317
|
1771 --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
|
1772 end
|
jcallahan@177
|
1773 killed_npc_id = unit_idnum
|
MMOSimca@383
|
1774 C_Timer.After(0.1, ClearKilledNPC)
|
jcallahan@65
|
1775 end,
|
jcallahan@23
|
1776 }
|
jcallahan@23
|
1777
|
jcallahan@23
|
1778
|
jcallahan@246
|
1779 local NON_DAMAGE_EVENTS = {
|
jcallahan@246
|
1780 SPELL_AURA_APPLIED = true,
|
jcallahan@246
|
1781 SPELL_AURA_REMOVED = true,
|
jcallahan@246
|
1782 SPELL_AURA_REMOVED_DOSE = true,
|
jcallahan@246
|
1783 SPELL_CAST_FAILED = true,
|
jcallahan@246
|
1784 SWING_MISSED = true,
|
jcallahan@246
|
1785 }
|
jcallahan@246
|
1786
|
jcallahan@299
|
1787 local DAMAGE_EVENTS = {
|
jcallahan@299
|
1788 RANGE_DAMAGE = true,
|
jcallahan@299
|
1789 SPELL_BUILDING_DAMAGE = true,
|
jcallahan@299
|
1790 SPELL_DAMAGE = true,
|
jcallahan@299
|
1791 SPELL_PERIODIC_DAMAGE = true,
|
jcallahan@299
|
1792 SWING_DAMAGE = true,
|
jcallahan@299
|
1793 }
|
jcallahan@299
|
1794
|
jcallahan@246
|
1795
|
atcaleb@552
|
1796 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
|
1797 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
|
1798
|
jcallahan@23
|
1799 local combat_log_func = COMBAT_LOG_FUNCS[sub_event]
|
jcallahan@23
|
1800
|
jcallahan@23
|
1801 if not combat_log_func then
|
jcallahan@299
|
1802 if DAMAGE_EVENTS[sub_event] then
|
jcallahan@299
|
1803 table.wipe(previous_combat_event)
|
jcallahan@246
|
1804 previous_combat_event.source_name = source_name
|
jcallahan@299
|
1805
|
jcallahan@299
|
1806 if source_guid ~= dest_guid and (in_instance or group_member_guids[source_guid] or group_pet_guids[source_guid]) then
|
jcallahan@299
|
1807 previous_combat_event.party_damage = true
|
jcallahan@299
|
1808 end
|
jcallahan@246
|
1809 end
|
jcallahan@23
|
1810 return
|
jcallahan@23
|
1811 end
|
atcaleb@552
|
1812 combat_log_func(sub_event, source_guid, source_name, source_flags, dest_guid, dest_name, dest_flags, spell_id)
|
jcallahan@297
|
1813
|
jcallahan@297
|
1814 if NON_DAMAGE_EVENTS[sub_event] then
|
jcallahan@297
|
1815 table.wipe(previous_combat_event)
|
jcallahan@297
|
1816 end
|
jcallahan@23
|
1817 end
|
jcallahan@23
|
1818
|
catherton@465
|
1819
|
jcallahan@44
|
1820 local DIPLOMACY_SPELL_ID = 20599
|
jcallahan@44
|
1821 local MR_POP_RANK1_SPELL_ID = 78634
|
jcallahan@44
|
1822 local MR_POP_RANK2_SPELL_ID = 78635
|
MMOSimca@418
|
1823 local TRADING_PACT_SPELL_ID = 170200
|
jcallahan@44
|
1824
|
jcallahan@44
|
1825
|
jcallahan@92
|
1826 function WDP:COMBAT_TEXT_UPDATE(event_name, message_type, faction_name, amount)
|
jcallahan@177
|
1827 if message_type ~= "FACTION" or not killed_npc_id then
|
jcallahan@44
|
1828 return
|
jcallahan@44
|
1829 end
|
jcallahan@44
|
1830 UpdateFactionData()
|
jcallahan@44
|
1831
|
jcallahan@46
|
1832 if not faction_name or not faction_standings[faction_name] then
|
jcallahan@46
|
1833 return
|
jcallahan@46
|
1834 end
|
jcallahan@177
|
1835 local npc = NPCEntry(killed_npc_id)
|
jcallahan@177
|
1836 ClearKilledNPC()
|
jcallahan@46
|
1837
|
jcallahan@44
|
1838 if not npc then
|
jcallahan@98
|
1839 private.harvesting = nil
|
jcallahan@44
|
1840 return
|
jcallahan@44
|
1841 end
|
jcallahan@98
|
1842 npc.harvested = private.harvesting
|
jcallahan@98
|
1843 private.harvesting = nil
|
jcallahan@98
|
1844
|
jcallahan@44
|
1845 local modifier = 1
|
jcallahan@44
|
1846
|
MMOSimca@340
|
1847 -- Check for modifiers from known spells
|
jcallahan@44
|
1848 if _G.IsSpellKnown(DIPLOMACY_SPELL_ID) then
|
jcallahan@44
|
1849 modifier = modifier + 0.1
|
jcallahan@44
|
1850 end
|
jcallahan@44
|
1851 if _G.IsSpellKnown(MR_POP_RANK2_SPELL_ID) then
|
jcallahan@44
|
1852 modifier = modifier + 0.1
|
jcallahan@44
|
1853 elseif _G.IsSpellKnown(MR_POP_RANK1_SPELL_ID) then
|
jcallahan@44
|
1854 modifier = modifier + 0.05
|
jcallahan@44
|
1855 end
|
MMOSimca@418
|
1856 if _G.IsSpellKnown(TRADING_PACT_SPELL_ID) then
|
MMOSimca@418
|
1857 modifier = modifier + 0.2
|
MMOSimca@418
|
1858 end
|
jcallahan@44
|
1859
|
MMOSimca@340
|
1860 -- Determine faction ID
|
MMOSimca@340
|
1861 local faction_ID
|
MMOSimca@418
|
1862 for pseudo_faction_name, faction_data_table in pairs(private.FACTION_DATA) do
|
MMOSimca@418
|
1863 if faction_name == faction_data_table[3] then
|
MMOSimca@418
|
1864 -- Check ignore flag
|
MMOSimca@418
|
1865 if faction_data_table[2] then
|
MMOSimca@418
|
1866 return
|
MMOSimca@418
|
1867 end
|
MMOSimca@340
|
1868 faction_ID = faction_data_table[1]
|
MMOSimca@418
|
1869 break
|
MMOSimca@340
|
1870 end
|
MMOSimca@340
|
1871 end
|
MMOSimca@340
|
1872 if faction_ID and faction_ID > 0 then
|
MMOSimca@340
|
1873 -- Check for modifiers from Commendations (applied directly to the faction, account-wide)
|
MMOSimca@340
|
1874 local _, _, _, _, _, _, _, _, _, _, _, _, _, _, has_bonus_rep_gain = GetFactionInfoByID(faction_ID)
|
MMOSimca@340
|
1875 if has_bonus_rep_gain then
|
MMOSimca@340
|
1876 modifier = modifier + 1
|
MMOSimca@340
|
1877 end
|
MMOSimca@340
|
1878 end
|
MMOSimca@340
|
1879
|
MMOSimca@340
|
1880 -- Check for modifiers from buffs
|
MMOSimca@418
|
1881 for buff_name, buff_data_table in pairs(private.REP_BUFFS) do
|
jcallahan@44
|
1882 if _G.UnitBuff("player", buff_name) then
|
MMOSimca@340
|
1883 local modded_faction = buff_data_table.faction
|
jcallahan@44
|
1884
|
jcallahan@44
|
1885 if not modded_faction or faction_name == modded_faction then
|
MMOSimca@340
|
1886 if buff_data_table.ignore then
|
MMOSimca@340
|
1887 -- Some buffs from tabards convert all rep of other factions into rep for a specific faction.
|
MMOSimca@340
|
1888 -- We can't know what faction the rep was orginally from, so we must ignore the data entirely in these cases.
|
MMOSimca@340
|
1889 return
|
MMOSimca@340
|
1890 else
|
MMOSimca@340
|
1891 modifier = modifier + buff_data_table.modifier
|
MMOSimca@340
|
1892 end
|
jcallahan@44
|
1893 end
|
jcallahan@44
|
1894 end
|
jcallahan@44
|
1895 end
|
catherton@465
|
1896
|
jcallahan@65
|
1897 npc.reputations = npc.reputations or {}
|
jcallahan@65
|
1898 npc.reputations[("%s:%s"):format(faction_name, faction_standings[faction_name])] = math.floor(amount / modifier)
|
jcallahan@32
|
1899 end
|
jcallahan@44
|
1900 end -- do-block
|
jcallahan@18
|
1901
|
jcallahan@18
|
1902
|
jcallahan@140
|
1903 function WDP:CURSOR_UPDATE(event_name)
|
MMOSimca@355
|
1904 if current_action.fishing_target or _G.Minimap:IsMouseOver() then
|
jcallahan@140
|
1905 return
|
jcallahan@140
|
1906 end
|
jcallahan@140
|
1907 local text = _G["GameTooltipTextLeft1"]:GetText()
|
jcallahan@140
|
1908
|
MMOSimca@355
|
1909 -- Handle Fishing
|
MMOSimca@355
|
1910 if (current_action.spell_label == "FISHING") then
|
MMOSimca@355
|
1911 if not text or text == "Fishing Bobber" then
|
MMOSimca@355
|
1912 text = "NONE"
|
MMOSimca@355
|
1913 else
|
MMOSimca@355
|
1914 current_action.fishing_target = true
|
MMOSimca@355
|
1915 end
|
MMOSimca@355
|
1916 current_action.identifier = ("%s:%s"):format(current_action.spell_label, text)
|
MMOSimca@355
|
1917 -- Handle Garrison Cache
|
MMOSimca@355
|
1918 elseif private.GARRISON_CACHE_OBJECT_NAME_TO_OBJECT_ID_MAP[text] then
|
MMOSimca@355
|
1919 last_garrison_cache_object_id = private.GARRISON_CACHE_OBJECT_NAME_TO_OBJECT_ID_MAP[text]
|
jcallahan@140
|
1920 end
|
jcallahan@140
|
1921 end
|
jcallahan@140
|
1922
|
jcallahan@140
|
1923
|
jcallahan@92
|
1924 function WDP:ITEM_TEXT_BEGIN(event_name)
|
jcallahan@42
|
1925 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@42
|
1926
|
jcallahan@42
|
1927 if not unit_idnum or unit_type ~= private.UNIT_TYPES.OBJECT or _G.UnitName("npc") ~= _G.ItemTextGetItem() then
|
jcallahan@42
|
1928 return
|
jcallahan@42
|
1929 end
|
jcallahan@42
|
1930 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@42
|
1931 end
|
jcallahan@42
|
1932
|
jcallahan@42
|
1933
|
jcallahan@13
|
1934 do
|
MMOSimca@343
|
1935 local LOOT_OPENED_VERIFY_FUNCS = {
|
jcallahan@324
|
1936 -- 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
|
1937 [AF.ITEM] = function()
|
jcallahan@16
|
1938 local locked_item_id
|
jcallahan@16
|
1939
|
jcallahan@16
|
1940 for bag_index = 0, _G.NUM_BAG_FRAMES do
|
jcallahan@16
|
1941 for slot_index = 1, _G.GetContainerNumSlots(bag_index) do
|
jcallahan@324
|
1942 local _, _, is_locked, _, _, is_lootable = _G.GetContainerItemInfo(bag_index, slot_index)
|
jcallahan@324
|
1943
|
jcallahan@324
|
1944 if is_locked and is_lootable then
|
jcallahan@16
|
1945 locked_item_id = ItemLinkToID(_G.GetContainerItemLink(bag_index, slot_index))
|
jcallahan@165
|
1946 break
|
jcallahan@16
|
1947 end
|
jcallahan@16
|
1948 end
|
jcallahan@165
|
1949
|
jcallahan@165
|
1950 if locked_item_id then
|
jcallahan@165
|
1951 break
|
jcallahan@165
|
1952 end
|
jcallahan@16
|
1953 end
|
jcallahan@16
|
1954
|
MMOSimca@367
|
1955 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
|
1956 return false
|
jcallahan@16
|
1957 end
|
jcallahan@122
|
1958 current_action.identifier = locked_item_id
|
jcallahan@16
|
1959 return true
|
jcallahan@16
|
1960 end,
|
MMOSimca@401
|
1961 [AF.NPC] = function()
|
MMOSimca@401
|
1962 return not _G.IsFishingLoot()
|
MMOSimca@401
|
1963 end,
|
MMOSimca@401
|
1964 [AF.OBJECT] = function()
|
MMOSimca@401
|
1965 return not _G.IsFishingLoot()
|
MMOSimca@401
|
1966 end,
|
jcallahan@17
|
1967 [AF.ZONE] = function()
|
jcallahan@140
|
1968 current_action.zone_data = UpdateDBEntryLocation("zones", current_action.identifier)
|
jcallahan@210
|
1969 return _G.IsFishingLoot()
|
jcallahan@17
|
1970 end,
|
jcallahan@13
|
1971 }
|
jcallahan@13
|
1972
|
jcallahan@13
|
1973
|
MMOSimca@343
|
1974 local LOOT_OPENED_UPDATE_FUNCS = {
|
jcallahan@16
|
1975 [AF.ITEM] = function()
|
jcallahan@28
|
1976 GenericLootUpdate("items")
|
jcallahan@28
|
1977 end,
|
jcallahan@28
|
1978 [AF.NPC] = function()
|
jcallahan@75
|
1979 local difficulty_token = InstanceDifficultyToken()
|
jcallahan@312
|
1980 local loot_label = current_loot.label
|
jcallahan@77
|
1981 local source_list = {}
|
jcallahan@75
|
1982
|
jcallahan@131
|
1983 for source_guid, loot_data in pairs(current_loot.sources) do
|
jcallahan@331
|
1984 local _, source_id = ParseGUID(source_guid)
|
jcallahan@75
|
1985 local npc = NPCEntry(source_id)
|
jcallahan@75
|
1986
|
jcallahan@75
|
1987 if npc then
|
jcallahan@248
|
1988 local encounter_data = npc:EncounterData(difficulty_token)
|
jcallahan@312
|
1989 encounter_data[loot_label] = encounter_data[loot_label] or {}
|
jcallahan@75
|
1990
|
jcallahan@78
|
1991 if not source_list[source_guid] then
|
jcallahan@77
|
1992 encounter_data.loot_counts = encounter_data.loot_counts or {}
|
MMOSimca@426
|
1993 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
|
jcallahan@312
|
1994 source_list[source_guid] = true
|
jcallahan@77
|
1995 end
|
jcallahan@77
|
1996
|
jcallahan@309
|
1997 for loot_token, quantity in pairs(loot_data) do
|
mmosimca@496
|
1998 local loot_type, currency_id = (":"):split(loot_token)
|
mmosimca@496
|
1999
|
mmosimca@496
|
2000 if loot_type == "currency" and currency_id then
|
mmosimca@496
|
2001 -- Convert currency_id back into number from string
|
mmosimca@496
|
2002 currency_id = tonumber(currency_id) or 0
|
mmosimca@496
|
2003 if currency_id ~= 0 then
|
mmosimca@496
|
2004 table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
|
mmosimca@496
|
2005 end
|
jcallahan@309
|
2006 elseif loot_token == "money" then
|
jcallahan@312
|
2007 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
|
jcallahan@309
|
2008 else
|
jcallahan@312
|
2009 table.insert(encounter_data[loot_label], ("%d:%d"):format(loot_token, quantity))
|
jcallahan@309
|
2010 end
|
jcallahan@75
|
2011 end
|
jcallahan@75
|
2012 end
|
jcallahan@75
|
2013 end
|
jcallahan@16
|
2014 end,
|
jcallahan@13
|
2015 [AF.OBJECT] = function()
|
jcallahan@28
|
2016 GenericLootUpdate("objects", InstanceDifficultyToken())
|
jcallahan@17
|
2017 end,
|
jcallahan@17
|
2018 [AF.ZONE] = function()
|
MMOSimca@328
|
2019 if not (current_loot.map_level and current_loot.x and current_loot.y and current_loot.zone_data) then
|
MMOSimca@328
|
2020 return
|
MMOSimca@328
|
2021 end
|
jcallahan@141
|
2022 local location_token = ("%d:%d:%d"):format(current_loot.map_level, current_loot.x, current_loot.y)
|
jcallahan@41
|
2023
|
jcallahan@41
|
2024 -- This will start life as a boolean true.
|
mmosimca@522
|
2025 if type(current_loot.zone_data[location_token]) ~= "table" then
|
jcallahan@131
|
2026 current_loot.zone_data[location_token] = {
|
jcallahan@41
|
2027 drops = {}
|
jcallahan@41
|
2028 }
|
jcallahan@41
|
2029 end
|
jcallahan@132
|
2030 local loot_count = ("%s_count"):format(current_loot.label)
|
jcallahan@131
|
2031 current_loot.zone_data[location_token][loot_count] = (current_loot.zone_data[location_token][loot_count] or 0) + 1
|
jcallahan@41
|
2032
|
jcallahan@131
|
2033 if current_loot.sources then
|
jcallahan@131
|
2034 for source_guid, loot_data in pairs(current_loot.sources) do
|
jcallahan@131
|
2035 for item_id, quantity in pairs(loot_data) do
|
jcallahan@131
|
2036 table.insert(current_loot.zone_data[location_token].drops, ("%d:%d"):format(item_id, quantity))
|
jcallahan@131
|
2037 end
|
jcallahan@131
|
2038 end
|
jcallahan@131
|
2039 end
|
jcallahan@131
|
2040
|
jcallahan@131
|
2041 if #current_loot.list <= 0 then
|
jcallahan@131
|
2042 return
|
jcallahan@131
|
2043 end
|
jcallahan@131
|
2044
|
jcallahan@131
|
2045 for index = 1, #current_loot.list do
|
MMOSimca@443
|
2046 table.insert(current_loot.zone_data[location_token].drops, current_loot.list[index])
|
jcallahan@41
|
2047 end
|
jcallahan@13
|
2048 end,
|
jcallahan@13
|
2049 }
|
jcallahan@13
|
2050
|
jcallahan@79
|
2051 -- Prevent opening the same loot window multiple times from recording data multiple times.
|
jcallahan@79
|
2052 local loot_guid_registry = {}
|
jcallahan@124
|
2053
|
jcallahan@124
|
2054
|
jcallahan@124
|
2055 function WDP:LOOT_CLOSED(event_name)
|
MMOSimca@398
|
2056 ClearChatLootData()
|
jcallahan@131
|
2057 current_loot = nil
|
jcallahan@131
|
2058 table.wipe(current_action)
|
jcallahan@124
|
2059 end
|
jcallahan@124
|
2060
|
jcallahan@13
|
2061
|
jcallahan@322
|
2062 local function ExtrapolatedCurrentActionFromLootData(event_name)
|
MMOSimca@402
|
2063 local log_source = event_name .. "- ExtrapolatedCurrentActionFromLootData"
|
MMOSimca@402
|
2064 local previous_spell_label = current_action.spell_label
|
jcallahan@322
|
2065 local extrapolated_guid_registry = {}
|
jcallahan@322
|
2066 local num_guids = 0
|
MMOSimca@402
|
2067 table.wipe(current_action)
|
MMOSimca@402
|
2068
|
MMOSimca@402
|
2069 if _G.IsFishingLoot() then
|
MMOSimca@402
|
2070 -- Set up a proper 'fishing' current_action table
|
MMOSimca@402
|
2071 local zone_name, area_id, x, y, map_level, instance_token = CurrentLocationData()
|
MMOSimca@402
|
2072 if not (zone_name and area_id and x and y and map_level) then
|
mmosimca@508
|
2073 if not (_G.IsInInstance()) then
|
mmosimca@508
|
2074 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
|
2075 end
|
MMOSimca@402
|
2076 return
|
MMOSimca@402
|
2077 end
|
MMOSimca@402
|
2078 current_action.instance_token = instance_token
|
MMOSimca@402
|
2079 current_action.map_level = map_level
|
MMOSimca@402
|
2080 current_action.x = x
|
MMOSimca@402
|
2081 current_action.y = y
|
MMOSimca@402
|
2082 current_action.zone_data = ("%s:%d"):format(zone_name, area_id)
|
MMOSimca@402
|
2083 current_action.spell_label = "FISHING"
|
MMOSimca@402
|
2084 current_action.loot_label = "fishing"
|
MMOSimca@402
|
2085 current_action.identifier = "FISHING:NONE"
|
MMOSimca@402
|
2086 current_action.target_type = AF.ZONE
|
MMOSimca@402
|
2087
|
MMOSimca@402
|
2088 Debug("%s: Fishing loot detected.", log_source)
|
MMOSimca@402
|
2089 return true
|
MMOSimca@402
|
2090 end
|
jcallahan@322
|
2091
|
MMOSimca@344
|
2092 -- Loot extrapolation cannot handle objects that need special spell labels (like HERBALISM or MINING) (MIND_CONTROL is okay)
|
MMOSimca@402
|
2093 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
|
2094 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
|
2095 return false
|
MMOSimca@344
|
2096 end
|
MMOSimca@344
|
2097
|
jcallahan@322
|
2098 for loot_slot = 1, _G.GetNumLootItems() do
|
jcallahan@322
|
2099 local loot_info = {
|
jcallahan@322
|
2100 _G.GetLootSourceInfo(loot_slot)
|
jcallahan@322
|
2101 }
|
jcallahan@322
|
2102
|
jcallahan@322
|
2103 for loot_index = 1, #loot_info, 2 do
|
jcallahan@322
|
2104 local source_guid = loot_info[loot_index]
|
jcallahan@322
|
2105
|
jcallahan@322
|
2106 if not extrapolated_guid_registry[source_guid] then
|
jcallahan@322
|
2107 local unit_type, unit_idnum = ParseGUID(source_guid)
|
jcallahan@322
|
2108
|
jcallahan@322
|
2109 if unit_type and unit_idnum then
|
jcallahan@322
|
2110 extrapolated_guid_registry[source_guid] = {
|
jcallahan@322
|
2111 unit_type,
|
jcallahan@322
|
2112 unit_idnum
|
jcallahan@322
|
2113 }
|
jcallahan@322
|
2114
|
jcallahan@322
|
2115 num_guids = num_guids + 1
|
jcallahan@322
|
2116 end
|
jcallahan@322
|
2117 end
|
jcallahan@322
|
2118 end
|
jcallahan@322
|
2119 end
|
jcallahan@322
|
2120
|
jcallahan@322
|
2121 if num_guids == 0 then
|
jcallahan@322
|
2122 Debug("%s: No GUIDs found in loot. Blank loot window?", log_source)
|
jcallahan@322
|
2123 return false
|
jcallahan@322
|
2124 end
|
jcallahan@326
|
2125
|
jcallahan@322
|
2126 local num_npcs = 0
|
jcallahan@322
|
2127 local num_objects = 0
|
jcallahan@324
|
2128 local num_itemcontainers = 0
|
jcallahan@322
|
2129
|
jcallahan@322
|
2130 for source_guid, guid_data in pairs(extrapolated_guid_registry) do
|
jcallahan@322
|
2131 local unit_type = guid_data[1]
|
mmosimca@516
|
2132 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
|
2133
|
jcallahan@322
|
2134 if loot_label then
|
jcallahan@322
|
2135 local unit_idnum = guid_data[2]
|
jcallahan@322
|
2136
|
jcallahan@322
|
2137 if loot_guid_registry[loot_label] and loot_guid_registry[loot_label][source_guid] then
|
jcallahan@322
|
2138 Debug("%s: Previously scanned loot for unit with GUID %s and identifier %s.", log_source, source_guid, unit_idnum)
|
jcallahan@322
|
2139 elseif unit_type == private.UNIT_TYPES.OBJECT and unit_idnum ~= OBJECT_ID_FISHING_BOBBER then
|
jcallahan@322
|
2140 current_action.loot_label = loot_label
|
jcallahan@322
|
2141 current_action.spell_label = "OPENING"
|
jcallahan@322
|
2142 current_action.target_type = AF.OBJECT
|
jcallahan@322
|
2143 current_action.identifier = unit_idnum
|
jcallahan@322
|
2144 num_objects = num_objects + 1
|
jcallahan@322
|
2145 elseif UnitTypeIsNPC(unit_type) then
|
jcallahan@322
|
2146 current_action.loot_label = loot_label
|
jcallahan@322
|
2147 current_action.target_type = AF.NPC
|
jcallahan@322
|
2148 current_action.identifier = unit_idnum
|
jcallahan@322
|
2149 num_npcs = num_npcs + 1
|
mmosimca@516
|
2150 elseif unit_type == private.UNIT_TYPES.ITEM then
|
jcallahan@324
|
2151 current_action.loot_label = loot_label
|
jcallahan@324
|
2152 current_action.target_type = AF.ITEM
|
jcallahan@324
|
2153 -- current_action.identifier assigned during loot verification.
|
jcallahan@324
|
2154 num_itemcontainers = num_itemcontainers + 1
|
jcallahan@322
|
2155 end
|
jcallahan@322
|
2156 else
|
jcallahan@322
|
2157 -- 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
|
2158 Debug("%s: Unit with GUID %s has unsupported type for looting.", log_source, source_guid)
|
jcallahan@322
|
2159 return false
|
jcallahan@322
|
2160 end
|
jcallahan@322
|
2161 end
|
jcallahan@322
|
2162
|
jcallahan@322
|
2163 if not current_action.target_type then
|
jcallahan@322
|
2164 Debug("%s: Failure to obtain target_type.", log_source)
|
jcallahan@322
|
2165 return false
|
jcallahan@322
|
2166 end
|
jcallahan@322
|
2167
|
jcallahan@322
|
2168 -- 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
|
2169 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
|
2170 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
|
2171 return false
|
jcallahan@322
|
2172 end
|
jcallahan@322
|
2173
|
jcallahan@322
|
2174 return true
|
jcallahan@322
|
2175 end
|
jcallahan@322
|
2176
|
jcallahan@322
|
2177
|
MMOSimca@343
|
2178 function WDP:LOOT_OPENED(event_name)
|
MMOSimca@398
|
2179 ClearChatLootData()
|
MMOSimca@387
|
2180
|
jcallahan@132
|
2181 if current_loot then
|
jcallahan@322
|
2182 current_loot = nil
|
jcallahan@322
|
2183 Debug("%s: Previous loot did not process in time for this event. Attempting to extrapolate current_action from loot data.", event_name)
|
jcallahan@322
|
2184
|
jcallahan@322
|
2185 if not ExtrapolatedCurrentActionFromLootData(event_name) then
|
jcallahan@322
|
2186 Debug("%s: Unable to extrapolate current_action. Aborting attempts to handle loot for now.", event_name)
|
jcallahan@322
|
2187 return
|
jcallahan@322
|
2188 end
|
jcallahan@18
|
2189 end
|
jcallahan@151
|
2190
|
jcallahan@151
|
2191 if not current_action.target_type then
|
jcallahan@322
|
2192 if not ExtrapolatedCurrentActionFromLootData(event_name) then
|
jcallahan@322
|
2193 Debug("%s: Unable to extrapolate current_action. Aborting attempts to handle loot for now.", event_name)
|
jcallahan@322
|
2194 return
|
jcallahan@322
|
2195 end
|
jcallahan@151
|
2196 end
|
MMOSimca@343
|
2197 local verify_func = LOOT_OPENED_VERIFY_FUNCS[current_action.target_type]
|
MMOSimca@343
|
2198 local update_func = LOOT_OPENED_UPDATE_FUNCS[current_action.target_type]
|
jcallahan@13
|
2199
|
jcallahan@14
|
2200 if not verify_func or not update_func then
|
jcallahan@322
|
2201 Debug("%s: The current action's target type is unsupported or nil.", event_name)
|
jcallahan@13
|
2202 return
|
jcallahan@13
|
2203 end
|
jcallahan@13
|
2204
|
mmosimca@522
|
2205 if type(verify_func) == "function" and not verify_func() then
|
jcallahan@324
|
2206 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
|
2207 return
|
jcallahan@14
|
2208 end
|
jcallahan@80
|
2209 local guids_used = {}
|
jcallahan@132
|
2210
|
jcallahan@301
|
2211 InitializeCurrentLoot()
|
jcallahan@217
|
2212 loot_guid_registry[current_loot.label] = loot_guid_registry[current_loot.label] or {}
|
jcallahan@217
|
2213
|
jcallahan@55
|
2214 for loot_slot = 1, _G.GetNumLootItems() do
|
mmosimca@496
|
2215 local texture_filedata_id, item_text, slot_quantity, quality, locked = _G.GetLootSlotInfo(loot_slot)
|
jcallahan@55
|
2216 local slot_type = _G.GetLootSlotType(loot_slot)
|
catherton@463
|
2217 local loot_info = { _G.GetLootSourceInfo(loot_slot) }
|
catherton@464
|
2218 local loot_link = _G.GetLootSlotLink(loot_slot)
|
jcallahan@13
|
2219
|
jcallahan@237
|
2220 -- Odd index is GUID, even is count.
|
jcallahan@237
|
2221 for loot_index = 1, #loot_info, 2 do
|
jcallahan@237
|
2222 local source_guid = loot_info[loot_index]
|
jcallahan@75
|
2223
|
jcallahan@237
|
2224 if not loot_guid_registry[current_loot.label][source_guid] then
|
jcallahan@237
|
2225 local loot_quantity = loot_info[loot_index + 1]
|
jcallahan@324
|
2226 -- There is a new bug in 5.4.0 that causes GetLootSlotInfo() to (rarely) return nil values for slot_quantity.
|
jcallahan@324
|
2227 if slot_quantity then
|
jcallahan@324
|
2228 -- 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
|
2229 if slot_quantity > loot_quantity then
|
jcallahan@324
|
2230 loot_quantity = slot_quantity
|
jcallahan@324
|
2231 end
|
jcallahan@324
|
2232 local source_type, source_id = ParseGUID(source_guid)
|
MMOSimca@329
|
2233 local source_key = ("%s:%d"):format(source_type, source_id)
|
jcallahan@324
|
2234
|
MMOSimca@366
|
2235 if slot_type == LOOT_SLOT_ITEM then
|
catherton@464
|
2236 if loot_link then
|
catherton@464
|
2237 local item_id = ItemLinkToID(loot_link)
|
catherton@464
|
2238 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
|
2239 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
catherton@464
|
2240 current_loot.sources[source_guid][item_id] = (current_loot.sources[source_guid][item_id] or 0) + loot_quantity
|
catherton@464
|
2241 guids_used[source_guid] = true
|
catherton@463
|
2242 else
|
catherton@463
|
2243 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
|
2244 end
|
MMOSimca@366
|
2245 elseif slot_type == LOOT_SLOT_MONEY then
|
jcallahan@324
|
2246 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
|
2247 if current_loot.target_type == AF.ZONE then
|
jcallahan@324
|
2248 table.insert(current_loot.list, ("money:%d"):format(loot_quantity))
|
jcallahan@324
|
2249 else
|
jcallahan@324
|
2250 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
MMOSimca@367
|
2251 current_loot.sources[source_guid]["money"] = (current_loot.sources[source_guid]["money"] or 0) + loot_quantity
|
jcallahan@324
|
2252 guids_used[source_guid] = true
|
jcallahan@324
|
2253 end
|
MMOSimca@366
|
2254 elseif slot_type == LOOT_SLOT_CURRENCY then
|
jcallahan@324
|
2255 -- Same bug with GetLootSlotInfo() will screw up currency when it happens, so we won't process this slot's loot.
|
catherton@463
|
2256 if loot_link then
|
mmosimca@496
|
2257 local currency_id = CurrencyLinkToID(loot_link)
|
mmosimca@496
|
2258 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
|
2259 if current_loot.target_type == AF.ZONE then
|
mmosimca@496
|
2260 table.insert(current_loot.list, ("currency:%d:%d"):format(loot_quantity, currency_id))
|
jcallahan@324
|
2261 else
|
mmosimca@496
|
2262 local currency_token = ("currency:%d"):format(currency_id)
|
jcallahan@324
|
2263
|
jcallahan@324
|
2264 current_loot.sources[source_guid] = current_loot.sources[source_guid] or {}
|
MMOSimca@367
|
2265 current_loot.sources[source_guid][currency_token] = (current_loot.sources[source_guid][currency_token] or 0) + loot_quantity
|
jcallahan@324
|
2266 guids_used[source_guid] = true
|
jcallahan@324
|
2267 end
|
jcallahan@324
|
2268 else
|
catherton@463
|
2269 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
|
2270 end
|
jcallahan@308
|
2271 end
|
jcallahan@324
|
2272 else
|
jcallahan@324
|
2273 -- 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
|
2274 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
|
2275 end
|
jcallahan@75
|
2276 end
|
jcallahan@13
|
2277 end
|
jcallahan@13
|
2278 end
|
jcallahan@80
|
2279
|
jcallahan@81
|
2280 for guid in pairs(guids_used) do
|
jcallahan@217
|
2281 loot_guid_registry[current_loot.label][guid] = true
|
jcallahan@80
|
2282 end
|
jcallahan@13
|
2283 update_func()
|
jcallahan@1
|
2284 end
|
jcallahan@13
|
2285 end -- do-block
|
jcallahan@0
|
2286
|
jcallahan@0
|
2287
|
jcallahan@89
|
2288 function WDP:MAIL_SHOW(event_name)
|
MMOSimca@436
|
2289 WDP:StopChatLootRecording(event_name)
|
jcallahan@89
|
2290 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@89
|
2291
|
jcallahan@89
|
2292 if not unit_idnum or unit_type ~= private.UNIT_TYPES.OBJECT then
|
jcallahan@89
|
2293 return
|
jcallahan@89
|
2294 end
|
jcallahan@89
|
2295 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@89
|
2296 end
|
jcallahan@89
|
2297
|
jcallahan@89
|
2298
|
jcallahan@44
|
2299 do
|
jcallahan@44
|
2300 local POINT_MATCH_PATTERNS = {
|
jcallahan@44
|
2301 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2302 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_3V3:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2303 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_5V5:gsub("%%d", "(%%d+)")), -- May no longer be necessary
|
jcallahan@44
|
2304 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_BG:gsub("%%d", "(%%d+)")),
|
jcallahan@44
|
2305 ("^%s$"):format(_G.ITEM_REQ_ARENA_RATING_3V3_BG:gsub("%%d", "(%%d+)")),
|
jcallahan@44
|
2306 }
|
jcallahan@5
|
2307
|
jcallahan@68
|
2308 local ITEM_REQ_REPUTATION_MATCH = "Requires (.-) %- (.*)"
|
jcallahan@87
|
2309 local ITEM_REQ_QUEST_MATCH1 = "Requires: .*"
|
jcallahan@87
|
2310 local ITEM_REQ_QUEST_MATCH2 = "Must have completed: .*"
|
jcallahan@68
|
2311
|
jcallahan@133
|
2312 local current_merchant
|
jcallahan@133
|
2313 local merchant_standing
|
jcallahan@133
|
2314
|
jcallahan@133
|
2315 function WDP:MERCHANT_CLOSED(event_name)
|
MMOSimca@436
|
2316 WDP:ResumeChatLootRecording(event_name)
|
jcallahan@133
|
2317 current_merchant = nil
|
jcallahan@133
|
2318 merchant_standing = nil
|
jcallahan@133
|
2319 end
|
jcallahan@133
|
2320
|
jcallahan@133
|
2321
|
jcallahan@89
|
2322 function WDP:UpdateMerchantItems(event_name)
|
jcallahan@144
|
2323 if not current_merchant or event_name == "MERCHANT_SHOW" then
|
MMOSimca@436
|
2324 WDP:StopChatLootRecording(event_name)
|
jcallahan@195
|
2325 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@4
|
2326
|
jcallahan@171
|
2327 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
jcallahan@133
|
2328 return
|
jcallahan@133
|
2329 end
|
jcallahan@331
|
2330 local _, faction_standing = UnitFactionStanding("npc")
|
jcallahan@331
|
2331 merchant_standing = faction_standing
|
jcallahan@133
|
2332 current_merchant = NPCEntry(unit_idnum)
|
jcallahan@133
|
2333 current_merchant.sells = current_merchant.sells or {}
|
jcallahan@44
|
2334 end
|
jcallahan@55
|
2335 local current_filters = _G.GetMerchantFilter()
|
jcallahan@57
|
2336 _G.SetMerchantFilter(_G.LE_LOOT_FILTER_ALL)
|
jcallahan@57
|
2337 _G.MerchantFrame_Update()
|
jcallahan@57
|
2338
|
jcallahan@150
|
2339 local num_items = _G.GetMerchantNumItems()
|
jcallahan@150
|
2340
|
jcallahan@44
|
2341 for item_index = 1, num_items do
|
jcallahan@44
|
2342 local _, _, copper_price, stack_size, num_available, _, extended_cost = _G.GetMerchantItemInfo(item_index)
|
jcallahan@44
|
2343 local item_id = ItemLinkToID(_G.GetMerchantItemLink(item_index))
|
jcallahan@5
|
2344
|
jcallahan@324
|
2345 DatamineTT:ClearLines()
|
jcallahan@324
|
2346 DatamineTT:SetMerchantItem(item_index)
|
jcallahan@324
|
2347
|
jcallahan@324
|
2348 if not item_id then
|
jcallahan@324
|
2349 local item_name, item_link = DatamineTT:GetItem()
|
jcallahan@324
|
2350 item_id = ItemLinkToID(item_link)
|
MMOSimca@354
|
2351 -- GetMerchantItemLink() still ocassionally fails as of Patch 6.0.2. It fails so badly that debug functions cause considerable slowdown.
|
jcallahan@324
|
2352 end
|
jcallahan@324
|
2353
|
jcallahan@44
|
2354 if item_id and item_id > 0 then
|
jcallahan@44
|
2355 local price_string = ActualCopperCost(copper_price, merchant_standing)
|
jcallahan@5
|
2356
|
jcallahan@68
|
2357 local num_lines = DatamineTT:NumLines()
|
jcallahan@68
|
2358
|
jcallahan@68
|
2359 for line_index = 1, num_lines do
|
jcallahan@68
|
2360 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@68
|
2361
|
jcallahan@68
|
2362 if not current_line then
|
jcallahan@68
|
2363 break
|
jcallahan@68
|
2364 end
|
jcallahan@68
|
2365 local faction, reputation = current_line:GetText():match(ITEM_REQ_REPUTATION_MATCH)
|
jcallahan@68
|
2366
|
jcallahan@68
|
2367 if faction or reputation then
|
jcallahan@68
|
2368 DBEntry("items", item_id).req_reputation = ("%s:%s"):format(faction:gsub("-", ""), reputation:upper())
|
jcallahan@68
|
2369 break
|
jcallahan@68
|
2370 end
|
jcallahan@68
|
2371 end
|
jcallahan@68
|
2372
|
jcallahan@87
|
2373 for line_index = 1, num_lines do
|
jcallahan@87
|
2374 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@87
|
2375
|
jcallahan@87
|
2376 if not current_line then
|
jcallahan@87
|
2377 break
|
jcallahan@87
|
2378 end
|
jcallahan@87
|
2379 local line_text = current_line:GetText()
|
jcallahan@87
|
2380 local quest_name = line_text:match(ITEM_REQ_QUEST_MATCH1) or line_text:match(ITEM_REQ_QUEST_MATCH2)
|
jcallahan@87
|
2381
|
jcallahan@87
|
2382 if quest_name then
|
jcallahan@87
|
2383 DBEntry("items", item_id).req_quest = ("%s"):format(quest_name:gsub("(.+): ", ""), quest_name)
|
jcallahan@87
|
2384 break
|
jcallahan@87
|
2385 end
|
jcallahan@87
|
2386 end
|
jcallahan@87
|
2387
|
jcallahan@44
|
2388 if extended_cost then
|
jcallahan@53
|
2389 local battleground_rating = 0
|
jcallahan@53
|
2390 local personal_rating = 0
|
jcallahan@53
|
2391 local required_season_amount
|
jcallahan@5
|
2392
|
jcallahan@68
|
2393 for line_index = 1, num_lines do
|
jcallahan@44
|
2394 local current_line = _G["WDPDatamineTTTextLeft" .. line_index]
|
jcallahan@5
|
2395
|
jcallahan@44
|
2396 if not current_line then
|
jcallahan@44
|
2397 break
|
jcallahan@44
|
2398 end
|
jcallahan@53
|
2399 required_season_amount = current_line:GetText():match("Requires earning a total of (%d+)\n(.-) for the season.")
|
jcallahan@5
|
2400
|
jcallahan@44
|
2401 for match_index = 1, #POINT_MATCH_PATTERNS do
|
jcallahan@44
|
2402 local match1, match2 = current_line:GetText():match(POINT_MATCH_PATTERNS[match_index])
|
jcallahan@53
|
2403 personal_rating = personal_rating + (match1 or 0)
|
jcallahan@53
|
2404 battleground_rating = battleground_rating + (match2 or 0)
|
jcallahan@5
|
2405
|
jcallahan@44
|
2406 if match1 or match2 then
|
jcallahan@44
|
2407 break
|
jcallahan@44
|
2408 end
|
jcallahan@44
|
2409 end
|
jcallahan@5
|
2410 end
|
jcallahan@44
|
2411 local currency_list = {}
|
jcallahan@44
|
2412 local item_count = _G.GetMerchantItemCostInfo(item_index)
|
jcallahan@50
|
2413
|
mmosimca@518
|
2414 -- Keeping this around in case Blizzard makes the two ratings (personal and battleground) diverge at some point
|
mmosimca@518
|
2415 --price_string = ("%s:%s:%s:%s"):format(price_string, battleground_rating, personal_rating, required_season_amount or 0)
|
jcallahan@53
|
2416 price_string = ("%s:%s:%s"):format(price_string, personal_rating, required_season_amount or 0)
|
jcallahan@5
|
2417
|
jcallahan@44
|
2418 for cost_index = 1, item_count do
|
jcallahan@324
|
2419 -- The third return (Blizz calls "currency_link") of GetMerchantItemCostItem only returns item links as of Patch 5.3.0.
|
MMOSimca@540
|
2420 local texture_id, amount_required, hyperlink, name = _G.GetMerchantItemCostItem(item_index, cost_index)
|
mmosimca@496
|
2421
|
mmosimca@519
|
2422 -- Try to get item ID
|
MMOSimca@540
|
2423 local item_id = ItemLinkToID(hyperlink)
|
mmosimca@519
|
2424
|
mmosimca@519
|
2425 -- 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
|
2426 -- Handle cases when the additional cost is another item
|
mmosimca@519
|
2427 if item_id and item_id > 0 then
|
mmosimca@519
|
2428 currency_list[#currency_list + 1] = ("(%s:%d)"):format(amount_required, item_id)
|
mmosimca@519
|
2429 else
|
MMOSimca@540
|
2430 -- Try to get currency ID
|
MMOSimca@540
|
2431 local currency_id = CurrencyLinkToID(hyperlink)
|
mmosimca@519
|
2432 if currency_id and currency_id > 0 then
|
mmosimca@501
|
2433 currency_list[#currency_list + 1] = ("(%s:%d)"):format(amount_required, currency_id)
|
MMOSimca@540
|
2434 else
|
MMOSimca@540
|
2435 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
|
2436 end
|
jcallahan@44
|
2437 end
|
jcallahan@44
|
2438 end
|
jcallahan@44
|
2439
|
jcallahan@44
|
2440 for currency_index = 1, #currency_list do
|
jcallahan@44
|
2441 price_string = ("%s:%s"):format(price_string, currency_list[currency_index])
|
jcallahan@5
|
2442 end
|
jcallahan@5
|
2443 end
|
jcallahan@133
|
2444 current_merchant.sells[item_id] = ("%s:%s:[%s]"):format(num_available, stack_size, price_string)
|
jcallahan@44
|
2445 end
|
jcallahan@44
|
2446 end
|
jcallahan@5
|
2447
|
jcallahan@44
|
2448 if _G.CanMerchantRepair() then
|
jcallahan@133
|
2449 current_merchant.can_repair = true
|
jcallahan@5
|
2450 end
|
jcallahan@57
|
2451 _G.SetMerchantFilter(current_filters)
|
jcallahan@57
|
2452 _G.MerchantFrame_Update()
|
jcallahan@4
|
2453 end
|
jcallahan@44
|
2454 end -- do-block
|
jcallahan@4
|
2455
|
jcallahan@89
|
2456
|
jcallahan@92
|
2457 function WDP:PET_BAR_UPDATE(event_name)
|
MMOSimca@336
|
2458 if not private.NON_LOOT_SPELL_LABELS[current_action.spell_label] then
|
jcallahan@25
|
2459 return
|
jcallahan@25
|
2460 end
|
jcallahan@34
|
2461 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("pet"))
|
jcallahan@25
|
2462
|
jcallahan@171
|
2463 if not unit_idnum or not UnitTypeIsNPC(unit_type) then
|
jcallahan@25
|
2464 return
|
jcallahan@25
|
2465 end
|
jcallahan@29
|
2466 NPCEntry(unit_idnum).mind_control = true
|
jcallahan@122
|
2467 table.wipe(current_action)
|
jcallahan@25
|
2468 end
|
jcallahan@25
|
2469
|
jcallahan@25
|
2470
|
MMOSimca@368
|
2471 -- This function produces data currently unused by wowdb.com, and it causes unneeded bloat in the raw lua DB.
|
MMOSimca@442
|
2472 --[[local LPJ = LibStub("LibPetJournal-2.0")
|
MMOSimca@442
|
2473 function WDP:PET_JOURNAL_LIST_UPDATE(event_name)
|
MMOSimca@346
|
2474 if DEBUGGING then
|
jcallahan@309
|
2475 return
|
jcallahan@309
|
2476 end
|
jcallahan@309
|
2477
|
jcallahan@115
|
2478 local num_pets = LPJ:NumPets()
|
jcallahan@115
|
2479
|
jcallahan@115
|
2480 for index, pet_id in LPJ:IteratePetIDs() do
|
jcallahan@115
|
2481 local _, _, is_owned, _, level, _, _, name, icon, pet_type, npc_id, _, _, is_wild = _G.C_PetJournal.GetPetInfoByIndex(index)
|
jcallahan@115
|
2482
|
jcallahan@115
|
2483 if is_owned then
|
jcallahan@115
|
2484 local health, max_health, attack, speed, rarity = _G.C_PetJournal.GetPetStats(pet_id)
|
jcallahan@115
|
2485
|
jcallahan@139
|
2486 if rarity then
|
jcallahan@139
|
2487 local rarity_name = _G["BATTLE_PET_BREED_QUALITY" .. rarity]
|
jcallahan@139
|
2488 local npc = NPCEntry(npc_id)
|
jcallahan@139
|
2489 npc.wild_pet = is_wild or nil
|
jcallahan@139
|
2490 npc.battle_pet_data = npc.battle_pet_data or {}
|
jcallahan@139
|
2491 npc.battle_pet_data[rarity_name] = npc.battle_pet_data[rarity_name] or {}
|
jcallahan@139
|
2492 npc.battle_pet_data[rarity_name]["level_" .. level] = npc.battle_pet_data[rarity_name]["level_" .. level] or {}
|
jcallahan@139
|
2493
|
jcallahan@139
|
2494 local data = npc.battle_pet_data[rarity_name]["level_" .. level]
|
jcallahan@139
|
2495 data.max_health = max_health
|
jcallahan@139
|
2496 data.attack = attack
|
jcallahan@139
|
2497 data.speed = speed
|
jcallahan@139
|
2498 end
|
jcallahan@115
|
2499 end
|
jcallahan@115
|
2500 end
|
MMOSimca@368
|
2501 end]]--
|
jcallahan@115
|
2502
|
jcallahan@115
|
2503
|
jcallahan@156
|
2504 function WDP:PLAYER_REGEN_DISABLED(event_name)
|
jcallahan@156
|
2505 private.in_combat = true
|
jcallahan@156
|
2506 end
|
jcallahan@156
|
2507
|
jcallahan@156
|
2508
|
jcallahan@156
|
2509 function WDP:PLAYER_REGEN_ENABLED(event_name)
|
jcallahan@156
|
2510 private.in_combat = nil
|
jcallahan@156
|
2511 end
|
jcallahan@156
|
2512
|
jcallahan@156
|
2513
|
jcallahan@118
|
2514 function WDP:PLAYER_TARGET_CHANGED(event_name)
|
jcallahan@215
|
2515 if not TargetedNPC() then
|
jcallahan@118
|
2516 return
|
jcallahan@2
|
2517 end
|
jcallahan@151
|
2518 current_action.target_type = AF.NPC
|
jcallahan@118
|
2519 self:UpdateTargetLocation()
|
jcallahan@118
|
2520 end
|
jcallahan@2
|
2521
|
jcallahan@89
|
2522
|
jcallahan@12
|
2523 do
|
jcallahan@12
|
2524 local function UpdateQuestJuncture(point)
|
jcallahan@12
|
2525 local unit_name = _G.UnitName("questnpc")
|
jcallahan@9
|
2526
|
jcallahan@12
|
2527 if not unit_name then
|
jcallahan@12
|
2528 return
|
jcallahan@12
|
2529 end
|
jcallahan@34
|
2530 local unit_type, unit_id = ParseGUID(_G.UnitGUID("questnpc"))
|
MMOSimca@351
|
2531 Debug("UpdateQuestJuncture: Updating quest juncture for %s.", ("%s:%d"):format(private.UNIT_TYPE_NAMES[unit_type], unit_id))
|
jcallahan@12
|
2532 if unit_type == private.UNIT_TYPES.OBJECT then
|
jcallahan@38
|
2533 UpdateDBEntryLocation("objects", unit_id)
|
jcallahan@12
|
2534 end
|
jcallahan@19
|
2535 local quest = DBEntry("quests", _G.GetQuestID())
|
jcallahan@12
|
2536 quest[point] = quest[point] or {}
|
MMOSimca@329
|
2537 quest[point][("%s:%d"):format(private.UNIT_TYPE_NAMES[unit_type], unit_id)] = true
|
jcallahan@24
|
2538
|
jcallahan@24
|
2539 return quest
|
jcallahan@12
|
2540 end
|
jcallahan@10
|
2541
|
jcallahan@12
|
2542
|
jcallahan@92
|
2543 function WDP:QUEST_COMPLETE(event_name)
|
jcallahan@97
|
2544 local quest = UpdateQuestJuncture("end")
|
catherton@465
|
2545
|
MMOSimca@446
|
2546 if not quest then
|
MMOSimca@446
|
2547 return
|
MMOSimca@446
|
2548 end
|
jcallahan@97
|
2549
|
jcallahan@112
|
2550 if ALLOWED_LOCALES[CLIENT_LOCALE] then
|
jcallahan@112
|
2551 quest.reward_text = ReplaceKeywords(_G.GetRewardText())
|
jcallahan@112
|
2552 end
|
jcallahan@67
|
2553 -- Make sure the quest NPC isn't erroneously recorded as giving reputation for quests which award it.
|
jcallahan@177
|
2554 ClearKilledNPC()
|
jcallahan@10
|
2555 end
|
jcallahan@10
|
2556
|
jcallahan@12
|
2557
|
jcallahan@92
|
2558 function WDP:QUEST_DETAIL(event_name)
|
jcallahan@24
|
2559 local quest = UpdateQuestJuncture("begin")
|
jcallahan@24
|
2560
|
jcallahan@46
|
2561 if not quest then
|
jcallahan@46
|
2562 return
|
jcallahan@46
|
2563 end
|
jcallahan@24
|
2564 quest.classes = quest.classes or {}
|
jcallahan@27
|
2565 quest.classes[PLAYER_CLASS] = true
|
jcallahan@24
|
2566
|
jcallahan@24
|
2567 quest.races = quest.races or {}
|
jcallahan@100
|
2568 quest.races[(PLAYER_RACE == "Pandaren") and ("%s_%s"):format(PLAYER_RACE, PLAYER_FACTION or "Neutral") or PLAYER_RACE] = true
|
jcallahan@10
|
2569 end
|
jcallahan@12
|
2570 end -- do-block
|
jcallahan@9
|
2571
|
jcallahan@9
|
2572
|
jcallahan@92
|
2573 function WDP:QUEST_LOG_UPDATE(event_name)
|
jcallahan@38
|
2574 local selected_quest = _G.GetQuestLogSelection() -- Save current selection to be restored when we're done.
|
jcallahan@36
|
2575 local entry_index, processed_quests = 1, 0
|
jcallahan@36
|
2576 local _, num_quests = _G.GetNumQuestLogEntries()
|
jcallahan@36
|
2577
|
jcallahan@36
|
2578 while processed_quests <= num_quests do
|
MMOSimca@329
|
2579 local _, _, _, is_header, _, _, _, quest_id = _G.GetQuestLogTitle(entry_index)
|
jcallahan@36
|
2580
|
jcallahan@84
|
2581 if quest_id == 0 then
|
jcallahan@84
|
2582 processed_quests = processed_quests + 1
|
jcallahan@84
|
2583 elseif not is_header then
|
jcallahan@36
|
2584 _G.SelectQuestLogEntry(entry_index);
|
jcallahan@36
|
2585
|
jcallahan@36
|
2586 local quest = DBEntry("quests", quest_id)
|
jcallahan@36
|
2587 quest.timer = _G.GetQuestLogTimeLeft()
|
jcallahan@37
|
2588 quest.can_share = _G.GetQuestLogPushable() and true or nil
|
jcallahan@36
|
2589 processed_quests = processed_quests + 1
|
jcallahan@36
|
2590 end
|
jcallahan@36
|
2591 entry_index = entry_index + 1
|
jcallahan@36
|
2592 end
|
jcallahan@36
|
2593 _G.SelectQuestLogEntry(selected_quest)
|
jcallahan@4
|
2594 self:UnregisterEvent("QUEST_LOG_UPDATE")
|
jcallahan@4
|
2595 end
|
jcallahan@4
|
2596
|
jcallahan@4
|
2597
|
jcallahan@97
|
2598 function WDP:QUEST_PROGRESS(event_name)
|
jcallahan@112
|
2599 if not ALLOWED_LOCALES[CLIENT_LOCALE] then
|
jcallahan@112
|
2600 return
|
jcallahan@112
|
2601 end
|
jcallahan@97
|
2602 DBEntry("quests", _G.GetQuestID()).progress_text = ReplaceKeywords(_G.GetProgressText())
|
jcallahan@97
|
2603 end
|
jcallahan@97
|
2604
|
jcallahan@97
|
2605
|
jcallahan@92
|
2606 function WDP:UNIT_QUEST_LOG_CHANGED(event_name, unit_id)
|
jcallahan@4
|
2607 if unit_id ~= "player" then
|
jcallahan@4
|
2608 return
|
jcallahan@4
|
2609 end
|
jcallahan@4
|
2610 self:RegisterEvent("QUEST_LOG_UPDATE")
|
jcallahan@4
|
2611 end
|
jcallahan@4
|
2612
|
jcallahan@4
|
2613
|
jcallahan@92
|
2614 do
|
jcallahan@92
|
2615 local TRADESKILL_TOOLS = {
|
jcallahan@92
|
2616 Anvil = anvil_spell_ids,
|
jcallahan@92
|
2617 Forge = forge_spell_ids,
|
jcallahan@92
|
2618 }
|
jcallahan@92
|
2619
|
jcallahan@92
|
2620
|
jcallahan@167
|
2621 local function RegisterTools(tradeskill_name, tradeskill_index)
|
catherton@479
|
2622 local link = _G.C_TradeSkillUI.GetRecipeLink(tradeskill_index)
|
catherton@465
|
2623
|
MMOSimca@352
|
2624 if link then
|
MMOSimca@352
|
2625 local spell_id = tonumber(link:match("^|c%x%x%x%x%x%x%x%x|H%w+:(%d+)"))
|
catherton@479
|
2626 local required_tool = _G.C_TradeSkillUI.GetRecipeTools(tradeskill_index)
|
MMOSimca@352
|
2627
|
MMOSimca@352
|
2628 if required_tool then
|
MMOSimca@352
|
2629 for tool_name, registry in pairs(TRADESKILL_TOOLS) do
|
MMOSimca@352
|
2630 if required_tool:find(tool_name) then
|
MMOSimca@352
|
2631 registry[spell_id] = true
|
MMOSimca@352
|
2632 end
|
jcallahan@167
|
2633 end
|
jcallahan@167
|
2634 end
|
jcallahan@167
|
2635 end
|
jcallahan@167
|
2636 end
|
jcallahan@167
|
2637
|
jcallahan@167
|
2638
|
jcallahan@92
|
2639 function WDP:TRADE_SKILL_SHOW(event_name)
|
catherton@479
|
2640 local profession_name, prof_level = _G.C_TradeSkillUI.GetTradeSkillLine()
|
jcallahan@92
|
2641
|
jcallahan@92
|
2642 if profession_name == _G.UNKNOWN then
|
jcallahan@92
|
2643 return
|
jcallahan@92
|
2644 end
|
jcallahan@167
|
2645 TradeSkillExecutePer(RegisterTools)
|
jcallahan@92
|
2646 end
|
jcallahan@92
|
2647 end -- do-block
|
jcallahan@92
|
2648
|
jcallahan@92
|
2649
|
jcallahan@167
|
2650 function WDP:TRAINER_CLOSED(event_name)
|
jcallahan@167
|
2651 private.trainer_shown = nil
|
jcallahan@167
|
2652 end
|
jcallahan@167
|
2653
|
jcallahan@167
|
2654
|
jcallahan@92
|
2655 function WDP:TRAINER_SHOW(event_name)
|
jcallahan@232
|
2656 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@164
|
2657 local trainer = NPCEntry(unit_idnum)
|
jcallahan@58
|
2658
|
jcallahan@164
|
2659 if not trainer then
|
jcallahan@58
|
2660 return
|
jcallahan@58
|
2661 end
|
jcallahan@331
|
2662 local _, trainer_standing = UnitFactionStanding("npc")
|
jcallahan@164
|
2663 trainer.teaches = trainer.teaches or {}
|
jcallahan@27
|
2664
|
jcallahan@167
|
2665 private.trainer_shown = true
|
jcallahan@167
|
2666
|
jcallahan@27
|
2667 -- Get the initial trainer filters
|
MMOSimca@344
|
2668 local available = _G.GetTrainerServiceTypeFilter("available") and 1 or 0
|
MMOSimca@344
|
2669 local unavailable = _G.GetTrainerServiceTypeFilter("unavailable") and 1 or 0
|
MMOSimca@344
|
2670 local used = _G.GetTrainerServiceTypeFilter("used") and 1 or 0
|
jcallahan@27
|
2671
|
jcallahan@27
|
2672 -- Clear the trainer filters
|
MMOSimca@344
|
2673 _G.SetTrainerServiceTypeFilter("available", 1)
|
MMOSimca@344
|
2674 _G.SetTrainerServiceTypeFilter("unavailable", 1)
|
MMOSimca@344
|
2675 _G.SetTrainerServiceTypeFilter("used", 1)
|
jcallahan@27
|
2676
|
jcallahan@27
|
2677 for index = 1, _G.GetNumTrainerServices(), 1 do
|
jcallahan@27
|
2678 local spell_name, rank_name, _, _, required_level = _G.GetTrainerServiceInfo(index)
|
jcallahan@27
|
2679
|
jcallahan@27
|
2680 if spell_name then
|
jcallahan@27
|
2681 DatamineTT:ClearLines()
|
jcallahan@27
|
2682 DatamineTT:SetTrainerService(index)
|
jcallahan@27
|
2683
|
jcallahan@27
|
2684 local _, _, spell_id = DatamineTT:GetSpell()
|
jcallahan@27
|
2685
|
jcallahan@43
|
2686 if spell_id then
|
jcallahan@164
|
2687 local class_professions = trainer.teaches[PLAYER_CLASS]
|
jcallahan@164
|
2688
|
jcallahan@164
|
2689 if not class_professions then
|
jcallahan@164
|
2690 trainer.teaches[PLAYER_CLASS] = {}
|
jcallahan@164
|
2691 class_professions = trainer.teaches[PLAYER_CLASS]
|
jcallahan@164
|
2692 end
|
jcallahan@43
|
2693 local profession, min_skill = _G.GetTrainerServiceSkillReq(index)
|
jcallahan@43
|
2694 profession = profession or "General"
|
jcallahan@43
|
2695
|
jcallahan@164
|
2696 local profession_skills = class_professions[profession]
|
jcallahan@43
|
2697
|
jcallahan@43
|
2698 if not profession_skills then
|
jcallahan@43
|
2699 class_professions[profession] = {}
|
jcallahan@43
|
2700 profession_skills = class_professions[profession]
|
jcallahan@43
|
2701 end
|
jcallahan@173
|
2702 profession_skills[spell_id] = ("%d:%d:%d"):format(required_level, min_skill, _G.GetTrainerServiceCost(index))
|
jcallahan@27
|
2703 end
|
jcallahan@27
|
2704 end
|
jcallahan@27
|
2705 end
|
jcallahan@27
|
2706 -- Reset the filters to what they were before
|
MMOSimca@344
|
2707 _G.SetTrainerServiceTypeFilter("available", available or 0)
|
MMOSimca@344
|
2708 _G.SetTrainerServiceTypeFilter("unavailable", unavailable or 0)
|
MMOSimca@344
|
2709 _G.SetTrainerServiceTypeFilter("used", used or 0)
|
jcallahan@27
|
2710 end
|
jcallahan@27
|
2711
|
jcallahan@27
|
2712
|
jcallahan@1
|
2713 function WDP:UNIT_SPELLCAST_SENT(event_name, unit_id, spell_name, spell_rank, target_name, spell_line)
|
jcallahan@1
|
2714 if private.tracked_line or unit_id ~= "player" then
|
jcallahan@1
|
2715 return
|
jcallahan@1
|
2716 end
|
jcallahan@1
|
2717 local spell_label = private.SPELL_LABELS_BY_NAME[spell_name]
|
jcallahan@1
|
2718
|
jcallahan@1
|
2719 if not spell_label then
|
jcallahan@1
|
2720 return
|
jcallahan@1
|
2721 end
|
jcallahan@306
|
2722
|
MMOSimca@343
|
2723 Debug("UNIT_SPELLCAST_SENT: %s was cast.", spell_name)
|
jcallahan@150
|
2724 local item_name, item_link = _G.GameTooltip:GetItem()
|
jcallahan@150
|
2725 local unit_name, unit_id = _G.GameTooltip:GetUnit()
|
jcallahan@1
|
2726
|
jcallahan@150
|
2727 if not unit_name and _G.UnitName("target") == target_name then
|
jcallahan@150
|
2728 unit_name = target_name
|
jcallahan@150
|
2729 unit_id = "target"
|
jcallahan@1
|
2730 end
|
jcallahan@1
|
2731 local spell_flags = private.SPELL_FLAGS_BY_LABEL[spell_label]
|
jcallahan@28
|
2732 local zone_name, area_id, x, y, map_level, instance_token = CurrentLocationData()
|
MMOSimca@328
|
2733 if not (zone_name and area_id and x and y and map_level) then
|
mmosimca@508
|
2734 if not (_G.IsInInstance()) then
|
mmosimca@508
|
2735 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
|
2736 end
|
MMOSimca@328
|
2737 return
|
MMOSimca@328
|
2738 end
|
jcallahan@28
|
2739
|
jcallahan@205
|
2740 table.wipe(current_action)
|
jcallahan@122
|
2741 current_action.instance_token = instance_token
|
jcallahan@122
|
2742 current_action.map_level = map_level
|
jcallahan@122
|
2743 current_action.x = x
|
jcallahan@122
|
2744 current_action.y = y
|
jcallahan@122
|
2745 current_action.zone_data = ("%s:%d"):format(zone_name, area_id)
|
jcallahan@122
|
2746 current_action.spell_label = spell_label
|
jcallahan@105
|
2747
|
jcallahan@105
|
2748 if not private.NON_LOOT_SPELL_LABELS[spell_label] then
|
jcallahan@122
|
2749 current_action.loot_label = spell_label:lower()
|
jcallahan@105
|
2750 end
|
jcallahan@1
|
2751
|
jcallahan@151
|
2752 if unit_name and unit_name == target_name and not item_name then
|
jcallahan@16
|
2753 if bit.band(spell_flags, AF.NPC) == AF.NPC then
|
jcallahan@150
|
2754 if not unit_id or unit_name ~= target_name then
|
jcallahan@16
|
2755 return
|
jcallahan@16
|
2756 end
|
jcallahan@123
|
2757 current_action.target_type = AF.NPC
|
jcallahan@16
|
2758 end
|
jcallahan@16
|
2759 elseif bit.band(spell_flags, AF.ITEM) == AF.ITEM then
|
jcallahan@123
|
2760 current_action.target_type = AF.ITEM
|
jcallahan@16
|
2761
|
jcallahan@150
|
2762 if item_name and item_name == target_name then
|
jcallahan@150
|
2763 current_action.identifier = ItemLinkToID(item_link)
|
jcallahan@16
|
2764 elseif target_name and target_name ~= "" then
|
jcallahan@331
|
2765 local _, item_link = _G.GetItemInfo(target_name)
|
jcallahan@331
|
2766 current_action.identifier = ItemLinkToID(item_link)
|
jcallahan@16
|
2767 end
|
jcallahan@150
|
2768 elseif not item_name and not unit_name then
|
jcallahan@1
|
2769 if bit.band(spell_flags, AF.OBJECT) == AF.OBJECT then
|
jcallahan@17
|
2770 if target_name == "" then
|
jcallahan@17
|
2771 return
|
jcallahan@17
|
2772 end
|
jcallahan@122
|
2773 current_action.object_name = target_name
|
jcallahan@123
|
2774 current_action.target_type = AF.OBJECT
|
jcallahan@1
|
2775 elseif bit.band(spell_flags, AF.ZONE) == AF.ZONE then
|
jcallahan@123
|
2776 current_action.target_type = AF.ZONE
|
jcallahan@1
|
2777 end
|
jcallahan@1
|
2778 end
|
jcallahan@1
|
2779 private.tracked_line = spell_line
|
jcallahan@0
|
2780 end
|
jcallahan@0
|
2781
|
jcallahan@94
|
2782
|
MMOSimca@393
|
2783 -- Triggered by bonus roll prompts, disenchant prompts, and in a few other rare circumstances
|
jcallahan@312
|
2784 function WDP:SPELL_CONFIRMATION_PROMPT(event_name, spell_id, confirm_type, text, duration, currency_id_cost)
|
jcallahan@306
|
2785 if private.RAID_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id] then
|
jcallahan@306
|
2786 ClearKilledBossID()
|
jcallahan@306
|
2787 ClearLootToastContainerID()
|
MMOSimca@387
|
2788 raid_boss_id = private.RAID_BOSS_BONUS_SPELL_ID_TO_NPC_ID_MAP[spell_id]
|
jcallahan@306
|
2789 else
|
MMOSimca@336
|
2790 Debug("%s: Spell ID %d is not a known raid boss 'Bonus' spell.", event_name, spell_id)
|
jcallahan@306
|
2791 return
|
jcallahan@1
|
2792 end
|
jcallahan@306
|
2793
|
jcallahan@324
|
2794 -- Assign existing loot data to boss if it exists
|
jcallahan@307
|
2795 if loot_toast_data then
|
MMOSimca@427
|
2796 local npc = NPCEntry(raid_boss_id)
|
MMOSimca@427
|
2797 if npc then
|
MMOSimca@427
|
2798 -- Create needed npc fields if required
|
MMOSimca@427
|
2799 local loot_label = "drops"
|
MMOSimca@427
|
2800 local encounter_data = npc:EncounterData(InstanceDifficultyToken())
|
MMOSimca@427
|
2801 encounter_data[loot_label] = encounter_data[loot_label] or {}
|
MMOSimca@427
|
2802 encounter_data.loot_counts = encounter_data.loot_counts or {}
|
MMOSimca@427
|
2803
|
MMOSimca@427
|
2804 for index = 1, #loot_toast_data do
|
MMOSimca@427
|
2805 local data = loot_toast_data[index]
|
MMOSimca@427
|
2806 local loot_type = data[1]
|
MMOSimca@427
|
2807 local hyperlink = data[2]
|
MMOSimca@427
|
2808 local quantity = data[3]
|
MMOSimca@427
|
2809
|
MMOSimca@427
|
2810 if loot_type == "item" then
|
MMOSimca@427
|
2811 local item_id = ItemLinkToID(hyperlink)
|
MMOSimca@427
|
2812 Debug("%s: Assigned stored item loot data - %s - %d:%d", event_name, hyperlink, item_id, quantity)
|
MMOSimca@427
|
2813 table.insert(encounter_data[loot_label], ("%d:%d"):format(item_id, quantity))
|
MMOSimca@427
|
2814 elseif loot_type == "money" then
|
MMOSimca@427
|
2815 Debug("%s: Assigned stored money loot data - money:%d", event_name, quantity)
|
MMOSimca@427
|
2816 table.insert(encounter_data[loot_label], ("money:%d"):format(quantity))
|
MMOSimca@427
|
2817 elseif loot_type == "currency" then
|
mmosimca@496
|
2818 local currency_id = CurrencyLinkToID(hyperlink)
|
mmosimca@496
|
2819 Debug("%s: Assigned stored currency loot data - %s - currency:%d (%d)", event_name, hyperlink, currency_id, quantity)
|
mmosimca@496
|
2820 table.insert(encounter_data[loot_label], ("currency:%d:%d"):format(quantity, currency_id))
|
MMOSimca@427
|
2821 end
|
jcallahan@317
|
2822 end
|
jcallahan@317
|
2823
|
MMOSimca@427
|
2824 if not boss_loot_toasting[raid_boss_id] then
|
MMOSimca@427
|
2825 encounter_data.loot_counts[loot_label] = (encounter_data.loot_counts[loot_label] or 0) + 1
|
MMOSimca@427
|
2826 boss_loot_toasting[raid_boss_id] = true -- Do not count further loots until timer expires or another boss is killed
|
jcallahan@307
|
2827 end
|
MMOSimca@427
|
2828 else
|
MMOSimca@427
|
2829 Debug("%s: NPC is nil, but we have stored loot data...", event_name)
|
jcallahan@307
|
2830 end
|
jcallahan@307
|
2831 end
|
jcallahan@307
|
2832
|
jcallahan@307
|
2833 ClearLootToastData()
|
MMOSimca@427
|
2834 killed_boss_id_timer_handle = C_Timer.NewTimer(5, ClearKilledBossID)
|
jcallahan@306
|
2835 end
|
jcallahan@306
|
2836
|
jcallahan@306
|
2837
|
jcallahan@306
|
2838 function WDP:UNIT_SPELLCAST_SUCCEEDED(event_name, unit_id, spell_name, spell_rank, spell_line, spell_id)
|
jcallahan@306
|
2839 if unit_id ~= "player" then
|
jcallahan@306
|
2840 return
|
jcallahan@306
|
2841 end
|
jcallahan@306
|
2842 private.tracked_line = nil
|
jcallahan@306
|
2843 private.previous_spell_id = spell_id
|
jcallahan@306
|
2844
|
MMOSimca@393
|
2845 -- For spells cast when Logging
|
MMOSimca@345
|
2846 if private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[spell_id] then
|
MMOSimca@345
|
2847 last_timber_spell_id = spell_id
|
MMOSimca@351
|
2848 UpdateDBEntryLocation("objects", ("OPENING:%s"):format(private.LOGGING_SPELL_ID_TO_OBJECT_ID_MAP[spell_id]))
|
MMOSimca@345
|
2849 return
|
MMOSimca@345
|
2850 end
|
MMOSimca@345
|
2851
|
MMOSimca@393
|
2852 -- For spells cast by items that always trigger loot toasts
|
MMOSimca@381
|
2853 if private.LOOT_TOAST_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id] then
|
jcallahan@306
|
2854 ClearKilledBossID()
|
jcallahan@306
|
2855 ClearLootToastContainerID()
|
jcallahan@307
|
2856 ClearLootToastData()
|
jcallahan@306
|
2857
|
MMOSimca@387
|
2858 loot_toast_container_id = private.LOOT_TOAST_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id]
|
MMOSimca@383
|
2859 loot_toast_container_timer_handle = C_Timer.NewTimer(1, ClearLootToastContainerID) -- we need to assign a handle here to cancel it later
|
MMOSimca@345
|
2860 return
|
jcallahan@306
|
2861 end
|
jcallahan@306
|
2862
|
MMOSimca@393
|
2863 -- For spells cast by items that don't usually trigger loot toasts
|
catherton@473
|
2864 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
|
2865 -- Set up timer
|
MMOSimca@393
|
2866 ClearChatLootData()
|
MMOSimca@393
|
2867 Debug("%s: Beginning chat-based loot timer for spellID %d", event_name, spell_id)
|
MMOSimca@411
|
2868 chat_loot_timer_handle = C_Timer.NewTimer(1.5, ClearChatLootData)
|
catherton@473
|
2869 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
|
2870 chat_loot_data.identifier = private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_BY_CLASS_ID_MAP[spell_id][PLAYER_CLASS_ID]
|
MMOSimca@454
|
2871 else
|
MMOSimca@454
|
2872 chat_loot_data.identifier = private.DELAYED_CONTAINER_SPELL_ID_TO_ITEM_ID_MAP[spell_id]
|
MMOSimca@454
|
2873 end
|
MMOSimca@347
|
2874 return
|
MMOSimca@347
|
2875 end
|
MMOSimca@347
|
2876
|
mmosimca@520
|
2877 -- 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
|
2878 local text = _G["GameTooltipTextLeft1"] and _G["GameTooltipTextLeft1"]:GetText() or nil
|
mmosimca@520
|
2879 if spell_id == SPELL_ID_UPDATE_INTERACTIONS and text and text == "Ephemeral Crystal" then
|
mmosimca@522
|
2880 Debug("%s: Detected location for an Ephemeral Crystal.", event_name)
|
mmosimca@520
|
2881 for index = 1, #private.EPHEMERAL_CRYSTAL_OBJECT_IDS do
|
mmosimca@520
|
2882 UpdateDBEntryLocation("objects", private.EPHEMERAL_CRYSTAL_OBJECT_IDS[index])
|
mmosimca@520
|
2883 end
|
mmosimca@520
|
2884 end
|
mmosimca@520
|
2885
|
jcallahan@306
|
2886 if anvil_spell_ids[spell_id] then
|
jcallahan@306
|
2887 UpdateDBEntryLocation("objects", OBJECT_ID_ANVIL)
|
jcallahan@306
|
2888 elseif forge_spell_ids[spell_id] then
|
jcallahan@306
|
2889 UpdateDBEntryLocation("objects", OBJECT_ID_FORGE)
|
jcallahan@306
|
2890 elseif spell_name:match("^Harvest.+") then
|
jcallahan@306
|
2891 killed_npc_id = current_target_id
|
MMOSimca@343
|
2892 private.harvesting = true -- Used to track which NPCs can be harvested (can we get this from CreatureCache instead?)
|
jcallahan@306
|
2893 end
|
jcallahan@306
|
2894 end
|
jcallahan@0
|
2895
|
jcallahan@90
|
2896
|
jcallahan@1
|
2897 function WDP:HandleSpellFailure(event_name, unit_id, spell_name, spell_rank, spell_line, spell_id)
|
jcallahan@1
|
2898 if unit_id ~= "player" then
|
jcallahan@1
|
2899 return
|
jcallahan@1
|
2900 end
|
jcallahan@0
|
2901
|
jcallahan@1
|
2902 if private.tracked_line == spell_line then
|
jcallahan@1
|
2903 private.tracked_line = nil
|
jcallahan@1
|
2904 end
|
jcallahan@147
|
2905 table.wipe(current_action)
|
jcallahan@0
|
2906 end
|
jcallahan@90
|
2907
|
jcallahan@90
|
2908
|
jcallahan@90
|
2909 do
|
jcallahan@90
|
2910 local function SetUnitField(field, required_type)
|
jcallahan@90
|
2911 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@90
|
2912
|
jcallahan@90
|
2913 if not unit_idnum or (required_type and unit_type ~= required_type) then
|
jcallahan@90
|
2914 return
|
jcallahan@90
|
2915 end
|
jcallahan@90
|
2916
|
jcallahan@171
|
2917 if UnitTypeIsNPC(unit_type) then
|
jcallahan@90
|
2918 NPCEntry(unit_idnum)[field] = true
|
jcallahan@90
|
2919 elseif unit_type == private.UNIT_TYPES.OBJECT then
|
jcallahan@90
|
2920 DBEntry("objects", unit_idnum)[field] = true
|
jcallahan@93
|
2921 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@90
|
2922 end
|
jcallahan@90
|
2923 end
|
jcallahan@90
|
2924
|
jcallahan@90
|
2925
|
jcallahan@90
|
2926 function WDP:AUCTION_HOUSE_SHOW(event_name)
|
MMOSimca@436
|
2927 WDP:StopChatLootRecording(event_name)
|
jcallahan@90
|
2928 SetUnitField("auctioneer", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
2929 end
|
jcallahan@90
|
2930
|
jcallahan@90
|
2931
|
jcallahan@90
|
2932 function WDP:BANKFRAME_OPENED(event_name)
|
MMOSimca@436
|
2933 WDP:StopChatLootRecording(event_name)
|
jcallahan@90
|
2934 SetUnitField("banker", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
2935 end
|
jcallahan@90
|
2936
|
jcallahan@90
|
2937
|
jcallahan@90
|
2938 function WDP:BATTLEFIELDS_SHOW(event_name)
|
jcallahan@90
|
2939 SetUnitField("battlemaster", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
2940 end
|
jcallahan@90
|
2941
|
jcallahan@90
|
2942
|
jcallahan@323
|
2943 local GOSSIP_SHOW_FUNCS = {
|
jcallahan@323
|
2944 [private.UNIT_TYPES.NPC] = function(unit_idnum)
|
jcallahan@323
|
2945 local gossip_options = { _G.GetGossipOptions() }
|
jcallahan@323
|
2946
|
jcallahan@323
|
2947 for index = 2, #gossip_options, 2 do
|
jcallahan@323
|
2948 if gossip_options[index] == "binder" then
|
jcallahan@323
|
2949 SetUnitField("innkeeper", private.UNIT_TYPES.NPC)
|
jcallahan@323
|
2950 return
|
jcallahan@323
|
2951 end
|
jcallahan@323
|
2952 end
|
jcallahan@323
|
2953 end,
|
jcallahan@323
|
2954 [private.UNIT_TYPES.OBJECT] = function(unit_idnum)
|
jcallahan@323
|
2955 UpdateDBEntryLocation("objects", unit_idnum)
|
jcallahan@323
|
2956 end,
|
jcallahan@323
|
2957 }
|
jcallahan@323
|
2958
|
jcallahan@323
|
2959
|
jcallahan@92
|
2960 function WDP:GOSSIP_SHOW(event_name)
|
MMOSimca@436
|
2961 WDP:StopChatLootRecording(event_name)
|
jcallahan@323
|
2962 local unit_type, unit_idnum = ParseGUID(_G.UnitGUID("npc"))
|
jcallahan@323
|
2963 if not unit_idnum then
|
jcallahan@323
|
2964 return
|
jcallahan@323
|
2965 end
|
jcallahan@323
|
2966
|
jcallahan@323
|
2967 if GOSSIP_SHOW_FUNCS[unit_type] then
|
jcallahan@323
|
2968 GOSSIP_SHOW_FUNCS[unit_type](unit_idnum)
|
jcallahan@90
|
2969 end
|
jcallahan@90
|
2970 end
|
jcallahan@90
|
2971
|
jcallahan@90
|
2972
|
jcallahan@93
|
2973 function WDP:GUILDBANKFRAME_OPENED(event_name)
|
MMOSimca@436
|
2974 WDP:StopChatLootRecording(event_name)
|
jcallahan@93
|
2975 SetUnitField("guild_bank", private.UNIT_TYPES.OBJECT)
|
jcallahan@93
|
2976 end
|
jcallahan@93
|
2977
|
jcallahan@93
|
2978
|
jcallahan@189
|
2979 function WDP:ITEM_UPGRADE_MASTER_OPENED(event_name)
|
jcallahan@189
|
2980 SetUnitField("item_upgrade_master", private.UNIT_TYPES.NPC)
|
jcallahan@189
|
2981 end
|
jcallahan@189
|
2982
|
jcallahan@189
|
2983
|
jcallahan@90
|
2984 function WDP:TAXIMAP_OPENED(event_name)
|
jcallahan@90
|
2985 SetUnitField("flight_master", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
2986 end
|
jcallahan@90
|
2987
|
jcallahan@90
|
2988
|
jcallahan@90
|
2989 function WDP:TRANSMOGRIFY_OPEN(event_name)
|
jcallahan@90
|
2990 SetUnitField("transmogrifier", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
2991 end
|
jcallahan@90
|
2992
|
jcallahan@90
|
2993
|
jcallahan@90
|
2994 function WDP:VOID_STORAGE_OPEN(event_name)
|
jcallahan@90
|
2995 SetUnitField("void_storage", private.UNIT_TYPES.NPC)
|
jcallahan@90
|
2996 end
|
jcallahan@90
|
2997 end -- do-block
|