mirror of
https://git.srhtnin.garden/sarah/srhtnin.github.io.git
synced 2026-10-13 18:38:11 +02:00
Added multiple gardens per user upgrade. Pretty cool!!!!
This commit is contained in:
1 parent
c7b5494385
commit
d72045d615
7 files changed
+930
-103
No files matched your search
@@ -78,6 +78,38 @@ $PageSection = "Garden";
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="GardenSelector"
|
||||
class="GardenSelectorPanel"
|
||||
>
|
||||
<button
|
||||
id="PreviousGardenButton"
|
||||
class="ActionButton GardenSelectorButton"
|
||||
type="button"
|
||||
aria-label="Previous Garden"
|
||||
>
|
||||
<
|
||||
</button>
|
||||
|
||||
<input
|
||||
id="GardenNameInput"
|
||||
class="GardenNameInput"
|
||||
type="text"
|
||||
maxlength="32"
|
||||
value="Garden"
|
||||
aria-label="Garden name"
|
||||
>
|
||||
|
||||
<button
|
||||
id="NextGardenButton"
|
||||
class="ActionButton GardenSelectorButton"
|
||||
type="button"
|
||||
aria-label="Next Garden"
|
||||
>
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="GardenLayout">
|
||||
<section id="Plots">
|
||||
<h2>Plots</h2>
|
||||
|
||||
+2
-2
@@ -47,8 +47,8 @@ $PageSection = "Shop";
|
||||
<h2>Permanent upgrades</h2>
|
||||
|
||||
<p>
|
||||
Permanently expand your Garden or unlock
|
||||
extra information and quality-of-life features.
|
||||
Expand your active Garden, buy additional Gardens,
|
||||
or unlock information and quality-of-life features.
|
||||
</p>
|
||||
|
||||
<div
|
||||
|
||||
+245
-2
@@ -27,10 +27,11 @@ async function StartGame() {
|
||||
GameSave = await LoadGame();
|
||||
|
||||
BindGardenTools();
|
||||
BindGardenSelector();
|
||||
EnsureSelectedSeed();
|
||||
|
||||
const InitialMutationResult =
|
||||
CheckGardenMutations(
|
||||
CheckAllGardenMutations(
|
||||
GameSave
|
||||
);
|
||||
|
||||
@@ -57,12 +58,235 @@ function RenderGame() {
|
||||
RenderCurrency();
|
||||
RenderSeeds();
|
||||
RenderTools();
|
||||
RenderGardenSelector();
|
||||
RenderGarden();
|
||||
RenderNextHarvest();
|
||||
RenderGardenOverview();
|
||||
}
|
||||
|
||||
|
||||
function BindGardenSelector() {
|
||||
const PreviousButton =
|
||||
document.getElementById(
|
||||
"PreviousGardenButton"
|
||||
);
|
||||
|
||||
const NextButton =
|
||||
document.getElementById(
|
||||
"NextGardenButton"
|
||||
);
|
||||
|
||||
const NameInput =
|
||||
document.getElementById(
|
||||
"GardenNameInput"
|
||||
);
|
||||
|
||||
|
||||
PreviousButton?.addEventListener(
|
||||
"click",
|
||||
() => {
|
||||
SwitchGarden(-1);
|
||||
}
|
||||
);
|
||||
|
||||
NextButton?.addEventListener(
|
||||
"click",
|
||||
() => {
|
||||
SwitchGarden(1);
|
||||
}
|
||||
);
|
||||
|
||||
NameInput?.addEventListener(
|
||||
"change",
|
||||
async () => {
|
||||
const GardenIndex =
|
||||
GameSave.ActiveGardenIndex;
|
||||
|
||||
const GardenName =
|
||||
RenameGarden(
|
||||
GameSave,
|
||||
GardenIndex,
|
||||
NameInput.value
|
||||
);
|
||||
|
||||
NameInput.value =
|
||||
GardenName;
|
||||
|
||||
SetGardenMessage(
|
||||
"Garden renamed to " +
|
||||
GardenName +
|
||||
"."
|
||||
);
|
||||
|
||||
await SaveGame(
|
||||
GameSave
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
NameInput?.addEventListener(
|
||||
"keydown",
|
||||
Event => {
|
||||
if (Event.key !== "Enter") {
|
||||
return;
|
||||
}
|
||||
|
||||
Event.preventDefault();
|
||||
NameInput.blur();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
async function SwitchGarden(
|
||||
Direction
|
||||
) {
|
||||
const GardenCount =
|
||||
GameSave.Gardens.length;
|
||||
|
||||
if (GardenCount <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const NewIndex =
|
||||
GameSave.ActiveGardenIndex +
|
||||
Direction;
|
||||
|
||||
if (
|
||||
NewIndex < 0 ||
|
||||
NewIndex >= GardenCount
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetActiveGardenIndex(
|
||||
GameSave,
|
||||
NewIndex
|
||||
);
|
||||
|
||||
const MutationResult =
|
||||
CheckGardenMutations(
|
||||
GameSave
|
||||
);
|
||||
|
||||
RenderGame();
|
||||
|
||||
SetGardenMessage(
|
||||
"Switched to " +
|
||||
GameSave.Garden.Name +
|
||||
"."
|
||||
);
|
||||
|
||||
await SaveGame(
|
||||
GameSave
|
||||
);
|
||||
|
||||
if (MutationResult.Attempted) {
|
||||
RenderGame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function RenderGardenSelector() {
|
||||
const PreviousButton =
|
||||
document.getElementById(
|
||||
"PreviousGardenButton"
|
||||
);
|
||||
|
||||
const NextButton =
|
||||
document.getElementById(
|
||||
"NextGardenButton"
|
||||
);
|
||||
|
||||
const NameInput =
|
||||
document.getElementById(
|
||||
"GardenNameInput"
|
||||
);
|
||||
|
||||
if (
|
||||
PreviousButton === null ||
|
||||
NextButton === null ||
|
||||
NameInput === null
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const GardenCount =
|
||||
GameSave.Gardens.length;
|
||||
|
||||
const GardenIndex =
|
||||
GameSave.ActiveGardenIndex;
|
||||
|
||||
PreviousButton.disabled =
|
||||
GardenIndex <= 0;
|
||||
|
||||
NextButton.disabled =
|
||||
GardenIndex >=
|
||||
GardenCount - 1;
|
||||
|
||||
if (
|
||||
document.activeElement !==
|
||||
NameInput
|
||||
) {
|
||||
NameInput.value =
|
||||
GameSave.Garden.Name;
|
||||
}
|
||||
|
||||
NameInput.title =
|
||||
"Garden " +
|
||||
(GardenIndex + 1) +
|
||||
" of " +
|
||||
GardenCount;
|
||||
}
|
||||
|
||||
|
||||
function CheckAllGardenMutations(
|
||||
SaveData
|
||||
) {
|
||||
const OriginalGardenIndex =
|
||||
SaveData.ActiveGardenIndex;
|
||||
|
||||
const Result = {
|
||||
Attempted: false,
|
||||
Changed: false
|
||||
};
|
||||
|
||||
|
||||
for (
|
||||
let GardenIndex = 0;
|
||||
GardenIndex <
|
||||
SaveData.Gardens.length;
|
||||
GardenIndex++
|
||||
) {
|
||||
SetActiveGardenIndex(
|
||||
SaveData,
|
||||
GardenIndex
|
||||
);
|
||||
|
||||
const GardenResult =
|
||||
CheckGardenMutations(
|
||||
SaveData
|
||||
);
|
||||
|
||||
Result.Attempted =
|
||||
Result.Attempted ||
|
||||
GardenResult.Attempted;
|
||||
|
||||
Result.Changed =
|
||||
Result.Changed ||
|
||||
GardenResult.Changed;
|
||||
}
|
||||
|
||||
|
||||
SetActiveGardenIndex(
|
||||
SaveData,
|
||||
OriginalGardenIndex
|
||||
);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
function BindGardenTools() {
|
||||
const ShovelButton =
|
||||
document.getElementById(
|
||||
@@ -326,6 +550,25 @@ function RenderGarden() {
|
||||
GameSave.Garden.Width
|
||||
);
|
||||
|
||||
const GardenBorderColours = [
|
||||
"var(--Lavender)",
|
||||
"var(--Mauve)",
|
||||
"var(--Pink)",
|
||||
"var(--Blue)",
|
||||
"var(--Teal)",
|
||||
"var(--Peach)",
|
||||
"var(--Yellow)",
|
||||
"var(--Green)"
|
||||
];
|
||||
|
||||
GardenGrid.style.setProperty(
|
||||
"--GardenBorderColour",
|
||||
GardenBorderColours[
|
||||
GameSave.ActiveGardenIndex %
|
||||
GardenBorderColours.length
|
||||
]
|
||||
);
|
||||
|
||||
GardenGrid.replaceChildren();
|
||||
|
||||
|
||||
@@ -954,7 +1197,7 @@ async function GardenTick() {
|
||||
|
||||
try {
|
||||
const MutationResult =
|
||||
CheckGardenMutations(
|
||||
CheckAllGardenMutations(
|
||||
GameSave
|
||||
);
|
||||
|
||||
|
||||
+395
-98
@@ -10,6 +10,357 @@ const StartingSeeds = {
|
||||
};
|
||||
|
||||
|
||||
const DefaultGardenName = "Garden";
|
||||
const MaximumGardenNameLength = 32;
|
||||
const StartingGardenWidth = 3;
|
||||
const StartingGardenHeight = 3;
|
||||
|
||||
|
||||
function CreateGardenData(
|
||||
Name = DefaultGardenName
|
||||
) {
|
||||
return {
|
||||
Name: NormalizeGardenName(
|
||||
Name
|
||||
),
|
||||
Width: StartingGardenWidth,
|
||||
Height: StartingGardenHeight,
|
||||
Plots: Array(
|
||||
StartingGardenWidth *
|
||||
StartingGardenHeight
|
||||
).fill(null),
|
||||
MutationCooldowns: {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function NormalizeGardenName(
|
||||
Value
|
||||
) {
|
||||
if (
|
||||
typeof Value !== "string"
|
||||
) {
|
||||
return DefaultGardenName;
|
||||
}
|
||||
|
||||
const Name = Value
|
||||
.trim()
|
||||
.slice(
|
||||
0,
|
||||
MaximumGardenNameLength
|
||||
);
|
||||
|
||||
return Name.length > 0
|
||||
? Name
|
||||
: DefaultGardenName;
|
||||
}
|
||||
|
||||
|
||||
function NormalizeGardenData(
|
||||
Garden,
|
||||
LegacyMutationCooldowns = null
|
||||
) {
|
||||
if (
|
||||
Garden === null ||
|
||||
typeof Garden !== "object" ||
|
||||
Array.isArray(Garden)
|
||||
) {
|
||||
Garden = CreateGardenData();
|
||||
}
|
||||
|
||||
Garden.Name = NormalizeGardenName(
|
||||
Garden.Name
|
||||
);
|
||||
|
||||
Garden.Width = Math.max(
|
||||
1,
|
||||
Math.floor(
|
||||
Number(
|
||||
Garden.Width ??
|
||||
StartingGardenWidth
|
||||
) || StartingGardenWidth
|
||||
)
|
||||
);
|
||||
|
||||
Garden.Height = Math.max(
|
||||
1,
|
||||
Math.floor(
|
||||
Number(
|
||||
Garden.Height ??
|
||||
StartingGardenHeight
|
||||
) || StartingGardenHeight
|
||||
)
|
||||
);
|
||||
|
||||
if (!Array.isArray(Garden.Plots)) {
|
||||
Garden.Plots = [];
|
||||
}
|
||||
|
||||
|
||||
for (
|
||||
let PlotIndex = 0;
|
||||
PlotIndex < Garden.Plots.length;
|
||||
PlotIndex++
|
||||
) {
|
||||
const Plot =
|
||||
Garden.Plots[PlotIndex];
|
||||
|
||||
if (Plot === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof Plot !== "object" ||
|
||||
Array.isArray(Plot)
|
||||
) {
|
||||
Garden.Plots[PlotIndex] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
Plot.Plant === "Rose"
|
||||
) {
|
||||
Plot.Plant = "RedRose";
|
||||
}
|
||||
|
||||
if (
|
||||
typeof Plot.Plant ===
|
||||
"number"
|
||||
) {
|
||||
const PlantKey =
|
||||
ResolvePlantKeyById(
|
||||
Plot.Plant
|
||||
);
|
||||
|
||||
if (PlantKey !== null) {
|
||||
Plot.Plant = PlantKey;
|
||||
}
|
||||
}
|
||||
|
||||
Plot.PlantedAt = Number(
|
||||
Plot.PlantedAt ??
|
||||
Date.now()
|
||||
);
|
||||
|
||||
delete Plot.VisualVariant;
|
||||
delete Plot.AddedTags;
|
||||
}
|
||||
|
||||
|
||||
const RequiredPlots =
|
||||
Garden.Width *
|
||||
Garden.Height;
|
||||
|
||||
while (
|
||||
Garden.Plots.length <
|
||||
RequiredPlots
|
||||
) {
|
||||
Garden.Plots.push(null);
|
||||
}
|
||||
|
||||
if (
|
||||
Garden.Plots.length >
|
||||
RequiredPlots
|
||||
) {
|
||||
Garden.Plots.length =
|
||||
RequiredPlots;
|
||||
}
|
||||
|
||||
|
||||
if (
|
||||
Garden.MutationCooldowns ===
|
||||
undefined &&
|
||||
LegacyMutationCooldowns !== null &&
|
||||
typeof LegacyMutationCooldowns ===
|
||||
"object" &&
|
||||
!Array.isArray(
|
||||
LegacyMutationCooldowns
|
||||
)
|
||||
) {
|
||||
Garden.MutationCooldowns =
|
||||
LegacyMutationCooldowns;
|
||||
}
|
||||
|
||||
if (
|
||||
Garden.MutationCooldowns === null ||
|
||||
typeof Garden.MutationCooldowns !==
|
||||
"object" ||
|
||||
Array.isArray(
|
||||
Garden.MutationCooldowns
|
||||
)
|
||||
) {
|
||||
Garden.MutationCooldowns = {};
|
||||
}
|
||||
|
||||
|
||||
return Garden;
|
||||
}
|
||||
|
||||
|
||||
function GetActiveGarden(
|
||||
SaveData
|
||||
) {
|
||||
if (
|
||||
!Array.isArray(
|
||||
SaveData.Gardens
|
||||
) ||
|
||||
SaveData.Gardens.length === 0
|
||||
) {
|
||||
SaveData.Gardens = [
|
||||
CreateGardenData()
|
||||
];
|
||||
}
|
||||
|
||||
const GardenIndex = Math.min(
|
||||
SaveData.Gardens.length - 1,
|
||||
Math.max(
|
||||
0,
|
||||
Math.floor(
|
||||
Number(
|
||||
SaveData.ActiveGardenIndex ??
|
||||
0
|
||||
) || 0
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
SaveData.ActiveGardenIndex =
|
||||
GardenIndex;
|
||||
|
||||
return SaveData.Gardens[
|
||||
GardenIndex
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
function SetActiveGardenIndex(
|
||||
SaveData,
|
||||
GardenIndex
|
||||
) {
|
||||
if (
|
||||
!Array.isArray(
|
||||
SaveData.Gardens
|
||||
) ||
|
||||
SaveData.Gardens.length === 0
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const NormalizedIndex = Math.min(
|
||||
SaveData.Gardens.length - 1,
|
||||
Math.max(
|
||||
0,
|
||||
Math.floor(
|
||||
Number(
|
||||
GardenIndex
|
||||
) || 0
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const Changed =
|
||||
SaveData.ActiveGardenIndex !==
|
||||
NormalizedIndex;
|
||||
|
||||
SaveData.ActiveGardenIndex =
|
||||
NormalizedIndex;
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
function RenameGarden(
|
||||
SaveData,
|
||||
GardenIndex,
|
||||
Name
|
||||
) {
|
||||
if (
|
||||
!Array.isArray(
|
||||
SaveData.Gardens
|
||||
) ||
|
||||
SaveData.Gardens[GardenIndex] ===
|
||||
undefined
|
||||
) {
|
||||
return DefaultGardenName;
|
||||
}
|
||||
|
||||
const NormalizedName =
|
||||
NormalizeGardenName(
|
||||
Name
|
||||
);
|
||||
|
||||
SaveData.Gardens[
|
||||
GardenIndex
|
||||
].Name = NormalizedName;
|
||||
|
||||
return NormalizedName;
|
||||
}
|
||||
|
||||
|
||||
function DefineActiveGardenAliases(
|
||||
SaveData
|
||||
) {
|
||||
delete SaveData.Garden;
|
||||
delete SaveData.MutationCooldowns;
|
||||
|
||||
Object.defineProperty(
|
||||
SaveData,
|
||||
"Garden",
|
||||
{
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
|
||||
get() {
|
||||
return GetActiveGarden(
|
||||
SaveData
|
||||
);
|
||||
},
|
||||
|
||||
set(Value) {
|
||||
const GardenIndex =
|
||||
SaveData.ActiveGardenIndex ??
|
||||
0;
|
||||
|
||||
SaveData.Gardens[
|
||||
GardenIndex
|
||||
] = NormalizeGardenData(
|
||||
Value
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Object.defineProperty(
|
||||
SaveData,
|
||||
"MutationCooldowns",
|
||||
{
|
||||
configurable: true,
|
||||
enumerable: false,
|
||||
|
||||
get() {
|
||||
return GetActiveGarden(
|
||||
SaveData
|
||||
).MutationCooldowns;
|
||||
},
|
||||
|
||||
set(Value) {
|
||||
const Garden =
|
||||
GetActiveGarden(
|
||||
SaveData
|
||||
);
|
||||
|
||||
Garden.MutationCooldowns =
|
||||
Value !== null &&
|
||||
typeof Value === "object" &&
|
||||
!Array.isArray(Value)
|
||||
? Value
|
||||
: {};
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function CreateNewSave() {
|
||||
const SeedInventory = {};
|
||||
const StartingPlants = [];
|
||||
@@ -40,8 +391,8 @@ function CreateNewSave() {
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
Version: 2,
|
||||
return NormalizeSaveData({
|
||||
Version: 3,
|
||||
Revision: 0,
|
||||
LastSavedAt: Date.now(),
|
||||
|
||||
@@ -83,19 +434,17 @@ function CreateNewSave() {
|
||||
ShowReadyPlots: true
|
||||
},
|
||||
|
||||
Garden: {
|
||||
Width: 3,
|
||||
Height: 3,
|
||||
Plots: Array(9).fill(null)
|
||||
},
|
||||
Gardens: [
|
||||
CreateGardenData()
|
||||
],
|
||||
|
||||
ActiveGardenIndex: 0,
|
||||
|
||||
Discoveries: {
|
||||
Plants: StartingPlants,
|
||||
Mutations: []
|
||||
},
|
||||
|
||||
MutationCooldowns: {}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +455,7 @@ function NormalizeSaveData(
|
||||
Number(
|
||||
SaveData.Version ?? 1
|
||||
),
|
||||
2
|
||||
3
|
||||
);
|
||||
|
||||
SaveData.Revision = Number(
|
||||
@@ -301,100 +650,48 @@ function NormalizeSaveData(
|
||||
false;
|
||||
|
||||
|
||||
SaveData.Garden ??= {
|
||||
Width: 3,
|
||||
Height: 3,
|
||||
Plots: []
|
||||
};
|
||||
const LegacyGarden =
|
||||
SaveData.Garden ??
|
||||
null;
|
||||
|
||||
SaveData.Garden.Width = Math.max(
|
||||
1,
|
||||
Math.floor(
|
||||
Number(
|
||||
SaveData.Garden.Width ?? 3
|
||||
) || 3
|
||||
)
|
||||
);
|
||||
const LegacyMutationCooldowns =
|
||||
SaveData.MutationCooldowns ??
|
||||
null;
|
||||
|
||||
SaveData.Garden.Height = Math.max(
|
||||
1,
|
||||
Math.floor(
|
||||
Number(
|
||||
SaveData.Garden.Height ?? 3
|
||||
) || 3
|
||||
)
|
||||
);
|
||||
|
||||
SaveData.Garden.Plots ??= [];
|
||||
|
||||
|
||||
for (
|
||||
let PlotIndex = 0;
|
||||
PlotIndex <
|
||||
SaveData.Garden.Plots.length;
|
||||
PlotIndex++
|
||||
) {
|
||||
const Plot =
|
||||
SaveData.Garden.Plots[
|
||||
PlotIndex
|
||||
];
|
||||
|
||||
if (Plot === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
Plot.Plant === "Rose"
|
||||
) {
|
||||
Plot.Plant =
|
||||
"RedRose";
|
||||
}
|
||||
|
||||
if (
|
||||
typeof Plot.Plant ===
|
||||
"number"
|
||||
) {
|
||||
const PlantKey =
|
||||
ResolvePlantKeyById(
|
||||
Plot.Plant
|
||||
);
|
||||
|
||||
if (PlantKey !== null) {
|
||||
Plot.Plant = PlantKey;
|
||||
}
|
||||
}
|
||||
|
||||
Plot.PlantedAt = Number(
|
||||
Plot.PlantedAt ??
|
||||
Date.now()
|
||||
);
|
||||
|
||||
delete Plot.VisualVariant;
|
||||
delete Plot.AddedTags;
|
||||
}
|
||||
|
||||
|
||||
const RequiredPlots =
|
||||
SaveData.Garden.Width *
|
||||
SaveData.Garden.Height;
|
||||
|
||||
while (
|
||||
SaveData.Garden.Plots.length <
|
||||
RequiredPlots
|
||||
) {
|
||||
SaveData.Garden.Plots.push(null);
|
||||
}
|
||||
|
||||
if (
|
||||
SaveData.Garden.Plots.length >
|
||||
RequiredPlots
|
||||
!Array.isArray(
|
||||
SaveData.Gardens
|
||||
) ||
|
||||
SaveData.Gardens.length === 0
|
||||
) {
|
||||
SaveData.Garden.Plots.length =
|
||||
RequiredPlots;
|
||||
SaveData.Gardens = [
|
||||
LegacyGarden ??
|
||||
CreateGardenData()
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
SaveData.MutationCooldowns ??= {};
|
||||
SaveData.Gardens =
|
||||
SaveData.Gardens.map(
|
||||
(Garden, GardenIndex) =>
|
||||
NormalizeGardenData(
|
||||
Garden,
|
||||
GardenIndex === 0
|
||||
? LegacyMutationCooldowns
|
||||
: null
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
SetActiveGardenIndex(
|
||||
SaveData,
|
||||
SaveData.ActiveGardenIndex ?? 0
|
||||
);
|
||||
|
||||
DefineActiveGardenAliases(
|
||||
SaveData
|
||||
);
|
||||
|
||||
|
||||
return SaveData;
|
||||
|
||||
@@ -124,6 +124,7 @@ function RenderGardenUpgrades() {
|
||||
CreateGardenExpansionCard(
|
||||
"Row"
|
||||
),
|
||||
CreateNewGardenCard(),
|
||||
CreatePlantInformationUpgradeCard(),
|
||||
CreateGardenOverviewUpgradeCard(),
|
||||
CreateMutationHintsUpgradeCard()
|
||||
@@ -210,6 +211,10 @@ function CreateGardenExpansionCard(
|
||||
"ShopItemDetails";
|
||||
|
||||
Details.append(
|
||||
CreateShopStat(
|
||||
"Garden",
|
||||
ShopSave.Garden.Name
|
||||
),
|
||||
CreateShopStat(
|
||||
"Current size",
|
||||
ShopSave.Garden.Width +
|
||||
@@ -273,6 +278,115 @@ function CreateGardenExpansionCard(
|
||||
}
|
||||
|
||||
|
||||
function CreateNewGardenCard() {
|
||||
const Cost =
|
||||
GetNewGardenCost(
|
||||
ShopSave
|
||||
);
|
||||
|
||||
const GardensOwned =
|
||||
ShopSave.Gardens.length;
|
||||
|
||||
|
||||
const Card =
|
||||
document.createElement(
|
||||
"article"
|
||||
);
|
||||
|
||||
Card.className =
|
||||
"Panel ShopItem";
|
||||
|
||||
|
||||
const Header =
|
||||
document.createElement(
|
||||
"div"
|
||||
);
|
||||
|
||||
Header.className =
|
||||
"ShopItemHeader";
|
||||
|
||||
|
||||
const Name =
|
||||
document.createElement(
|
||||
"h3"
|
||||
);
|
||||
|
||||
Name.textContent =
|
||||
"Buy new Garden";
|
||||
|
||||
Header.appendChild(Name);
|
||||
|
||||
|
||||
const Description =
|
||||
document.createElement(
|
||||
"p"
|
||||
);
|
||||
|
||||
Description.textContent =
|
||||
"Buy another independent 3×3 Garden. New Gardens can be named and expanded separately.";
|
||||
|
||||
|
||||
const Details =
|
||||
document.createElement(
|
||||
"div"
|
||||
);
|
||||
|
||||
Details.className =
|
||||
"ShopItemDetails";
|
||||
|
||||
Details.append(
|
||||
CreateShopStat(
|
||||
"Gardens owned",
|
||||
GardensOwned.toLocaleString()
|
||||
),
|
||||
CreateShopStat(
|
||||
"New Garden size",
|
||||
"3×3 (9 plots)"
|
||||
),
|
||||
CreateShopStat(
|
||||
"Price scaling",
|
||||
"+50% per Garden"
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
const BuyButton =
|
||||
document.createElement(
|
||||
"button"
|
||||
);
|
||||
|
||||
BuyButton.className =
|
||||
"ActionButton ShopBuyButton";
|
||||
|
||||
BuyButton.type = "button";
|
||||
|
||||
BuyButton.textContent =
|
||||
"Buy - " +
|
||||
Cost.toLocaleString() +
|
||||
" Dew";
|
||||
|
||||
BuyButton.disabled =
|
||||
ShopSave.Currency.Dew < Cost ||
|
||||
ShopPurchasePending;
|
||||
|
||||
BuyButton.addEventListener(
|
||||
"click",
|
||||
BuyNewGarden
|
||||
);
|
||||
|
||||
|
||||
Card.append(
|
||||
Header,
|
||||
Description,
|
||||
Details,
|
||||
BuyButton
|
||||
);
|
||||
|
||||
|
||||
return Card;
|
||||
}
|
||||
|
||||
|
||||
function CreatePlantInformationUpgradeCard() {
|
||||
const Cost =
|
||||
GetPlantInformationUpgradeCost();
|
||||
@@ -1188,6 +1302,60 @@ async function BuyGardenExpansion(
|
||||
}
|
||||
|
||||
|
||||
async function BuyNewGarden() {
|
||||
if (ShopPurchasePending) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const Cost =
|
||||
GetNewGardenCost(
|
||||
ShopSave
|
||||
);
|
||||
|
||||
if (
|
||||
ShopSave.Currency.Dew <
|
||||
Cost
|
||||
) {
|
||||
SetShopMessage(
|
||||
"You don't have enough Dew for a new Garden."
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
ShopPurchasePending = true;
|
||||
|
||||
try {
|
||||
ShopSave.Currency.Dew -=
|
||||
Cost;
|
||||
|
||||
ShopSave.Statistics.CurrencySpent.Dew +=
|
||||
Cost;
|
||||
|
||||
AddNewGarden(
|
||||
ShopSave
|
||||
);
|
||||
|
||||
SetShopMessage(
|
||||
"Bought a new 3×3 Garden for " +
|
||||
Cost.toLocaleString() +
|
||||
" Dew. It is now your active Garden."
|
||||
);
|
||||
|
||||
RenderShop();
|
||||
|
||||
await SaveGame(
|
||||
ShopSave
|
||||
);
|
||||
} finally {
|
||||
ShopPurchasePending = false;
|
||||
RenderShop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function BuyPlantInformationUpgrade() {
|
||||
if (
|
||||
ShopPurchasePending ||
|
||||
|
||||
@@ -2,6 +2,9 @@ const GardenExpansionBaseCost = 1000;
|
||||
const PlantInformationUpgradeCost = 500;
|
||||
const GardenOverviewUpgradeCost = 1000;
|
||||
const MutationHintsUpgradeCost = 1500;
|
||||
const NewGardenBaseCost = 30000;
|
||||
const NewGardenCostMultiplier = 1.5;
|
||||
const NewGardenCostRounding = 1000;
|
||||
|
||||
|
||||
function GetGardenColumnUpgradeCost(
|
||||
@@ -112,6 +115,51 @@ function ResetGardenMutationCooldowns(
|
||||
}
|
||||
|
||||
|
||||
function GetNewGardenCost(
|
||||
SaveData
|
||||
) {
|
||||
const GardensOwned = Math.max(
|
||||
1,
|
||||
SaveData.Gardens?.length ?? 1
|
||||
);
|
||||
|
||||
let Cost =
|
||||
NewGardenBaseCost;
|
||||
|
||||
for (
|
||||
let GardenNumber = 1;
|
||||
GardenNumber < GardensOwned;
|
||||
GardenNumber++
|
||||
) {
|
||||
Cost = Math.round(
|
||||
Cost *
|
||||
NewGardenCostMultiplier /
|
||||
NewGardenCostRounding
|
||||
) * NewGardenCostRounding;
|
||||
}
|
||||
|
||||
return Cost;
|
||||
}
|
||||
|
||||
|
||||
function AddNewGarden(
|
||||
SaveData
|
||||
) {
|
||||
SaveData.Gardens ??= [];
|
||||
|
||||
SaveData.Gardens.push(
|
||||
CreateGardenData()
|
||||
);
|
||||
|
||||
SetActiveGardenIndex(
|
||||
SaveData,
|
||||
SaveData.Gardens.length - 1
|
||||
);
|
||||
|
||||
return SaveData.Garden;
|
||||
}
|
||||
|
||||
|
||||
function HasPlantInformationUpgrade(
|
||||
SaveData
|
||||
) {
|
||||
|
||||
+40
-1
@@ -313,6 +313,45 @@ input, button, textarea, select {
|
||||
image-rendering: auto;
|
||||
}
|
||||
|
||||
.GardenSelectorPanel {
|
||||
display: grid;
|
||||
grid-template-columns: 3rem minmax(0, 1fr) 3rem;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
padding: 0.5rem;
|
||||
background-color: var(--Mantle);
|
||||
border: 3px solid var(--Surface2);
|
||||
}
|
||||
|
||||
.GardenSelectorButton {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.GardenNameInput {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
padding: 0.6rem 0.75rem;
|
||||
color: var(--Text);
|
||||
background-color: var(--Surface0);
|
||||
border: 3px solid var(--Surface2);
|
||||
border-radius: 0;
|
||||
text-align: center;
|
||||
box-shadow: 3px 3px 0 var(--Crust);
|
||||
}
|
||||
|
||||
.GardenNameInput:hover {
|
||||
border-color: var(--Sky);
|
||||
}
|
||||
|
||||
.GardenNameInput:focus {
|
||||
outline: 3px solid var(--Yellow);
|
||||
outline-offset: 3px;
|
||||
}
|
||||
|
||||
.GardenLayout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 12rem;
|
||||
@@ -327,7 +366,7 @@ input, button, textarea, select {
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
background-color: var(--Mantle);
|
||||
border: 4px solid var(--Lavender);
|
||||
border: 4px solid var(--GardenBorderColour, var(--Lavender));
|
||||
}
|
||||
|
||||
.GardenPlot {
|
||||
|
||||
Reference in new issue
Block a user