diff --git a/src/App.tsx b/src/App.tsx
index b8ddbe1..7510d1f 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -9,6 +9,7 @@ import { useGameTick } from './hooks/useGameTick'
import Field from './components/Field'
import Warehouse from './components/Warehouse'
import Market from './components/Market'
+import Temple from './components/Temple'
import { ActionCooldown } from './components/ActionCooldown'
import { useSaveSystem } from './store/useSaveSystem'
import { Console } from './components/Console'
@@ -38,9 +39,7 @@ function App() {
Fields
Warehouse
Market
-
- Temple
-
+ Temple
@@ -51,6 +50,9 @@ function App() {
+
+
+
diff --git a/src/components/Temple.tsx b/src/components/Temple.tsx
new file mode 100644
index 0000000..b666165
--- /dev/null
+++ b/src/components/Temple.tsx
@@ -0,0 +1,121 @@
+import React from 'react'
+import { useGameStore } from '../store/useGameStore'
+import { UPGRADES } from '../constants'
+import { styled } from '@linaria/react'
+import type { UpgradeCost } from '../types'
+
+const TempleContainer = styled.div`
+ padding: 1rem;
+`
+
+const Title = styled.h2`
+ font-size: 1.5rem;
+ font-weight: bold;
+ margin-bottom: 1rem;
+ text-align: center;
+`
+
+const UpgradesGrid = styled.div`
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
+ gap: 1rem;
+ margin-top: 1rem;
+`
+
+const UpgradeCard = styled.div<{ purchased?: boolean }>`
+ background-color: ${props => props.purchased ? '#e5e7eb' : '#f3f4f6'};
+ border: 1px solid #d1d5db;
+ border-radius: 0.5rem;
+ padding: 1rem;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+`
+
+const UpgradeName = styled.h3`
+ font-size: 1.25rem;
+ font-weight: 500;
+ margin: 0;
+`
+
+const UpgradeDescription = styled.p`
+ color: #4b5563;
+ margin: 0;
+`
+
+const UpgradeCost = styled.div`
+ display: flex;
+ flex-direction: column;
+ gap: 0.25rem;
+ margin-top: 0.5rem;
+`
+
+const CostItem = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+`
+
+const PurchaseButton = styled.button<{ disabled?: boolean }>`
+ padding: 0.5rem 1rem;
+ border-radius: 0.25rem;
+ background-color: ${props => props.disabled ? '#9ca3af' : '#3b82f6'};
+ color: white;
+ font-weight: bold;
+ cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
+ border: none;
+ margin-top: auto;
+`
+
+const TempleComponent: React.FC = () => {
+ const { inventory, purchasedUpgrades, purchaseUpgrade } = useGameStore()
+
+ const handlePurchase = (upgradeId: string) => {
+ purchaseUpgrade(upgradeId)
+ }
+
+ const canAffordUpgrade = (costs: UpgradeCost[]) => {
+ return costs.every(cost =>
+ inventory[cost.itemId] !== undefined &&
+ inventory[cost.itemId] >= cost.amount
+ )
+ }
+
+ return (
+
+ Temple
+
+ {Object.values(UPGRADES).map((upgrade) => {
+ const isPurchased = purchasedUpgrades.includes(upgrade.id)
+ const canAfford = canAffordUpgrade(upgrade.cost)
+
+ return (
+
+ {upgrade.name}
+ {upgrade.description}
+
+ Cost:
+ {upgrade.cost.map((cost, index) => (
+
+ {cost.amount} {cost.itemId}
+
+ (You have: {inventory[cost.itemId] || 0})
+
+
+ ))}
+
+ handlePurchase(upgrade.id)}
+ disabled={isPurchased || !canAfford}
+ >
+ {isPurchased ? 'Purchased' : 'Purchase'}
+
+
+ )
+ })}
+
+
+ )
+}
+
+export default TempleComponent
\ No newline at end of file
diff --git a/src/constants/index.ts b/src/constants/index.ts
index 387c7e6..c5345ed 100644
--- a/src/constants/index.ts
+++ b/src/constants/index.ts
@@ -1,4 +1,4 @@
-import { CropDefinitions } from '../types'
+import { CropDefinitions, Upgrade } from '../types'
export const INITIAL_CASH = 50
export const INITIAL_FIELD_SIZE = 3
@@ -38,6 +38,18 @@ export const INITIAL_INVENTORY = {
celery_seed: 8,
}
+export const UPGRADES: Record = {
+ aqueous_vigor_1: {
+ id: 'aqueous_vigor_1',
+ name: 'Aqueous Vigor I',
+ description: 'Reduces watering cooldown by 25%',
+ cost: [{
+ itemId: 'celery',
+ amount: 10
+ }]
+ }
+}
+
export interface MarketItem {
id: string
name: string
diff --git a/src/store/useGameStore.ts b/src/store/useGameStore.ts
index b558c2e..264335c 100644
--- a/src/store/useGameStore.ts
+++ b/src/store/useGameStore.ts
@@ -9,6 +9,7 @@ import {
INITIAL_GAME_SPEED,
COOLDOWN_DURATION,
MARKET_ITEMS,
+ UPGRADES,
} from '../constants'
import { GameState, PlotState } from '../types'
@@ -79,6 +80,7 @@ export const useGameStore = create<
sellItem: (itemId: string) => void
saveToSlot: (slot: number) => void
loadFromSlot: (slot: number) => void
+ purchaseUpgrade: (upgradeId: string) => void
}
>((set, get) => ({
cash: INITIAL_CASH,
@@ -91,6 +93,7 @@ export const useGameStore = create<
actionCooldown: 0,
tickCount: 0,
consoleMessages: [],
+ purchasedUpgrades: [],
assignCrop: (row, col, cropId) => {
set(
@@ -129,7 +132,7 @@ export const useGameStore = create<
},
water: (row, col) => {
- const { plots, actionCooldown } = get()
+ const { plots, actionCooldown, purchasedUpgrades } = get()
if (actionCooldown > 0) {
return
@@ -137,10 +140,21 @@ export const useGameStore = create<
const plot = plots[row][col]
if (plot.current && plot.moisture < 1) {
+ // Calculate cooldown reduction from upgrades
+ let cooldownReduction = 0
+ if (purchasedUpgrades.includes('aqueous_vigor_1')) {
+ cooldownReduction += 0.25 // 25% reduction
+ }
+
+ const finalCooldown = Math.max(
+ 0,
+ COOLDOWN_DURATION * (1 - cooldownReduction)
+ )
+
set(
produce((state) => {
state.plots[row][col].moisture = 1
- state.actionCooldown = COOLDOWN_DURATION
+ state.actionCooldown = finalCooldown
}),
)
}
@@ -331,6 +345,7 @@ export const useGameStore = create<
sellItem,
saveToSlot,
loadFromSlot,
+ purchaseUpgrade,
...gameState
} = state
saveGame(slot, gameState)
@@ -342,4 +357,36 @@ export const useGameStore = create<
set(savedState)
}
},
+
+ purchaseUpgrade: (upgradeId) => {
+ const { inventory, purchasedUpgrades } = get()
+ const upgrade = UPGRADES[upgradeId]
+
+ if (!upgrade || purchasedUpgrades.includes(upgradeId)) {
+ return
+ }
+
+ // Check if player can afford all costs
+ const canAfford = upgrade.cost.every(
+ cost => inventory[cost.itemId] !== undefined && inventory[cost.itemId] >= cost.amount
+ )
+
+ if (!canAfford) {
+ return
+ }
+
+ set(
+ produce((state) => {
+ // Deduct all costs
+ upgrade.cost.forEach(cost => {
+ state.inventory[cost.itemId] -= cost.amount
+ })
+ state.purchasedUpgrades.push(upgradeId)
+ addConsoleMessage(
+ state,
+ `Purchased upgrade: ${upgrade.name}`
+ )
+ }),
+ )
+ },
}))
diff --git a/src/types/index.ts b/src/types/index.ts
index 5f0d942..bfb1a05 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -36,6 +36,18 @@ export interface ConsoleMessage {
timestamp: number
}
+export interface UpgradeCost {
+ itemId: string
+ amount: number
+}
+
+export interface Upgrade {
+ id: string
+ name: string
+ description: string
+ cost: UpgradeCost[]
+}
+
export interface GameState {
cash: number
inventory: Record
@@ -46,6 +58,7 @@ export interface GameState {
gameSpeed: number
actionCooldown: number
consoleMessages: ConsoleMessage[]
+ purchasedUpgrades: string[]
}
export interface MarketTransaction {