Added mutation hint upgrade.

This commit is contained in:
sarah committed 2026-09-03 09:36:16 +02:00
1 parent f37d0a77f9
commit 8f27468b5e
7 files changed
+582 -19

No files matched your search

+4 -1
View File
@@ -20,7 +20,9 @@ $PageSection = "Mutations";
<p>
Every mutation you discover is recorded here.
Once found, its recipe and result stay visible so
you can recreate it whenever you want.
you can recreate it whenever you want. Mutation
hints may also appear here for recipes you are
currently capable of discovering.
</p>
<div
@@ -43,6 +45,7 @@ $PageSection = "Mutations";
<script src="/Scripts/Garden/Save.js"></script>
<script src="/Scripts/Garden/Content.js"></script>
<script src="/Scripts/Garden/Economy.js"></script>
<script src="/Scripts/Garden/Upgrades.js"></script>
<script src="/Scripts/Garden/MutationEncyclopedia.js"></script>
</body>
</html>
+1 -1
View File
@@ -1,7 +1,7 @@
const GameContentCacheName =
"SarahtoninGardenContent";
const GameContentCacheSchemaVersion = 1;
const GameContentCacheSchemaVersion = 2;
/*
* Once content has been checked, page loads for the next
+357 -15
View File
@@ -31,31 +31,54 @@ function RenderMutationEncyclopedia() {
List.replaceChildren();
const DiscoveredMutations =
const AllMutations =
Object.values(
MutationSets
)
.filter(
Mutation =>
HasDiscoveredMutation(
MutationEncyclopediaSave,
Mutation.Id
)
)
.sort(
(A, B) =>
A.Id - B.Id
);
if (
DiscoveredMutations.length === 0
) {
SetMutationEncyclopediaMessage(
"No mutations discovered yet."
const DiscoveredMutations =
AllMutations.filter(
Mutation =>
HasDiscoveredMutation(
MutationEncyclopediaSave,
Mutation.Id
)
);
return;
const AvailableHints =
HasMutationHintsUpgrade(
MutationEncyclopediaSave
)
? AllMutations.filter(
Mutation =>
!HasDiscoveredMutation(
MutationEncyclopediaSave,
Mutation.Id
) &&
HasUsableMutationHint(
Mutation
) &&
CanAttemptHintedMutation(
Mutation,
MutationEncyclopediaSave
)
)
: [];
for (
const Mutation
of AvailableHints
) {
List.appendChild(
CreateMutationHintCard(
Mutation.Hint
)
);
}
@@ -71,13 +94,332 @@ function RenderMutationEncyclopedia() {
}
if (
DiscoveredMutations.length === 0 &&
AvailableHints.length === 0
) {
SetMutationEncyclopediaMessage(
"No mutations discovered yet."
);
return;
}
const MessageParts = [];
MessageParts.push(
DiscoveredMutations.length === 1
? "1 mutation discovered."
: DiscoveredMutations.length
.toLocaleString() +
" mutations discovered."
);
if (AvailableHints.length > 0) {
MessageParts.push(
AvailableHints.length === 1
? "1 hint available."
: AvailableHints.length
.toLocaleString() +
" hints available."
);
}
SetMutationEncyclopediaMessage(
MessageParts.join(
" "
)
);
}
function HasUsableMutationHint(
Mutation
) {
return (
typeof Mutation.Hint ===
"string" &&
Mutation.Hint.trim().length > 0
);
}
function CanAttemptHintedMutation(
Mutation,
SaveData
) {
if (
!CanMutationPatternFitGarden(
Mutation,
SaveData
)
) {
return false;
}
if (!Array.isArray(Mutation.Pattern)) {
return false;
}
return Mutation.Pattern.every(
Row =>
Array.isArray(Row) &&
Row.every(
Matcher =>
IsHintMatcherAvailable(
Matcher,
SaveData
)
)
);
}
function CanMutationPatternFitGarden(
Mutation,
SaveData
) {
const Pattern =
Mutation.Pattern;
if (
!Array.isArray(Pattern) ||
Pattern.length === 0
) {
return false;
}
const PatternHeight =
Pattern.length;
const PatternWidth =
Math.max(
0,
...Pattern.map(
Row =>
Array.isArray(Row)
? Row.length
: 0
)
);
if (PatternWidth === 0) {
return false;
}
const GardenWidth =
Number(
SaveData.Garden?.Width ?? 0
);
const GardenHeight =
Number(
SaveData.Garden?.Height ?? 0
);
const FitsNormally =
PatternWidth <= GardenWidth &&
PatternHeight <= GardenHeight;
if (FitsNormally) {
return true;
}
return (
Mutation.Rotation === "Any" &&
PatternHeight <= GardenWidth &&
PatternWidth <= GardenHeight
);
}
function IsHintMatcherAvailable(
Matcher,
SaveData
) {
if (
Matcher === null ||
Matcher === "Any" ||
Matcher === "Empty"
) {
return true;
}
if (typeof Matcher === "string") {
const Plant =
Plants[Matcher];
return (
Plant !== undefined &&
HasDiscoveredPlant(
SaveData,
Plant.Id
)
);
}
if (
Matcher === null ||
typeof Matcher !== "object" ||
Array.isArray(Matcher)
) {
return false;
}
return Object.entries(
Plants
).some(
([PlantKey, Plant]) =>
HasDiscoveredPlant(
SaveData,
Plant.Id
) &&
DoesPlantMatchHintMatcher(
PlantKey,
Plant,
Matcher
)
);
}
function DoesPlantMatchHintMatcher(
PlantKey,
Plant,
Matcher
) {
if (
typeof Matcher.Plant ===
"string" &&
Matcher.Plant !== PlantKey
) {
return false;
}
const Tags =
Array.isArray(Plant.Tags)
? Plant.Tags
: [];
if (
Array.isArray(
Matcher.Tags
) &&
!Matcher.Tags.every(
Tag =>
Tags.includes(Tag)
)
) {
return false;
}
if (
Array.isArray(
Matcher.TagsAny
) &&
Matcher.TagsAny.length > 0 &&
!Matcher.TagsAny.some(
Tag =>
Tags.includes(Tag)
)
) {
return false;
}
if (
Array.isArray(
Matcher.TagsNot
) &&
Matcher.TagsNot.some(
Tag =>
Tags.includes(Tag)
)
) {
return false;
}
return true;
}
function CreateMutationHintCard(
Hint
) {
const Card =
document.createElement(
"article"
);
Card.className =
"Panel MutationEncyclopediaCard MutationHintCard";
const Header =
document.createElement(
"header"
);
Header.className =
"MutationEncyclopediaHeader";
const Name =
document.createElement(
"h2"
);
Name.textContent =
"Mutation hint";
Header.appendChild(Name);
const Body =
document.createElement(
"div"
);
Body.className =
"MutationEncyclopediaBody";
const HintText =
document.createElement(
"p"
);
HintText.className =
"MutationEncyclopediaDescription";
HintText.textContent =
Hint.trim();
Body.appendChild(
HintText
);
Card.append(
Header,
Body
);
return Card;
}
+6 -1
View File
@@ -68,7 +68,8 @@ function CreateNewSave() {
Upgrades: {
PlotSize: 0,
PlantInformation: false,
GardenOverview: false
GardenOverview: false,
MutationHints: false
},
Preferences: {
@@ -260,6 +261,10 @@ function NormalizeSaveData(
SaveData.Upgrades.GardenOverview ===
true;
SaveData.Upgrades.MutationHints =
SaveData.Upgrades.MutationHints ===
true;
SaveData.Preferences ??= {};
+174 -1
View File
@@ -125,7 +125,8 @@ function RenderGardenUpgrades() {
"Row"
),
CreatePlantInformationUpgradeCard(),
CreateGardenOverviewUpgradeCard()
CreateGardenOverviewUpgradeCard(),
CreateMutationHintsUpgradeCard()
);
}
@@ -504,6 +505,120 @@ function CreateGardenOverviewUpgradeCard() {
}
function CreateMutationHintsUpgradeCard() {
const Cost =
GetMutationHintsUpgradeCost();
const IsOwned =
HasMutationHintsUpgrade(
ShopSave
);
const Card =
document.createElement(
"article"
);
Card.className =
"Panel ShopItem";
const Header =
document.createElement(
"div"
);
Header.className =
"ShopItemHeader";
const Name =
document.createElement(
"h3"
);
Name.textContent =
"Mutation hints";
Header.appendChild(Name);
const Description =
document.createElement(
"p"
);
Description.textContent =
"Show subtle hints for undiscovered mutations once you've discovered the plants needed to attempt them. Hints appear in the Mutation encyclopedia without revealing the recipe.";
const Details =
document.createElement(
"div"
);
Details.className =
"ShopItemDetails";
Details.append(
CreateShopStat(
"Mutation hints",
IsOwned
? "Unlocked"
: "Locked"
),
CreateShopStat(
"Requirements",
"Required plants discovered"
)
);
const BuyButton =
document.createElement(
"button"
);
BuyButton.className =
"ActionButton ShopBuyButton";
BuyButton.type = "button";
if (IsOwned) {
BuyButton.textContent =
"Purchased";
BuyButton.disabled = true;
} else {
BuyButton.textContent =
"Buy - " +
Cost.toLocaleString() +
" Dew";
BuyButton.disabled =
ShopSave.Currency.Dew < Cost ||
ShopPurchasePending;
BuyButton.addEventListener(
"click",
BuyMutationHintsUpgrade
);
}
Card.append(
Header,
Description,
Details,
BuyButton
);
return Card;
}
function CreateShopSeedCard(
Plant
) {
@@ -1189,6 +1304,64 @@ async function BuyGardenOverviewUpgrade() {
}
async function BuyMutationHintsUpgrade() {
if (
ShopPurchasePending ||
HasMutationHintsUpgrade(
ShopSave
)
) {
return;
}
const Cost =
GetMutationHintsUpgradeCost();
if (
ShopSave.Currency.Dew <
Cost
) {
SetShopMessage(
"You don't have enough Dew for Mutation hints."
);
return;
}
ShopPurchasePending = true;
try {
ShopSave.Currency.Dew -=
Cost;
ShopSave.Statistics.CurrencySpent.Dew +=
Cost;
UnlockMutationHints(
ShopSave
);
SetShopMessage(
"Bought Mutation hints for " +
Cost.toLocaleString() +
" Dew. Eligible hints are now visible in the Mutation encyclopedia."
);
RenderShop();
await SaveGame(
ShopSave
);
} finally {
ShopPurchasePending = false;
RenderShop();
}
}
function SetShopMessage(
Message
) {
+27
View File
@@ -1,6 +1,7 @@
const GardenExpansionBaseCost = 1000;
const PlantInformationUpgradeCost = 500;
const GardenOverviewUpgradeCost = 1000;
const MutationHintsUpgradeCost = 1000;
function GetGardenColumnUpgradeCost(
@@ -189,3 +190,29 @@ function UnlockGardenOverview(
SaveData.Preferences.ShowReadyPlots =
true;
}
function HasMutationHintsUpgrade(
SaveData
) {
return (
SaveData
?.Upgrades
?.MutationHints ===
true
);
}
function GetMutationHintsUpgradeCost() {
return MutationHintsUpgradeCost;
}
function UnlockMutationHints(
SaveData
) {
SaveData.Upgrades ??= {};
SaveData.Upgrades.MutationHints =
true;
}
+13
View File
@@ -1292,6 +1292,19 @@ input, button, textarea, select {
margin-bottom: 1rem;
}
.MutationHintCard {
border-color: var(--Yellow);
}
.MutationHintCard .MutationEncyclopediaHeader h2 {
color: var(--Yellow);
}
.MutationHintCard .MutationEncyclopediaDescription {
margin-bottom: 0;
color: var(--Subtext1);
}
.MutationEncyclopediaStats {
display: grid;
grid-template-columns: repeat( 2, minmax(0, 1fr) );