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