Mercurial > wow > wowdb-profiler
comparison Main.lua @ 485:5e5ddb69f845 7.0.3-3
Added full world quest data recording support.
author | MMOSimca <mmosimca@gmail.com> |
---|---|
date | Tue, 06 Sep 2016 09:37:07 -0400 |
parents | 679e2846ff88 |
children | b661f10e04d9 |
comparison
equal
deleted
inserted
replaced
484:679e2846ff88 | 485:5e5ddb69f845 |
---|---|
10 local math = _G.math | 10 local math = _G.math |
11 local table = _G.table | 11 local table = _G.table |
12 | 12 |
13 local next = _G.next | 13 local next = _G.next |
14 local select = _G.select | 14 local select = _G.select |
15 local type = _G.type | |
15 local unpack = _G.unpack | 16 local unpack = _G.unpack |
16 | 17 |
17 local C_Timer = _G.C_Timer | 18 local C_Timer = _G.C_Timer |
18 | 19 |
19 | 20 |
38 local CLIENT_LOCALE = _G.GetLocale() | 39 local CLIENT_LOCALE = _G.GetLocale() |
39 local DB_VERSION = 18 | 40 local DB_VERSION = 18 |
40 local DEBUGGING = false | 41 local DEBUGGING = false |
41 local EVENT_DEBUG = false | 42 local EVENT_DEBUG = false |
42 | 43 |
44 -- Timer durations in seconds | |
45 local DELAY_PROCESS_ITEMS = 30 | |
46 local DELAY_PROCESS_WORLD_QUESTS = 60 | |
47 local DELAY_UPDATE_TARGET_LOCATION = 0.5 | |
48 | |
43 local ITEM_ID_TIMBER = 114781 | 49 local ITEM_ID_TIMBER = 114781 |
44 | 50 |
45 local LOOT_SOURCE_ID_REDUNDANT = 3 | 51 local LOOT_SOURCE_ID_REDUNDANT = 3 |
46 local LOOT_SOURCE_ID_GARRISON_CACHE = 10 | 52 local LOOT_SOURCE_ID_GARRISON_CACHE = 10 |
47 | 53 |
50 local OBJECT_ID_FORGE = 1685 | 56 local OBJECT_ID_FORGE = 1685 |
51 | 57 |
52 local PLAYER_CLASS, PLAYER_CLASS_ID = _G.select(2, _G.UnitClass("player")) | 58 local PLAYER_CLASS, PLAYER_CLASS_ID = _G.select(2, _G.UnitClass("player")) |
53 local PLAYER_FACTION = _G.UnitFactionGroup("player") | 59 local PLAYER_FACTION = _G.UnitFactionGroup("player") |
54 local PLAYER_GUID | 60 local PLAYER_GUID |
61 local PLAYER_LEVEL = _G.UnitLevel("player") | |
55 local PLAYER_NAME = _G.UnitName("player") | 62 local PLAYER_NAME = _G.UnitName("player") |
56 local PLAYER_RACE = _G.select(2, _G.UnitRace("player")) | 63 local PLAYER_RACE = _G.select(2, _G.UnitRace("player")) |
57 | 64 |
58 local LOOT_SLOT_CURRENCY = _G.LOOT_SLOT_CURRENCY | 65 local LOOT_SLOT_CURRENCY = _G.LOOT_SLOT_CURRENCY |
59 local LOOT_SLOT_ITEM = _G.LOOT_SLOT_ITEM | 66 local LOOT_SLOT_ITEM = _G.LOOT_SLOT_ITEM |
60 local LOOT_SLOT_MONEY = _G.LOOT_SLOT_MONEY | 67 local LOOT_SLOT_MONEY = _G.LOOT_SLOT_MONEY |
68 | |
69 local WORLD_MAP_ID_BROKEN_ISLES = 1007 | |
61 | 70 |
62 -- Removed in Legion but still needed | 71 -- Removed in Legion but still needed |
63 local ERR_QUEST_REWARD_ITEM_MULT_IS = _G.ERR_QUEST_REWARD_ITEM_MULT_IS or "Received %d of item: %s." | 72 local ERR_QUEST_REWARD_ITEM_MULT_IS = _G.ERR_QUEST_REWARD_ITEM_MULT_IS or "Received %d of item: %s." |
64 local ERR_QUEST_REWARD_ITEM_S = _G.ERR_QUEST_REWARD_ITEM_S or "Received item: %s." | 73 local ERR_QUEST_REWARD_ITEM_S = _G.ERR_QUEST_REWARD_ITEM_S or "Received item: %s." |
65 | 74 |
181 local last_timber_spell_id | 190 local last_timber_spell_id |
182 local last_garrison_cache_object_id | 191 local last_garrison_cache_object_id |
183 local block_chat_loot_data | 192 local block_chat_loot_data |
184 local chat_loot_data = {} | 193 local chat_loot_data = {} |
185 local chat_loot_timer_handle | 194 local chat_loot_timer_handle |
195 local world_quest_timer_handle | |
196 local world_quest_event_timestamp = 0 | |
186 local current_target_id | 197 local current_target_id |
187 local current_loot | 198 local current_loot |
188 | 199 |
189 | 200 |
190 -- Data for our current action. Including possible values as a reference. | 201 -- Data for our current action. Including possible values as a reference. |
325 | 336 |
326 -- Put coordinates into expected format (as integers, they don't get a billion decimals output in the SavedVariables) | 337 -- Put coordinates into expected format (as integers, they don't get a billion decimals output in the SavedVariables) |
327 local x_int = nil | 338 local x_int = nil |
328 if (x and type(x) == "number") then | 339 if (x and type(x) == "number") then |
329 x_int = _G.floor(x * 1000) | 340 x_int = _G.floor(x * 1000) |
330 | 341 |
331 -- Limit precision to 0.2 | 342 -- Limit precision to 0.2 |
332 if x_int % 2 ~= 0 then | 343 if x_int % 2 ~= 0 then |
333 x_int = x_int + 1 | 344 x_int = x_int + 1 |
334 end | 345 end |
335 | 346 |
336 -- Prevent out of bounds coordinates | 347 -- Prevent out of bounds coordinates |
337 if (x_int < 0 or x_int > 1000) then | 348 if (x_int < 0 or x_int > 1000) then |
338 x_int = nil | 349 x_int = nil |
339 end | 350 end |
340 end | 351 end |
341 local y_int = nil | 352 local y_int = nil |
342 if (y and type(y) == "number") then | 353 if (y and type(y) == "number") then |
343 y_int = _G.floor(y * 1000) | 354 y_int = _G.floor(y * 1000) |
344 | 355 |
345 -- Limit precision to 0.2 | 356 -- Limit precision to 0.2 |
346 if y_int % 2 ~= 0 then | 357 if y_int % 2 ~= 0 then |
347 y_int = y_int + 1 | 358 y_int = y_int + 1 |
348 end | 359 end |
349 | 360 |
350 -- Prevent out of bounds coordinates | 361 -- Prevent out of bounds coordinates |
351 if (y_int < 0 or y_int > 1000) then | 362 if (y_int < 0 or y_int > 1000) then |
352 y_int = nil | 363 y_int = nil |
353 end | 364 end |
354 end | 365 end |
839 global_db = db.global | 850 global_db = db.global |
840 char_db = db.char | 851 char_db = db.char |
841 | 852 |
842 local raw_db = _G.WoWDBProfilerData | 853 local raw_db = _G.WoWDBProfilerData |
843 local build_num = tonumber(private.build_num) | 854 local build_num = tonumber(private.build_num) |
844 | 855 |
845 -- Get current region from LibRealmInfo (and account for the fact that PTR and Beta return nil) | 856 -- Get current region from LibRealmInfo (and account for the fact that PTR and Beta return nil) |
846 local current_region = LibRealmInfo:GetCurrentRegion() or "XX" | 857 local current_region = LibRealmInfo:GetCurrentRegion() or "XX" |
847 | 858 |
848 -- Wipe all data if DB version or build number changed | 859 -- Wipe all data if DB version or build number changed |
849 if (raw_db.version and raw_db.version < DB_VERSION) or (raw_db.build_num and raw_db.build_num < build_num) then | 860 if (raw_db.version and raw_db.version < DB_VERSION) or (raw_db.build_num and raw_db.build_num < build_num) then |
850 for entry in pairs(DATABASE_DEFAULTS.global) do | 861 for entry in pairs(DATABASE_DEFAULTS.global) do |
851 global_db[entry] = {} | 862 global_db[entry] = {} |
852 end | 863 end |
853 end | 864 end |
865 -- Wipe World Quest data if region changed | |
866 if raw_db.region and raw_db.region ~= current_region and global_db["world_quests"] then | |
867 global_db["world_quests"] = {} | |
868 end | |
869 | |
854 raw_db.build_num = build_num | 870 raw_db.build_num = build_num |
855 raw_db.region = current_region | 871 raw_db.region = current_region |
856 raw_db.version = DB_VERSION | 872 raw_db.version = DB_VERSION |
857 | 873 |
858 private.InitializeCommentSystem() | 874 private.InitializeCommentSystem() |
893 | 909 |
894 for index = 1, _G.GetNumLanguages() do | 910 for index = 1, _G.GetNumLanguages() do |
895 languages_known[_G.GetLanguageByIndex(index)] = true | 911 languages_known[_G.GetLanguageByIndex(index)] = true |
896 end | 912 end |
897 | 913 |
898 -- These two timers loop indefinitely using Lua's infinity constant | 914 -- These timers loop indefinitely using Lua's infinity constant |
899 item_process_timer_handle = C_Timer.NewTicker(30, WDP.ProcessItems, math.huge) | 915 item_process_timer_handle = C_Timer.NewTicker(DELAY_PROCESS_ITEMS, WDP.ProcessItems, math.huge) |
900 target_location_timer_handle = C_Timer.NewTicker(0.5, WDP.UpdateTargetLocation, math.huge) | 916 target_location_timer_handle = C_Timer.NewTicker(DELAY_UPDATE_TARGET_LOCATION, WDP.UpdateTargetLocation, math.huge) |
917 world_quest_timer_handle = C_Timer.NewTicker(DELAY_PROCESS_WORLD_QUESTS, WDP.ProcessWorldQuests, math.huge) | |
901 | 918 |
902 _G.hooksecurefunc("UseContainerItem", function(bag_index, slot_index, target_unit) | 919 _G.hooksecurefunc("UseContainerItem", function(bag_index, slot_index, target_unit) |
903 if target_unit then | 920 if target_unit then |
904 return | 921 return |
905 end | 922 end |
913 local _, item_link = _G.GetItemInfo(identifier) | 930 local _, item_link = _G.GetItemInfo(identifier) |
914 HandleItemUse(item_link) | 931 HandleItemUse(item_link) |
915 end) | 932 end) |
916 | 933 |
917 self:GROUP_ROSTER_UPDATE() | 934 self:GROUP_ROSTER_UPDATE() |
935 end | |
936 | |
937 | |
938 -- Record data for a specific quest ID; reward data must be available or nothing will be recorded | |
939 -- When we reach this point, we've already checked for a valid mapID, questID, quest data, and worldQuestType | |
940 local function RecordWorldQuestData(world_map_id, quest_id, api_data_table) | |
941 | |
942 -- Ensure we have location data and rewards (barely readable so putting it on multiple lines) | |
943 if not api_data_table.x or not api_data_table.y or not api_data_table.floor or not | |
944 (_G.GetQuestLogRewardXP(quest_id) > 0 or _G.GetNumQuestLogRewardCurrencies(quest_id) > 0 | |
945 or _G.GetNumQuestLogRewards(quest_id) > 0 or _G.GetQuestLogRewardMoney(quest_id) > 0 | |
946 or _G.GetQuestLogRewardArtifactXP(quest_id) > 0 or _G.GetQuestLogRewardHonor(quest_id) > 0) then | |
947 return | |
948 end | |
949 | |
950 local entry = DBEntry("world_quests", quest_id) | |
951 | |
952 if entry then | |
953 | |
954 -- Record location | |
955 entry["location"] = {} | |
956 entry["location"]["world_map_id"] = world_map_id | |
957 entry["location"]["x"] = (tonumber(api_data_table.x) or 0) * 100 | |
958 entry["location"]["y"] = (tonumber(api_data_table.y) or 0) * 100 | |
959 entry["location"]["floor"] = tonumber(api_data_table.floor) or 0 | |
960 | |
961 -- Record simple rewards (XP, money, artifact XP, honor) | |
962 entry["rewards"] = {} | |
963 entry["rewards"]["xp"] = tonumber(_G.GetQuestLogRewardXP(quest_id)) or 0 | |
964 entry["rewards"]["money"] = tonumber(_G.GetQuestLogRewardMoney(quest_id)) or 0 | |
965 local actualXP, scaling = _G.GetQuestLogRewardArtifactXP(quest_id) | |
966 entry["rewards"]["artifact_xp"] = ("%d:%d"):format(tonumber(actualXP) or 0, tonumber(scaling) or 0) | |
967 entry["rewards"]["honor"] = tonumber(_G.GetQuestLogRewardHonor(quest_id)) or 0 | |
968 | |
969 -- Record currencies | |
970 entry["rewards"]["currency_count"] = tonumber(_G.GetNumQuestLogRewardCurrencies(quest_id)) or 0 | |
971 | |
972 if entry["rewards"]["currency_count"] > 0 then | |
973 | |
974 -- Create currency rewards sub-table and fill | |
975 entry["rewards"]["currencies"] = {} | |
976 for i = 1, entry["rewards"]["currency_count"] do | |
977 local name, texture_path, quantity = _G.GetQuestLogRewardCurrencyInfo(i, quest_id) | |
978 local currency_texture = texture_path:match("[^\\]+$"):lower() | |
979 table.insert(entry["rewards"]["currencies"], ("%d:%s"):format(quantity, currency_texture)) | |
980 end | |
981 end | |
982 | |
983 -- Record items | |
984 entry["rewards"]["item_count"] = tonumber(_G.GetNumQuestLogRewards(quest_id)) or 0 | |
985 | |
986 if entry["rewards"]["item_count"] > 0 then | |
987 | |
988 -- Create item rewards sub-table and fill | |
989 entry["rewards"]["items"] = {} | |
990 for i = 1, entry["rewards"]["item_count"] do | |
991 local item_name, item_texture, quantity, quality, is_usable, item_id = _G.GetQuestLogRewardInfo(i, quest_id) | |
992 table.insert(entry["rewards"]["items"], ("%d:%d"):format(item_id, quantity)) | |
993 end | |
994 end | |
995 | |
996 -- Record time remaining | |
997 entry["estimated_end_time"] = _G.GetServerTime() + ((_G.C_TaskQuest.GetQuestTimeLeftMinutes(quest_id) or 0) * 60) | |
998 end | |
999 end | |
1000 | |
1001 | |
1002 function WDP:ProcessWorldQuests() | |
1003 -- Ignore if player is low level | |
1004 if _G.UnitLevel("player") ~= 110 then return end | |
1005 | |
1006 local current_world_map_id = _G.GetCurrentMapAreaID() | |
1007 | |
1008 -- Iterate over known World Quest maps | |
1009 for i = 1, #private.WORLD_QUEST_MAP_IDS do | |
1010 local world_map_id = private.WORLD_QUEST_MAP_IDS[i] | |
1011 | |
1012 -- Only bother checking the API if the world map in question is currently displayed OR its continent is currently displayed | |
1013 if current_world_map_id == WORLD_MAP_ID_BROKEN_ISLES or current_world_map_id == world_map_id then | |
1014 | |
1015 -- Get data for World Quests on map | |
1016 local api_data = _G.C_TaskQuest.GetQuestsForPlayerByMapID(world_map_id) | |
1017 | |
1018 -- Iterate over the questIDs for each map, doing preload reward requests and creating SavedVariables entries | |
1019 if api_data and type(api_data) == "table" and #api_data > 0 then | |
1020 for j = 1, #api_data do | |
1021 local current_data = api_data[j] | |
1022 | |
1023 -- Check if we had a valid API table returned to us | |
1024 if current_data and type(current_data) == "table" and current_data["questId"] then | |
1025 local quest_id = tonumber(current_data["questId"]) or 0 | |
1026 | |
1027 -- Check if we have quest data | |
1028 if _G.HaveQuestData(quest_id) then | |
1029 local tag_id, tag_name, world_quest_type, rarity, is_elite, tradeskill_line_index = _G.GetQuestTagInfo(quest_id) | |
1030 | |
1031 -- Check for valid questID and whether or not it is a World Quest | |
1032 if quest_id > 0 and world_quest_type ~= nil then | |
1033 _G.C_TaskQuest.RequestPreloadRewardData(quest_id) | |
1034 RecordWorldQuestData(world_map_id, quest_id, current_data) | |
1035 end | |
1036 end | |
1037 end | |
1038 end | |
1039 end | |
1040 end | |
1041 end | |
918 end | 1042 end |
919 | 1043 |
920 | 1044 |
921 local function RecordItemData(item_id, item_link, process_bonus_ids, durability) | 1045 local function RecordItemData(item_id, item_link, process_bonus_ids, durability) |
922 local _, _, item_string = item_link:find("^|%x+|H(.+)|h%[.+%]") | 1046 local _, _, item_string = item_link:find("^|%x+|H(.+)|h%[.+%]") |
1161 | 1285 |
1162 function WDP:ResumeChatLootRecording(event_name) | 1286 function WDP:ResumeChatLootRecording(event_name) |
1163 if block_chat_loot_data then | 1287 if block_chat_loot_data then |
1164 Debug("%s: Resuming chat-based loot recording.", event_name) | 1288 Debug("%s: Resuming chat-based loot recording.", event_name) |
1165 block_chat_loot_data = false | 1289 block_chat_loot_data = false |
1290 end | |
1291 end | |
1292 | |
1293 | |
1294 -- Process world quests if the map is moved to the Broken Isles continent world map (this provides us an opportunity to get data for all zones on the continent without moving the map) | |
1295 function WDP:WORLD_MAP_UPATE(event_name) | |
1296 if _G.GetCurrentMapAreaID() == WORLD_MAP_ID_BROKEN_ISLES and _G.GetServerTime() > (world_quest_event_timestamp + DELAY_PROCESS_WORLD_QUESTS) then | |
1297 world_quest_event_timestamp = _G.GetServerTime() | |
1298 WDP:ProcessWorldQuests() | |
1166 end | 1299 end |
1167 end | 1300 end |
1168 | 1301 |
1169 | 1302 |
1170 -- 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. | 1303 -- 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. |