Added plant info upgrade.

This commit is contained in:
sarah committed 2026-09-02 22:40:58 +02:00
1 parent 23cc94dc69
commit 367e34ef18
8 files changed
+733 -10

No files matched your search

+257 -8
View File
@@ -327,12 +327,18 @@ function RenderGarden() {
GardenGrid.replaceChildren();
const DisplaySettings =
GetGardenDisplaySettings();
GameSave.Garden.Plots.forEach(
(Plot, PlotIndex) => {
const PlotElement =
CreatePlotElement(
Plot,
PlotIndex
PlotIndex,
DisplaySettings
);
GardenGrid.appendChild(
@@ -343,9 +349,32 @@ function RenderGarden() {
}
function GetGardenDisplaySettings() {
const HasPlantInformation =
HasPlantInformationUpgrade(
GameSave
);
return {
ShowPlantNames:
HasPlantInformation &&
GameSave.Preferences
.ShowPlantNames !==
false,
ShowGrowthTimers:
HasPlantInformation &&
GameSave.Preferences
.ShowGrowthTimers !==
false
};
}
function CreatePlotElement(
Plot,
PlotIndex
PlotIndex,
DisplaySettings
) {
const Button =
document.createElement(
@@ -358,6 +387,53 @@ function CreatePlotElement(
Button.type = "button";
if (
DisplaySettings.ShowPlantNames
) {
Button.classList.add(
"GardenPlotWithName"
);
}
if (
DisplaySettings.ShowGrowthTimers
) {
Button.classList.add(
"GardenPlotWithTimer"
);
}
const Plant =
Plot === null
? null
: Plants[Plot.Plant];
if (
DisplaySettings.ShowPlantNames
) {
Button.appendChild(
CreateGardenPlotName(
Plot,
Plant
)
);
}
const Visual =
document.createElement(
"span"
);
Visual.className =
"GardenPlotVisual";
Button.appendChild(
Visual
);
if (Plot === null) {
Button.classList.add(
"GardenPlotEmpty"
@@ -366,6 +442,19 @@ function CreatePlotElement(
Button.title =
"Empty plot";
if (
DisplaySettings
.ShowGrowthTimers
) {
Button.appendChild(
CreateGardenPlotTimer(
null,
null,
0
)
);
}
if (
SelectedGardenTool ===
"Seed"
@@ -384,11 +473,21 @@ function CreatePlotElement(
}
const Plant =
Plants[Plot.Plant];
if (Plant === undefined) {
Button.textContent = "?";
Visual.textContent = "?";
if (
DisplaySettings
.ShowGrowthTimers
) {
Button.appendChild(
CreateGardenPlotTimer(
Plot,
null,
0
)
);
}
return Button;
}
@@ -427,7 +526,7 @@ function CreatePlotElement(
Image.src =
ImagePath;
Button.appendChild(
Visual.appendChild(
Image
);
} else {
@@ -442,12 +541,25 @@ function CreatePlotElement(
MissingImage.textContent =
Plant.Name;
Button.appendChild(
Visual.appendChild(
MissingImage
);
}
if (
DisplaySettings.ShowGrowthTimers
) {
Button.appendChild(
CreateGardenPlotTimer(
Plot,
Plant,
Progress
)
);
}
if (
SelectedGardenTool ===
"Shovel"
@@ -507,6 +619,143 @@ function CreatePlotElement(
}
function CreateGardenPlotName(
Plot,
Plant
) {
const Name =
document.createElement(
"span"
);
Name.className =
"GardenPlotName";
if (Plot === null) {
Name.textContent =
"Empty";
} else if (Plant === undefined) {
Name.textContent =
"Unknown";
} else {
Name.textContent =
Plant.Name;
Name.title =
Plant.Name;
}
return Name;
}
function CreateGardenPlotTimer(
Plot,
Plant,
Progress
) {
const Timer =
document.createElement(
"span"
);
Timer.className =
"GardenPlotTimer";
if (
Plot === null ||
Plant === null ||
Plant === undefined
) {
Timer.textContent = "";
return Timer;
}
if (Progress >= 1) {
Timer.textContent =
"Ready";
return Timer;
}
const RemainingTime =
Math.max(
0,
Plant.GrowthTime -
(
Date.now() -
Plot.PlantedAt
)
);
Timer.textContent =
FormatGardenRemainingTime(
RemainingTime
);
return Timer;
}
function FormatGardenRemainingTime(
Milliseconds
) {
const TotalSeconds =
Math.max(
0,
Math.ceil(
Number(
Milliseconds
) / 1000
)
);
const Hours =
Math.floor(
TotalSeconds / 3600
);
const Minutes =
Math.floor(
(
TotalSeconds % 3600
) / 60
);
const Seconds =
TotalSeconds % 60;
if (Hours > 0) {
return (
Hours +
":" +
String(Minutes).padStart(
2,
"0"
) +
":" +
String(Seconds).padStart(
2,
"0"
)
);
}
return (
Minutes +
":" +
String(Seconds).padStart(
2,
"0"
)
);
}
async function PlantSeed(
PlotIndex
) {
+151
View File
@@ -11,6 +11,8 @@ async function StartProfile() {
await LoadGame();
RenderProfileStatistics();
RenderGardenDisplayPreferences();
BindGardenDisplayPreferences();
} catch (Error) {
console.error(
"Couldn't load profile statistics:",
@@ -72,6 +74,155 @@ async function StartProfile() {
}
function BindGardenDisplayPreferences() {
const PlantNamesButton =
document.getElementById(
"TogglePlantNamesButton"
);
const GrowthTimersButton =
document.getElementById(
"ToggleGrowthTimersButton"
);
if (
PlantNamesButton === null ||
GrowthTimersButton === null
) {
return;
}
PlantNamesButton.addEventListener(
"click",
() => {
ToggleGardenDisplayPreference(
"ShowPlantNames"
);
}
);
GrowthTimersButton.addEventListener(
"click",
() => {
ToggleGardenDisplayPreference(
"ShowGrowthTimers"
);
}
);
}
function RenderGardenDisplayPreferences() {
const PlantNamesButton =
document.getElementById(
"TogglePlantNamesButton"
);
const GrowthTimersButton =
document.getElementById(
"ToggleGrowthTimersButton"
);
const Message =
document.getElementById(
"GardenDisplayMessage"
);
if (
PlantNamesButton === null ||
GrowthTimersButton === null ||
Message === null
) {
return;
}
const IsOwned =
HasPlantInformationUpgrade(
ProfileSave
);
if (!IsOwned) {
PlantNamesButton.textContent =
"Plant names: Locked";
GrowthTimersButton.textContent =
"Growth timers: Locked";
PlantNamesButton.disabled = true;
GrowthTimersButton.disabled = true;
Message.textContent =
"Unlock Plant information in the Shop to use these settings.";
return;
}
const ShowPlantNames =
ProfileSave.Preferences
.ShowPlantNames !== false;
const ShowGrowthTimers =
ProfileSave.Preferences
.ShowGrowthTimers !== false;
PlantNamesButton.disabled = false;
GrowthTimersButton.disabled = false;
PlantNamesButton.textContent =
"Plant names: " +
(ShowPlantNames
? "On"
: "Off");
GrowthTimersButton.textContent =
"Growth timers: " +
(ShowGrowthTimers
? "On"
: "Off");
Message.textContent =
"Plant names and growth timers can be changed independently.";
}
async function ToggleGardenDisplayPreference(
PreferenceName
) {
if (
!HasPlantInformationUpgrade(
ProfileSave
)
) {
return;
}
if (
PreferenceName !==
"ShowPlantNames" &&
PreferenceName !==
"ShowGrowthTimers"
) {
return;
}
ProfileSave.Preferences[
PreferenceName
] = !ProfileSave.Preferences[
PreferenceName
];
RenderGardenDisplayPreferences();
await SaveGame(
ProfileSave
);
}
async function RenderProfilePlayer() {
const UsernameInput =
document.getElementById(
+21 -1
View File
@@ -66,7 +66,13 @@ function CreateNewSave() {
},
Upgrades: {
PlotSize: 0
PlotSize: 0,
PlantInformation: false
},
Preferences: {
ShowPlantNames: true,
ShowGrowthTimers: true
},
Garden: {
@@ -239,6 +245,20 @@ function NormalizeSaveData(
SaveData.Upgrades ??= {};
SaveData.Upgrades.PlotSize ??= 0;
SaveData.Upgrades.PlantInformation =
SaveData.Upgrades.PlantInformation ===
true;
SaveData.Preferences ??= {};
SaveData.Preferences.ShowPlantNames =
SaveData.Preferences.ShowPlantNames !==
false;
SaveData.Preferences.ShowGrowthTimers =
SaveData.Preferences.ShowGrowthTimers !==
false;
SaveData.Garden ??= {
+176 -1
View File
@@ -123,7 +123,8 @@ function RenderGardenUpgrades() {
),
CreateGardenExpansionCard(
"Row"
)
),
CreatePlantInformationUpgradeCard()
);
}
@@ -270,6 +271,122 @@ function CreateGardenExpansionCard(
}
function CreatePlantInformationUpgradeCard() {
const Cost =
GetPlantInformationUpgradeCost();
const IsOwned =
HasPlantInformationUpgrade(
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 =
"Plant information";
Header.appendChild(Name);
const Description =
document.createElement(
"p"
);
Description.textContent =
"Show each plant's name above its sprite and exact time remaining below it. Both displays can be toggled on or off from your Profile.";
const Details =
document.createElement(
"div"
);
Details.className =
"ShopItemDetails";
Details.append(
CreateShopStat(
"Plant names",
IsOwned
? "Unlocked"
: "Locked"
),
CreateShopStat(
"Growth timers",
IsOwned
? "Unlocked"
: "Locked"
)
);
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",
BuyPlantInformationUpgrade
);
}
Card.append(
Header,
Description,
Details,
BuyButton
);
return Card;
}
function CreateShopSeedCard(
Plant
) {
@@ -839,6 +956,64 @@ async function BuyGardenExpansion(
}
async function BuyPlantInformationUpgrade() {
if (
ShopPurchasePending ||
HasPlantInformationUpgrade(
ShopSave
)
) {
return;
}
const Cost =
GetPlantInformationUpgradeCost();
if (
ShopSave.Currency.Dew <
Cost
) {
SetShopMessage(
"You don't have enough Dew for Plant information."
);
return;
}
ShopPurchasePending = true;
try {
ShopSave.Currency.Dew -=
Cost;
ShopSave.Statistics.CurrencySpent.Dew +=
Cost;
UnlockPlantInformation(
ShopSave
);
SetShopMessage(
"Bought Plant information for " +
Cost.toLocaleString() +
" Dew. Plant names and growth timers are now visible."
);
RenderShop();
await SaveGame(
ShopSave
);
} finally {
ShopPurchasePending = false;
RenderShop();
}
}
function SetShopMessage(
Message
) {
+35
View File
@@ -1,4 +1,5 @@
const GardenExpansionBaseCost = 1000;
const PlantInformationUpgradeCost = 500;
function GetGardenColumnUpgradeCost(
@@ -107,3 +108,37 @@ function ResetGardenMutationCooldowns(
) {
SaveData.MutationCooldowns = {};
}
function HasPlantInformationUpgrade(
SaveData
) {
return (
SaveData
?.Upgrades
?.PlantInformation ===
true
);
}
function GetPlantInformationUpgradeCost() {
return PlantInformationUpgradeCost;
}
function UnlockPlantInformation(
SaveData
) {
SaveData.Upgrades ??= {};
SaveData.Preferences ??= {};
SaveData.Upgrades.PlantInformation =
true;
SaveData.Preferences.ShowPlantNames =
true;
SaveData.Preferences.ShowGrowthTimers =
true;
}