From b38cc9762ec0b5300c95c0ba19fb6f6218d83f16 Mon Sep 17 00:00:00 2001 From: Ryan Lanny Jenkins Date: Sun, 18 May 2025 12:53:49 -0500 Subject: [PATCH] Add the basis of the fertility system. --- src/components/Field.tsx | 16 +++++++++++++--- src/components/FloatingMessages.tsx | 15 ++++++++++----- src/components/Market.tsx | 4 ++-- src/constants/index.ts | 2 ++ src/store/useGameStore.ts | 28 ++++++++++++++++++++++++---- src/store/useSaveSystem.ts | 5 ++--- src/types/index.ts | 2 ++ 7 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/components/Field.tsx b/src/components/Field.tsx index 12d2b8d..c53751a 100644 --- a/src/components/Field.tsx +++ b/src/components/Field.tsx @@ -164,10 +164,20 @@ const FieldComponent: React.FC = () => { } } - const getBgColor = (hasCrop: boolean, isMature: boolean) => { + const getBgColor = ( + hasCrop: boolean, + isMature: boolean, + fertility: number, + ) => { if (isMature) return '#22c55e' if (hasCrop) return '#86efac' - return '#92400e' + + // For empty plots, show fertility level through color + // Convert fertility (0-1) to a color between light grey-brown and dark brown + const r = Math.floor(146 + (73 - 146) * fertility) // 146 to 73 + const g = Math.floor(131 + (47 - 131) * fertility) // 131 to 47 + const b = Math.floor(120 + (23 - 120) * fertility) // 120 to 23 + return `rgb(${r}, ${g}, ${b})` } const availableSpeeds = [1, 2, 4, 8, 16, 32, 64] @@ -233,7 +243,7 @@ const FieldComponent: React.FC = () => { row.slice(0, fieldSize).map((plot, colIndex) => { const hasCrop = !!plot.current const isMature = !!plot.current?.mature - const bgColor = getBgColor(hasCrop, isMature) + const bgColor = getBgColor(hasCrop, isMature, plot.fertility) return (
((_, ref) => { text, position, } - setMessages(prev => [...prev, newMessage]) - } + setMessages((prev) => [...prev, newMessage]) + }, })) const handleAnimationEnd = (messageId: string) => { - setMessages(prev => prev.filter(msg => msg.id !== messageId)) + setMessages((prev) => prev.filter((msg) => msg.id !== messageId)) } return ( @@ -52,7 +57,7 @@ const FloatingMessages = forwardRef((_, ref) => { } `} - {messages.map(message => ( + {messages.map((message) => (
{ floatingMessagesRef.current?.addMessage( `+1 ${item.emoji} ${item.name}`, - position + position, ) } @@ -107,7 +107,7 @@ const MarketComponent: React.FC = () => { floatingMessagesRef.current?.addMessage( `-1 ${item.emoji} ${item.name}`, - position + position, ) } diff --git a/src/constants/index.ts b/src/constants/index.ts index 9014145..387c7e6 100644 --- a/src/constants/index.ts +++ b/src/constants/index.ts @@ -21,6 +21,7 @@ export const CROPS: CropDefinitions = { waterPerTick: 1 / 20, yield: 1, yieldType: 'celery', + fertilityDepletion: 0.1, }, corn: { id: 'corn', @@ -29,6 +30,7 @@ export const CROPS: CropDefinitions = { waterPerTick: 1 / 40, yield: 5, yieldType: 'corn', + fertilityDepletion: 0.3, }, } diff --git a/src/store/useGameStore.ts b/src/store/useGameStore.ts index a7d8fa8..5eef734 100644 --- a/src/store/useGameStore.ts +++ b/src/store/useGameStore.ts @@ -20,6 +20,7 @@ const initializeField = (size: number): PlotState[][] => { .fill(0) .map(() => ({ moisture: 0, + fertility: 1, })), ) } @@ -175,6 +176,10 @@ export const useGameStore = create< state.plots[row][col].current = undefined state.inventory[yieldItem] = (state.inventory[yieldItem] || 0) + yieldAmount + state.plots[row][col].fertility = Math.max( + 0, + state.plots[row][col].fertility - crop.fertilityDepletion, + ) state.actionCooldown = COOLDOWN_DURATION }), ) @@ -190,6 +195,14 @@ export const useGameStore = create< // Update plots state.plots.forEach((row: PlotState[], rowIndex: number) => { row.forEach((plot: PlotState, colIndex: number) => { + // Regenerate fertility every 100 ticks + if (state.tickCount % 100 === 0 && plot.fertility < 1) { + state.plots[rowIndex][colIndex].fertility = Math.min( + 1, + plot.fertility + 0.1, + ) + } + if (!plot.current || plot.current.mature) { return } @@ -197,8 +210,15 @@ export const useGameStore = create< const crop = CROPS[plot.current.cropId] const waterNeeded = crop.waterPerTick - if (plot.moisture >= waterNeeded) { - const newProgress = plot.current.progress + 1 + // Only grow if fertility is above 0.2 + if (plot.moisture >= waterNeeded && plot.fertility >= 0.2) { + let growthRate = 1 + // Half growth rate if fertility is between 0.2 and 0.5 + if (plot.fertility < 0.5) { + growthRate = 0.5 + } + + const newProgress = plot.current.progress + growthRate const mature = newProgress >= crop.growthTicks state.plots[rowIndex][colIndex].moisture = @@ -257,7 +277,7 @@ export const useGameStore = create< const { cash } = get() const item = MARKET_ITEMS[itemId] - if (!item || item.buyPrice === null) { + if (!item || item.buyPrice === null || item.buyPrice === undefined) { return } @@ -267,7 +287,7 @@ export const useGameStore = create< set( produce((state) => { - state.cash -= item.buyPrice + state.cash -= item.buyPrice! state.inventory[itemId] = (state.inventory[itemId] || 0) + 1 }), ) diff --git a/src/store/useSaveSystem.ts b/src/store/useSaveSystem.ts index 51cd3ec..fd86ef3 100644 --- a/src/store/useSaveSystem.ts +++ b/src/store/useSaveSystem.ts @@ -1,5 +1,5 @@ -import { useEffect } from "react" -import { hasSaveInSlot, useGameStore } from "./useGameStore" +import { useEffect } from 'react' +import { hasSaveInSlot, useGameStore } from './useGameStore' export const useSaveSystem = () => { const { saveToSlot, loadFromSlot } = useGameStore() @@ -31,7 +31,6 @@ export const useSaveSystem = () => { } } - window.addEventListener('keydown', handleKeyDown) const interval = setInterval(() => { saveToSlot(0) diff --git a/src/types/index.ts b/src/types/index.ts index 6670f81..e1fd1b1 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -5,6 +5,7 @@ export interface Crop { waterPerTick: number yield: number yieldType: string + fertilityDepletion: number } export interface CropDefinitions { @@ -19,6 +20,7 @@ export interface PlotState { mature: boolean } moisture: number + fertility: number } export interface InventoryItem {