Add remove tool, fix the way olives are presented in the warehouse tab.

This commit is contained in:
Ryan Lanny Jenkins 2025-05-26 14:24:56 -05:00
parent c11a2dde94
commit 5724da535a
6 changed files with 74 additions and 60 deletions

View file

@ -256,6 +256,7 @@ const FieldComponent: React.FC = () => {
plant,
water,
harvest,
remove,
assignCrop,
gameSpeed,
setGameSpeed,
@ -288,6 +289,9 @@ const FieldComponent: React.FC = () => {
case 'harvest':
harvest(row, col)
break
case 'remove':
remove(row, col)
break
case 'inspect':
setInspectedPlot({ plot: plots[row][col], row, col })
break
@ -317,6 +321,7 @@ const FieldComponent: React.FC = () => {
{ id: 'plant', label: 'Plant', icon: '🌱' },
{ id: 'water', label: 'Water', icon: '💧' },
{ id: 'harvest', label: 'Harvest', icon: '✂️' },
{ id: 'remove', label: 'Remove', icon: '🗑️' },
{ id: 'inspect', label: 'Inspect', icon: '🔍' },
]

View file

@ -1,6 +1,6 @@
import React, { useRef } from 'react'
import { useGameStore } from '../store/useGameStore'
import { MARKET_ITEMS, MarketItem } from '../constants'
import { ITEMS, Item } from '../constants'
import FloatingMessage, { FloatingMessagesHandle } from './FloatingMessages'
import { styled } from '@linaria/react'
@ -75,7 +75,7 @@ const MarketComponent: React.FC = () => {
const { inventory, cash, buyItem, sellItem, landPurchases } = useGameStore()
const floatingMessagesRef = useRef<FloatingMessagesHandle>(null)
const getItemPrice = (item: MarketItem) => {
const getItemPrice = (item: Item) => {
if (item.id === 'additional_land') {
return Math.floor(100 * Math.pow(1.5, landPurchases))
}
@ -83,7 +83,7 @@ const MarketComponent: React.FC = () => {
}
const handleBuy = (itemId: string, e: React.MouseEvent) => {
const item = MARKET_ITEMS[itemId]
const item = ITEMS[itemId]
const price = getItemPrice(item)
if (!item || price === null || cash < price) return
@ -99,7 +99,7 @@ const MarketComponent: React.FC = () => {
}
const handleSell = (itemId: string, e: React.MouseEvent) => {
const item = MARKET_ITEMS[itemId]
const item = ITEMS[itemId]
if (
!item ||
item.sellPrice === null ||
@ -119,14 +119,14 @@ const MarketComponent: React.FC = () => {
)
}
const sellableItems = Object.entries(MARKET_ITEMS)
const sellableItems = Object.entries(ITEMS)
.filter(
([_, item]) =>
item.sellPrice !== null && inventory[item.id] && inventory[item.id] > 0,
)
.map(([_, item]) => item)
const buyableItems = Object.entries(MARKET_ITEMS)
const buyableItems = Object.entries(ITEMS)
.filter(([_, item]) => item.buyPrice !== null)
.map(([_, item]) => item)
@ -174,37 +174,41 @@ const MarketComponent: React.FC = () => {
</>
)}
<SectionTitle>Buy Items</SectionTitle>
<MarketTable>
<thead>
<tr>
<TableHeader>Item</TableHeader>
<TableHeader>Buy Price</TableHeader>
<TableHeader>Action</TableHeader>
</tr>
</thead>
<tbody>
{buyableItems.map((item) => (
<MarketItemRow key={`buy-${item.id}`}>
<MarketItemCell>
<ItemIcon>{item.emoji}</ItemIcon>
{item.name}
</MarketItemCell>
<MarketItemCell>${getItemPrice(item)}</MarketItemCell>
<MarketItemCell>
<ActionButton
onClick={(e) => handleBuy(item.id, e)}
disabled={
getItemPrice(item) ? cash < getItemPrice(item)! : true
}
>
Buy
</ActionButton>
</MarketItemCell>
</MarketItemRow>
))}
</tbody>
</MarketTable>
{buyableItems.length > 0 && (
<>
<SectionTitle>Buy Items</SectionTitle>
<MarketTable>
<thead>
<tr>
<TableHeader>Item</TableHeader>
<TableHeader>Buy Price</TableHeader>
<TableHeader>Action</TableHeader>
</tr>
</thead>
<tbody>
{buyableItems.map((item) => (
<MarketItemRow key={`buy-${item.id}`}>
<MarketItemCell>
<ItemIcon>{item.emoji}</ItemIcon>
{item.name}
</MarketItemCell>
<MarketItemCell>${getItemPrice(item)}</MarketItemCell>
<MarketItemCell>
<ActionButton
onClick={(e) => handleBuy(item.id, e)}
disabled={
getItemPrice(item) ? cash < getItemPrice(item)! : true
}
>
Buy
</ActionButton>
</MarketItemCell>
</MarketItemRow>
))}
</tbody>
</MarketTable>
</>
)}
<FloatingMessage ref={floatingMessagesRef} />
</MarketContainer>

View file

@ -1,6 +1,6 @@
import React from 'react'
import { useGameStore } from '../store/useGameStore'
import { CROPS } from '../constants'
import { ITEMS } from '../constants'
const warehouseContainerStyle: React.CSSProperties = {
padding: '1rem',
@ -65,25 +65,11 @@ const itemNameStyle: React.CSSProperties = {
}
const formatItemName = (id: string) => {
if (id.endsWith('_seed')) {
const cropId = id.replace('_seed', '')
return `${CROPS[cropId]?.name || cropId} Seeds`
}
return CROPS[id]?.name || id
return ITEMS[id]?.name || id
}
const getItemIcon = (id: string) => {
if (id.endsWith('_seed')) {
return '🌰'
}
const cropIcons: Record<string, string> = {
celery: '🥬',
corn: '🌽',
}
return cropIcons[id] || '📦'
return ITEMS[id]?.emoji || '📦'
}
const WarehouseComponent: React.FC = () => {

View file

@ -108,7 +108,7 @@ export const UPGRADES: Record<string, Upgrade> = {
},
}
export interface MarketItem {
export interface Item {
id: string
name: string
emoji: string
@ -116,7 +116,7 @@ export interface MarketItem {
sellPrice: number | null // null means not sellable
}
export const MARKET_ITEMS: Record<string, MarketItem> = {
export const ITEMS: Record<string, Item> = {
additional_land: {
id: 'additional_land',
name: 'Additional Land',

View file

@ -8,7 +8,7 @@ import {
CROPS,
INITIAL_GAME_SPEED,
COOLDOWN_DURATION,
MARKET_ITEMS,
ITEMS,
UPGRADES,
} from '../constants'
import { GameState, PlotState } from '../types'
@ -100,6 +100,7 @@ export const useGameStore = create<
plant: (row: number, col: number) => void
water: (row: number, col: number) => void
harvest: (row: number, col: number) => void
remove: (row: number, col: number) => void
tick: () => void
assignCrop: (row: number, col: number, cropId: string) => void
upgradeField: () => void
@ -265,6 +266,24 @@ export const useGameStore = create<
}
},
remove: (row, col) => {
const { plots, actionCooldown } = get()
if (actionCooldown > 0) {
return
}
const plot = plots[row][col]
if (plot.current) {
set(
produce((state) => {
state.plots[row][col].current = undefined
state.actionCooldown = COOLDOWN_DURATION
}),
)
}
},
tick: () => {
set(
produce((state) => {
@ -368,7 +387,7 @@ export const useGameStore = create<
buyItem: (itemId) => {
const { cash, landPurchases, plots, fieldSize } = get()
const item = MARKET_ITEMS[itemId]
const item = ITEMS[itemId]
if (!item || item.buyPrice === null || item.buyPrice === undefined) {
return
@ -424,7 +443,7 @@ export const useGameStore = create<
sellItem: (itemId) => {
const { inventory } = get()
const item = MARKET_ITEMS[itemId]
const item = ITEMS[itemId]
if (
!item ||

View file

@ -31,7 +31,7 @@ export interface InventoryItem {
count: number
}
export type FieldTool = 'mark' | 'plant' | 'water' | 'harvest' | 'inspect'
export type FieldTool = 'mark' | 'plant' | 'water' | 'harvest' | 'inspect' | 'remove'
export interface ConsoleMessage {
id: string