Added tools and tool upgrades.

This commit is contained in:
sarah committed 2026-09-05 11:02:21 +02:00
1 parent fbc44883d4
commit 7b804feba8
10 files changed
+2418 -69

No files matched your search

+5 -10
View File
@@ -216,15 +216,10 @@ $PageSection = "Garden";
>
<h2>Tools</h2>
<div class="ToolList">
<button
id="ShovelToolButton"
class="ActionButton ToolButton ToolButtonShovel"
type="button"
>
Shovel
</button>
</div>
<div
id="ToolList"
class="ToolList"
></div>
</section>
<section
@@ -254,7 +249,7 @@ $PageSection = "Garden";
</section>
<p id="GardenMessage" class="PageMessage">
Select a seed, then choose an empty plot.
Select a seed and use the Trowel on an empty plot.
</p>
<section
+37 -5
View File
@@ -203,11 +203,43 @@ $PageSection = "Guide";
<h2>Tools</h2>
<p>
The Shovel removes a planted crop without giving a
harvest reward. Select it, click the plant you want
to remove, and click the Shovel again when you want
to have no tool equipped. It's very useful when you
decide you want to try a new mutation, for example.
The <strong>Trowel</strong> is the default tool. Select
a seed from your inventory, then use the Trowel on an
empty plot to plant it.
</p>
<p>
The <strong>Magic trowel</strong> fills as many empty
plots as it can with the selected seed. If you have
fewer seeds than empty plots, it simply plants every
seed you have.
</p>
<p>
The <strong>Shovel</strong> removes planted crops. At
level 0 it returns nothing, level 1 returns 33% of the
seed cost, level 2 returns 66%, and level 3 returns the
planted seed itself.
</p>
<p>
<strong>Fertilizer</strong> consumes one Fertilizer use
to advance a growing plant. Its six levels advance 10,
20, 30, 40, 50, or 60 minutes respectively. Additional
Fertilizer uses are bought from the Shop.
</p>
<p>
<strong>Future Sight</strong> previews the Garden's next
mutation as though that mutation succeeded. The preview
does not actually mutate or discover anything, and Future
Sight must recharge for two hours after a successful use.
</p>
<p>
Tools and their upgrades are bought from the Shop. Shovel
and Fertilizer upgrade prices rise exponentially as their
levels increase.
</p>
</section>
+23
View File
@@ -105,6 +105,29 @@ $PageTitle = "Profile";
>
<h2>Garden display</h2>
<h3>Tool selection</h3>
<p>
Choose which Garden actions automatically change
your selected seed or tool.
</p>
<div class="ProfileButtonRow">
<button
id="ToggleSelectQuickBoughtPlantButton"
type="button"
>
Select bought plant when you quick-buy one: On
</button>
<button
id="ToggleSelectTrowelWithInventoryPlantButton"
type="button"
>
Select trowel when you select an inventory plant: On
</button>
</div>
<h3>Plant information</h3>
<p>
+33
View File
@@ -40,6 +40,39 @@ $PageSection = "Shop";
seed price, rounded up.
</p>
<section
id="Tools"
class="ShopSection"
>
<h2 class="ShopSectionHeading">
<button
id="ToolsToggle"
class="ShopSectionToggle"
type="button"
aria-expanded="true"
aria-controls="ToolsContent"
>
<span class="ShopSectionArrow" aria-hidden="true">&gt;</span>
<span>Tools</span>
</button>
</h2>
<div
id="ToolsContent"
class="ShopSectionContent"
>
<p>
Unlock Garden tools, improve the Shovel and
Fertilizer, and restock Fertilizer uses.
</p>
<div
id="ShopToolList"
class="ShopSeedList"
></div>
</div>
</section>
<section
id="PermanentUpgrades"
class="ShopSection"
+792 -50
View File
File diff suppressed because it is too large. Load diff
+57
View File
@@ -76,6 +76,14 @@ async function StartProfile() {
function BindGardenDisplayPreferences() {
const PreferenceButtons = [
[
"ToggleSelectQuickBoughtPlantButton",
"SelectQuickBoughtPlant"
],
[
"ToggleSelectTrowelWithInventoryPlantButton",
"SelectTrowelWithInventoryPlant"
],
[
"TogglePlantNamesButton",
"ShowPlantNames"
@@ -140,11 +148,49 @@ function BindGardenDisplayPreferences() {
function RenderGardenDisplayPreferences() {
RenderToolSelectionPreferences();
RenderPlantInformationPreferences();
RenderGardenOverviewPreferences();
}
function RenderToolSelectionPreferences() {
const QuickBuyButton =
document.getElementById(
"ToggleSelectQuickBoughtPlantButton"
);
const TrowelButton =
document.getElementById(
"ToggleSelectTrowelWithInventoryPlantButton"
);
if (
QuickBuyButton === null ||
TrowelButton === null
) {
return;
}
SetPreferenceButtonState(
QuickBuyButton,
"Select bought plant when you quick-buy one",
ProfileSave.Preferences
.SelectQuickBoughtPlant !==
false
);
SetPreferenceButtonState(
TrowelButton,
"Select trowel when you select an inventory plant",
ProfileSave.Preferences
.SelectTrowelWithInventoryPlant !==
false
);
}
function RenderPlantInformationPreferences() {
const PlantNamesButton =
document.getElementById(
@@ -322,6 +368,11 @@ function SetPreferenceButtonState(
async function ToggleGardenDisplayPreference(
PreferenceName
) {
const ToolSelectionPreferences = [
"SelectQuickBoughtPlant",
"SelectTrowelWithInventoryPlant"
];
const PlantInformationPreferences = [
"ShowPlantNames",
"ShowGrowthTimers"
@@ -337,6 +388,11 @@ async function ToggleGardenDisplayPreference(
];
const IsToolSelectionPreference =
ToolSelectionPreferences.includes(
PreferenceName
);
const IsPlantInformationPreference =
PlantInformationPreferences.includes(
PreferenceName
@@ -349,6 +405,7 @@ async function ToggleGardenDisplayPreference(
if (
!IsToolSelectionPreference &&
!IsPlantInformationPreference &&
!IsGardenOverviewPreference
) {
+81 -4
View File
@@ -392,7 +392,7 @@ function CreateNewSave() {
return NormalizeSaveData({
Version: 3,
Version: 4,
Revision: 0,
LastSavedAt: Date.now(),
@@ -413,7 +413,18 @@ function CreateNewSave() {
},
Inventory: {
Seeds: SeedInventory
Seeds: SeedInventory,
Fertilizer: 0
},
Tools: {
MagicTrowel: false,
Shovel: false,
Fertilizer: false,
FutureSight: false,
ShovelLevel: 0,
FertilizerLevel: 0,
FutureSightCooldownUntil: 0
},
Upgrades: {
@@ -432,7 +443,9 @@ function CreateNewSave() {
ShowEmptyPlots: true,
ShowPlantedPlots: true,
ShowGrowingPlots: true,
ShowReadyPlots: true
ShowReadyPlots: true,
SelectQuickBoughtPlant: true,
SelectTrowelWithInventoryPlant: true
},
Gardens: [
@@ -456,7 +469,7 @@ function NormalizeSaveData(
Number(
SaveData.Version ?? 1
),
3
4
);
SaveData.Revision = Number(
@@ -492,6 +505,14 @@ function NormalizeSaveData(
SaveData.Inventory ??= {};
SaveData.Inventory.Seeds ??= {};
SaveData.Inventory.Fertilizer = Math.max(
0,
Math.floor(
Number(
SaveData.Inventory.Fertilizer ?? 0
) || 0
)
);
/*
@@ -563,6 +584,54 @@ function NormalizeSaveData(
delete SaveData.Seeds;
SaveData.Tools ??= {};
SaveData.Tools.MagicTrowel =
SaveData.Tools.MagicTrowel === true;
SaveData.Tools.Shovel =
SaveData.Tools.Shovel === true;
SaveData.Tools.Fertilizer =
SaveData.Tools.Fertilizer === true;
SaveData.Tools.FutureSight =
SaveData.Tools.FutureSight === true;
SaveData.Tools.ShovelLevel = Math.max(
0,
Math.min(
3,
Math.floor(
Number(
SaveData.Tools.ShovelLevel ?? 0
) || 0
)
)
);
SaveData.Tools.FertilizerLevel = Math.max(
0,
Math.min(
5,
Math.floor(
Number(
SaveData.Tools.FertilizerLevel ?? 0
) || 0
)
)
);
SaveData.Tools.FutureSightCooldownUntil = Math.max(
0,
Math.floor(
Number(
SaveData.Tools.FutureSightCooldownUntil ?? 0
) || 0
)
);
SaveData.Discoveries ??= {};
SaveData.Discoveries.Plants =
@@ -654,6 +723,14 @@ function NormalizeSaveData(
SaveData.Preferences.ShowReadyPlots !==
false;
SaveData.Preferences.SelectQuickBoughtPlant =
SaveData.Preferences.SelectQuickBoughtPlant !==
false;
SaveData.Preferences.SelectTrowelWithInventoryPlant =
SaveData.Preferences.SelectTrowelWithInventoryPlant !==
false;
const LegacyGarden =
SaveData.Garden ??
File diff suppressed because it is too large. Load diff
+342
View File
@@ -1,3 +1,24 @@
const MagicTrowelUnlockCost = 1000;
const ShovelUnlockCost = 50;
const FertilizerUnlockCost = 200;
const FutureSightUnlockCost = 5000;
const ToolUpgradeCostMultiplier = 2;
const ShovelMaximumLevel = 3;
const FertilizerMaximumLevel = 5;
const FertilizerUseCost = 100;
const FertilizerGrowthMinutes = [
10,
20,
30,
40,
50,
60
];
const FutureSightCooldown =
2 * 60 * 60 * 1000;
const GardenExpansionBaseCost = 1000;
const PlantInformationUpgradeCost = 500;
const GardenOverviewUpgradeCost = 1000;
@@ -281,3 +302,324 @@ function UnlockMutationHints(
SaveData.Upgrades.MutationHints =
true;
}
function IsGardenToolUnlocked(
SaveData,
Tool
) {
if (Tool === "Trowel") {
return true;
}
if (Tool === "MagicTrowel") {
return SaveData?.Tools?.MagicTrowel === true;
}
if (Tool === "Shovel") {
return SaveData?.Tools?.Shovel === true;
}
if (Tool === "Fertilizer") {
return SaveData?.Tools?.Fertilizer === true;
}
if (Tool === "FutureSight") {
return SaveData?.Tools?.FutureSight === true;
}
return false;
}
function GetGardenToolUnlockCost(
Tool
) {
const Costs = {
MagicTrowel: MagicTrowelUnlockCost,
Shovel: ShovelUnlockCost,
Fertilizer: FertilizerUnlockCost,
FutureSight: FutureSightUnlockCost
};
return Costs[Tool] ?? null;
}
function UnlockGardenTool(
SaveData,
Tool
) {
SaveData.Tools ??= {};
if (
![
"MagicTrowel",
"Shovel",
"Fertilizer",
"FutureSight"
].includes(Tool)
) {
return false;
}
SaveData.Tools[Tool] = true;
return true;
}
function GetShovelLevel(
SaveData
) {
return Math.max(
0,
Math.min(
ShovelMaximumLevel,
Math.floor(
Number(
SaveData?.Tools?.ShovelLevel ?? 0
) || 0
)
)
);
}
function GetShovelUpgradeCost(
SaveData
) {
const Level = GetShovelLevel(
SaveData
);
if (Level >= ShovelMaximumLevel) {
return null;
}
return Math.round(
ShovelUnlockCost *
Math.pow(
ToolUpgradeCostMultiplier,
Level + 1
)
);
}
function UpgradeShovel(
SaveData
) {
if (
!IsGardenToolUnlocked(
SaveData,
"Shovel"
)
) {
return false;
}
const Level = GetShovelLevel(
SaveData
);
if (Level >= ShovelMaximumLevel) {
return false;
}
SaveData.Tools.ShovelLevel =
Level + 1;
return true;
}
function GetShovelRefundRate(
SaveData
) {
const Level = GetShovelLevel(
SaveData
);
if (Level === 1) {
return 0.33;
}
if (Level === 2) {
return 0.66;
}
return 0;
}
function DoesShovelReturnSeed(
SaveData
) {
return GetShovelLevel(
SaveData
) >= 3;
}
function GetFertilizerLevel(
SaveData
) {
return Math.max(
0,
Math.min(
FertilizerMaximumLevel,
Math.floor(
Number(
SaveData?.Tools?.FertilizerLevel ?? 0
) || 0
)
)
);
}
function GetFertilizerUpgradeCost(
SaveData
) {
const Level = GetFertilizerLevel(
SaveData
);
if (Level >= FertilizerMaximumLevel) {
return null;
}
return Math.round(
FertilizerUnlockCost *
Math.pow(
ToolUpgradeCostMultiplier,
Level + 1
)
);
}
function UpgradeFertilizer(
SaveData
) {
if (
!IsGardenToolUnlocked(
SaveData,
"Fertilizer"
)
) {
return false;
}
const Level = GetFertilizerLevel(
SaveData
);
if (Level >= FertilizerMaximumLevel) {
return false;
}
SaveData.Tools.FertilizerLevel =
Level + 1;
return true;
}
function GetFertilizerGrowthMinutes(
SaveData
) {
return FertilizerGrowthMinutes[
GetFertilizerLevel(
SaveData
)
];
}
function GetFertilizerUseCost(
Amount = 1
) {
return FertilizerUseCost *
Math.max(
1,
Math.floor(
Number(Amount) || 1
)
);
}
function AddFertilizerUses(
SaveData,
Amount = 1
) {
SaveData.Inventory ??= {};
SaveData.Inventory.Fertilizer ??= 0;
SaveData.Inventory.Fertilizer +=
Math.max(
0,
Math.floor(
Number(Amount) || 0
)
);
}
function TakeFertilizerUse(
SaveData
) {
const CurrentUses = Math.max(
0,
Math.floor(
Number(
SaveData?.Inventory?.Fertilizer ?? 0
) || 0
)
);
if (CurrentUses <= 0) {
return false;
}
SaveData.Inventory.Fertilizer =
CurrentUses - 1;
return true;
}
function GetFutureSightCooldownRemaining(
SaveData,
Now = Date.now()
) {
return Math.max(
0,
Number(
SaveData?.Tools?.FutureSightCooldownUntil ?? 0
) - Now
);
}
function IsFutureSightReady(
SaveData,
Now = Date.now()
) {
return GetFutureSightCooldownRemaining(
SaveData,
Now
) <= 0;
}
function StartFutureSightCooldown(
SaveData,
Now = Date.now()
) {
SaveData.Tools ??= {};
SaveData.Tools.FutureSightCooldownUntil =
Now + FutureSightCooldown;
}
+66
View File
@@ -719,6 +719,20 @@ input, button, textarea, select {
gap: 0.5rem;
}
.ToolButtonTrowel[aria-current="true"] {
--ActionAccent: var(--Green);
color: var(--Green);
background-color: var(--Surface1);
border-color: var(--Green);
}
.ToolButtonMagicTrowel[aria-current="true"] {
--ActionAccent: var(--Mauve);
color: var(--Mauve);
background-color: var(--Surface1);
border-color: var(--Mauve);
}
.ToolButtonShovel[aria-current="true"] {
--ActionAccent: var(--Red);
color: var(--Red);
@@ -726,11 +740,62 @@ input, button, textarea, select {
border-color: var(--Red);
}
.ToolButtonFertilizer[aria-current="true"] {
--ActionAccent: var(--Yellow);
color: var(--Yellow);
background-color: var(--Surface1);
border-color: var(--Yellow);
}
.ToolButtonFutureSight[aria-current="true"] {
--ActionAccent: var(--Lavender);
color: var(--Lavender);
background-color: var(--Surface1);
border-color: var(--Lavender);
}
.ToolButton:disabled {
cursor: not-allowed;
color: var(--Overlay1);
background-color: var(--Mantle);
border-color: var(--Surface1);
box-shadow: none;
}
.GardenPlotMagicPlant:hover {
--PlotBorderColour: var(--Mauve);
}
.GardenPlotRemove:hover {
--GrowthColour: var(--Red);
--PlotBorderColour: var(--Red);
}
.GardenPlotFertilize:hover {
--GrowthColour: var(--Yellow);
--PlotBorderColour: var(--Yellow);
}
.GardenPlotsFutureSight {
border-color: var(--Lavender);
}
.GardenPlotFutureSight {
cursor: default;
}
.GardenPlotFutureSight:hover {
transform: none;
box-shadow: 3px 3px 0 var(--Crust);
}
.GardenPlotFutureSightChanged {
--GrowthColour: var(--Lavender);
--PlotBorderColour: var(--Lavender);
outline: 3px solid var(--Lavender);
outline-offset: -3px;
}
.GardenUser, .Leaderboard {
margin-top: 1.5rem;
padding: 1rem;
@@ -1344,6 +1409,7 @@ input, button, textarea, select {
padding: 0.65rem 0.8rem;
}
.ShopItemActions,
.ShopSeedBuyOptions {
display: flex;
flex-direction: column;