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