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