Compare commits

..

No commits in common. "master" and "newquests" have entirely different histories.

19 changed files with 324206 additions and 633179 deletions

View File

@ -1,4 +1,10 @@
namespace DumpCleaner
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DumpCleaner
{
public static class DumpFiles
{
@ -8,8 +14,6 @@
new DumpData{InputName = "resp.client.handbook.templates", OutputName = "handbook", OutputFolder = "templates"},
new DumpData{InputName = "resp.client.customization", OutputName = "customization", OutputFolder = "templates"},
new DumpData{InputName = "resp.client.account.customization", OutputName = "character", OutputFolder = "templates"},
new DumpData{InputName= "resp.client.achievement.list", OutputName = "achievements", OutputFolder = "templates", SpecialCase = true},
new DumpData{InputName = "resp.client.locale.ru", OutputName = "ru", OutputFolder = "locales\\global"},
new DumpData{InputName = "resp.client.locale.en", OutputName = "en", OutputFolder = "locales\\global"},
new DumpData{InputName = "resp.client.locale.jp", OutputName = "jp", OutputFolder = "locales\\global"},
@ -26,9 +30,6 @@
new DumpData{InputName = "resp.client.locale.sk", OutputName = "sk", OutputFolder = "locales\\global"},
new DumpData{InputName = "resp.client.locale.cz", OutputName = "cz", OutputFolder = "locales\\global"},
new DumpData{InputName = "resp.client.locale.ch", OutputName = "ch", OutputFolder = "locales\\global"},
new DumpData{InputName = "resp.client.locale.ro", OutputName = "ro", OutputFolder = "locales\\global"},
new DumpData{InputName = "resp.client.match.local.start", OutputName = "locations", OutputFolder = "locations", SpecialCase = true},
new DumpData{InputName = "resp.client.menu.locale.en", OutputName = "en", OutputFolder = "locales\\menu"},
@ -47,7 +48,7 @@
new DumpData{InputName = "resp.client.trading.api.traderSettings", OutputName = "traders", OutputFolder = "traders", SpecialCase = true},
new DumpData{InputName= "usec.resp.client.trading.customization", OutputName= "usecsuits", OutputFolder = "traders/5ac3b934156ae10c4430e83c"},
new DumpData{InputName= "bear.resp.client.trading.customization", OutputName= "bearsuits", OutputFolder = "traders/5ac3b934156ae10c4430e83c"},
new DumpData{InputName= "bear.resp.client.trading.customization", OutputName= "bearsuits", OutputFolder = "traders/5ac3b934156ae10c4430e83c"}
};
}

View File

@ -140,8 +140,7 @@ public static class TraderSellCategories
"5b5f757486f774093e6cb507",
"5b5f78e986f77447ed5636b1",
"5b5f78fc86f77409407a7f90"} },
{"638f541a29ffd1183d187f57", new List<string> { } },
{"656f0f98d80a697f855d34b1", new List<string> { } },
{"638f541a29ffd1183d187f57", new List<string> { } }
};
public static List<string> GetCategoriesByTraderId(string id)

View File

@ -1,24 +1,11 @@
using DumpCleaner;
using DumpCleaner.Models;
using QuestValidator.Common;
using QuestValidator.Common.Helpers;
using System.Text.Json;
using System.Text.Json.Nodes;
public class LocationData
{
public LocationData(Location location, object rawLocation)
{
Location = location;
RawLocation = rawLocation;
}
public Location Location { get; set; }
public object RawLocation { get; set; }
}
public class LocationParser
{
private readonly Dictionary<string, LocationData> locations = new Dictionary<string, LocationData>();
private readonly Dictionary<string, Location> locations = new();
private readonly string outputPath;
public LocationParser(string outputPath)
@ -26,10 +13,9 @@ public class LocationParser
this.outputPath = outputPath;
}
internal void AddLocalLootDump(Dump dumpFile, string rawJson)
internal void AddLocalLootDump(Dump dumpFile)
{
var localStart = JsonSerializer.Deserialize<LocalStart>(dumpFile.data.ToString());
var locationData = JsonSerializer.Deserialize<Location>(localStart.locationLoot.ToString());
var locationData = JsonSerializer.Deserialize<Location>(dumpFile.data.ToString());
var locationName = locationData.Id;
// already parsed, skip
@ -41,16 +27,7 @@ public class LocationParser
// remove loot as not needed for base.json
locationData.Loot?.Clear();
// remove loot from raw file
JsonNode? parsedJson = JsonNode.Parse(rawJson);
var data = parsedJson["data"];
var locationLoot = data["locationLoot"];
locationLoot["Loot"] = new JsonArray();
var lootFreeJson = locationLoot.ToString();
locations.Add(locationName, new LocationData(locationData, JsonSerializer.Deserialize<object>(locationLoot)));
locations.Add(locationName, locationData);
}
internal void CreateLocationFile()
@ -58,13 +35,13 @@ public class LocationParser
foreach (var location in locations)
{
if (string.Equals(location.Value.Location.Id, "lighthouse2", StringComparison.CurrentCultureIgnoreCase))
if (string.Equals(location.Value.Id, "lighthouse2", StringComparison.CurrentCultureIgnoreCase))
{
continue;
}
JsonWriter.WriteJson(location.Value.RawLocation, $"{outputPath}/{location.Value.Location.Id.ToLower()}", Directory.GetCurrentDirectory(), "base");
LoggingHelpers.LogToConsole($"Found map file: {location.Value.Location.Id} wrote file to output folder");
JsonWriter.WriteJson(location.Value, $"{outputPath}/{location.Value.Id.ToLower()}", Directory.GetCurrentDirectory(), "base");
LoggingHelpers.LogToConsole($"Found map file: {location.Value.Id} wrote file to output folder");
}
}
}

View File

@ -79,5 +79,4 @@ public class Location
public List<object> Banners { get; set; }
public bool GenerateLocalLootCache { get; set; }
public List<object> AirdropParameters { get; set; }
public bool ForceOnlineRaidInPVE { get; set; }
}

View File

@ -25,11 +25,7 @@ public class Trader
public List<object> loyaltyLevels { get; set; }
public List<string> sell_category { get; set; }
public ItemsBuy items_buy { get; set; }
public bool isCanTransferItems { get; set; }
public ItemsBuy items_buy_prohibited { get; set; }
public object prohibitedTransferableItems { get; set; }
public object transferableItems { get; set; }
public int sell_modifier_for_prohibited_items { get; set; }
}
public class ItemsBuy

View File

@ -32,7 +32,7 @@ foreach (var path in InputFileHelper.GetInputFilePaths())
// Special case, Do special tasks with it
if (names.SpecialCase)
{
HandleSpecialCase(names, dumpFile, rawJson);
HandleSpecialCase(names, dumpFile);
}
else
{
@ -44,25 +44,16 @@ foreach (var path in InputFileHelper.GetInputFilePaths())
locationParser.CreateLocationFile();
void HandleSpecialCase(DumpData names, Dump dumpFile, string rawJson)
void HandleSpecialCase(DumpData names, Dump dumpFile)
{
if (names.InputName == "resp.client.match.local.start")
if (names.InputName == "resp.client.location.getLocalloot")
{
locationParser.AddLocalLootDump(dumpFile, rawJson);
return;
locationParser.AddLocalLootDump(dumpFile);
}
if (names.InputName == "resp.client.trading.api.traderSettings")
{
HandleTraderSettingsFile(names, dumpFile);
return;
}
if (names.InputName == "resp.client.achievement.list")
{
HandleAchievementFile(names, dumpFile);
}
}
@ -98,20 +89,9 @@ void HandleTraderSettingsFile(DumpData names, Dump dumpFile)
foreach (var trader in traders)
{
var traderData = JsonSerializer.Deserialize<Trader>(trader.ToString());
//traderData.sell_category = TraderSellCategories.GetCategoriesByTraderId(traderData._id);
traderData.sell_category = TraderSellCategories.GetCategoriesByTraderId(traderData._id);
JsonWriter.WriteJson(traderData, $"{names.OutputFolder}/{traderData._id}", Directory.GetCurrentDirectory(), "base");
LoggingHelpers.LogToConsole($"Found trader file: {traderData._id} wrote file to output folder");
}
}
void HandleAchievementFile(DumpData names, Dump dumpFile)
{
var achievements = JsonSerializer.Deserialize<Achievements>(dumpFile.data.ToString());
JsonWriter.WriteJson(achievements.elements, $"{names.OutputFolder}", Directory.GetCurrentDirectory(), "achievements");
}
public class Achievements
{
public List<object> elements { get;set;}
}

View File

