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