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