From d259bf3fb933f25564875c9c162559029f5704e2 Mon Sep 17 00:00:00 2001 From: DrakiaXYZ <565558+TheDgtl@users.noreply.github.com> Date: Wed, 10 May 2023 20:34:30 -0700 Subject: [PATCH] - Add a few missing properties in QuestRewardUpd - Make quest diffs more deterministic by copying IDs from previous quest.json files where possible, and generating deterministic random IDs when we need new ones --- GenerateQuestFile/Program.cs | 92 +++++++++++++++++++++++++++- QuestValidator.Models/Input/Quest.cs | 2 + 2 files changed, 91 insertions(+), 3 deletions(-) diff --git a/GenerateQuestFile/Program.cs b/GenerateQuestFile/Program.cs index 94c15fc..595a737 100644 --- a/GenerateQuestFile/Program.cs +++ b/GenerateQuestFile/Program.cs @@ -103,6 +103,9 @@ namespace GenerateQuestFile { AddMissingFailRewards(originalQuest, quest); } + + // To make diffs more sane, copy the random IDs from the existing quests.json if possible + CopyExistingRandomIds(originalQuest, quest.Value); } // Iterate over quest objects a final time and add hard coded quest requirements if they dont already exist @@ -125,12 +128,14 @@ namespace GenerateQuestFile && 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 { _parent = "Quest", _props = new AvailableForProps { - id = Sha256(new DateTime().ToString()), + id = Sha256(hashData), index = quest.Value.conditions.AvailableForStart.Count, parentId = "", status = GetQuestStatus(requirement.QuestStatus), @@ -165,12 +170,14 @@ namespace GenerateQuestFile && 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 { _parent = "Level", _props = new AvailableForProps { - id = Sha256(new DateTime().ToString()), + id = Sha256(hashData), index = quest.Value.conditions.AvailableForStart.Count, parentId = "", dynamicLocale = false, @@ -191,6 +198,13 @@ namespace GenerateQuestFile } } } + + // To make diffs more sane, copy the random IDs from the existing quests.json if possible + var originalQuest = existingQuestData.FirstOrDefault(x => x.Key == quest.Key).Value; + if (originalQuest != null) + { + CopyExistingRandomIds(originalQuest, quest.Value); + } } OutputQuestRequirementsToConsole2(questsToOutputToFile); JsonWriter.WriteJson(questsToOutputToFile, "output", Directory.GetCurrentDirectory(), "quests"); @@ -298,6 +312,79 @@ namespace GenerateQuestFile } } + private static void CopyExistingRandomIds(Quest originalQuest, Quest quest) + { + CopyRewardRandomIds(originalQuest.rewards.Started, quest.rewards.Started); + CopyRewardRandomIds(originalQuest.rewards.Success, quest.rewards.Success); + CopyRewardRandomIds(originalQuest.rewards.Fail, quest.rewards.Fail); + + CopyConditionRandomIds(originalQuest.conditions.AvailableForStart, quest.conditions.AvailableForStart); + CopyConditionRandomIds(originalQuest.conditions.AvailableForFinish, quest.conditions.AvailableForFinish); + } + + private static void CopyRewardRandomIds(List originalRewards, List rewards) + { + foreach (var reward in rewards) + { + var originalReward = originalRewards.FirstOrDefault(x => x.id == reward.id); + if (originalReward == null) + { + LoggingHelpers.LogWarning($"Unable to find matching original reward for {reward.id}. Skipping."); + continue; + } + + reward.target = originalReward.target; + + if (reward.items != null) + { + foreach (var item in reward.items) + { + QuestRewardItem originalItem = originalReward.items.FirstOrDefault(x => x._tpl == item._tpl && x.slotId == item.slotId); + if (originalItem == null) + { + LoggingHelpers.LogWarning($"Unable to find matching original reward item for {reward.id}-{item._tpl}. Skipping"); + continue; + } + + item._id = originalItem._id; + item.parentId = originalItem.parentId; + } + } + } + } + + // Allow stripping all whitespace in a string, used for comparing _props.target, which may have differing whitespace but still match + private static readonly Regex whitespace = new Regex(@"\s+"); + private static string StripAllWhitespace(string input) + { + if (input == null) + { + return ""; + } + + return whitespace.Replace(input, ""); + } + + private static void CopyConditionRandomIds(List originalConditions, List conditions) + { + foreach (var condition in conditions) + { + var originalCondition = originalConditions.FirstOrDefault( + x => x._parent == condition._parent && + x._props.index == condition._props.index && + StripAllWhitespace(x._props.target?.ToString()) == StripAllWhitespace(condition._props.target?.ToString()) + ); + + if (originalCondition == null) + { + LoggingHelpers.LogWarning($"Unable to find matching original condition for {condition._parent}-{StripAllWhitespace(condition._props.target?.ToString())}. Skipping."); + continue; + } + + condition._props.id = originalCondition._props.id; + } + } + /// /// Check original quest for start conditions and if missing from new quest, add them /// @@ -325,7 +412,6 @@ namespace GenerateQuestFile if (questRequirementToAdd._parent == "Quest") { LoggingHelpers.LogInfo($"Quest {questToUpdate.Value.QuestName} missing AvailableForStart quest requirement, adding prereq of {questRequirementToAdd._props.target} {QuestHelper.GetQuestNameById(questRequirementToAdd._props.target?.ToString())}"); - questRequirementToAdd._props.id = Sha256(new DateTime().ToString()); if (!questRequirementToAdd._props.availableAfter.HasValue) { diff --git a/QuestValidator.Models/Input/Quest.cs b/QuestValidator.Models/Input/Quest.cs index 282ed5f..f39247a 100644 --- a/QuestValidator.Models/Input/Quest.cs +++ b/QuestValidator.Models/Input/Quest.cs @@ -160,6 +160,8 @@ namespace QuestValidator.Models public int? StackObjectsCount { get; set; } public FireModeReward FireMode { get; set; } public FoldeableReward Foldable { get; set; } + public bool? SpawnedInSession { get; set; } + public object? Repairable { get; set; } } public class FireModeReward