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