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