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