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