From fe27562aec3c73301349e52dcd1a57335b46f2aa Mon Sep 17 00:00:00 2001 From: J-128 Date: Mon, 30 Oct 2023 20:17:18 -0500 Subject: [PATCH 01/21] missiontext: correct "preposition" to "proposition" Context: Harald: "Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a proposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy." --- src/Resources/missions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index f0496989..cbd131b7 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -93170,7 +93170,7 @@ 6118 2020SnoggletogStory01T04 - <Data><Offer><Type>Popup</Type><ID>940068</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Whatever do you mean, dear Hiccup? Do you think that you have cause to be worried? Fret not, old friend! We have a lot of history between us, and you know I will not attack you without provocation.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><ID>940069</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>'A lot of history between us' is why I'm tense, Harald.</Text><ItemID>0</ItemID><Priority>1</Priority></Offer><End><Type>Popup</Type><ID>940070</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a preposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy.</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubDragonsEdgeDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWHarald</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Harald</Text><ID>927532</ID></Title></Data> + <Data><Offer><Type>Popup</Type><ID>940068</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Whatever do you mean, dear Hiccup? Do you think that you have cause to be worried? Fret not, old friend! We have a lot of history between us, and you know I will not attack you without provocation.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><ID>940069</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>'A lot of history between us' is why I'm tense, Harald.</Text><ItemID>0</ItemID><Priority>1</Priority></Offer><End><Type>Popup</Type><ID>940070</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a proposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy.</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubDragonsEdgeDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWHarald</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Harald</Text><ID>927532</ID></Title></Data> 0 false From 8b3ed124c6a60002447ddadde918b44add4dbf3b Mon Sep 17 00:00:00 2001 From: Spirtix Date: Thu, 7 Dec 2023 20:38:06 +0100 Subject: [PATCH 02/21] wallets --- src/Controllers/Common/ContentController.cs | 41 +++++++++++++++++++-- src/Controllers/Common/ProfileController.cs | 6 ++- src/Resources/items.xml | 8 ++-- src/Services/AchievementService.cs | 18 +++++++-- src/Services/ItemService.cs | 16 ++++++++ 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index eb66216f..9637c402 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -749,8 +749,19 @@ public IActionResult PurchaseItems(Viking viking, [FromForm] string purchaseItem PurchaseStoreItemRequest request = XmlUtil.DeserializeXml(purchaseItemRequest); List items = new List(); Gender gender = XmlUtil.DeserializeXml(viking.AvatarSerialized).GenderType; + bool success = true; for (int i = 0; i < request.Items.Length; i++) { int itemId = request.Items[i]; + ItemData item = itemService.GetItem(itemId); + UserGameCurrency currency = achievementService.GetUserCurrency(viking); + int coinCost = (int)Math.Round(0.8 * item.Cost); // 20% discount for members + int gemCost = (int)Math.Round(0.8 * item.CashCost); + if (currency.GameCurrency - coinCost < 0 && currency.CashCurrency - gemCost < 0) { + success = false; + break; + } + achievementService.AddAchievementPoints(viking, AchievementPointTypes.GameCurrency, -coinCost); + achievementService.AddAchievementPoints(viking, AchievementPointTypes.CashCurrency, -gemCost); if (request.AddMysteryBoxToInventory) { // force add boxes as item (without "opening") items.Add(inventoryService.AddItemToInventoryAndGetResponse(viking, itemId, 1)); @@ -762,7 +773,22 @@ public IActionResult PurchaseItems(Viking viking, [FromForm] string purchaseItem for (int j=0; j(itemIDArrayXml); List items = new List(); Gender gender = XmlUtil.DeserializeXml(viking.AvatarSerialized).GenderType; + bool success = true; for (int i = 0; i < itemIdArr.Length; i++) { + ItemData item = itemService.GetItem(itemIdArr[i]); + UserGameCurrency currency = achievementService.GetUserCurrency(viking); + if (currency.GameCurrency - item.Cost < 0 && currency.CashCurrency - item.CashCost < 0) { + success = false; + break; + } + achievementService.AddAchievementPoints(viking, AchievementPointTypes.GameCurrency, -item.Cost); + achievementService.AddAchievementPoints(viking, AchievementPointTypes.CashCurrency, -item.CashCost); itemService.CheckAndOpenBox(itemIdArr[i], gender, out int itemId, out int quantity); for (int j=0; j 12732 - 436 - Dragons Bundle + 425 + Dragons Treasure 12732 @@ -909766,8 +909766,8 @@ This bundle contains 10 Frostbite Powerups. 12721 - 436 - Dragons Bundle + 425 + Dragons Treasure 12721 diff --git a/src/Services/AchievementService.cs b/src/Services/AchievementService.cs index 87e8ad6b..9396dfa7 100644 --- a/src/Services/AchievementService.cs +++ b/src/Services/AchievementService.cs @@ -88,6 +88,8 @@ public void SetAchievementPoints(Viking viking, AchievementPointTypes type, int value = 0; } + ctx.SaveChanges(); + return new AchievementReward{ EntityID = viking.Uid, PointTypeID = type, @@ -157,10 +159,20 @@ public AchievementReward[] ApplyAchievementRewardsByTask(Viking viking, Achievem public UserGameCurrency GetUserCurrency(Viking viking) { // TODO: return real values (after implement currency collecting methods) + int? coins = viking.AchievementPoints.FirstOrDefault(x => x.Type == (int)AchievementPointTypes.GameCurrency)?.Value; + int? gems = viking.AchievementPoints.FirstOrDefault(x => x.Type == (int)AchievementPointTypes.CashCurrency)?.Value; + if (coins is null) { + coins = 300; + AddAchievementPoints(viking, AchievementPointTypes.GameCurrency, coins); + } + if (gems is null) { + gems = 75; + AddAchievementPoints(viking, AchievementPointTypes.CashCurrency, gems); + } return new UserGameCurrency { - CashCurrency = 65536, - GameCurrency = 65536, - UserGameCurrencyID = 1, // TODO: user's wallet ID? + CashCurrency = gems, + GameCurrency = coins, + UserGameCurrencyID = viking.Id, UserID = viking.Uid }; } diff --git a/src/Services/ItemService.cs b/src/Services/ItemService.cs index 13c1ae52..38c0e94f 100644 --- a/src/Services/ItemService.cs +++ b/src/Services/ItemService.cs @@ -90,6 +90,22 @@ public bool IsBundleItem(int itemId) { return items[itemId].Relationship?.FirstOrDefault(e => e.Type == "Bundle") != null; } + public bool IsGemBundle(int itemId, out int value) { + value = 0; + ItemAttribute? attribute = items[itemId].Attribute?.FirstOrDefault(e => e.Key == "VCashRedemptionValue"); + if (attribute != null && int.TryParse(attribute.Value, out int result)) + value = result; + return attribute != null; + } + + public bool IsCoinBundle(int itemId, out int value) { + value = 0; + ItemAttribute? attribute = items[itemId].Attribute?.FirstOrDefault(e => e.Key == "CoinRedemptionValue"); + if (attribute != null && int.TryParse(attribute.Value, out int result)) + value = result; + return attribute != null; + } + public bool CheckItemGender(ItemData itemData, Gender gender) { string? itemGender = itemData.Attribute?.FirstOrDefault(e => e.Key == "Gender")?.Value; if (itemGender != null) { From 474605dd53bb0276f89818b72c98c3c6c7a13c9a Mon Sep 17 00:00:00 2001 From: Spirtix Date: Thu, 7 Dec 2023 21:03:14 +0100 Subject: [PATCH 03/21] fix highscores involving time --- src/Services/GameDataService.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Services/GameDataService.cs b/src/Services/GameDataService.cs index cd4eed2f..dc40974c 100644 --- a/src/Services/GameDataService.cs +++ b/src/Services/GameDataService.cs @@ -115,7 +115,9 @@ private void SavePairs(Model.GameData gameData, string xmlDocumentData) { GameDataPair? dbPair = gameData.GameDataPairs.FirstOrDefault(x => x.Name == pair.Name); if (dbPair == null) gameData.GameDataPairs.Add(pair); - else if (dbPair.Value <= pair.Value) + else if (pair.Name == "time" && dbPair.Value > pair.Value) + dbPair.Value = pair.Value; + else if (pair.Name != "time" && dbPair.Value <= pair.Value) dbPair.Value = pair.Value; } } From 5b8c952419c9197b7b475a8745f574790d42f321 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Thu, 7 Dec 2023 21:02:57 +0000 Subject: [PATCH 04/21] wallet-store fix for old SoD (1.13, 2.9) --- src/Controllers/Common/ContentController.cs | 35 ++++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 9637c402..932ddf8d 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -819,17 +819,36 @@ public IActionResult PurchaseItemsV1(Viking viking, [FromForm] string itemIDArra for (int i = 0; i < itemIdArr.Length; i++) { ItemData item = itemService.GetItem(itemIdArr[i]); UserGameCurrency currency = achievementService.GetUserCurrency(viking); - if (currency.GameCurrency - item.Cost < 0 && currency.CashCurrency - item.CashCost < 0) { + int coinCost = (int)Math.Round(0.8 * item.Cost); // 20% discount for members + int gemCost = (int)Math.Round(0.8 * item.CashCost); + if (currency.GameCurrency - coinCost < 0 && currency.CashCurrency - gemCost < 0) { success = false; break; } - achievementService.AddAchievementPoints(viking, AchievementPointTypes.GameCurrency, -item.Cost); - achievementService.AddAchievementPoints(viking, AchievementPointTypes.CashCurrency, -item.CashCost); - itemService.CheckAndOpenBox(itemIdArr[i], gender, out int itemId, out int quantity); - for (int j=0; j Date: Sat, 9 Dec 2023 22:01:10 +0100 Subject: [PATCH 05/21] include discounts in purchase prices --- src/Controllers/Common/ContentController.cs | 8 ++--- src/Schema/ItemData.cs | 13 +++++++ src/Services/StoreService.cs | 40 ++++++++++++++++++++- 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 932ddf8d..3a8abbf7 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -754,8 +754,8 @@ public IActionResult PurchaseItems(Viking viking, [FromForm] string purchaseItem int itemId = request.Items[i]; ItemData item = itemService.GetItem(itemId); UserGameCurrency currency = achievementService.GetUserCurrency(viking); - int coinCost = (int)Math.Round(0.8 * item.Cost); // 20% discount for members - int gemCost = (int)Math.Round(0.8 * item.CashCost); + int coinCost = (int)Math.Round(item.FinalDiscoutModifier * item.Cost); + int gemCost = (int)Math.Round(item.FinalDiscoutModifier * item.CashCost); if (currency.GameCurrency - coinCost < 0 && currency.CashCurrency - gemCost < 0) { success = false; break; @@ -819,8 +819,8 @@ public IActionResult PurchaseItemsV1(Viking viking, [FromForm] string itemIDArra for (int i = 0; i < itemIdArr.Length; i++) { ItemData item = itemService.GetItem(itemIdArr[i]); UserGameCurrency currency = achievementService.GetUserCurrency(viking); - int coinCost = (int)Math.Round(0.8 * item.Cost); // 20% discount for members - int gemCost = (int)Math.Round(0.8 * item.CashCost); + int coinCost = (int)Math.Round(item.FinalDiscoutModifier * item.Cost); + int gemCost = (int)Math.Round(item.FinalDiscoutModifier * item.CashCost); if (currency.GameCurrency - coinCost < 0 && currency.CashCurrency - gemCost < 0) { success = false; break; diff --git a/src/Schema/ItemData.cs b/src/Schema/ItemData.cs index bd959334..fc189477 100644 --- a/src/Schema/ItemData.cs +++ b/src/Schema/ItemData.cs @@ -97,4 +97,17 @@ public class ItemData [XmlElement(ElementName = "p", IsNullable = true)] public int? Points; + + [XmlIgnore] + public float NormalDiscoutModifier; + + [XmlIgnore] + public float MemberDiscountModifier; + + [XmlIgnore] + public float FinalDiscoutModifier { + get { + return Math.Min(1f, (1f - NormalDiscoutModifier) * (1f - MemberDiscountModifier)); + } + } } diff --git a/src/Services/StoreService.cs b/src/Services/StoreService.cs index b20a7ced..8994043c 100644 --- a/src/Services/StoreService.cs +++ b/src/Services/StoreService.cs @@ -17,8 +17,11 @@ public StoreService(ItemService itemService) { SalesAtStore = s.SalesAtStore, PopularItems = s.PopularItems }; - for (int i=0; i? memberSales = s.SalesAtStore?.Where(x => x.ForMembers == true); + IEnumerable? normalSales = s.SalesAtStore?.Where(x => x.ForMembers == false || x.ForMembers == null); + for (int i = 0; i < s.ItemId.Length; ++i) { newStore.Items[i] = itemService.GetItem(s.ItemId[i]); + UpdateItemSaleModifier(newStore.Items[i], memberSales, normalSales); } stores.Add(s.Id, newStore); } @@ -27,4 +30,39 @@ public StoreService(ItemService itemService) { public ItemsInStoreData GetStore(int id) { return stores[id]; } + + private bool IsSaleOutdated(ItemsInStoreDataSale sale) { + if (sale.EndDate == null) + return false; + return sale.EndDate < DateTime.Now; + } + + private void UpdateItemSaleModifier(ItemData item, IEnumerable? memberSales, IEnumerable? normalSales) { + if (memberSales != null) { + foreach (var memberSale in memberSales) { + if (IsSaleOutdated(memberSale)) continue; + if (item.Category != null && memberSale.CategoryIDs != null && item.Category.Any(x => memberSale.CategoryIDs.Contains(x.CategoryId))) { + item.MemberDiscountModifier = memberSale.Modifier; + break; + } + if (memberSale.ItemIDs != null && memberSale.ItemIDs.Contains(item.ItemID)) { + item.MemberDiscountModifier = memberSale.Modifier; + break; + } + } + } + if (normalSales != null) { + foreach (var normalSale in normalSales) { + if (IsSaleOutdated(normalSale)) continue; + if (item.Category != null && normalSale.CategoryIDs != null && item.Category.Any(x => normalSale.CategoryIDs.Contains(x.CategoryId))) { + item.NormalDiscoutModifier = normalSale.Modifier; + break; + } + if (normalSale.ItemIDs != null && normalSale.ItemIDs.Contains(item.ItemID)) { + item.NormalDiscoutModifier = normalSale.Modifier; + break; + } + } + } + } } From 47e1bfb065da940ff84ef51c63326de408adc6aa Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Mon, 11 Dec 2023 00:10:31 +0000 Subject: [PATCH 06/21] SoD 1.6 fixes - CreateRaisedPet endpoint - support for 1.6 apiKey + util class for management apiKey version recognition --- .../Common/AuthenticationController.cs | 4 +- src/Controllers/Common/ContentController.cs | 47 +++++++++++++++++++ src/Controllers/Common/ProfileController.cs | 4 +- .../Common/RegistrationController.cs | 2 +- src/Services/MissionService.cs | 25 ++++++---- src/Services/MissionStoreSingleton.cs | 4 +- src/Util/ClientVersion.cs | 30 ++++++++++++ 7 files changed, 99 insertions(+), 17 deletions(-) create mode 100644 src/Util/ClientVersion.cs diff --git a/src/Controllers/Common/AuthenticationController.cs b/src/Controllers/Common/AuthenticationController.cs index cd144678..d7962b62 100644 --- a/src/Controllers/Common/AuthenticationController.cs +++ b/src/Controllers/Common/AuthenticationController.cs @@ -95,7 +95,7 @@ public IActionResult GetUserInfoByApiToken([FromForm] Guid apiToken, [FromForm] Username = user.Username, MembershipID = "ef84db9-59c6-4950-b8ea-bbc1521f899b", // placeholder FacebookUserID = 0, - MultiplayerEnabled = (apiKey != "a1a13a0a-7c6e-4e9b-b0f7-22034d799013" && apiKey != "a2a09a0a-7c6e-4e9b-b0f7-22034d799013" && apiKey != "a3a12a0a-7c6e-4e9b-b0f7-22034d799013"), + MultiplayerEnabled = !ClientVersion.IsOldSoD(apiKey), IsApproved = true, Age = 24, OpenChatEnabled = true @@ -110,7 +110,7 @@ public IActionResult GetUserInfoByApiToken([FromForm] Guid apiToken, [FromForm] UserID = viking.Uid.ToString(), Username = viking.Name, FacebookUserID = 0, - MultiplayerEnabled = (apiKey != "a1a13a0a-7c6e-4e9b-b0f7-22034d799013" && apiKey != "a2a09a0a-7c6e-4e9b-b0f7-22034d799013" && apiKey != "a3a12a0a-7c6e-4e9b-b0f7-22034d799013"), + MultiplayerEnabled = !ClientVersion.IsOldSoD(apiKey), IsApproved = true, Age = 24, OpenChatEnabled = true diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 3a8abbf7..44bc7472 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -271,6 +271,53 @@ public IActionResult SetAvatar(Viking viking, [FromForm] string contentXML) { }); } + [HttpPost] + [Produces("application/xml")] + [Route("ContentWebService.asmx/CreateRaisedPet")] // used by SoD 1.6 + [VikingSession] + public RaisedPetData? CreateRaisedPet(Viking viking, int petTypeID) { + // Update the RaisedPetData with the info + String dragonId = Guid.NewGuid().ToString(); + + var raisedPetData = new RaisedPetData(); + raisedPetData.IsPetCreated = true; + raisedPetData.PetTypeID = petTypeID; + raisedPetData.RaisedPetID = 0; // Initially make zero, so the db auto-fills + raisedPetData.EntityID = Guid.Parse(dragonId); + raisedPetData.Name = string.Concat("Dragon-", dragonId.AsSpan(0, 8)); // Start off with a random name + raisedPetData.IsSelected = false; // The api returns false, not sure why + raisedPetData.CreateDate = new DateTime(DateTime.Now.Ticks); + raisedPetData.UpdateDate = new DateTime(DateTime.Now.Ticks); + raisedPetData.GrowthState = new RaisedPetGrowthState { Name = "BABY" }; + int imageSlot = (viking.Images.Select(i => i.ImageSlot).DefaultIfEmpty(-1).Max() + 1); + raisedPetData.ImagePosition = imageSlot; + // NOTE: Placing an egg into a hatchery slot calls CreatePet, but doesn't SetImage. + // NOTE: We need to force create an image slot because hatching multiple eggs at once would create dragons with the same slot + Image image = new Image { + ImageType = "EggColor", // NOTE: The game doesn't seem to use anything other than EggColor. + ImageSlot = imageSlot, + Viking = viking, + }; + // Save the dragon in the db + Dragon dragon = new Dragon { + EntityId = Guid.NewGuid(), + Viking = viking, + RaisedPetData = XmlUtil.SerializeXml(raisedPetData), + }; + + ctx.Dragons.Add(dragon); + ctx.Images.Add(image); + + if (petTypeID != 2) { + // Minisaurs should not be set as active pet + viking.SelectedDragon = dragon; + ctx.Update(viking); + } + ctx.SaveChanges(); + + return GetRaisedPetDataFromDragon(dragon); + } + [HttpPost] [Produces("application/xml")] [Route("V2/ContentWebService.asmx/CreatePet")] diff --git a/src/Controllers/Common/ProfileController.cs b/src/Controllers/Common/ProfileController.cs index 8f45dfdd..971d5fee 100644 --- a/src/Controllers/Common/ProfileController.cs +++ b/src/Controllers/Common/ProfileController.cs @@ -116,7 +116,7 @@ private UserProfileData GetProfileDataFromViking(Viking viking, [FromForm] strin avatarData.Id = viking.Id; } - if (avatarData != null && (apiKey == "a3a12a0a-7c6e-4e9b-b0f7-22034d799013")) { + if (avatarData != null && ClientVersion.Use2019SoDTutorial(apiKey)) { if (avatarData.Part.FirstOrDefault(e => e.PartType == "Sword") is null) { var extraParts = new AvatarDataPart[] { new AvatarDataPart { @@ -139,7 +139,7 @@ private UserProfileData GetProfileDataFromViking(Viking viking, [FromForm] strin ParentUserID = viking.UserId.ToString(), Username = viking.Name, FirstName = viking.Name, - MultiplayerEnabled = (apiKey != "a1a13a0a-7c6e-4e9b-b0f7-22034d799013" && apiKey != "a2a09a0a-7c6e-4e9b-b0f7-22034d799013" && apiKey != "a3a12a0a-7c6e-4e9b-b0f7-22034d799013"), + MultiplayerEnabled = !ClientVersion.IsOldSoD(apiKey), Locale = "en-US", // placeholder GenderID = Gender.Male, // placeholder OpenChatEnabled = true, diff --git a/src/Controllers/Common/RegistrationController.cs b/src/Controllers/Common/RegistrationController.cs index d19cff51..45882e8d 100644 --- a/src/Controllers/Common/RegistrationController.cs +++ b/src/Controllers/Common/RegistrationController.cs @@ -131,7 +131,7 @@ public IActionResult RegisterChild([FromForm] Guid parentApiToken, [FromForm] st ctx.Vikings.Add(v); ctx.SaveChanges(); - if (apiKey == "a1a13a0a-7c6e-4e9b-b0f7-22034d799013") { + if (ClientVersion.Use2013SoDTutorial(apiKey)) { keyValueService.SetPairData(null, v, null, 2017, new Schema.PairData { Pairs = new Schema.Pair[]{ new Schema.Pair { diff --git a/src/Services/MissionService.cs b/src/Services/MissionService.cs index 3a28f010..82583c66 100644 --- a/src/Services/MissionService.cs +++ b/src/Services/MissionService.cs @@ -1,5 +1,6 @@ using sodoff.Model; using sodoff.Schema; +using sodoff.Util; using System.Runtime.Serialization.Formatters.Binary; using System.Threading.Tasks; @@ -17,19 +18,23 @@ public MissionService(DBContext ctx, MissionStoreSingleton missionStore, Achieve } public Mission GetMissionWithProgress(int missionId, int userId, string apiKey) { - Mission mission; - if (missionId == 999 && apiKey == "a3a12a0a-7c6e-4e9b-b0f7-22034d799013") { // TODO This is not a pretty solution with hard-coded values. - mission = missionStore.GetMission(10999); - mission.MissionID = 999; - } else if (missionId == 999 && apiKey == "a2a09a0a-7c6e-4e9b-b0f7-22034d799013") { - mission = missionStore.GetMission(20999); - mission.MissionID = 999; - } else if (missionId == 999 && apiKey == "a1a13a0a-7c6e-4e9b-b0f7-22034d799013") { - mission = missionStore.GetMission(30999); + Mission mission = null; + + if (missionId == 999) { // TODO This is not a pretty solution with hard-coded values. + if (ClientVersion.Use2013SoDTutorial(apiKey)) { + mission = missionStore.GetMission(30999); + } else if (ClientVersion.Use2016SoDTutorial(apiKey)) { + mission = missionStore.GetMission(20999); + } else if (ClientVersion.Use2019SoDTutorial(apiKey)) { + mission = missionStore.GetMission(10999); + } mission.MissionID = 999; - } else { + } + + if (mission is null) { mission = missionStore.GetMission(missionId); } + UpdateMissionRecursive(mission, userId); return mission; } diff --git a/src/Services/MissionStoreSingleton.cs b/src/Services/MissionStoreSingleton.cs index 4acadabd..e44a6b70 100644 --- a/src/Services/MissionStoreSingleton.cs +++ b/src/Services/MissionStoreSingleton.cs @@ -30,14 +30,14 @@ public Mission GetMission(int missionID) { } public int[] GetActiveMissions(string apiKey) { - if (apiKey == "a1a13a0a-7c6e-4e9b-b0f7-22034d799013") { + if (ClientVersion.Use2013SoDTutorial(apiKey)) { return activeMissionsV1; } return activeMissions; } public int[] GetUpcomingMissions(string apiKey) { - if (apiKey == "a1a13a0a-7c6e-4e9b-b0f7-22034d799013") { + if (ClientVersion.Use2013SoDTutorial(apiKey)) { return upcomingMissionsV1; } return upcomingMissions; diff --git a/src/Util/ClientVersion.cs b/src/Util/ClientVersion.cs new file mode 100644 index 00000000..24f65c6e --- /dev/null +++ b/src/Util/ClientVersion.cs @@ -0,0 +1,30 @@ +namespace sodoff.Util; +public class ClientVersion { + public static bool IsOldSoD(string apiKey) { + return ( + apiKey == "a1a06a0a-7c6e-4e9b-b0f7-22034d799013" || + apiKey == "a1a13a0a-7c6e-4e9b-b0f7-22034d799013" || + apiKey == "a2a09a0a-7c6e-4e9b-b0f7-22034d799013" || + apiKey == "a3a12a0a-7c6e-4e9b-b0f7-22034d799013" + ); + } + public static bool Use2013SoDTutorial(string apiKey) { + return ( + apiKey == "a1a06a0a-7c6e-4e9b-b0f7-22034d799013" || + apiKey == "a1a13a0a-7c6e-4e9b-b0f7-22034d799013" + ); + } + public static bool Use2016SoDTutorial(string apiKey) { + return ( + apiKey == "a2a09a0a-7c6e-4e9b-b0f7-22034d799013" + ); + } + public static bool Use2019SoDTutorial(string apiKey) { + return ( + apiKey == "a3a12a0a-7c6e-4e9b-b0f7-22034d799013" + ); + } + public static bool Use2021SoDTutorial(string apiKey) { + return !IsOldSoD(apiKey); + } +} From e5570f7c918b575c053f6f34edbf6bc25671d4d6 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Sat, 9 Dec 2023 21:23:45 +0000 Subject: [PATCH 07/21] Magic and Mythies fixes: - add fake missions for unlock fishing and mythie grow up - add games to store --- src/Resources/defaultmissionlistmam.xml | 12 ++ src/Resources/missions.xml | 186 +++++++++++++++++++++++- src/Resources/store.xml | 2 + src/Services/MissionService.cs | 6 + src/Services/MissionStoreSingleton.cs | 14 +- src/Util/ClientVersion.cs | 4 + src/sodoff.csproj | 4 + 7 files changed, 225 insertions(+), 3 deletions(-) create mode 100644 src/Resources/defaultmissionlistmam.xml diff --git a/src/Resources/defaultmissionlistmam.xml b/src/Resources/defaultmissionlistmam.xml new file mode 100644 index 00000000..b71746b0 --- /dev/null +++ b/src/Resources/defaultmissionlistmam.xml @@ -0,0 +1,12 @@ + + + + + 1750 + 2298 + 1044 + 1074 + + + + diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index f0496989..39610f55 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -2,7 +2,7 @@ 1000 - Quest 1 + Unlock Fishing 3 false @@ -27,7 +27,7 @@ 0 1 - 999 + 1000 1000 1 @@ -125774,4 +125774,186 @@ false + + 1750 + Unlock Fishing + 3 + + false + 1 + + + 2 + False + 0 + false + + + 1 + False + 0 + false + + + all + true + 1 + 0 + + 1 + 1750 + 1000 + 1 + + + + 1 + 0 + 0 + + 1000 + Unlock Fishing + + 1 + false + + false + + + 2298 + Unlock Fishing + 3 + + false + 1 + + + 2 + False + 0 + false + + + 1 + False + 0 + false + + + all + true + 1 + 0 + + 1 + 2298 + 1000 + 1 + + + + 1 + 0 + 0 + + 1000 + Unlock Fishing + + 1 + false + + false + + + 11044 + + Unlock Grow Up + 3 + + false + 0 + + + 1 + False + 0 + false + + + 4 + 8,5 + 0 + true + + + all + true + 1 + 1 + + 1 + 1044 + 11044 + 0 + + + + 1 + 0 + 0 + + 11044 + Unlock Grow Up + <Data><Objective><Pair><Key>Name</Key><Value>GrowDragon</Value></Pair></Objective><Type>Action</Type></Data> + 0 + false + + true + + + 11074 + + Unlock Grow Up + 3 + + false + 0 + + + 1 + False + 0 + false + + + 4 + 8,10 + 0 + true + + + all + true + 1 + 1 + + 1 + 1074 + 11074 + 0 + + + + 1 + 0 + 0 + + 11074 + Unlock Grow Up + <Data><Objective><Pair><Key>Name</Key><Value>GrowDragon</Value></Pair></Objective><Type>Action</Type></Data> + 0 + false + + true + diff --git a/src/Resources/store.xml b/src/Resources/store.xml index 7aaf1083..3ecb7fee 100644 --- a/src/Resources/store.xml +++ b/src/Resources/store.xml @@ -17100,6 +17100,8 @@ SoD 3.31 main store section and subsection filtering: 2013-01-01T00:00:00 2030-12-31T00:00:00 + 12732 + 12721 12238 12239 12016 diff --git a/src/Services/MissionService.cs b/src/Services/MissionService.cs index 82583c66..c2d65bf2 100644 --- a/src/Services/MissionService.cs +++ b/src/Services/MissionService.cs @@ -29,6 +29,12 @@ public Mission GetMissionWithProgress(int missionId, int userId, string apiKey) mission = missionStore.GetMission(10999); } mission.MissionID = 999; + } else if (missionId == 1044 && ClientVersion.IsMaM(apiKey)) { + mission = missionStore.GetMission(11044); + mission.MissionID = 1044; + } else if (missionId == 1074 && ClientVersion.IsMaM(apiKey)) { + mission = missionStore.GetMission(11074); + mission.MissionID = 1074; } if (mission is null) { diff --git a/src/Services/MissionStoreSingleton.cs b/src/Services/MissionStoreSingleton.cs index e44a6b70..6e294dbd 100644 --- a/src/Services/MissionStoreSingleton.cs +++ b/src/Services/MissionStoreSingleton.cs @@ -10,6 +10,8 @@ public class MissionStoreSingleton { private int[] upcomingMissions; private int[] activeMissionsV1; private int[] upcomingMissionsV1; + private int[] activeMissionsMaM; + private int[] upcomingMissionsMaM; public MissionStoreSingleton() { ServerMissionArray missionArray = XmlUtil.DeserializeXml(XmlUtil.ReadResourceXmlString("missions")); @@ -19,10 +21,14 @@ public MissionStoreSingleton() { } activeMissions = defaultMissions.Active; upcomingMissions = defaultMissions.Upcoming; - + defaultMissions = XmlUtil.DeserializeXml(XmlUtil.ReadResourceXmlString("defaultmissionlistv1")); activeMissionsV1 = defaultMissions.Active; upcomingMissionsV1 = defaultMissions.Upcoming; + + defaultMissions = XmlUtil.DeserializeXml(XmlUtil.ReadResourceXmlString("defaultmissionlistmam")); + activeMissionsMaM = defaultMissions.Active; + upcomingMissionsMaM = defaultMissions.Upcoming; } public Mission GetMission(int missionID) { @@ -33,6 +39,9 @@ public int[] GetActiveMissions(string apiKey) { if (ClientVersion.Use2013SoDTutorial(apiKey)) { return activeMissionsV1; } + if (ClientVersion.IsMaM(apiKey)) { + return activeMissionsMaM; + } return activeMissions; } @@ -40,6 +49,9 @@ public int[] GetUpcomingMissions(string apiKey) { if (ClientVersion.Use2013SoDTutorial(apiKey)) { return upcomingMissionsV1; } + if (ClientVersion.IsMaM(apiKey)) { + return upcomingMissionsMaM; + } return upcomingMissions; } diff --git a/src/Util/ClientVersion.cs b/src/Util/ClientVersion.cs index 24f65c6e..88e1697f 100644 --- a/src/Util/ClientVersion.cs +++ b/src/Util/ClientVersion.cs @@ -27,4 +27,8 @@ public static bool Use2019SoDTutorial(string apiKey) { public static bool Use2021SoDTutorial(string apiKey) { return !IsOldSoD(apiKey); } + + public static bool IsMaM(string apiKey) { + return apiKey == "e20150cc-ff70-435c-90fd-341dc9161cc3"; + } } diff --git a/src/sodoff.csproj b/src/sodoff.csproj index 069b2dfe..5bded66d 100644 --- a/src/sodoff.csproj +++ b/src/sodoff.csproj @@ -25,6 +25,7 @@ + @@ -89,5 +90,8 @@ PreserveNewest + + PreserveNewest + From 25ebba6f658a44e20526c515e670bcd91832e958 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Mon, 11 Dec 2023 16:27:46 +0000 Subject: [PATCH 08/21] fix MissionID restore bug --- src/Services/MissionService.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Services/MissionService.cs b/src/Services/MissionService.cs index c2d65bf2..9704c832 100644 --- a/src/Services/MissionService.cs +++ b/src/Services/MissionService.cs @@ -28,17 +28,17 @@ public Mission GetMissionWithProgress(int missionId, int userId, string apiKey) } else if (ClientVersion.Use2019SoDTutorial(apiKey)) { mission = missionStore.GetMission(10999); } - mission.MissionID = 999; } else if (missionId == 1044 && ClientVersion.IsMaM(apiKey)) { mission = missionStore.GetMission(11044); - mission.MissionID = 1044; } else if (missionId == 1074 && ClientVersion.IsMaM(apiKey)) { mission = missionStore.GetMission(11074); - mission.MissionID = 1074; } if (mission is null) { mission = missionStore.GetMission(missionId); + } else { + // mission use overwrite variant ... so we need fix MissionID + mission.MissionID = missionId; } UpdateMissionRecursive(mission, userId); From 5301de694d3d2cb1881d65ec609f923cfd62f1cb Mon Sep 17 00:00:00 2001 From: J-128 Date: Mon, 30 Oct 2023 20:17:18 -0500 Subject: [PATCH 09/21] missiontext: correct "preposition" to "proposition" Context: Harald: "Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a proposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy." --- src/Resources/missions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index 39610f55..9a12d815 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -93170,7 +93170,7 @@ 6118 2020SnoggletogStory01T04 - <Data><Offer><Type>Popup</Type><ID>940068</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Whatever do you mean, dear Hiccup? Do you think that you have cause to be worried? Fret not, old friend! We have a lot of history between us, and you know I will not attack you without provocation.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><ID>940069</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>'A lot of history between us' is why I'm tense, Harald.</Text><ItemID>0</ItemID><Priority>1</Priority></Offer><End><Type>Popup</Type><ID>940070</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a preposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy.</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubDragonsEdgeDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWHarald</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Harald</Text><ID>927532</ID></Title></Data> + <Data><Offer><Type>Popup</Type><ID>940068</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Whatever do you mean, dear Hiccup? Do you think that you have cause to be worried? Fret not, old friend! We have a lot of history between us, and you know I will not attack you without provocation.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><ID>940069</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>'A lot of history between us' is why I'm tense, Harald.</Text><ItemID>0</ItemID><Priority>1</Priority></Offer><End><Type>Popup</Type><ID>940070</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a proposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy.</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubDragonsEdgeDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWHarald</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Harald</Text><ID>927532</ID></Title></Data> 0 false From 32723602599be7fc55de1c02587933b647c22da7 Mon Sep 17 00:00:00 2001 From: J-128 Date: Sun, 24 Dec 2023 14:35:47 -0600 Subject: [PATCH 10/21] missiontext: correct "Skrill" to "Skrills" context: Dagur: "We were out searching for Skrills to join the Berserkers when we came across her. We think she was trying to become friends with a Skrill at Glacier Island, but the Skrill was having none of it. No fault of our mystery dragon; Skrills just are very territorial!" --- src/Resources/missions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index 9a12d815..1989ca94 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -3842,7 +3842,7 @@ 5691 Dreadfall2019Q03T06 - <Data><Offer><Type>Popup</Type><ID>939093</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWMala</NPC><Text>That you are, my fierce flame. It's just as well that you're here, {{Name}}. Our dragon hasn't been too cooperative on the way over here.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><ID>939094</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWDagur</NPC><Text>My darling Mala was the one to discover the one you were looking for. We were out searching for Skrills to join the Berserkers when we came across her. We think she was trying to become friends with a Skrill at Glacier Island, but the Skrill was having none of it. No fault of our mystery dragon; Skrill just are very territorial!</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubTrainingDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWDagur</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Dagur</Text><ID>928987</ID></Title><Desc><Text>Talk to Dagur.</Text><ID>931908</ID></Desc></Data> + <Data><Offer><Type>Popup</Type><ID>939093</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWMala</NPC><Text>That you are, my fierce flame. It's just as well that you're here, {{Name}}. Our dragon hasn't been too cooperative on the way over here.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><ID>939094</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWDagur</NPC><Text>My darling Mala was the one to discover the one you were looking for. We were out searching for Skrills to join the Berserkers when we came across her. We think she was trying to become friends with a Skrill at Glacier Island, but the Skrill was having none of it. No fault of our mystery dragon; Skrills just are very territorial!</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubTrainingDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWDagur</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Dagur</Text><ID>928987</ID></Title><Desc><Text>Talk to Dagur.</Text><ID>931908</ID></Desc></Data> 0 false From 3b0dfa80718d7487f3ecda43a35599482c38f9d4 Mon Sep 17 00:00:00 2001 From: J-128 Date: Sun, 24 Dec 2023 14:45:56 -0600 Subject: [PATCH 11/21] taskdesc: correct 12 to 15 Context: <Text>Work with your dragon to collect 15 flowers</Text> --- src/Resources/missions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index 1989ca94..3141b67f 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -92316,7 +92316,7 @@ 441 Task 2.1 collect 15 flowers - <Data><Setup><Scene>HubSchoolDO</Scene><Asset>RS_DATA/PfGrpQTeenHic02T01.unity3d/PfGrpQTeenHic02T01</Asset><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Toothless is my best friend; the very first time I looked at him, I saw myself. I knew it would be just me and him forever. That's the bond you and your dragon need to make. You should trust {{dragon name}} as much as you do yourself. @@ How about some bonding exercises? Ride {{dragon name}} and collect the scented flowers around the school. Dragons love the smell!</Text><ID>904750</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>VO</Type><Asset>RS_DATA/DlgDWHiccupDO.unity3d/DlgHiccupToothless01</Asset><NPC>PfDWHiccup</NPC><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>That was amazing and some great team work! </Text><ID>904751</ID><ItemID>0</ItemID><Priority>0</Priority></End><End><Type>VO</Type><Asset>RS_DATA/DlgDWHiccupDO.unity3d/DlgHiccupPos03</Asset><NPC>PfDWHiccup</NPC><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Name</Key><Value>PfCollectDWFlower02</Value></Pair><Pair><Key>Quantity</Key><Value>15</Value></Pair></Objective><Type>Collect</Type><Title><Text>Work with your dragon to collect 12 flowers</Text><ID>904748</ID></Title><Desc><Text>Collect 12 scented flowers around the school.</Text><ID>922953</ID></Desc></Data> + <Data><Setup><Scene>HubSchoolDO</Scene><Asset>RS_DATA/PfGrpQTeenHic02T01.unity3d/PfGrpQTeenHic02T01</Asset><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Toothless is my best friend; the very first time I looked at him, I saw myself. I knew it would be just me and him forever. That's the bond you and your dragon need to make. You should trust {{dragon name}} as much as you do yourself. @@ How about some bonding exercises? Ride {{dragon name}} and collect the scented flowers around the school. Dragons love the smell!</Text><ID>904750</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>VO</Type><Asset>RS_DATA/DlgDWHiccupDO.unity3d/DlgHiccupToothless01</Asset><NPC>PfDWHiccup</NPC><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>That was amazing and some great team work! </Text><ID>904751</ID><ItemID>0</ItemID><Priority>0</Priority></End><End><Type>VO</Type><Asset>RS_DATA/DlgDWHiccupDO.unity3d/DlgHiccupPos03</Asset><NPC>PfDWHiccup</NPC><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Name</Key><Value>PfCollectDWFlower02</Value></Pair><Pair><Key>Quantity</Key><Value>15</Value></Pair></Objective><Type>Collect</Type><Title><Text>Work with your dragon to collect 15 flowers</Text><ID>904748</ID></Title><Desc><Text>Collect 12 scented flowers around the school.</Text><ID>922953</ID></Desc></Data> 0 false From 512348336caa8a24eac70987f84144c06b65a73b Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Fri, 29 Dec 2023 00:36:29 +0000 Subject: [PATCH 12/21] fix missing blueprints --- src/Services/InventoryService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Services/InventoryService.cs b/src/Services/InventoryService.cs index 825e1184..9b4e8fb5 100644 --- a/src/Services/InventoryService.cs +++ b/src/Services/InventoryService.cs @@ -26,8 +26,8 @@ public InventoryItem AddItemToInventory(Viking viking, int itemID, int quantity) ItemId = itemID, Quantity = 0 }; - if (itemData.ItemStatsMap is null && itemData.PossibleStatsMap != null) { - // battle item without default stats + if (itemData.ItemStatsMap is null && itemData.PossibleStatsMap != null && !itemService.ItemHasCategory(itemData, 651)) { + // battle item without default stats, but not blueprints Random random = new Random(); int itemTier = random.Next(1, 3); item.StatsSerialized = XmlUtil.SerializeXml(new ItemStatsMap { From e50207ac2e3124c475eb9afeec2f2fa6d0021846 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Fri, 29 Dec 2023 22:49:11 +0000 Subject: [PATCH 13/21] add support for customizable items --- src/Controllers/Common/ContentController.cs | 36 +++++++++++++++++++++ src/Model/InventoryItem.cs | 4 ++- src/Services/InventoryService.cs | 5 ++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 44bc7472..45173cc2 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -208,6 +208,42 @@ public IActionResult SetCommonInventory(Viking viking, [FromForm] string commonI return Ok(response); } + [HttpPost] + [Produces("application/xml")] + [Route("ContentWebService.asmx/SetCommonInventoryAttribute")] + [VikingSession] + public IActionResult SetCommonInventoryAttribute(Viking viking, [FromForm] int commonInventoryID, [FromForm] string pairxml) { + InventoryItem? item = viking.InventoryItems.FirstOrDefault(e => e.Id == commonInventoryID); + + List itemAttributes; + if (item.AttributesSerialized != null) { + itemAttributes = XmlUtil.DeserializeXml(item.AttributesSerialized).Pairs.ToList(); + } else { + itemAttributes = new List(); + } + + Schema.PairData newItemAttributes = XmlUtil.DeserializeXml(pairxml); + foreach (var p in newItemAttributes.Pairs) { + var pairItem = itemAttributes.FirstOrDefault(e => e.PairKey == p.PairKey); + if (pairItem != null){ + pairItem.PairValue = p.PairValue; + } else { + itemAttributes.Add(p); + } + } + + if (itemAttributes.Count > 0) { + item.AttributesSerialized = XmlUtil.SerializeXml( + new Schema.PairData{ + Pairs = itemAttributes.ToArray() + } + ); + } + + ctx.SaveChanges(); + return Ok(true); + } + [HttpPost] [Produces("application/xml")] [Route("ContentWebService.asmx/UseInventory")] diff --git a/src/Model/InventoryItem.cs b/src/Model/InventoryItem.cs index 02a62dcb..ea6c5d19 100644 --- a/src/Model/InventoryItem.cs +++ b/src/Model/InventoryItem.cs @@ -8,9 +8,11 @@ public class InventoryItem { public int ItemId { get; set; } public int VikingId { get; set; } - + public string? StatsSerialized { get; set; } + public string? AttributesSerialized { get; set; } + public virtual Viking Viking { get; set; } = null!; public int Quantity { get; set; } diff --git a/src/Services/InventoryService.cs b/src/Services/InventoryService.cs index 9b4e8fb5..ad2c0622 100644 --- a/src/Services/InventoryService.cs +++ b/src/Services/InventoryService.cs @@ -136,6 +136,9 @@ public CommonInventoryData GetCommonInventoryData(Viking viking) { uid.ItemStats = itemData.ItemStatsMap?.ItemStats; uid.ItemTier = itemData.ItemStatsMap?.ItemTier; } + if (item.AttributesSerialized != null) { + uid.UserItemAttributes = XmlUtil.DeserializeXml(item.AttributesSerialized); + } userItemData.Add(uid); } @@ -149,7 +152,7 @@ public bool ItemNeedUniqueInventorySlot(int itemId) { ItemData itemData = itemService.GetItem(itemId); if (itemData.PossibleStatsMap != null) // dragons tactics (battle) items return true; - if (itemService.ItemHasCategory(itemData, 541)) // farm expansion + if (itemService.ItemHasCategory(itemData, new int[] {541, 657})) // farm expansion or customizable items return true; return false; } From 5c802927a02b32ff34f234ded35d7280f279bdf0 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Thu, 4 Jan 2024 00:19:16 +0000 Subject: [PATCH 14/21] job board and quests bugfixes * fix: jobs disappear after completing * fix: jobs (and quest) does not cost items --- src/Controllers/Common/ContentController.cs | 8 +++++++- src/Services/MissionService.cs | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 45173cc2..141c0382 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -759,7 +759,7 @@ public IActionResult SetTaskStatev1(Viking viking, [FromForm] Guid userId, [From [Produces("application/xml")] [Route("V2/ContentWebService.asmx/SetTaskState")] [VikingSession] - public IActionResult SetTaskState(Viking viking, [FromForm] Guid userId, [FromForm] int missionId, [FromForm] int taskId, [FromForm] bool completed, [FromForm] string xmlPayload, [FromForm] string apiKey) { + public IActionResult SetTaskState(Viking viking, [FromForm] Guid userId, [FromForm] int missionId, [FromForm] int taskId, [FromForm] bool completed, [FromForm] string xmlPayload, [FromForm] string commonInventoryRequestXml, [FromForm] string apiKey) { if (viking.Uid != userId) return Unauthorized("Can't set not owned task"); @@ -770,6 +770,12 @@ public IActionResult SetTaskState(Viking viking, [FromForm] Guid userId, [FromFo Status = SetTaskStateStatus.TaskCanBeDone, }; + if (commonInventoryRequestXml.Length > 44) { // avoid process inventory on empty xml request, + // NOTE: client do not set this on empty string when no inventory change request, but send + SetCommonInventory(viking, commonInventoryRequestXml); + taskResult.CommonInvRes = new CommonInventoryResponse { Success = true }; + } + if (results.Count > 0) taskResult.MissionsCompleted = results.ToArray(); diff --git a/src/Services/MissionService.cs b/src/Services/MissionService.cs index 9704c832..767d4234 100644 --- a/src/Services/MissionService.cs +++ b/src/Services/MissionService.cs @@ -74,7 +74,10 @@ public List UpdateTaskProgress(int missionId, int taskId task.Payload = null; task.Completed = false; } - missionState.MissionStatus = MissionStatus.Upcoming; + if (missionStore.GetActiveMissions(apiKey).Contains(missionId)) + missionState.MissionStatus = MissionStatus.Active; + else + missionState.MissionStatus = MissionStatus.Upcoming; } else { missionState.MissionStatus = MissionStatus.Completed; } From ea3de10100f174cdfa23ae89fcb1c068d73bf233 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Sun, 7 Jan 2024 16:24:00 +0000 Subject: [PATCH 15/21] disable sending email in LoginParent reply --- src/Controllers/Common/AuthenticationController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controllers/Common/AuthenticationController.cs b/src/Controllers/Common/AuthenticationController.cs index d7962b62..eff74bb1 100644 --- a/src/Controllers/Common/AuthenticationController.cs +++ b/src/Controllers/Common/AuthenticationController.cs @@ -54,7 +54,7 @@ public IActionResult LoginParent() { var response = new ParentLoginInfo { UserName = user.Username, - Email = user.Email, + //Email = user.Email, /* disabled to avoid put email in client debug logs */ ApiToken = session.ApiToken.ToString(), UserID = user.Id.ToString(), Status = MembershipUserStatus.Success, From 7e5a90ba87857eba9e7c59c8b07d466edc9524da Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Tue, 9 Jan 2024 16:08:42 +0000 Subject: [PATCH 16/21] use utf-8 in xml headers from SerializeXml we use ascii/utf-8 (not utf-16) encoding in files and network data so XML header should be always `` --- src/Util/XmlUtil.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Util/XmlUtil.cs b/src/Util/XmlUtil.cs index ec31f938..aaaaa2e6 100644 --- a/src/Util/XmlUtil.cs +++ b/src/Util/XmlUtil.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Xml.Serialization; +using System.Text; namespace sodoff.Util; public class XmlUtil { @@ -9,9 +10,13 @@ public static T DeserializeXml(string xmlString) { return (T)serializer.Deserialize(reader); } + private class Utf8StringWriter : StringWriter { + public override Encoding Encoding => Encoding.UTF8; + } + public static string SerializeXml(T xmlObject) { var serializer = new XmlSerializer(typeof(T)); - using (var writer = new StringWriter()) { + using (var writer = new Utf8StringWriter()) { serializer.Serialize(writer, xmlObject); return writer.ToString(); } From 36d009dc3a4a466910494740b3eab77f388d4840 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Tue, 9 Jan 2024 20:43:38 +0000 Subject: [PATCH 17/21] implemented SetDisplayName --- README.md | 1 + mitm-redirect.py | 1 + src/Controllers/Common/ContentController.cs | 27 +++++++++++++++++++++ src/Schema/SetDisplayNameRequest.cs | 16 ++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 src/Schema/SetDisplayNameRequest.cs diff --git a/README.md b/README.md index ede22b79..36aa9bf1 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ Then run School of Dragons. - SetAchievementByEntityIDs - SetAvatar - SetCommonInventory +- SetDisplayName (V2) - SetDragonXP (used by account import tools) - SetImage - SetKeyValuePair diff --git a/mitm-redirect.py b/mitm-redirect.py index 86661cf6..360a2132 100644 --- a/mitm-redirect.py +++ b/mitm-redirect.py @@ -86,6 +86,7 @@ 'GetGameDataByGame', 'GetGameDataByGameForDateRange', 'GetTopAchievementPointUsers', + 'SetDisplayName', ] def routable(path): diff --git a/src/Controllers/Common/ContentController.cs b/src/Controllers/Common/ContentController.cs index 141c0382..95610352 100644 --- a/src/Controllers/Common/ContentController.cs +++ b/src/Controllers/Common/ContentController.cs @@ -102,6 +102,33 @@ public IActionResult ValidateName([FromForm] string nameValidationRequest) { } } + [HttpPost] + [Produces("application/xml")] + [Route("/V2/ContentWebService.asmx/SetDisplayName")] + [VikingSession] + public IActionResult SetDisplayName(Viking viking, [FromForm] string request) { + string newName = XmlUtil.DeserializeXml(request).DisplayName; + + if (String.IsNullOrWhiteSpace(newName) || ctx.Vikings.Count(e => e.Name == newName) > 0) { + return Ok(new SetAvatarResult { + Success = false, + StatusCode = AvatarValidationResult.AvatarDisplayNameInvalid + }); + } + + viking.Name = newName; + AvatarData avatarData = XmlUtil.DeserializeXml(viking.AvatarSerialized); + avatarData.DisplayName = newName; + viking.AvatarSerialized = XmlUtil.SerializeXml(avatarData); + ctx.SaveChanges(); + + return Ok(new SetAvatarResult { + Success = true, + DisplayName = viking.Name, + StatusCode = AvatarValidationResult.Valid + }); + } + [HttpPost] [Produces("application/xml")] [Route("ContentWebService.asmx/GetKeyValuePair")] diff --git a/src/Schema/SetDisplayNameRequest.cs b/src/Schema/SetDisplayNameRequest.cs new file mode 100644 index 00000000..ce030aa1 --- /dev/null +++ b/src/Schema/SetDisplayNameRequest.cs @@ -0,0 +1,16 @@ +using System.Xml.Serialization; + +namespace sodoff.Schema; + +[XmlRoot(ElementName = "sdnr", Namespace = "")] +[Serializable] +public class SetDisplayNameRequest { + [XmlElement(ElementName = "dn")] + public string DisplayName { get; set; } + + [XmlElement(ElementName = "iid")] + public int ItemID { get; set; } + + [XmlElement(ElementName = "sid")] + public int StoreID { get; set; } +} From 291324580db37b2edd5154fbdb295f5cc86c1e04 Mon Sep 17 00:00:00 2001 From: J-128 Date: Mon, 30 Oct 2023 20:17:18 -0500 Subject: [PATCH 18/21] missiontext: correct "preposition" to "proposition" Context: Harald: "Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a proposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy." --- src/Resources/missions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index 39610f55..9a12d815 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -93170,7 +93170,7 @@ 6118 2020SnoggletogStory01T04 - <Data><Offer><Type>Popup</Type><ID>940068</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Whatever do you mean, dear Hiccup? Do you think that you have cause to be worried? Fret not, old friend! We have a lot of history between us, and you know I will not attack you without provocation.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><ID>940069</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>'A lot of history between us' is why I'm tense, Harald.</Text><ItemID>0</ItemID><Priority>1</Priority></Offer><End><Type>Popup</Type><ID>940070</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a preposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy.</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubDragonsEdgeDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWHarald</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Harald</Text><ID>927532</ID></Title></Data> + <Data><Offer><Type>Popup</Type><ID>940068</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Whatever do you mean, dear Hiccup? Do you think that you have cause to be worried? Fret not, old friend! We have a lot of history between us, and you know I will not attack you without provocation.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><ID>940069</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>'A lot of history between us' is why I'm tense, Harald.</Text><ItemID>0</ItemID><Priority>1</Priority></Offer><End><Type>Popup</Type><ID>940070</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHarald</NPC><Text>Regardless: I know Snoggletog is important to Berkians. Stormheart and I have a proposition for you, in the spirit of the holidays. I only hope that you can approach it with the same courtesy.</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubDragonsEdgeDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWHarald</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Harald</Text><ID>927532</ID></Title></Data> 0 false From da238de95440b18b57cb819731cf174f2538ebea Mon Sep 17 00:00:00 2001 From: J-128 Date: Sun, 24 Dec 2023 14:35:47 -0600 Subject: [PATCH 19/21] missiontext: correct "Skrill" to "Skrills" context: Dagur: "We were out searching for Skrills to join the Berserkers when we came across her. We think she was trying to become friends with a Skrill at Glacier Island, but the Skrill was having none of it. No fault of our mystery dragon; Skrills just are very territorial!" --- src/Resources/missions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index 9a12d815..1989ca94 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -3842,7 +3842,7 @@ 5691 Dreadfall2019Q03T06 - <Data><Offer><Type>Popup</Type><ID>939093</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWMala</NPC><Text>That you are, my fierce flame. It's just as well that you're here, {{Name}}. Our dragon hasn't been too cooperative on the way over here.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><ID>939094</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWDagur</NPC><Text>My darling Mala was the one to discover the one you were looking for. We were out searching for Skrills to join the Berserkers when we came across her. We think she was trying to become friends with a Skrill at Glacier Island, but the Skrill was having none of it. No fault of our mystery dragon; Skrill just are very territorial!</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubTrainingDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWDagur</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Dagur</Text><ID>928987</ID></Title><Desc><Text>Talk to Dagur.</Text><ID>931908</ID></Desc></Data> + <Data><Offer><Type>Popup</Type><ID>939093</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWMala</NPC><Text>That you are, my fierce flame. It's just as well that you're here, {{Name}}. Our dragon hasn't been too cooperative on the way over here.</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><ID>939094</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWDagur</NPC><Text>My darling Mala was the one to discover the one you were looking for. We were out searching for Skrills to join the Berserkers when we came across her. We think she was trying to become friends with a Skrill at Glacier Island, but the Skrill was having none of it. No fault of our mystery dragon; Skrills just are very territorial!</Text><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Scene</Key><Value>HubTrainingDO</Value></Pair><Pair><Key>NPC</Key><Value>PfDWDagur</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Meet</Type><Title><Text>Talk to Dagur</Text><ID>928987</ID></Title><Desc><Text>Talk to Dagur.</Text><ID>931908</ID></Desc></Data> 0 false From de914d6e3eb07288b167c782acd40c8f211e049f Mon Sep 17 00:00:00 2001 From: J-128 Date: Sun, 24 Dec 2023 14:45:56 -0600 Subject: [PATCH 20/21] taskdesc: correct 12 to 15 Context: <Text>Work with your dragon to collect 15 flowers</Text> --- src/Resources/missions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index 1989ca94..3141b67f 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -92316,7 +92316,7 @@ 441 Task 2.1 collect 15 flowers - <Data><Setup><Scene>HubSchoolDO</Scene><Asset>RS_DATA/PfGrpQTeenHic02T01.unity3d/PfGrpQTeenHic02T01</Asset><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Toothless is my best friend; the very first time I looked at him, I saw myself. I knew it would be just me and him forever. That's the bond you and your dragon need to make. You should trust {{dragon name}} as much as you do yourself. @@ How about some bonding exercises? Ride {{dragon name}} and collect the scented flowers around the school. Dragons love the smell!</Text><ID>904750</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>VO</Type><Asset>RS_DATA/DlgDWHiccupDO.unity3d/DlgHiccupToothless01</Asset><NPC>PfDWHiccup</NPC><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>That was amazing and some great team work! </Text><ID>904751</ID><ItemID>0</ItemID><Priority>0</Priority></End><End><Type>VO</Type><Asset>RS_DATA/DlgDWHiccupDO.unity3d/DlgHiccupPos03</Asset><NPC>PfDWHiccup</NPC><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Name</Key><Value>PfCollectDWFlower02</Value></Pair><Pair><Key>Quantity</Key><Value>15</Value></Pair></Objective><Type>Collect</Type><Title><Text>Work with your dragon to collect 12 flowers</Text><ID>904748</ID></Title><Desc><Text>Collect 12 scented flowers around the school.</Text><ID>922953</ID></Desc></Data> + <Data><Setup><Scene>HubSchoolDO</Scene><Asset>RS_DATA/PfGrpQTeenHic02T01.unity3d/PfGrpQTeenHic02T01</Asset><Recursive>false</Recursive><Persistent>false</Persistent></Setup><Offer><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>Toothless is my best friend; the very first time I looked at him, I saw myself. I knew it would be just me and him forever. That's the bond you and your dragon need to make. You should trust {{dragon name}} as much as you do yourself. @@ How about some bonding exercises? Ride {{dragon name}} and collect the scented flowers around the school. Dragons love the smell!</Text><ID>904750</ID><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>VO</Type><Asset>RS_DATA/DlgDWHiccupDO.unity3d/DlgHiccupToothless01</Asset><NPC>PfDWHiccup</NPC><ItemID>0</ItemID><Priority>0</Priority></Offer><End><Type>Popup</Type><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWHiccup</NPC><Text>That was amazing and some great team work! </Text><ID>904751</ID><ItemID>0</ItemID><Priority>0</Priority></End><End><Type>VO</Type><Asset>RS_DATA/DlgDWHiccupDO.unity3d/DlgHiccupPos03</Asset><NPC>PfDWHiccup</NPC><ItemID>0</ItemID><Priority>0</Priority></End><Objective><Pair><Key>Name</Key><Value>PfCollectDWFlower02</Value></Pair><Pair><Key>Quantity</Key><Value>15</Value></Pair></Objective><Type>Collect</Type><Title><Text>Work with your dragon to collect 15 flowers</Text><ID>904748</ID></Title><Desc><Text>Collect 12 scented flowers around the school.</Text><ID>922953</ID></Desc></Data> 0 false From f66c3e49da4332b8832afa8cc53da15ae8785272 Mon Sep 17 00:00:00 2001 From: J-128 Date: Tue, 9 Jan 2024 19:44:26 -0600 Subject: [PATCH 21/21] missiontext: correct "aren't" to "didn't" Context: Ruffnut: "You just picked a random island, didn't you?" --- src/Resources/missions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/missions.xml b/src/Resources/missions.xml index 3141b67f..369a3c33 100644 --- a/src/Resources/missions.xml +++ b/src/Resources/missions.xml @@ -41969,7 +41969,7 @@ 6573 Thawfest2022Story02T01 - <Data><Offer><Type>Popup</Type><ID>942370</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWRuffnut</NPC><Text>Let’s chase down that new zipple-dragon! Now, which way did it go again…</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><ID>942371</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWTuffnut</NPC><Text>Well, it left [c][3eebff]Old Berk[/c][ffffff] heading in a northeast direction. Based on that heading, and accounting for air currents, I surmise that it was headed for [c][3eebff]Scuttleclaw Island[/c][ffffff]!</Text><ItemID>0</ItemID><Priority>1</Priority></Offer><Offer><Type>Popup</Type><ID>942372</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWRuffnut</NPC><Text>You just picked a random island, aren’t you?</Text><ItemID>0</ItemID><Priority>2</Priority></Offer><Offer><Type>Popup</Type><ID>942373</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWTuffnut</NPC><Text>Of course I did, who do I look like Heather? @@Well, I guess my hair is long enough…</Text><ItemID>0</ItemID><Priority>3</Priority></Offer><Offer><Type>Popup</Type><ID>942374</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWRuffnut</NPC><Text>Race you to [c][3eebff]Scuttleclaw Island[/c][ffffff], {{Name}}!</Text><ItemID>0</ItemID><Priority>4</Priority></Offer><Objective><Pair><Key>Scene</Key><Value>ScuttleclawIslandDO</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Visit</Type><Title><Text>Go to Scuttleclaw Island</Text><ID>930024</ID></Title><Desc><Text>Go to Scuttleclaw Island</Text><ID>938741</ID></Desc></Data> + <Data><Offer><Type>Popup</Type><ID>942370</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWRuffnut</NPC><Text>Let’s chase down that new zipple-dragon! Now, which way did it go again…</Text><ItemID>0</ItemID><Priority>0</Priority></Offer><Offer><Type>Popup</Type><ID>942371</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWTuffnut</NPC><Text>Well, it left [c][3eebff]Old Berk[/c][ffffff] heading in a northeast direction. Based on that heading, and accounting for air currents, I surmise that it was headed for [c][3eebff]Scuttleclaw Island[/c][ffffff]!</Text><ItemID>0</ItemID><Priority>1</Priority></Offer><Offer><Type>Popup</Type><ID>942372</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWRuffnut</NPC><Text>You just picked a random island, didn’t you?</Text><ItemID>0</ItemID><Priority>2</Priority></Offer><Offer><Type>Popup</Type><ID>942373</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWTuffnut</NPC><Text>Of course I did, who do I look like Heather? @@Well, I guess my hair is long enough…</Text><ItemID>0</ItemID><Priority>3</Priority></Offer><Offer><Type>Popup</Type><ID>942374</ID><Asset>PfUiMissionActionDBDO</Asset><NPC>PfDWRuffnut</NPC><Text>Race you to [c][3eebff]Scuttleclaw Island[/c][ffffff], {{Name}}!</Text><ItemID>0</ItemID><Priority>4</Priority></Offer><Objective><Pair><Key>Scene</Key><Value>ScuttleclawIslandDO</Value></Pair><Pair><Key>Time</Key><Value>0</Value></Pair><Pair><Key>HideArrow</Key><Value>False</Value></Pair></Objective><Type>Visit</Type><Title><Text>Go to Scuttleclaw Island</Text><ID>930024</ID></Title><Desc><Text>Go to Scuttleclaw Island</Text><ID>938741</ID></Desc></Data> 0 false