diff --git a/Pages/Garden.php b/Pages/Garden.php index ebf58f3..f673a41 100644 --- a/Pages/Garden.php +++ b/Pages/Garden.php @@ -18,11 +18,64 @@ $PageSection = "Garden";

Garden

- Dew: - 0 -
- Next harvest: - Nothing planted +
+ Dew: + 0 +
+ +
+ Next harvest: + Nothing planted +
+ +
diff --git a/Pages/Profile.php b/Pages/Profile.php index ce108e4..82d7772 100644 --- a/Pages/Profile.php +++ b/Pages/Profile.php @@ -105,6 +105,8 @@ $PageTitle = "Profile"; >

Garden display

+

Plant information

+

Choose which Plant information details are shown on Garden plots. @@ -133,6 +135,65 @@ $PageTitle = "Profile"; Unlock Plant information in the Shop to use these settings.

+ +

Garden overview

+ +

+ Choose which Garden overview lines are + shown in the Garden status box. +

+ +
+ + + + + + + + + + + +
+ +

+ Unlock Garden overview in the Shop + to use these settings. +

Permanent upgrades

- Expand your Garden one row or column at a time. - Existing plants keep their positions. + Permanently expand your Garden or unlock + extra information and quality-of-life features.

{ + ToggleGardenDisplayPreference( + PreferenceName + ); + } + ); } - - - PlantNamesButton.addEventListener( - "click", - () => { - ToggleGardenDisplayPreference( - "ShowPlantNames" - ); - } - ); - - GrowthTimersButton.addEventListener( - "click", - () => { - ToggleGardenDisplayPreference( - "ShowGrowthTimers" - ); - } - ); } function RenderGardenDisplayPreferences() { + RenderPlantInformationPreferences(); + RenderGardenOverviewPreferences(); +} + + +function RenderPlantInformationPreferences() { const PlantNamesButton = document.getElementById( "TogglePlantNamesButton" @@ -144,14 +176,19 @@ function RenderGardenDisplayPreferences() { ); if (!IsOwned) { - PlantNamesButton.textContent = - "Plant names: Locked"; + SetPreferenceButtonState( + PlantNamesButton, + "Plant names", + false, + true + ); - GrowthTimersButton.textContent = - "Growth timers: Locked"; - - PlantNamesButton.disabled = true; - GrowthTimersButton.disabled = true; + SetPreferenceButtonState( + GrowthTimersButton, + "Growth timers", + false, + true + ); Message.textContent = "Unlock Plant information in the Shop to use these settings."; @@ -160,38 +197,166 @@ function RenderGardenDisplayPreferences() { } - const ShowPlantNames = + SetPreferenceButtonState( + PlantNamesButton, + "Plant names", ProfileSave.Preferences - .ShowPlantNames !== false; + .ShowPlantNames !== false + ); - const ShowGrowthTimers = + SetPreferenceButtonState( + GrowthTimersButton, + "Growth timers", ProfileSave.Preferences - .ShowGrowthTimers !== false; - - PlantNamesButton.disabled = false; - GrowthTimersButton.disabled = false; - - PlantNamesButton.textContent = - "Plant names: " + - (ShowPlantNames - ? "On" - : "Off"); - - GrowthTimersButton.textContent = - "Growth timers: " + - (ShowGrowthTimers - ? "On" - : "Off"); + .ShowGrowthTimers !== false + ); Message.textContent = "Plant names and growth timers can be changed independently."; } +function RenderGardenOverviewPreferences() { + const Settings = [ + [ + "ToggleNextHarvestButton", + "Next harvest", + "ShowNextHarvest" + ], + [ + "ToggleGardenSizeButton", + "Garden size", + "ShowGardenSize" + ], + [ + "ToggleEmptyPlotsButton", + "Empty plots", + "ShowEmptyPlots" + ], + [ + "TogglePlantedPlotsButton", + "Planted plots", + "ShowPlantedPlots" + ], + [ + "ToggleGrowingPlotsButton", + "Growing", + "ShowGrowingPlots" + ], + [ + "ToggleReadyPlotsButton", + "Ready to harvest", + "ShowReadyPlots" + ] + ]; + + const Message = + document.getElementById( + "GardenOverviewDisplayMessage" + ); + + if (Message === null) { + return; + } + + + const IsOwned = + HasGardenOverviewUpgrade( + ProfileSave + ); + + for ( + const [ + ButtonId, + Label, + PreferenceName + ] + of Settings + ) { + const Button = + document.getElementById( + ButtonId + ); + + if (Button === null) { + continue; + } + + SetPreferenceButtonState( + Button, + Label, + ProfileSave.Preferences[ + PreferenceName + ] !== false, + !IsOwned + ); + } + + + Message.textContent = + IsOwned + ? "Every Garden overview line can be changed independently." + : "Unlock Garden overview in the Shop to use these settings."; +} + + +function SetPreferenceButtonState( + Button, + Label, + IsEnabled, + IsLocked = false +) { + Button.disabled = IsLocked; + + Button.textContent = + Label + + ": " + + (IsLocked + ? "Locked" + : IsEnabled + ? "On" + : "Off"); +} + + async function ToggleGardenDisplayPreference( PreferenceName ) { + const PlantInformationPreferences = [ + "ShowPlantNames", + "ShowGrowthTimers" + ]; + + const GardenOverviewPreferences = [ + "ShowNextHarvest", + "ShowGardenSize", + "ShowEmptyPlots", + "ShowPlantedPlots", + "ShowGrowingPlots", + "ShowReadyPlots" + ]; + + + const IsPlantInformationPreference = + PlantInformationPreferences.includes( + PreferenceName + ); + + const IsGardenOverviewPreference = + GardenOverviewPreferences.includes( + PreferenceName + ); + + if ( + !IsPlantInformationPreference && + !IsGardenOverviewPreference + ) { + return; + } + + if ( + IsPlantInformationPreference && !HasPlantInformationUpgrade( ProfileSave ) @@ -200,10 +365,10 @@ async function ToggleGardenDisplayPreference( } if ( - PreferenceName !== - "ShowPlantNames" && - PreferenceName !== - "ShowGrowthTimers" + IsGardenOverviewPreference && + !HasGardenOverviewUpgrade( + ProfileSave + ) ) { return; } diff --git a/Scripts/Garden/Save.js b/Scripts/Garden/Save.js index 4ceeb62..d04d858 100644 --- a/Scripts/Garden/Save.js +++ b/Scripts/Garden/Save.js @@ -67,12 +67,19 @@ function CreateNewSave() { Upgrades: { PlotSize: 0, - PlantInformation: false + PlantInformation: false, + GardenOverview: false }, Preferences: { ShowPlantNames: true, - ShowGrowthTimers: true + ShowGrowthTimers: true, + ShowNextHarvest: true, + ShowGardenSize: true, + ShowEmptyPlots: true, + ShowPlantedPlots: true, + ShowGrowingPlots: true, + ShowReadyPlots: true }, Garden: { @@ -249,6 +256,10 @@ function NormalizeSaveData( SaveData.Upgrades.PlantInformation === true; + SaveData.Upgrades.GardenOverview = + SaveData.Upgrades.GardenOverview === + true; + SaveData.Preferences ??= {}; @@ -260,6 +271,30 @@ function NormalizeSaveData( SaveData.Preferences.ShowGrowthTimers !== false; + SaveData.Preferences.ShowNextHarvest = + SaveData.Preferences.ShowNextHarvest !== + false; + + SaveData.Preferences.ShowGardenSize = + SaveData.Preferences.ShowGardenSize !== + false; + + SaveData.Preferences.ShowEmptyPlots = + SaveData.Preferences.ShowEmptyPlots !== + false; + + SaveData.Preferences.ShowPlantedPlots = + SaveData.Preferences.ShowPlantedPlots !== + false; + + SaveData.Preferences.ShowGrowingPlots = + SaveData.Preferences.ShowGrowingPlots !== + false; + + SaveData.Preferences.ShowReadyPlots = + SaveData.Preferences.ShowReadyPlots !== + false; + SaveData.Garden ??= { Width: 3, diff --git a/Scripts/Garden/Shop.js b/Scripts/Garden/Shop.js index e002eaf..2312895 100644 --- a/Scripts/Garden/Shop.js +++ b/Scripts/Garden/Shop.js @@ -124,7 +124,8 @@ function RenderGardenUpgrades() { CreateGardenExpansionCard( "Row" ), - CreatePlantInformationUpgradeCard() + CreatePlantInformationUpgradeCard(), + CreateGardenOverviewUpgradeCard() ); } @@ -387,6 +388,122 @@ function CreatePlantInformationUpgradeCard() { } +function CreateGardenOverviewUpgradeCard() { + const Cost = + GetGardenOverviewUpgradeCost(); + + const IsOwned = + HasGardenOverviewUpgrade( + 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 = + "Garden overview"; + + Header.appendChild(Name); + + + const Description = + document.createElement( + "p" + ); + + Description.textContent = + "Expand the Garden status box with detailed plot counts and the name of the next plant ready to harvest. Every overview line can be toggled on/off from the profile page."; + + + const Details = + document.createElement( + "div" + ); + + Details.className = + "ShopItemDetails"; + + Details.append( + CreateShopStat( + "Garden details", + IsOwned + ? "Unlocked" + : "Locked" + ), + CreateShopStat( + "Profile controls", + 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", + BuyGardenOverviewUpgrade + ); + } + + + Card.append( + Header, + Description, + Details, + BuyButton + ); + + + return Card; +} + + function CreateShopSeedCard( Plant ) { @@ -1014,6 +1131,64 @@ async function BuyPlantInformationUpgrade() { } +async function BuyGardenOverviewUpgrade() { + if ( + ShopPurchasePending || + HasGardenOverviewUpgrade( + ShopSave + ) + ) { + return; + } + + + const Cost = + GetGardenOverviewUpgradeCost(); + + if ( + ShopSave.Currency.Dew < + Cost + ) { + SetShopMessage( + "You don't have enough Dew for Garden overview." + ); + + return; + } + + + ShopPurchasePending = true; + + try { + ShopSave.Currency.Dew -= + Cost; + + ShopSave.Statistics.CurrencySpent.Dew += + Cost; + + UnlockGardenOverview( + ShopSave + ); + + + SetShopMessage( + "Bought Garden overview for " + + Cost.toLocaleString() + + " Dew. All overview lines are now visible." + ); + + RenderShop(); + + await SaveGame( + ShopSave + ); + } finally { + ShopPurchasePending = false; + RenderShop(); + } +} + + function SetShopMessage( Message ) { diff --git a/Scripts/Garden/Upgrades.js b/Scripts/Garden/Upgrades.js index ce2daad..eb1e10d 100644 --- a/Scripts/Garden/Upgrades.js +++ b/Scripts/Garden/Upgrades.js @@ -1,5 +1,6 @@ const GardenExpansionBaseCost = 1000; const PlantInformationUpgradeCost = 500; +const GardenOverviewUpgradeCost = 1000; function GetGardenColumnUpgradeCost( @@ -142,3 +143,49 @@ function UnlockPlantInformation( SaveData.Preferences.ShowGrowthTimers = true; } + + +function HasGardenOverviewUpgrade( + SaveData +) { + return ( + SaveData + ?.Upgrades + ?.GardenOverview === + true + ); +} + + +function GetGardenOverviewUpgradeCost() { + return GardenOverviewUpgradeCost; +} + + +function UnlockGardenOverview( + SaveData +) { + SaveData.Upgrades ??= {}; + SaveData.Preferences ??= {}; + + SaveData.Upgrades.GardenOverview = + true; + + SaveData.Preferences.ShowNextHarvest = + true; + + SaveData.Preferences.ShowGardenSize = + true; + + SaveData.Preferences.ShowEmptyPlots = + true; + + SaveData.Preferences.ShowPlantedPlots = + true; + + SaveData.Preferences.ShowGrowingPlots = + true; + + SaveData.Preferences.ShowReadyPlots = + true; +} diff --git a/Styles/Style.css b/Styles/Style.css index 04e7af1..bafa984 100644 --- a/Styles/Style.css +++ b/Styles/Style.css @@ -84,6 +84,14 @@ body { border: 3px solid var(--Surface2); } +.GardenOverviewDetails { + margin-top: 0.5rem; +} + +.GardenStatusLine + .GardenStatusLine { + margin-top: 0.1rem; +} + .PageMessage { margin-top: 1rem; margin-bottom: 0; @@ -623,6 +631,10 @@ input, button, textarea, select { margin-bottom: 1rem; } +.ProfileSection h3 { + margin-top: 1.5rem; +} + .ProfileFormRow, .ProfileButtonRow { display: flex; flex-wrap: wrap;