Add our first upgrade to the temple.
This commit is contained in:
parent
9644cc4b4a
commit
6d72c8c0f9
|
|
@ -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() {
|
|||
<TabsTrigger value="fields">Fields</TabsTrigger>
|
||||
<TabsTrigger value="warehouse">Warehouse</TabsTrigger>
|
||||
<TabsTrigger value="market">Market</TabsTrigger>
|
||||
<TabsTrigger value="temple" disabled>
|
||||
Temple
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="temple">Temple</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="fields">
|
||||
<Field />
|
||||
|
|
@ -51,6 +50,9 @@ function App() {
|
|||
<TabsContent value="market">
|
||||
<Market />
|
||||
</TabsContent>
|
||||
<TabsContent value="temple">
|
||||
<Temple />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
<Console />
|
||||
</div>
|
||||
|
|
|
|||
121
src/components/Temple.tsx
Normal file
121
src/components/Temple.tsx
Normal file
|
|
@ -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 (
|
||||
<TempleContainer>
|
||||
<Title>Temple</Title>
|
||||
<UpgradesGrid>
|
||||
{Object.values(UPGRADES).map((upgrade) => {
|
||||
const isPurchased = purchasedUpgrades.includes(upgrade.id)
|
||||
const canAfford = canAffordUpgrade(upgrade.cost)
|
||||
|
||||
return (
|
||||
<UpgradeCard key={upgrade.id} purchased={isPurchased}>
|
||||
<UpgradeName>{upgrade.name}</UpgradeName>
|
||||
<UpgradeDescription>{upgrade.description}</UpgradeDescription>
|
||||
<UpgradeCost>
|
||||
<span>Cost:</span>
|
||||
{upgrade.cost.map((cost, index) => (
|
||||
<CostItem key={index}>
|
||||
<span>{cost.amount} {cost.itemId}</span>
|
||||
<span>
|
||||
(You have: {inventory[cost.itemId] || 0})
|
||||
</span>
|
||||
</CostItem>
|
||||
))}
|
||||
</UpgradeCost>
|
||||
<PurchaseButton
|
||||
onClick={() => handlePurchase(upgrade.id)}
|
||||
disabled={isPurchased || !canAfford}
|
||||
>
|
||||
{isPurchased ? 'Purchased' : 'Purchase'}
|
||||
</PurchaseButton>
|
||||
</UpgradeCard>
|
||||
)
|
||||
})}
|
||||
</UpgradesGrid>
|
||||
</TempleContainer>
|
||||
)
|
||||
}
|
||||
|
||||
export default TempleComponent
|
||||
|
|
@ -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<string, Upgrade> = {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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}`
|
||||
)
|
||||
}),
|
||||
)
|
||||
},
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -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<string, number>
|
||||
|
|
@ -46,6 +58,7 @@ export interface GameState {
|
|||
gameSpeed: number
|
||||
actionCooldown: number
|
||||
consoleMessages: ConsoleMessage[]
|
||||
purchasedUpgrades: string[]
|
||||
}
|
||||
|
||||
export interface MarketTransaction {
|
||||
|
|
|
|||
Loading…
Reference in a new issue