Added archiving and fixed list economy tracing bug.

This commit is contained in:
sarah committed 2026-09-07 21:54:53 +02:00
1 parent 8a6d3b27e3
commit bf630894e1
6 files changed
+580 -19

No files matched your search

+8
View File
@@ -205,6 +205,14 @@ $PageSection = "Guide";
<a href="/Pages/Mutations.html">Mutation encyclopedia</a>.
</p>
<p>
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.
</p>
<p>
Experiment with different plants, empty spaces, and
arrangements. Not every recipe has to look like the
+302 -4
View File
@@ -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;
}
+121 -4
View File
@@ -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(
+4
View File
@@ -277,6 +277,10 @@ function FindGardenMutationCandidates(
MutationSets
)
) {
if (Mutation.Archived === true) {
continue;
}
for (
const Orientation
of GetMutationOrientations(
+3
View File
@@ -33,6 +33,9 @@ function DoesPlantCatalogueMatchSearch(
Plant.Id,
Plant.Name,
Plant.Description,
Plant.Archived === true
? "Archived"
: "",
...(Array.isArray(Plant.Tags)
? Plant.Tags
: [])
+142 -11
View File
@@ -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
);