@ -1,23 +0,0 @@
[
"64b90786bbf5bf2b460ad982",
"64b90792f43eebce7c01e7af",
"64b907978d327e5bf9085bd9",
"64b9079cdd13d43b9d01d6cd",
"64b907a49ff61a79b10fab9c",
"64b907a85e9b86ab7a08cf0d",
"64b907ad60d47bcb98044d10",
"64b907b205b23872610c0794",
"64b907b5b1548514f3015707",
"64b907bae1ed4f11f209e8de",
"64b907bd55f4156df8007d14",
"64b907c29bd0fad76c072e97",
"64b907c4e87866541c0d747e",
"64b907cabbf5bf2b460ad984",
"64b907cef43eebce7c01e7b1",
"64b907d18d327e5bf9085bdb",
"64b907d7dd13d43b9d01d6cf",
"64b907dc9ff61a79b10fab9e",
"64bd4f1d4c2e9f141400bf07",
"63913703e705511c8a4a1b7c"
]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -28,24 +28,24 @@ namespace GenerateQuestFile
InputFileHelper.SetInputFiles(inputPath);
// Read in quest files
var questBlacklist = QuestHelper.GetQuestBlacklist();
var existingQuestData = QuestHelper.GetQuestData();
var liveQuestData = QuestHelper.GetLiveQuestData();
var mergedLiveData = QuestHelper.MergeLiveQuestFiles(liveQuestData, questBlacklist);
var mergedLiveData = QuestHelper.MergeLiveQuestFiles(liveQuestData);
OutputQuestRequirementsToConsole(mergedLiveData.data);
JsonWriter.WriteJson(mergedLiveData, "output", Directory.GetCurrentDirectory(), "mergedlivejson");
JsonWriter.WriteJson<QuestRoot>(mergedLiveData, "output", Directory.GetCurrentDirectory(), "mergedlivejson");
// Find the quests that are missing from the live file from existing quests.json
var missingQuests = GetMissingQuestsNotInLiveFile(existingQuestData, mergedLiveData, questBlacklist);
// Find the quests that are missing from the live file from existing quest data
var missingQuests = GetMissingQuestsNotInLiveFile(existingQuestData, mergedLiveData);
// Create a list of quests to output
// Use all quests in live file
// Use quests from quests.json to fill in missing quests
// Add live quests to collection to return later
var questsToOutputToFile = new Dictionary<string, Quest>();
// Add live quests to collection to return later
foreach (var liveQuest in mergedLiveData.data)
{
questsToOutputToFile.Add(liveQuest._id, liveQuest);
@ -94,10 +94,10 @@ namespace GenerateQuestFile
AddMissingFields(quest);
// Quest has start conditions, check to ensure they're carried over
//if (originalQuest.conditions.AvailableForStart.Count > 0)
//{
// AddMissingAvailableForStartConditions(originalQuest, quest);
//}
if (originalQuest.conditions.AvailableForStart.Count > 0)
{
AddMissingAvailableForStartConditions(originalQuest, quest);
}
if (originalQuest.rewards.Fail.Count > 0)
{
@ -124,23 +124,26 @@ namespace GenerateQuestFile
if (requirement.PreReqType == PreRequisiteType.Quest)
{
// Does quest have requirement
if (!quest.Value.conditions.AvailableForStart.Any(x => x.conditionType == "Quest"
&& x.target.ToString() == requirement.Quest.Id))
if (!quest.Value.conditions.AvailableForStart.Any(x => x._parent == "Quest"
&& x._props.target.ToString() == requirement.Quest.Id))
{
LoggingHelpers.LogSuccess($"{quest.Value.QuestName} needs a prereq of quest {requirement.Quest.Name}, adding.");
string hashData = quest.Value._id + requirement.Quest.Id;
quest.Value.conditions.AvailableForStart.Add(new AvailableFor
{
conditionType = "Quest",
_parent = "Quest",
_props = new AvailableForProps
{
id = Sha256(hashData),
index = GetNextIndex(quest.Value.conditions.AvailableForStart.LastOrDefault()?.index),
index = GetNextIndex(quest.Value.conditions.AvailableForStart.LastOrDefault()?._props?.index),
parentId = "",
status = GetQuestStatus(requirement.QuestStatus),
target = requirement.Quest.Id,
visibilityConditions = new List<object>(),
availableAfter = 0
}
}
);
}
else
@ -155,7 +158,7 @@ namespace GenerateQuestFile
if (requirement.PreReqType == PreRequisiteType.RemoveQuest)
{
if (quest.Value.conditions.AvailableForStart.RemoveAll(x =>
x.conditionType == "Quest" && x.target.ToString() == requirement.Quest.Id) > 0)
x._parent == "Quest" && x._props.target.ToString() == requirement.Quest.Id) > 0)
{
LoggingHelpers.LogSuccess($"{quest.Value.QuestName} required {requirement.Quest.Name}, removing.");
}
@ -163,30 +166,33 @@ namespace GenerateQuestFile
if (requirement.PreReqType == PreRequisiteType.Level)
{
if (!quest.Value.conditions.AvailableForStart.Any(x => x.conditionType == "Level"
&& int.Parse(x.value.ToString()) == requirement.Level))
if (!quest.Value.conditions.AvailableForStart.Any(x => x._parent == "Level"
&& int.Parse(x._props.value.ToString()) == requirement.Level))
{
LoggingHelpers.LogSuccess($"{quest.Value.QuestName} needs a prereq of level {requirement.Level}, adding.");
string hashData = quest.Value._id + "Level";
quest.Value.conditions.AvailableForStart.Add(new AvailableFor
{
conditionType = "Level",
_parent = "Level",
_props = new AvailableForProps
{
id = Sha256(hashData),
index = GetNextIndex(quest.Value.conditions.AvailableForStart.LastOrDefault()?.index),
index = GetNextIndex(quest.Value.conditions.AvailableForStart.LastOrDefault()?._props?.index),
parentId = "",
dynamicLocale = false,
value = requirement.Level,
compareMethod = ">=",
visibilityConditions = new List<object>()
}
}
);
}
}
if (requirement.PreReqType == PreRequisiteType.RemoveLevel)
{
if (quest.Value.conditions.AvailableForStart.RemoveAll(x => x.conditionType == "Level") > 0)
if (quest.Value.conditions.AvailableForStart.RemoveAll(x => x._parent == "Level") > 0)
{
LoggingHelpers.LogSuccess($"{quest.Value.QuestName} required level {requirement.Level}, removing.");
}
@ -209,12 +215,12 @@ namespace GenerateQuestFile
var output = new List<string>();
foreach (var quest in quests)
{
var questConditions = quest.conditions.AvailableForStart.Where(x => x.conditionType == "Quest");
var questConditions = quest.conditions.AvailableForStart.Where(x => x._parent == "Quest");
if (questConditions != null)
{
foreach (var questCondition in questConditions)
{
var x = questCondition.target.ToString();
var x = questCondition._props.target.ToString();
Console.WriteLine($"{QuestHelper.GetQuestNameById(quest._id)} needs {QuestHelper.GetQuestNameById(x)}");
}
}
@ -228,12 +234,12 @@ namespace GenerateQuestFile
var output = new List<string>();
foreach (var quest in quests)
{
var questConditions = quest.Value.conditions.AvailableForStart.Where(x => x.conditionType == "Quest");
var questConditions = quest.Value.conditions.AvailableForStart.Where(x => x._parent == "Quest");
if (questConditions != null)
{
foreach (var questCondition in questConditions)
{
var x = questCondition.target.ToString();
var x = questCondition._props.target.ToString();
Console.WriteLine($"{QuestHelper.GetQuestNameById(quest.Value._id)} needs {QuestHelper.GetQuestNameById(x)}");
}
}
@ -342,12 +348,6 @@ namespace GenerateQuestFile
item._id = originalItem._id;
item.parentId = originalItem.parentId;
}
// Above changes can cause the target and first items id to become mismatched
if (reward.items.FirstOrDefault()._id != reward.target)
{
reward.target = reward.items.FirstOrDefault()._id;
}
}
}
}
@ -369,19 +369,19 @@ namespace GenerateQuestFile
foreach (var condition in conditions)
{
var originalCondition = originalConditions.FirstOrDefault(
x => x.conditionType == condition.conditionType &&
x.index == condition.index &&
StripAllWhitespace(x.target?.ToString()) == StripAllWhitespace(condition.target?.ToString()) &&
x.counter?.id == condition.counter?.id
x => x._parent == condition._parent &&
x._props.index == condition._props.index &&
StripAllWhitespace(x._props.target?.ToString()) == StripAllWhitespace(condition._props.target?.ToString()) &&
x._props.counter?.id == condition._props.counter?.id
);
if (originalCondition == null)
{
LoggingHelpers.LogWarning($"Unable to find matching original condition for {condition.conditionType}-{StripAllWhitespace(condition.target?.ToString())}. Skipping.");
LoggingHelpers.LogWarning($"Unable to find matching original condition for {condition._parent}-{StripAllWhitespace(condition._props.target?.ToString())}. Skipping.");
continue;
}
condition.id = originalCondition.id;
condition._props.id = originalCondition._props.id;
}
}
@ -404,33 +404,33 @@ namespace GenerateQuestFile
// continue;
//}
if (questToUpdate.Value.conditions.AvailableForStart.Any(x => string.Equals(x.conditionType, "quest", StringComparison.CurrentCultureIgnoreCase)))
if (questToUpdate.Value.conditions.AvailableForStart.Any(x => string.Equals(x._parent, "quest", StringComparison.CurrentCultureIgnoreCase)))
{
continue;
}
if (questRequirementToAdd.conditionType == "Quest")
if (questRequirementToAdd._parent == "Quest")
{
LoggingHelpers.LogInfo($"Quest {questToUpdate.Value.QuestName} missing AvailableForStart quest requirement, adding prereq of {questRequirementToAdd.target} {QuestHelper.GetQuestNameById(questRequirementToAdd.target?.ToString())}");
LoggingHelpers.LogInfo($"Quest {questToUpdate.Value.QuestName} missing AvailableForStart quest requirement, adding prereq of {questRequirementToAdd._props.target} {QuestHelper.GetQuestNameById(questRequirementToAdd._props.target?.ToString())}");
if (!questRequirementToAdd.availableAfter.HasValue)
if (!questRequirementToAdd._props.availableAfter.HasValue)
{
questRequirementToAdd.availableAfter = 0;
questRequirementToAdd._props.availableAfter = 0;
}
if (questRequirementToAdd.visibilityConditions == null || !questRequirementToAdd.visibilityConditions.Any())
if (questRequirementToAdd._props.visibilityConditions == null || !questRequirementToAdd._props.visibilityConditions.Any())
{
questRequirementToAdd.visibilityConditions = new List<object>();
questRequirementToAdd._props.visibilityConditions = new List<object>();
}
questRequirementToAdd.index = GetNextIndex(questToUpdate.Value.conditions.AvailableForStart.LastOrDefault()?.index);
questRequirementToAdd._props.index = GetNextIndex(questToUpdate.Value.conditions.AvailableForStart.LastOrDefault()?._props?.index);
}
// Already exists, skip
if (questToUpdate.Value.conditions.AvailableForStart
.Any(x => x.target?.ToString() == questRequirementToAdd.target?.ToString()
&& x.conditionType == questRequirementToAdd.conditionType))
.Any(x => x._props.target?.ToString() == questRequirementToAdd._props.target?.ToString()
&& x._parent == questRequirementToAdd._parent))
{
continue;
}
@ -438,9 +438,9 @@ namespace GenerateQuestFile
questToUpdate.Value.conditions.AvailableForStart.Add(questRequirementToAdd);
}
if (questToUpdate.Value.conditions.AvailableForStart.Count(x => x.conditionType == "Quest") > 1)
if (questToUpdate.Value.conditions.AvailableForStart.Count(x => x._parent == "Quest") > 1)
{
LoggingHelpers.LogWarning($"Quest {questToUpdate.Value.QuestName} has {questToUpdate.Value.conditions.AvailableForStart.Count(x => x.conditionType == "Quest")} quest prereqs, is this correct?");
LoggingHelpers.LogWarning($"Quest {questToUpdate.Value.QuestName} has {questToUpdate.Value.conditions.AvailableForStart.Count(x => x._parent == "Quest")} quest prereqs, is this correct?");
}
}
@ -475,7 +475,7 @@ namespace GenerateQuestFile
/// <summary>
/// Loop over live quests and use if it exists, otherwise use existing data
/// </summary>
private static List<Quest> GetMissingQuestsNotInLiveFile(Dictionary<string, Quest> existingQuests, QuestRoot liveQuestData, List<string> blacklistedQuests)
private static List<Quest> GetMissingQuestsNotInLiveFile(Dictionary<string, Quest> existingQuests, QuestRoot liveQuestData)
{
var missingQuestsToReturn = new List<Quest>();
foreach (var quest in existingQuests.Values)
@ -483,12 +483,6 @@ namespace GenerateQuestFile
var liveQuest = liveQuestData.data.Find(x => x._id == quest._id);
if (liveQuest is null)
{
if (blacklistedQuests.Contains(quest._id))
{
LoggingHelpers.LogInfo($"Skipping quest: {quest.QuestName}");
continue;
}
missingQuestsToReturn.Add(quest);
LoggingHelpers.LogError($"ERROR Quest {quest._id} {QuestHelper.GetQuestNameById(quest._id)} missing in live file. Will use fallback quests.json");
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
using QuestValidator.Common.Helpers;
using QuestValidator.Models;
using QuestValidator.Models.Other;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -15,7 +14,6 @@ namespace AssortGenerator.Common.Helpers
private static List<QuestRoot> _liveQuestData;
private static Dictionary<string, QuestValidator.Models.Quest> _questData;
private static List<string> _questBlacklistData;
private static List<AssortUnlocks> _assortUnlocks;
public static Dictionary<string, QuestValidator.Models.Quest> GetQuestData(string filename = "quests")
@ -40,27 +38,21 @@ namespace AssortGenerator.Common.Helpers
/// </summary>
/// <param name="liveQuestDataFiles"></param>
/// <returns></returns>
public static QuestRoot MergeLiveQuestFiles(List<QuestRoot> liveQuestDataFiles, List<string> questBlacklist)
public static QuestRoot MergeLiveQuestFiles(List<QuestRoot> liveQuestDataFiles)
{
QuestRoot mergedResult = new QuestRoot
{
data = new List<Quest>()
};
QuestRoot mergedResult = null;
foreach (var liveQuestDataFile in liveQuestDataFiles)
{
// If null, use whole file
mergedResult ??= liveQuestDataFile;
foreach (var quest in liveQuestDataFile.data)
{
// Skip quests on blacklist
if (questBlacklist.Contains(quest._id))
{
continue;
}
// Already has quest, skip
var mergedExistingQuest = mergedResult.data.FirstOrDefault(x => x._id == quest._id);
// Already has quest
var mergedExistingQuest = mergedResult.data.Find(x => x._id == quest._id);
if (mergedExistingQuest != null)
{
// new quest has more `avail for start` conditions, use instead
// new quest has more avail for start conditions, use instead
if (mergedExistingQuest.conditions.AvailableForStart.Count < quest.conditions.AvailableForStart.Count)
{
mergedExistingQuest = quest;
@ -68,6 +60,7 @@ namespace AssortGenerator.Common.Helpers
continue;
}
LoggingHelpers.LogWarning($"missing quest {quest._id} {QuestNames.GetNameById(quest._id)} found in subsequent live quest dump");
mergedResult.data.Add(quest);
}
}
@ -75,7 +68,7 @@ namespace AssortGenerator.Common.Helpers
return mergedResult;
}
public static List<QuestRoot> GetLiveQuestData(string filename = "resp.client.quest.list_")
public static List<QuestRoot> GetLiveQuestData(string filename = "resp.client.quest.list")
{
if (_liveQuestData is null)
{
@ -138,22 +131,5 @@ namespace AssortGenerator.Common.Helpers
var filesInPath = Directory.GetFiles(iconPath);
return filesInPath.Any(x => x.Contains(imageId));
}
public static List<string> GetQuestBlacklist()
{
if (_questBlacklistData is null)
{
var questBlacklistPath = InputFileHelper.GetInputFilePaths().FirstOrDefault(x => x.Contains("blacklist"));
if (questBlacklistPath is null)
{
return null;
}
var questBlacklistJson = File.ReadAllText(questBlacklistPath);
_questBlacklistData = JsonSerializer.Deserialize<List<string>>(questBlacklistJson);
}
return _questBlacklistData;
}
}
}

View File

@ -1,6 +1,7 @@
using QuestValidator.Common.Models;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Linq.Expressions;
using System.Threading;
namespace QuestValidator.Common.Helpers
{
@ -9,7 +10,7 @@ namespace QuestValidator.Common.Helpers
private static readonly Dictionary<Quest, string> questLookup = new Dictionary<Quest, string>
{
{ Quest.Debut, "5936d90786f7742b1420ba5b" },
{ Quest.BackgroundCheck, "5936da9e86f7742d65037edf"},
{ Quest.Checking, "5936da9e86f7742d65037edf"},
{ Quest.ShootoutPicnic, "59674cd986f7744ab26e32f2"},
{ Quest.DeliveryFromThePast, "59674eb386f774539f14813a"},
{ Quest.BadRepEvidence, "5967530a86f77462ba22226b"},
@ -193,7 +194,7 @@ namespace QuestValidator.Common.Helpers
{ Quest.HuntsmanPathJustice, "5d25e43786f7740a212217fa"},
{ Quest.HuntsmanPathEvilWatchman, "5d25e44386f77409453bce7b"},
{ Quest.HuntsmanPathFactoryChief, "60c0c018f7afb4354815096a"},
{ Quest.HuntsmanPathEraserP1, "5d25e44f86f77443e625e385"},
{ Quest.HuntsmanPathEraser, "5d25e44f86f77443e625e385"},
{ Quest.HuntsmanPathEraserP2, "5d25e45e86f77408251c4bfa"},
{ Quest.Ambulance, "5d25e46e86f77409453bce7c"},
{ Quest.CourtesyVisit, "5d25e48186f77443e625e386"},
@ -283,7 +284,7 @@ namespace QuestValidator.Common.Helpers
{ Quest.HouseArrestPart1, "639135c3744e452011470807" },
{ Quest.HouseArrestPart2, "639135cd8ba6894d155e77cb" },
{ Quest.Audiophile, "639135bbc115f907b14700a6" },
{ Quest.GloryToCPSUP1, "639135b04ed9512be67647d7" },
{ Quest.GloryToCPSU, "639135b04ed9512be67647d7" },
{ Quest.BalletLover, "639135a7e705511c8a4a1b78" },
{ Quest.YouveGotMail, "6391359b9444fb141f4e6ee6" },
{ Quest.YourCarNeedsAService, "639135534b15ca31f76bc317" },
@ -322,6 +323,7 @@ namespace QuestValidator.Common.Helpers
{ Quest.BestJobInTheWorld, "63a9ae24009ffc6a551631a5" },
{ Quest.BroadcastPart4, "6391372c8ba6894d155e77d7" },
{ Quest.RoadClosed, "639282134ed9512be67647ed"},
{ Quest.MakeAmends, "6391d9144b15ca31f76bc323" },
{ Quest.InformationSource, "63966faeea19ac7ed845db2c" },
{ Quest.MissingInformant, "63966fbeea19ac7ed845db2e" },
{ Quest.Snatch, "63966fccac6f8f3c677b9d89" },
@ -331,164 +333,13 @@ namespace QuestValidator.Common.Helpers
{ Quest.FollowingTheBreadCrumbs, "639670029113f06a7c3b2377" },
{ Quest.Spotter, "6396700fea19ac7ed845db32" },
{ Quest.MakeAnImpression, "6396701b9113f06a7c3b2379" },
{ Quest.TroubleInTheBigCity, "63967028c4a91c5cb76abd81" },
{ Quest.Bloodhounds, "64764abcd125ab430a14ccb5" },
{ Quest.Hint, "647710905320c660d91c15a5" },
{ Quest.ImportantPatient, "641dbfd7f43eda9d810d7137"},
{ Quest.FailedSetup, "64916da7ad4e722c106f2345" },
{ Quest.Hustle, "649567f359eab30d1b7c9585"},
{ Quest.Tourist, "649570491bb4d158bc4d0168" },
{ Quest.CocktailTasting, "649af47d717cb30e7e4b5e26" },
{ Quest.TerraGroupTrailP1, "64b90786bbf5bf2b460ad982"},
{ Quest.TerraGroupTrailP2, "64b90792f43eebce7c01e7af"},
{ Quest.TerraGroupTrailP3, "64b907978d327e5bf9085bd9"},
{ Quest.TerraGroupTrailP4, "64b9079cdd13d43b9d01d6cd"},
{ Quest.TerraGroupTrailP5, "64b907a49ff61a79b10fab9c"},
{ Quest.TerraGroupTrailP6, "64b907a85e9b86ab7a08cf0d"},
{ Quest.TerraGroupTrailP7, "64b907ad60d47bcb98044d10"},
{ Quest.TerraGroupTrailP8, "64b907b205b23872610c0794"},
{ Quest.TerraGroupTrailP9, "64b907b5b1548514f3015707"},
{ Quest.TerraGroupTrailP10, "64b907bae1ed4f11f209e8de"},
{ Quest.TerraGroupTrailP11, "64b907bd55f4156df8007d14"},
{ Quest.TerraGroupTrailP12, "64b907c29bd0fad76c072e97"},
{ Quest.TerraGroupTrailP13, "64b907c4e87866541c0d747e"},
{ Quest.TerraGroupTrailP14, "64b907cabbf5bf2b460ad984"},
{ Quest.TerraGroupTrailP15, "64b907cef43eebce7c01e7b1"},
{ Quest.TerraGroupTrailP16, "64b907d18d327e5bf9085bdb"},
{ Quest.TerraGroupTrailP17, "64b907d7dd13d43b9d01d6cf"},
{ Quest.TerraGroupTrailP18, "64b907dc9ff61a79b10fab9e"},
{ Quest.TerraGroupTrailP19, "64bd4f1d4c2e9f141400bf07"},
{ Quest.MakeAmendsP1, "6391d90f4ed9512be67647df"},
{ Quest.MakeAmendsP2, "6391d912f8e5dd32bf4e3ab2"},
{ Quest.MakeAmendsP2Copy, "6391d9144b15ca31f76bc323"},
{ Quest.HuntsmanPathBigGame, "64e7b971f9d6fa49d6769b44"},
{ Quest.GendarmerieSchoolGuard, "64e7b985e34817363c4684d2"},
{ Quest.GendarmerieMallCop, "64e7b99017ab941a6f7bf9d7"},
{ Quest.GendarmerieTicketsPlease, "64e7b9a4aac4cd0a726562cb"},
{ Quest.GendarmerieDistrictPatrol, "64e7b9bffd30422ed03dad38"},
{ Quest.OutoOfTime, "64edbb1317ab941a6f7cc247"},
{ Quest.BroadcastPart5, "64ee99639878a0569d6ec8c9"},
{ Quest.TheDoor, "64ee9df4496db64f9b7a4432"},
{ Quest.OverseasTrustPart1, "64f1cc571a5f313cb144bf90"},
{ Quest.OverseasTrustPart2, "64f1d6e732bed22c3e0c7423"},
{ Quest.AmbulancesAgain, "64f3176921045e77405d63b5"},
{ Quest.GloryToCPSUP2, "64f5aac4b63b74469b6c14c2"},
{ Quest.TestDriveP3, "64f5deac39e45b527a7c4232"},
{ Quest.BeyondTheRedMeatP1, "64f5e20652fc01298e2c61e3"},
{ Quest.BeyondTheRedMeatP2, "64f6aafd67e11a7c6206e0d0"},
{ Quest.PetsWontNeedItP1, "64f731ab83cfca080a361e42"},
{ Quest.GunsmithP23, "64f83bb69878a0569d6ecfbe"},
{ Quest.GunsmithP24, "64f83bcdde58fc437700d8fa"},
{ Quest.GunsmithP25, "64f83bd983cfca080a362c82"},
{ Quest.ThePunisherHarvest, "655e427b64d09b4122018228"},
{ Quest.ShootingCans, "657315df034d76585f032e01"},
{ Quest.FirstInLine, "657315ddab5a49b71f098853"},
{ Quest.BurningRubber, "657315e270bb0b8dba00cc48"},
{ Quest.SavingTheMole, "657315e4a6af4ab4b50f3459"},
{ Quest.DevelopersSecretsP1, "65733403eefc2c312a759ddb" },
{ Quest.DevelopersSecretsP2, "6573382e557ff128bf3da536" },
{ Quest.LuxuriousLife, "657315e1dccd301f1301416a"},
{ Quest.PyramidScheme, "6572e876dc0d635f633a5714" },
{ Quest.PetsWontNeedItP2, "6573387d0b26ed4fde798de3" },
{ Quest.PropertiesAllAround, "6573397ef3f8344c4575cd87" },
{ Quest.Dandies, "65734c186dc1e402c80dc19e" },
{ Quest.SteadySignal, "6578ec473dbd035d04531a8d" },
{ Quest.NothingFishyAboutThis, "65802b627b44fa5e14638899" },
{ Quest.HuntsmaPathCrookedCop, "6578eb36e5020875d64645cd" },
{ Quest.NoSwiping, "6578eb36e5020875d64645cd"},
{ Quest.EvilSpiritsEvent, "65e85198e32da31f2b30978e"},
{ Quest.TheTarkovMystery, "6603fe74e773dcf3b0099f88"},
{ Quest.DripOutP1, "6613f3007f6666d56807c929"},
{ Quest.DripOutP2, "6613f307fca4f2f386029409" },
{ Quest.TestDriveP4, "6574e0dedc0d635f633a5805" },
{ Quest.Hustle2, "6658a15615cbb1b2c6014d5b" },
{ Quest.EasyMoneyP1, "66058cb22cee99303f1ba067" },
{ Quest.EasyMoneyP2, "66058cb5ae4719735349b9e8" },
{ Quest.BalancingP1, "66058cb7c7f3584787181476" },
{ Quest.BalancingP2, "66058cb9e8e4f17985230805" },
{ Quest.Surprise, "66058cbb06ef1d50a60c1f46" },
{ Quest.CreateADistractionP1, "66058cbd9f59e625462acc8e" },
{ Quest.CreateADistractionP2, "66058cbf2f19c31a5a1337ec" },
{ Quest.ToGreatHeightsP1, "66058cc1da30b620a34e6e86" },
{ Quest.ToGreatHeightsP2, "66058cc208308761cf390993" },
{ Quest.ToGreatHeightsP3, "66058cc5bb83da7ba474aba9" },
{ Quest.ToGreatHeightsP4, "66058cc72cee99303f1ba069" },
{ Quest.ToGreatHeightsP5, "66058cc9ae4719735349b9ea" },
{ Quest.AKeyToSalvation, "6672ec2a2b6f3b71be794cc5" },
{ Quest.ThirstyHounds, "665eeacf5d86b6c8aa03c79b"},
{ Quest.ThirstyBreadwinner, "665eec1f5e47a79f8605565a"},
{ Quest.ImportControl, "668bcccc167d507eb01a268b" },
{ Quest.DripOutP1Bear, "66151401efb0539ae10875ae"},
{ Quest.DripOutP2Bear, "6615141bfda04449120269a7" },
{ Quest.WhatsYourEvidence, "668bccf963acb16d63707043"},
{ Quest.CaughtRedHanded, "668bcd1b194be70f18427a00"},
{ Quest.RisksOfSmallBusiness, "668bcd253e2c5f65cc64d7da"},
{ Quest.ProtectionOfInterests, "668bcd367eb38c3c4d58603c"},
{ Quest.TimeTested, "668bcd6c3e2c5f65cc64d7dc"},
{ Quest.WesternQualityStandards, "668bcd7459a35c28386482d0"},
{ Quest.HighCompetition, "668bf47c781d446fdc083711"},
{ Quest.BadFeeling, "66a1a806bd092031693a6e25" },
{ Quest.GunsmithSpecialOrder, "66a74c628410476dd65543be"},
{ Quest.GunConnoisseur, "66a75b44243a6548ff5e5ff9"},
{ Quest.CustomerCommunication, "66a77394243a6548ff5e601d"},
{ Quest.SupplyAndDemand, "66a78dada472ad7f845b71f7"},
{ Quest.OneLessLooseEnd, "669fa38fad7f1eac2607ed46"},
{ Quest.AHealthyAlternative, "669fa3910c828825de06d69f"},
{ Quest.ExitHere , "669fa395c4c5c04798002497"},
{ Quest.Claustrophobia , "669fa3979b0ce3feae01a130"},
{ Quest.Possessor , "669fa399033a3ce9870338a8"},
{ Quest.BlackSwan , "669fa39b91b0a8c9680fc467"},
{ Quest.HealthCarePrivacyP6 , "669fa3a3ad7f1eac2607ed48"},
{ Quest.RoughTarkov , "66b38c7bf85b8bf7250f9cb6"},
{ Quest.ForklistCertified, "669fa394e0c9f9fafa082897"},
{ Quest.EveryHunterKnowsThis, "66b38e144f2ab7cc530c3fe7"},
{ Quest.PMCsBestFriend, "6512ea46f7a078264a4376e4"},
{ Quest.Traveler, "6512eb3ddfb0ae1ee75a0376"},
{ Quest.KillerOfKillers, "6512f16bde333c33d5127cbc"},
{ Quest.TheWallsHaveEyes, "669fa39c64ea11e84c0642a6"},
{ Quest.AllIsRevealed, "669fa39ee749756c920d02c8"},
{ Quest.Dragnet, "669fa3a08b4a64b332041ff7"},
{ Quest.CapacityCheck, "669fa3a1c26f13bd04030f37"},
//{ "665eec4a4dfc83b0ed0a9dca", "Thirsty - Delivery"},
//{ "665eeca45d86b6c8aa03c79d", "Thirsty - Echo"},
//{ "665eeca92f7aedcc900b0437", "Thirsty - Secrets"},
//{ "66631489acf8442f8b05319f", "Friend Among Strangers"},
//{ "6663148ca9290f9e0806cca1", "Immunity"},
//{ "6663148ed7f171c4c20226c1", "Small Business - Part 1"},
//{ "6663149196a9349baa021baa", "Small Business - Part 2"},
//{ "66631493312343839d032d22", "Small Business - Part 3"},
//{ "6663149cfd5ca9577902e037", "The Invisible Hand"},
//{ "6663149f1d3ec95634095e75", "Circulate"},
//{ "666314a1920800278d0f6746", "Special Offer"},
//{ "666314a31cd52e3d040a2e76", "Combat Proven"},
//{ "666314a50aa5c7436c00908a", "Old Patterns"},
//{ "666314b0acf8442f8b0531a1", "Hell on Earth - Part 1"},
//{ "666314b2a9290f9e0806cca3", "Hell on Earth - Part 2"},
//{ "666314b4d7f171c4c20226c3", "The Good Times - Part 1"},
//{ "666314b696a9349baa021bac", "Quality Standard"},
//{ "666314b8312343839d032d24", "Airmail"},
//{ "666314bafd5ca9577902e03a", "The Good Times - Part 2"},
//{ "666314bc1d3ec95634095e77", "Minute of Fame"},
//{ "666314bd920800278d0f6748", "Viewer"},
//{ "666314bf1cd52e3d040a2e78", "Serious Allegations"},
//{ "666314c10aa5c7436c00908c", "Camera, Action!"},
//{ "666314c3acf8442f8b0531a3", "Proper Comeback"},
//{ "666314c5a9290f9e0806cca5", "Key to the City"},
//{ "6672d9def1c88688a707d042", "Establish Contact"}
{ Quest.TroubleInTheBigCity, "63967028c4a91c5cb76abd81" }
};
private static readonly Dictionary<string, string> questNames = new Dictionary<string, string>
private static readonly Dictionary<string, string> questNames = new Dictionary<string, string>
{
{ "5936d90786f7742b1420ba5b", "Debut" },
{ "5936da9e86f7742d65037edf", "Background Check"},
{ "5936da9e86f7742d65037edf", "Checking"},
{ "59674cd986f7744ab26e32f2", "Shootout picnic"},
{ "59674eb386f774539f14813a", "Delivery from the past"},
{ "5967530a86f77462ba22226b", "Bad rep evidence"},
@ -617,10 +468,10 @@ namespace QuestValidator.Common.Helpers
{ "5b47891f86f7744d1b23c571", "Living high is not a crime" },
{ "5b478b1886f7744d1b23c57d", "Hot delivery"},
{ "5b478d0f86f7744d190d91b5", "Minibus"},
{ "5b478eca86f7744642012254", "Vitamins - Part 1"},
{ "5b478ff486f7744d184ecbbf", "Vitamins - Part 2"},
{ "5b478eca86f7744642012254", "Vitamins Part 1"},
{ "5b478ff486f7744d184ecbbf", "Vitamins Part 2"},
{ "5b47926a86f7747ccc057c15", "Informed means armed"},
{ "5b4794cb86f774598100d5d4", "Lend Lease - Part 1"},
{ "5b4794cb86f774598100d5d4", "Lend lease pt 1"},
{ "5b4795fb86f7745876267770", "Chumming"},
{ "5bc4776586f774512d07cf05", "The Tarkov shooter Part 1"},
{ "5bc479e586f7747f376c7da3", "The Tarkov shooter Part 2"},
@ -630,24 +481,24 @@ namespace QuestValidator.Common.Helpers
{ "5bc4836986f7740c0152911c", "The Tarkov shooter Part 6"},
{ "5bc4856986f77454c317bea7", "The Tarkov shooter Part 7"},
{ "5bc4893c86f774626f5ebf3e", "The Tarkov shooter Part 8"},
{ "5c0bbaa886f7746941031d82", "Bullshit"},
{ "5c0bc91486f7746ab41857a2", "Silent caliber"},
{ "5c0bd01e86f7747cdd799e56", "Insomnia"},
{ "5c0bd94186f7747a727f09b2", "Test drive - Part 1"},
{ "5c0bdb5286f774166e38eed4", "Flint"},
{ "5c0bde0986f77479cf22c2f8", "A Shooter Born in Heaven"},
{ "5c0be13186f7746f016734aa", "Psycho Sniper"},
{ "5c0be5fc86f774467a116593", "Private clinic"},
{ "5c0bbaa886f7746941031d82", "Bullshit" },
{ "5c0bc91486f7746ab41857a2", "Silent caliber" },
{ "5c0bd01e86f7747cdd799e56", "Insomnia" },
{ "5c0bd94186f7747a727f09b2", "Test drive Part 1" },
{ "5c0bdb5286f774166e38eed4", "Flint" },
{ "5c0bde0986f77479cf22c2f8", "A Shooter Born in Heaven" },
{ "5c0be13186f7746f016734aa", "Psycho Sniper" },
{ "5c0be5fc86f774467a116593", "Private clinic" },
{ "5c0d0d5086f774363760aef2", "Athlete" },
{ "5c0d0f1886f77457b8210226", "Lend lease - Part 2" },
{ "5c0d0f1886f77457b8210226", "Lend lease Part 2" },
{ "5c0d190cd09282029f5390d8", "Grenadier" },
{ "5c0d1c4cd0928202a02a6f5c", "Decontamination service" },
{ "5c0d4c12d09282029f539173", "Peacekeeping mission" },
{ "5c0d4e61d09282029f53920e", "The guide" },
{ "5c10f94386f774227172c572", "The Blood of War - Part 3" },
{ "5c10f94386f774227172c572", "The Blood of War Part 3" },
{ "5c1128e386f7746565181106", "Fertilizers" },
{ "5c112d7e86f7740d6f647486", "Scavenger" },
{ "5c1141f386f77430ff393792", "Living high is not a crime - Part 2"},
{ "5c1141f386f77430ff393792", "Living high is not a crime Part 2"},
{ "5c1234c286f77406fa13baeb", "Setup" },
{ "5c12452c86f7744b83469073", "Perfect mediator" },
{ "5c139eb686f7747878361a6f", "Import" },
@ -655,12 +506,12 @@ namespace QuestValidator.Common.Helpers
{ "5d2495a886f77425cd51e403", "Introduction" },
{ "5d24b81486f77439c92d6ba8", "Acquaintance" },
{ "5d25aed386f77442734d25d2", "The survivalist path Unprotected but dangerous"},
{ "5d25b6be86f77444001e1b89", "The survivalist path Thrifty"},
{ "5d25bfd086f77442734d3007", "The survivalist path Zhivchik"},
{ "5d25c81b86f77443e625dd71", "The survivalist path Wounded beast"},
{ "5d25cf2686f77443e75488d4", "The survivalist path Tough guy"},
{ "5d25d2c186f77443e35162e5", "The survivalist path Cold blooded"},
{ "5d25dae186f77443e55d2f78", "The survivalist path Zatoichi"},
{ "5d25b6be86f77444001e1b89", "The survivalist path Thrifty" },
{ "5d25bfd086f77442734d3007", "The survivalist path Zhivchik" },
{ "5d25c81b86f77443e625dd71", "The survivalist path Wounded beast" },
{ "5d25cf2686f77443e75488d4", "The survivalist path Tough guy" },
{ "5d25d2c186f77443e35162e5", "The survivalist path Cold blooded" },
{ "5d25dae186f77443e55d2f78", "The survivalist path Zatoichi" },
{ "5d25e29d86f7740a22516326", "The survivalist path Eagle-owl" },
{ "5d25e2a986f77409dd5cdf2a", "The survivalist path Combat medic" },
{ "5eaaaa7c93afa0558f3b5a1c", "The survivalist path Junkie" },
@ -673,8 +524,8 @@ namespace QuestValidator.Common.Helpers
{ "5d25e43786f7740a212217fa", "Huntsman path Justice" },
{ "5d25e44386f77409453bce7b", "Huntsman path Evil watchman" },
{ "60c0c018f7afb4354815096a", "Huntsman Path- Factory Chief"},
{ "5d25e44f86f77443e625e385", "Huntsman path Eraser - Part 1"},
{ "5d25e45e86f77408251c4bfa", "Huntsman path Eraser- Part 2"},
{ "5d25e44f86f77443e625e385", "Huntsman path Eraser Part 1"},
{ "5d25e45e86f77408251c4bfa", "Huntsman path Eraser Part 2"},
{ "5edab4b1218d181e29451435", "Huntsman path Sadist"},
{ "60e71e8ed54b755a3b53eb67", "Huntsman Path - Relentless" },
{ "5d25e46e86f77409453bce7c", "Ambulance"},
@ -692,12 +543,12 @@ namespace QuestValidator.Common.Helpers
{ "5e4d4ac186f774264f758336", "Textile Part 2 - Bear"},
{ "5e383a6386f77465910ce1f3", "Textile Part 1 - Usec"},
{ "5e4d515e86f77438b2195244", "Textile Part 2 - Usec"},
{ "5ede55112c95834b583f052a", "Bunker - Part 1"},
{ "5ede567cfa6dc072ce15d6e3", "Bunker - Part 2"},
{ "5ede55112c95834b583f052a", "Bunker Part 1"},
{ "5ede567cfa6dc072ce15d6e3", "Bunker Part 2"},
{ "5eda19f0edce541157209cee", "Anesthesia"},
{ "5edab736cc183c769d778bc2", "Colleagues - Part 1"},
{ "5edaba7c0c502106f869bc02", "Colleagues - Part 2"},
{ "5edac34d0bb72a50635c2bfa", "Colleagues - Part 3"},
{ "5edab736cc183c769d778bc2", "Colleagues Part 1"},
{ "5edaba7c0c502106f869bc02", "Colleagues Part 2"},
{ "5edac34d0bb72a50635c2bfa", "Colleagues Part 3"},
{ "5edabd13218d181e29451442", "Rigged game"},
{ "5edac020218d181e29451446", "Samples"},
{ "5edac63b930f5454f51e128b", "TerraGroup employee"},
@ -757,7 +608,7 @@ namespace QuestValidator.Common.Helpers
{ "60e71ccb5688f6424c7bfec4", "Trophies" },
{ "60e71c9ad54b755a3b53eb66", "The Cleaner" },
{ "60e71ce009d7c801eb0c0ec6", "Special Equipment" },
{ "636a2f5759cb834f8a5825d6", "Letters-Event"},
{ "636a2f5759cb834f8a5825d6", "EVENT - Letters"},
{ "639135d89444fb141f4e6eea", "Population Census"},
{ "639135e0fa894f0a866afde6", "Urban Medicine"},
{ "639135c3744e452011470807", "House Arrest - Part 1"},
@ -788,7 +639,6 @@ namespace QuestValidator.Common.Helpers
{ "625d70031ed3bb5bcc5bd9e5", "Key to the Tower"},
{ "625d7005a4eb80027c4f2e09", "Knock - Knock"},
{ "625d700cc48e6c62a440fab5", "Getting Acquainted"},
{ "6391d90f4ed9512be67647df", "Make Amends P1"},
{ "626148251ed3bb5bcc5bd9ed", "Make Amends - Buyout"},
{ "6261482fa4eb80027c4f2e11", "Make Amends - Equipment"},
{ "626148334149f1149b5b12ca", "Make Amends - Security"},
@ -804,8 +654,7 @@ namespace QuestValidator.Common.Helpers
{ "63a9ae24009ffc6a551631a5", "Best Job in the World" },
{ "6391372c8ba6894d155e77d7", "Broadcast - Part 4"},
{ "639282134ed9512be67647ed", "Road Closed" },
{ "6391d912f8e5dd32bf4e3ab2", "Make Amends p2"},
{ "6391d9144b15ca31f76bc323", "Make Amends p2 copy"},
{ "6391d9144b15ca31f76bc323", "Make Amends"},
{ "63966faeea19ac7ed845db2c", "Information Source"},
{ "63966fbeea19ac7ed845db2e", "Missing Informant"},
{ "63966fccac6f8f3c677b9d89", "Snatch"},
@ -815,155 +664,7 @@ namespace QuestValidator.Common.Helpers
{ "639670029113f06a7c3b2377", "Following the Bread Crumbs"},
{ "6396700fea19ac7ed845db32", "Spotter"},
{ "6396701b9113f06a7c3b2379", "Make an Impression"},
{ "63967028c4a91c5cb76abd81", "Trouble in the Big City"},
{ "64764abcd125ab430a14ccb5", "Bloodhounds-Event" },
{ "647710905320c660d91c15a5", "Hint-Event" },
{ "641dbfd7f43eda9d810d7137", "Important Patient-Event" },
{ "64916da7ad4e722c106f2345", "Failed setup-Event" },
{ "649567f359eab30d1b7c9585", "Hustle-Event"},
{ "649570491bb4d158bc4d0168", "Tourist-Event"},
{ "649af47d717cb30e7e4b5e26", "Cocktail Tasting-Event" },
{ "64b90786bbf5bf2b460ad982", "TerraGroup Trail Part 1-Event" },
{ "64b90792f43eebce7c01e7af", "TerraGroup Trail Part 2-Event" },
{ "64b907978d327e5bf9085bd9", "TerraGroup Trail Part 3-Event" },
{ "64b9079cdd13d43b9d01d6cd", "TerraGroup Trail Part 4-Event" },
{ "64b907a49ff61a79b10fab9c", "TerraGroup Trail Part 5-Event" },
{ "64b907a85e9b86ab7a08cf0d", "TerraGroup Trail Part 6-Event" },
{ "64b907ad60d47bcb98044d10", "TerraGroup Trail Part 7-Event" },
{ "64b907b205b23872610c0794", "TerraGroup Trail Part 8-Event" },
{ "64b907b5b1548514f3015707", "TerraGroup Trail Part 9-Event" },
{ "64b907bae1ed4f11f209e8de", "TerraGroup Trail Part 10-Event" },
{ "64b907bd55f4156df8007d14", "TerraGroup Trail Part 11-Event" },
{ "64b907c29bd0fad76c072e97", "TerraGroup Trail Part 12-Event" },
{ "64b907c4e87866541c0d747e", "TerraGroup Trail Part 13-Event" },
{ "64b907cabbf5bf2b460ad984", "TerraGroup Trail Part 14-Event" },
{ "64b907cef43eebce7c01e7b1", "TerraGroup Trail Part 15-Event" },
{ "64b907d18d327e5bf9085bdb", "TerraGroup Trail Part 16-Event" },
{ "64b907d7dd13d43b9d01d6cf", "TerraGroup Trail Part 17-Event" },
{ "64b907dc9ff61a79b10fab9e", "TerraGroup Trail Part 18-Event" },
{ "64bd4f1d4c2e9f141400bf07", "TerraGroup Trail Part 19-Event" },
{ "64e7b971f9d6fa49d6769b44", "Huntsman Path Big Game"},
{ "64e7b985e34817363c4684d2", "Gendarmerie School Guard"},
{ "64e7b99017ab941a6f7bf9d7", "Gendarmerie Mall Cop"},
{ "64e7b9a4aac4cd0a726562cb", "Gendarmerie Tickets Please"},
{ "64e7b9bffd30422ed03dad38", "Gendarmerie District Patrol"},
{ "64edbb1317ab941a6f7cc247", "Out Of Time"},
{ "64ee99639878a0569d6ec8c9", "Broadcast Part 5"},
{ "64ee9df4496db64f9b7a4432", "The Door"},
{ "64f1cc571a5f313cb144bf90", "Overseas trust. Part 1"},
{ "64f1d6e732bed22c3e0c7423", "Overseas trust. Part 2"},
{ "64f3176921045e77405d63b5", "Ambulances Again"},
{ "64f5aac4b63b74469b6c14c2", "Glory To CPSU P2"},
{ "64f5deac39e45b527a7c4232", "Test Drive - Part 3"},
{ "64f5e20652fc01298e2c61e3", "Beyond The RedMeat P1"},
{ "64f6aafd67e11a7c6206e0d0", "Beyond The RedMeat P2"},
{ "64f731ab83cfca080a361e42", "Pets Wont Need It P1"},
{ "64f83bb69878a0569d6ecfbe", "Gunsmith Part 23"},
{ "64f83bcdde58fc437700d8fa", "Gunsmith Part 24"},
{ "64f83bd983cfca080a362c82", "Gunsmith Part 25"},
{ "655e427b64d09b4122018228", "The Punisher - Harvest - Event"},
{ "657315df034d76585f032e01", "Shooting Cans"},
{ "657315ddab5a49b71f098853", "First In Line"},
{ "657315e270bb0b8dba00cc48", "Burning Rubber"},
{ "657315e4a6af4ab4b50f3459", "Saving The Mole"},
{ "65733403eefc2c312a759ddb", "Developers Secrets Part 1" },
{ "6573382e557ff128bf3da536", "Developers Secrets Part 2" },
{ "657315e1dccd301f1301416a", "Luxurious Life"},
{ "6572e876dc0d635f633a5714", "Pyramid Scheme" },
{ "6573387d0b26ed4fde798de3", "Pets Wont Need It Part 2" },
{ "6573397ef3f8344c4575cd87", "Properties All Around" },
{ "65734c186dc1e402c80dc19e", "Dandies" },
{ "6578ec473dbd035d04531a8d", "Steady Signal" },
{ "65802b627b44fa5e14638899", "Nothing Fishy About This" },
{ "6578eb36e5020875d64645cd", "Huntsman Path Crooked Cop" },
{ "658027799634223183395339", "No Swiping" },
{ "65e85198e32da31f2b30978e", "Evil Spirits - Event" },
{ "6603fe74e773dcf3b0099f88", "The Tarkov Mystery"},
{ "6613f3007f6666d56807c929", "Drip Out Part 1" },
{ "6613f307fca4f2f386029409", "Drip Out Part 2" },
{ "6574e0dedc0d635f633a5805", "Test Drive - Part 4"},
{ "6658a15615cbb1b2c6014d5b", "Hustle2" },
{ "66058cb22cee99303f1ba067", "EasyMoney Part 1" },
{ "66058cb5ae4719735349b9e8", "EasyMoney Part 2" },
{ "66058cb7c7f3584787181476", "Balancing Part 1" },
{ "66058cb9e8e4f17985230805", "Balancing Part 2" },
{ "66058cbb06ef1d50a60c1f46", "Surprise" },
{ "66058cbd9f59e625462acc8e", "Create A Distraction Part 1" },
{ "66058cbf2f19c31a5a1337ec", "Create A Distraction Part 2" },
{ "66058cc1da30b620a34e6e86", "To Great Heights Part 1" },
{ "66058cc208308761cf390993", "To Great Heights Part 2" },
{ "66058cc5bb83da7ba474aba9", "To Great Heights Part 3" },
{ "66058cc72cee99303f1ba069", "To Great Heights Part 4" },
{ "66058cc9ae4719735349b9ea", "To Great Heights Part 5" },
{ "665eeacf5d86b6c8aa03c79b", "Thirsty - Hounds"},
{ "665eec1f5e47a79f8605565a", "Thirsty - Breadwinner"},
{ "665eec4a4dfc83b0ed0a9dca", "Thirsty - Delivery"},
{ "665eeca45d86b6c8aa03c79d", "Thirsty - Echo"},
{ "665eeca92f7aedcc900b0437", "Thirsty - Secrets"},
{ "66631489acf8442f8b05319f", "Friend Among Strangers"},
{ "6663148ca9290f9e0806cca1", "Immunity"},
{ "6663148ed7f171c4c20226c1", "Small Business - Part 1"},
{ "6663149196a9349baa021baa", "Small Business - Part 2"},
{ "66631493312343839d032d22", "Small Business - Part 3"},
{ "6663149cfd5ca9577902e037", "The Invisible Hand"},
{ "6663149f1d3ec95634095e75", "Circulate"},
{ "666314a1920800278d0f6746", "Special Offer"},
{ "666314a31cd52e3d040a2e76", "Combat Proven"},
{ "666314a50aa5c7436c00908a", "Old Patterns"},
{ "666314b0acf8442f8b0531a1", "Hell on Earth - Part 1"},
{ "666314b2a9290f9e0806cca3", "Hell on Earth - Part 2"},
{ "666314b4d7f171c4c20226c3", "The Good Times - Part 1"},
{ "666314b696a9349baa021bac", "Quality Standard"},
{ "666314b8312343839d032d24", "Airmail"},
{ "666314bafd5ca9577902e03a", "The Good Times - Part 2"},
{ "666314bc1d3ec95634095e77", "Minute of Fame"},
{ "666314bd920800278d0f6748", "Viewer"},
{ "666314bf1cd52e3d040a2e78", "Serious Allegations"},
{ "666314c10aa5c7436c00908c", "Camera, Action!"},
{ "666314c3acf8442f8b0531a3", "Proper Comeback"},
{ "666314c5a9290f9e0806cca5", "Key to the City"},
{ "6672d9def1c88688a707d042", "Establish Contact"},
{ "668bcccc167d507eb01a268b", "Import Control" },
{ "6672ec2a2b6f3b71be794cc5", "A Key to Salvation" },
{ "66151401efb0539ae10875ae", "Drip out - Part 1 BEAR"},
{ "6615141bfda04449120269a7", "Drip out - Part 2 BEAR"},
{ "668bccf963acb16d63707043", "Whats your evidence?"},
{ "668bcd1b194be70f18427a00", "Caught Red-Handed"},
{ "668bcd253e2c5f65cc64d7da", "Risks Of Small Business - EVENT"},
{ "668bcd367eb38c3c4d58603c", "Protection Of Interests - EVENT"},
{ "668bcd6c3e2c5f65cc64d7dc", "Time Tested - EVENT"},
{ "668bcd7459a35c28386482d0","Western Quality Standards - EVENT"},
{ "668bf47c781d446fdc083711", "High Competition - EVENT"},
{ "66a1a806bd092031693a6e25", "Bad Feeling - EVENT" },
{ "66a74c628410476dd65543be", "Gunsmith Special Order - EVENT"},
{ "66a75b44243a6548ff5e5ff9", "Gun Connoisseur - EVENT"},
{ "66a77394243a6548ff5e601d", "Customer Communication - EVENT"},
{ "66a78dada472ad7f845b71f7", "Supply And Demand - EVENT"},
{ "669fa38fad7f1eac2607ed46", "One Less Loose End"},
{ "669fa3910c828825de06d69f", "A Healthy Alternative"},
{ "669fa395c4c5c04798002497", "Exit Here"},
{ "669fa3979b0ce3feae01a130", "Claustrophobia"},
{ "669fa399033a3ce9870338a8", "Possessor"},
{ "669fa39b91b0a8c9680fc467", "BlackSwan"},
{ "669fa3a3ad7f1eac2607ed48", "Health Care Privacy P6"},
{ "66b38c7bf85b8bf7250f9cb6", "Rough Tarkov"},
{ "669fa394e0c9f9fafa082897", "Forklift Certified"},
{ "66b38e144f2ab7cc530c3fe7", "Every Hunter Knows This"},
{ "6512ea46f7a078264a4376e4", "PMCs Best Friend"},
{ "6512eb3ddfb0ae1ee75a0376", "Traveler"},
{ "6512f16bde333c33d5127cbc", "Killer Of Killers"},
{ "65f30eb9b079ea68582f97b0", "Some event quest?"},
{ "65e851a98f0b5f70ff393d90", "Some event quest?"},
{ "669fa39c64ea11e84c0642a6", "The Walls Have Eyes"},
{ "669fa39ee749756c920d02c8", "All Is Revealed"},
{ "669fa3a08b4a64b332041ff7", "Dragnet"},
{ "669fa3a1c26f13bd04030f37", "Capacity Check"}
{ "63967028c4a91c5cb76abd81", "Trouble in the Big City"}
};
public static string GetNameById(string id)
{

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
{
NOQUESTFOUND = 0,
Debut = 1,
BackgroundCheck = 2,
Checking = 2,
ShootoutPicnic = 3,
DeliveryFromThePast = 4,
BadRepEvidence = 5,
@ -182,7 +182,7 @@
HuntsmanPathJustice = 176,
HuntsmanPathEvilWatchman = 177,
HuntsmanPathFactoryChief = 178,
HuntsmanPathEraserP1 = 179,
HuntsmanPathEraser = 179,
HuntsmanPathEraserP2 = 180,
HuntsmanPathSadist = 197,
HuntsmanPathRelentless = 220,
@ -271,7 +271,7 @@
HouseArrestPart1 = 266,
HouseArrestPart2 = 267,
Audiophile = 268,
GloryToCPSUP1 = 269,
GloryToCPSU = 269,
BalletLover = 270,
YouveGotMail = 271,
YourCarNeedsAService = 272,
@ -328,124 +328,6 @@
FollowingTheBreadCrumbs = 323,
Spotter = 324,
MakeAnImpression = 325,
TroubleInTheBigCity = 326,
Bloodhounds = 327,
Hint = 328,
ImportantPatient = 329,
FailedSetup = 330,
Hustle = 331,
Tourist = 332,
CocktailTasting = 333,
TerraGroupTrailP1 = 334,
TerraGroupTrailP2 = 335,
TerraGroupTrailP3 = 336,
MakeAmendsP1 = 337,
MakeAmendsP2 = 338,
MakeAmendsP2Copy = 339,
TerraGroupTrailP4 = 340,
TerraGroupTrailP5 = 341,
TerraGroupTrailP6 = 342,
TerraGroupTrailP7 = 343,
TerraGroupTrailP8 = 344,
TerraGroupTrailP9 = 345,
TerraGroupTrailP10 = 346,
TerraGroupTrailP11 = 347,
TerraGroupTrailP12 = 348,
TerraGroupTrailP13 = 349,
TerraGroupTrailP14 = 350,
TerraGroupTrailP15 = 351,
TerraGroupTrailP16 = 352,
TerraGroupTrailP17 = 353,
TerraGroupTrailP18 = 354,
TerraGroupTrailP19 = 355,
HuntsmanPathBigGame = 356,
GendarmerieSchoolGuard = 357,
GendarmerieMallCop = 358,
GendarmerieTicketsPlease = 359,
GendarmerieDistrictPatrol = 360,
OutoOfTime = 361,
BroadcastPart5 = 362,
TheDoor = 363,
OverseasTrustPart1 = 364,
OverseasTrustPart2 = 365,
AmbulancesAgain = 366,
GloryToCPSUP2 = 367,
SecretComponent = 368,
TestDriveP3 = 369,
BeyondTheRedMeatP1 = 370,
BeyondTheRedMeatP2 = 371,
PetsWontNeedItP1 = 372,
GunsmithP23 = 373,
GunsmithP24 = 374,
GunsmithP25 =375,
ThePunisherHarvest = 376,
ShootingCans = 377,
FirstInLine = 378,
BurningRubber = 379,
SavingTheMole = 380,
DevelopersSecretsP1 = 381,
DevelopersSecretsP2 = 382,
LuxuriousLife = 383,
PyramidScheme = 384,
PetsWontNeedItP2 = 385,
PropertiesAllAround = 386,
Dandies = 387,
SteadySignal = 388,
NothingFishyAboutThis = 389,
HuntsmaPathCrookedCop = 390,
NoSwiping = 391,
EvilSpiritsEvent = 392,
TheTarkovMystery = 393,
DripOutP1 = 394,
DripOutP2 = 395,
TestDriveP4 = 396,
Hustle2 = 397,
EasyMoneyP1 = 398,
EasyMoneyP2 = 399,
BalancingP1 = 400,
BalancingP2 = 401,
Surprise = 402,
CreateADistractionP1 = 403,
CreateADistractionP2 = 404,
ToGreatHeightsP1 = 405,
ToGreatHeightsP2 = 406,
ToGreatHeightsP3 = 407,
ToGreatHeightsP4 = 408,
ToGreatHeightsP5 = 409,
AKeyToSalvation = 410,
ThirstyHounds = 411,
ThirstyBreadwinner = 412,
ImportControl = 413,
DripOutP1Bear = 414,
DripOutP2Bear = 415,
WhatsYourEvidence = 416,
CaughtRedHanded = 417,
RisksOfSmallBusiness,
ProtectionOfInterests,
TimeTested,
WesternQualityStandards,
HighCompetition,
BadFeeling,
GunsmithSpecialOrder,
GunConnoisseur,
CustomerCommunication,
SupplyAndDemand,
OneLessLooseEnd,
AHealthyAlternative,
ExitHere,
Claustrophobia,
Possessor,
BlackSwan,
HealthCarePrivacyP6,
RoughTarkov,
ForklistCertified,
EveryHunterKnowsThis,
PMCsBestFriend,
Traveler,
KillerOfKillers,
TheWallsHaveEyes,
AllIsRevealed,
Dragnet,
CapacityCheck
TroubleInTheBigCity = 326
}
}

View File

@ -17,10 +17,9 @@ namespace QuestValidator.Models
public string acceptPlayerMessage { get;set;}
public string changeQuestMessageText { get;set;}
public string completePlayerMessage { get; set; }
public QuestConditions conditions { get; set; }
public Conditions conditions { get; set; }
public string description { get;set;}
public string failMessageText { get; set; }
public string declinePlayerMessage { get; set; }
public string name { get; set; }
public string note { get; set; }
public object? questStatus { get;set; }
@ -36,22 +35,36 @@ namespace QuestValidator.Models
public string successMessageText { get; set; }
public string templateId { get; set; }
public Rewards rewards { get; set; }
public string? side { get; set; }
public object acceptanceAndFinishingSource { get; set; }
public object progressSource { get; set; }
public object rankingModes { get; set; }
public object gameModes { get; set; }
public object arenaLocations { get; set; }
public object status { get; set; }
}
public class QuestConditions
public class Conditions
{
public string _parent { get; set; }
public ConditionProps _props { get; set; }
public List<AvailableFor> AvailableForFinish { get; set; }
public List<AvailableFor> AvailableForStart { get; set; }
public List<AvailableFor> Fail { get; set; }
}
public class ConditionProps
{
public string compareMethod { get; set; }
public string id { get; set; }
public object target { get; set; }
public string value { get; set; }
public Counter counter { get; set; }
public int index { get; set; }
public string parentId { get; set; }
public string type { get; set; }
public int? dogtagLevel { get; set; }
public object maxDurability { get; set; }
public int? minDurability { get; set; }
public List<object> visibilityConditions { get; set; }
public List<int> status { get; set; }
}
public class Counter
{
public string id { get; set; }
@ -60,36 +73,39 @@ namespace QuestValidator.Models
public class AvailableFor
{
public int? areaType { get; set; }
public int? completeInSeconds { get; set; }
public string conditionType { get; set; }
public Counter counter { get; set; }
public object dogtagLevel { get; set; }
public string _parent { get; set; }
public AvailableForProps _props { get; set; }
public bool dynamicLocale { get;set;}
}
public class AvailableForProps
{
public Counter counter { get; set;}
public int? dogtagLevel { get; set; }
public string id { get; set; }
public int? index { get; set; }
public object maxDurability { get; set; }
public object minDurability { get; set; }
public string parentId { get; set; }
public bool? resetOnSessionEnd { get; set; }
public bool? isEncoded { get; set; }
public bool? isEncoded { get;set; }
public bool? onlyFoundInRaid { get; set; }
public bool? oneSessionOnly { get; set; }
public bool dynamicLocale { get; set; }
public bool dynamicLocale { get;set;}
public object? plantTime { get; set; }
public string zoneId { get; set; }
public object target { get; set; }
public string type { get; set; }
public bool? countInRaid { get; set; }
public object status { get; set; }
public string type { get;set;}
public bool? countInRaid { get;set;}
public object status { get; set;}
public bool? unknown { get; set; }
public bool? doNotResetIfCounterCompleted { get; set; }
public string globalQuestCounterId { get; set; }
public object value { get; set; }
public int? availableAfter { get; set; }
public int? dispersion { get; set; }
public string compareMethod { get; set; }
public string compareMethod { get;set;}
public List<object> visibilityConditions { get; set; }
public SkillCondition baseAccuracy { get; set; }
public SkillCondition baseAccuracy { get;set;}
public SkillCondition durability { get; set; }
public SkillCondition effectiveDistance { get; set; }
public SkillCondition emptyTacticalSlot { get; set; }
@ -102,11 +118,6 @@ namespace QuestValidator.Models
public SkillCondition width { get; set; }
public object containsItems { get; set; }
public object hasItemFromCategory { get; set; }
public string traderId { get; set; }
public bool? isNecessary { get; set; }
public bool? isResetOnConditionFailed { get; set; }
public object illustrationConfig { get; set; }
public bool? isHidden { get; set; }
}
public class SkillCondition
@ -124,8 +135,6 @@ namespace QuestValidator.Models
public class RewardStatus
{
public object availableInGameEditions { get; set; }
public object notAvailableInGameEditions { get; set; }
public object value { get; set; }
public string id { get; set; }
public string type { get; set; }
@ -135,7 +144,7 @@ namespace QuestValidator.Models
public bool? findInRaid {get; set;}
public List<QuestRewardItem> items { get; set; }
public int? loyaltyLevel { get; set; }
public object traderId { get; set; }
public string traderId { get; set; }
}
public class QuestRewardItem
@ -150,9 +159,9 @@ namespace QuestValidator.Models
public class QuestRewardUpd
{
public int? StackObjectsCount { get; set; }
public object FireMode { get; set; }
public object Foldable { get; set; }
public object? SpawnedInSession { get; set; }
public FireModeReward FireMode { get; set; }
public FoldeableReward Foldable { get; set; }
public bool? SpawnedInSession { get; set; }
public object? Repairable { get; set; }
}

View File

@ -1,20 +1,23 @@
# ChompQuestVerifier
# Dump cleaner
### Clean up raw EFT dump JSONs into files usable by SPT
TODO: write details
# Generate Quest File
### Create a quest file for use by SPT by providing a raw quest dump JSON as input
## How to use
1. Build GenerateQuestFile project
2. Copy your aki quests.json into `ChompQuestVerifier\GenerateQuestFile\bin\Debug\net6.0\input` create the input folder if necessary
3. Copy your `resp.client.quest.list.xxx` file into the above folder
4. Run `GenerateQuestFile.exe`
5. Your completed `quests.json` is written to `output` folder
TODO: write details
# Quest Validator
### Verifies an SPT quest JSON against a live dump of quest data
Verifies an aki quest json against a live dump of quest data
## How to use
1. Copy your aki quests.json into QuestValidator\bin\Debug\net6.0\input
2. Copy a live quest file dump (resp.client.quest.list_xxxx) into QuestValidator\bin\Debug\net6.0\input
3. Run QuestValidator project to generate a list of warnings found in aki quests.json, separated by quest.
Use the example dump file found in QuestValidator/Examples if you dont have a live quest dump file