From bf630894e1a01dd1edfc40cbaa283c10b092f87d Mon Sep 17 00:00:00 2001
From: Sarahtonin
+ Retired content may be archived instead of deleted. + Archived plants and mutations no longer take part in + normal progression, but anything you already discovered + stays part of your Garden history and remains identified + as archived in the encyclopedias. +
+Experiment with different plants, empty spaces, and arrangements. Not every recipe has to look like the diff --git a/Scripts/Garden/Economy.js b/Scripts/Garden/Economy.js index cddc021..d377148 100644 --- a/Scripts/Garden/Economy.js +++ b/Scripts/Garden/Economy.js @@ -177,6 +177,10 @@ function IsPlantAvailableInShop( SaveData, Plant ) { + if (Plant.Archived === true) { + return false; + } + if ( Plant.Shop?.ShopPlant === true @@ -325,6 +329,10 @@ function GetPlantShopCost( MutationSets ) ) { + if (Mutation.Archived === true) { + continue; + } + if ( !HasDiscoveredMutation( SaveData, @@ -392,6 +400,10 @@ function GetMutationIngredientCost( Visiting ) { let TotalCost = 0; + const ListReferenceCounts = + GetEconomyMutationListReferenceCounts( + Mutation.Pattern + ); for ( @@ -405,7 +417,10 @@ function GetMutationIngredientCost( if ( Matcher === null || Matcher === "Empty" || - Matcher === "Any" + Matcher === "Any" || + GetEconomyMutationListReference( + Matcher + ) !== null ) { continue; } @@ -428,10 +443,240 @@ function GetMutationIngredientCost( } + for ( + const [ + ListNumber, + ReferenceCount + ] + of ListReferenceCounts + ) { + const List = + Mutation.Lists?.[ + ListNumber - 1 + ]; + + const ListCost = + GetMutationListSeedCost( + List, + ReferenceCount, + Item => + GetMutationListItemSeedCost( + Item, + Plants, + Plant => + GetPlantShopCost( + SaveData, + Plant.Id, + Cache, + Visiting + ), + Plant => + IsPlantAvailableInShop( + SaveData, + Plant + ) + ) + ); + + if (ListCost === null) { + return null; + } + + TotalCost += ListCost; + } + + return TotalCost; } +function GetEconomyMutationListReference( + Matcher +) { + if (typeof Matcher !== "string") { + return null; + } + + const Match = + /^List:([1-9][0-9]*)$/.exec( + Matcher + ); + + return Match === null + ? null + : Number(Match[1]); +} + + +function GetEconomyMutationListReferenceCounts( + Pattern +) { + const Counts = new Map(); + + for (const Row of Pattern ?? []) { + if (!Array.isArray(Row)) { + continue; + } + + for (const Matcher of Row) { + const ListNumber = + GetEconomyMutationListReference( + Matcher + ); + + if (ListNumber === null) { + continue; + } + + Counts.set( + ListNumber, + (Counts.get(ListNumber) ?? 0) + 1 + ); + } + } + + return Counts; +} + + +function GetMutationListSeedCost( + List, + ReferenceCount, + GetItemCost +) { + if ( + List === null || + typeof List !== "object" || + !Array.isArray(List.Items) || + List.Items.length === 0 || + !Number.isInteger(ReferenceCount) || + ReferenceCount <= 0 + ) { + return null; + } + + const ItemCosts = []; + + for (const Item of List.Items) { + const Cost = GetItemCost(Item); + + if ( + Cost === null || + !Number.isFinite(Cost) || + Cost < 0 + ) { + continue; + } + + ItemCosts.push(Cost); + } + + if (ItemCosts.length === 0) { + return null; + } + + if (List.Mode !== "Once") { + return ( + Math.min(...ItemCosts) * + ReferenceCount + ); + } + + if (ItemCosts.length < ReferenceCount) { + return null; + } + + ItemCosts.sort( + (A, B) => A - B + ); + + return ItemCosts + .slice(0, ReferenceCount) + .reduce( + (Total, Cost) => + Total + Cost, + 0 + ); +} + + +function GetMutationListItemSeedCost( + Item, + PlantCatalogue, + GetPlantCost, + IsPlantCandidateAvailable +) { + if ( + Item === null || + typeof Item !== "object" || + Array.isArray(Item) + ) { + return null; + } + + if ( + Item.Type === "Any" || + Item.Type === "Empty" + ) { + return 0; + } + + if (Item.Type === "Plant") { + const Plant = + PlantCatalogue[Item.Value]; + + if ( + Plant === undefined || + Plant.Archived === true + ) { + return null; + } + + return GetPlantCost(Plant); + } + + if (Item.Type !== "Tag") { + return null; + } + + let CheapestCost = null; + + for ( + const Plant + of Object.values( + PlantCatalogue + ) + ) { + if ( + !IsPlantCandidateAvailable( + Plant + ) || + !Array.isArray(Plant.Tags) || + !Plant.Tags.includes( + Item.Value + ) + ) { + continue; + } + + const Cost = GetPlantCost(Plant); + + if (Cost === null) { + continue; + } + + if ( + CheapestCost === null || + Cost < CheapestCost + ) { + CheapestCost = Cost; + } + } + + return CheapestCost; +} + + function GetMatcherSeedCost( SaveData, Matcher, @@ -442,7 +687,10 @@ function GetMatcherSeedCost( const Plant = Plants[Matcher]; - if (Plant === undefined) { + if ( + Plant === undefined || + Plant.Archived === true + ) { return null; } @@ -470,7 +718,10 @@ function GetMatcherSeedCost( const Plant = Plants[Matcher.Plant]; - if (Plant === undefined) { + if ( + Plant === undefined || + Plant.Archived === true + ) { return null; } @@ -974,13 +1225,20 @@ function GetCatalogueMutationIngredientCost( Visiting ) { let TotalCost = 0; + const ListReferenceCounts = + GetEconomyMutationListReferenceCounts( + Mutation.Pattern + ); for (const Row of Mutation.Pattern ?? []) { for (const Matcher of Row) { if ( Matcher === null || Matcher === "Empty" || - Matcher === "Any" + Matcher === "Any" || + GetEconomyMutationListReference( + Matcher + ) !== null ) { continue; } @@ -1002,6 +1260,46 @@ function GetCatalogueMutationIngredientCost( } } + for ( + const [ + ListNumber, + ReferenceCount + ] + of ListReferenceCounts + ) { + const List = + Mutation.Lists?.[ + ListNumber - 1 + ]; + + const ListCost = + GetMutationListSeedCost( + List, + ReferenceCount, + Item => + GetMutationListItemSeedCost( + Item, + PlantCatalogue, + Plant => + GetCataloguePlantCostInfo( + Plant.Id, + PlantCatalogue, + MutationCatalogue, + Cache, + Visiting + )?.Cost ?? null, + Plant => + Plant.Archived !== true + ) + ); + + if (ListCost === null) { + return null; + } + + TotalCost += ListCost; + } + return TotalCost; } diff --git a/Scripts/Garden/MutationEncyclopedia.js b/Scripts/Garden/MutationEncyclopedia.js index 1ac3784..9aa728e 100644 --- a/Scripts/Garden/MutationEncyclopedia.js +++ b/Scripts/Garden/MutationEncyclopedia.js @@ -97,12 +97,25 @@ function RenderMutationEncyclopedia() { ) ); + const ActiveDiscoveredMutations = + DiscoveredMutations.filter( + Mutation => + Mutation.Archived !== true + ); + + const ArchivedDiscoveredMutations = + DiscoveredMutations.filter( + Mutation => + Mutation.Archived === true + ); + const AvailableHints = HasMutationHintsUpgrade( MutationEncyclopediaSave ) ? AllMutations.filter( Mutation => + Mutation.Archived !== true && !HasDiscoveredMutation( MutationEncyclopediaSave, Mutation.Id @@ -142,8 +155,8 @@ function RenderMutationEncyclopedia() { ) ); - const VisibleMutations = - DiscoveredMutations + const VisibleActiveMutations = + ActiveDiscoveredMutations .filter( Mutation => DoesMutationEncyclopediaMatchSearch( @@ -155,6 +168,24 @@ function RenderMutationEncyclopedia() { CompareMutationEncyclopediaMutations ); + const VisibleArchivedMutations = + ArchivedDiscoveredMutations + .filter( + Mutation => + DoesMutationEncyclopediaMatchSearch( + Mutation, + SearchQuery + ) + ) + .sort( + CompareMutationEncyclopediaMutations + ); + + const VisibleMutations = [ + ...VisibleActiveMutations, + ...VisibleArchivedMutations + ]; + if (VisibleHints.length > 0) { List.appendChild( @@ -173,7 +204,7 @@ function RenderMutationEncyclopedia() { for ( const Mutation - of VisibleMutations + of VisibleActiveMutations ) { List.appendChild( CreateMutationEncyclopediaCard( @@ -183,6 +214,26 @@ function RenderMutationEncyclopedia() { } + if (VisibleArchivedMutations.length > 0) { + List.appendChild( + CreateMutationEncyclopediaArchivedHeading( + VisibleArchivedMutations.length + ) + ); + + for ( + const Mutation + of VisibleArchivedMutations + ) { + List.appendChild( + CreateMutationEncyclopediaCard( + Mutation + ) + ); + } + } + + if ( DiscoveredMutations.length === 0 && AvailableHints.length === 0 @@ -229,6 +280,16 @@ function RenderMutationEncyclopedia() { ); } + if (ArchivedDiscoveredMutations.length > 0) { + MessageParts.push( + ArchivedDiscoveredMutations.length === 1 + ? "1 archived mutation." + : ArchivedDiscoveredMutations.length + .toLocaleString() + + " archived mutations." + ); + } + if (AvailableHints.length > 0) { MessageParts.push( "Showing " + @@ -251,6 +312,41 @@ function RenderMutationEncyclopedia() { } +function CreateMutationEncyclopediaArchivedHeading( + Count +) { + const Header = + document.createElement( + "header" + ); + + const Heading = + document.createElement( + "h2" + ); + + Heading.textContent = + "Archived (" + + Count.toLocaleString() + + ")"; + + const Description = + document.createElement( + "p" + ); + + Description.textContent = + "Retired mutations you discovered remain recorded here."; + + Header.append( + Heading, + Description + ); + + return Header; +} + + function DoesMutationHintMatchSearch( Mutation, SearchQuery @@ -282,6 +378,9 @@ function DoesMutationEncyclopediaMatchSearch( Mutation.Name, Mutation.Description, Mutation.Hint, + Mutation.Archived === true + ? "Archived" + : "", FormatMutationChance( Mutation.Chance ), @@ -552,6 +651,7 @@ function IsHintListItemAvailable( return ( Plant !== undefined && + Plant.Archived !== true && HasDiscoveredPlant( SaveData, Plant.Id @@ -564,6 +664,7 @@ function IsHintListItemAvailable( Plants ).some( Plant => + Plant.Archived !== true && HasDiscoveredPlant( SaveData, Plant.Id @@ -677,6 +778,7 @@ function IsHintMatcherAvailable( return ( Plant !== undefined && + Plant.Archived !== true && HasDiscoveredPlant( SaveData, Plant.Id @@ -698,6 +800,7 @@ function IsHintMatcherAvailable( Plants ).some( ([PlantKey, Plant]) => + Plant.Archived !== true && HasDiscoveredPlant( SaveData, Plant.Id @@ -1019,6 +1122,15 @@ function CreateMutationEncyclopediaStats( ) ); + if (Mutation.Archived === true) { + Stats.appendChild( + CreateMutationEncyclopediaStat( + "Status", + "Archived" + ) + ); + } + return Stats; } @@ -2049,7 +2161,12 @@ function CreateMutationPlantRelation( PlantId; Link.textContent = - Plant.Name; + Plant.Name + + ( + Plant.Archived === true + ? " (archived)" + : "" + ); Item.appendChild( diff --git a/Scripts/Garden/MutationEngine.js b/Scripts/Garden/MutationEngine.js index 5b01645..80e5462 100644 --- a/Scripts/Garden/MutationEngine.js +++ b/Scripts/Garden/MutationEngine.js @@ -277,6 +277,10 @@ function FindGardenMutationCandidates( MutationSets ) ) { + if (Mutation.Archived === true) { + continue; + } + for ( const Orientation of GetMutationOrientations( diff --git a/Scripts/Garden/PlantCatalogue.js b/Scripts/Garden/PlantCatalogue.js index 58f9390..72e6a44 100644 --- a/Scripts/Garden/PlantCatalogue.js +++ b/Scripts/Garden/PlantCatalogue.js @@ -33,6 +33,9 @@ function DoesPlantCatalogueMatchSearch( Plant.Id, Plant.Name, Plant.Description, + Plant.Archived === true + ? "Archived" + : "", ...(Array.isArray(Plant.Tags) ? Plant.Tags : []) diff --git a/Scripts/Garden/PlantEncyclopedia.js b/Scripts/Garden/PlantEncyclopedia.js index ba43baa..85be84c 100644 --- a/Scripts/Garden/PlantEncyclopedia.js +++ b/Scripts/Garden/PlantEncyclopedia.js @@ -88,13 +88,25 @@ function RenderPlantEncyclopedia() { ) ); + const ActivePlants = + DiscoveredPlants.filter( + Plant => + Plant.Archived !== true + ); + + const ArchivedPlants = + DiscoveredPlants.filter( + Plant => + Plant.Archived === true + ); + const SearchQuery = PlantEncyclopediaSearchQuery .trim() .toLocaleLowerCase(); - const VisiblePlants = - DiscoveredPlants + const VisibleActivePlants = + ActivePlants .filter( Plant => DoesPlantEncyclopediaMatchSearch( @@ -106,6 +118,24 @@ function RenderPlantEncyclopedia() { ComparePlantEncyclopediaPlants ); + const VisibleArchivedPlants = + ArchivedPlants + .filter( + Plant => + DoesPlantEncyclopediaMatchSearch( + Plant, + SearchQuery + ) + ) + .sort( + ComparePlantEncyclopediaPlants + ); + + const VisiblePlants = [ + ...VisibleActivePlants, + ...VisibleArchivedPlants + ]; + if (DiscoveredPlants.length === 0) { SetPlantEncyclopediaMessage( @@ -127,7 +157,7 @@ function RenderPlantEncyclopedia() { for ( const Plant - of VisiblePlants + of VisibleActivePlants ) { List.appendChild( CreatePlantEncyclopediaCard( @@ -137,6 +167,36 @@ function RenderPlantEncyclopedia() { } + if (VisibleArchivedPlants.length > 0) { + List.appendChild( + CreatePlantEncyclopediaArchivedHeading( + VisibleArchivedPlants.length + ) + ); + + for ( + const Plant + of VisibleArchivedPlants + ) { + List.appendChild( + CreatePlantEncyclopediaCard( + Plant + ) + ); + } + } + + + const ArchivedSummary = + ArchivedPlants.length > 0 + ? " " + + ArchivedPlants.length + .toLocaleString() + + (ArchivedPlants.length === 1 + ? " archived plant." + : " archived plants.") + : ""; + if (SearchQuery.length > 0) { SetPlantEncyclopediaMessage( "Showing " + @@ -145,7 +205,8 @@ function RenderPlantEncyclopedia() { " of " + DiscoveredPlants.length .toLocaleString() + - " discovered plants." + " discovered plants." + + ArchivedSummary ); return; @@ -153,15 +214,52 @@ function RenderPlantEncyclopedia() { SetPlantEncyclopediaMessage( - DiscoveredPlants.length === 1 - ? "1 plant discovered." - : DiscoveredPlants.length - .toLocaleString() + - " plants discovered." + ( + DiscoveredPlants.length === 1 + ? "1 plant discovered." + : DiscoveredPlants.length + .toLocaleString() + + " plants discovered." + ) + ArchivedSummary ); } +function CreatePlantEncyclopediaArchivedHeading( + Count +) { + const Header = + document.createElement( + "header" + ); + + const Heading = + document.createElement( + "h2" + ); + + Heading.textContent = + "Archived (" + + Count.toLocaleString() + + ")"; + + const Description = + document.createElement( + "p" + ); + + Description.textContent = + "Retired plants you discovered remain recorded here."; + + Header.append( + Heading, + Description + ); + + return Header; +} + + function DoesPlantEncyclopediaMatchSearch( Plant, SearchQuery @@ -384,6 +482,16 @@ function CreatePlantEncyclopediaDetails( ); + if (Plant.Archived === true) { + Details.appendChild( + CreatePlantEncyclopediaStat( + "Status", + "Archived" + ) + ); + } + + Details.appendChild( CreatePlantEncyclopediaStat( "Growth", @@ -545,6 +653,15 @@ function CreatePlantMutationRelationGroup( Heading, Mutations ) { + Mutations = Mutations.filter( + Mutation => + Mutation.Archived !== true || + HasDiscoveredMutation( + PlantEncyclopediaSave, + Mutation.Id + ) + ); + const Group = document.createElement( "section" @@ -646,7 +763,12 @@ function CreatePlantMutationRelation( Mutation.Id; Link.textContent = - Mutation.Name; + Mutation.Name + + ( + Mutation.Archived === true + ? " (archived)" + : "" + ); Item.appendChild( @@ -684,7 +806,16 @@ function GetPlantRecipeProgress( Number(PlantId) ); - if (IsRelated) { + if ( + IsRelated && + ( + Mutation.Archived !== true || + HasDiscoveredMutation( + PlantEncyclopediaSave, + Mutation.Id + ) + ) + ) { RelatedMutationIds.add( Mutation.Id );