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