Get Linaria actually working, add global cooldown for actions.
This commit is contained in:
parent
974d851767
commit
6408fcd199
71
package-lock.json
generated
71
package-lock.json
generated
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "idle-farm-game",
|
"name": "dionysian-idle",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "idle-farm-game",
|
"name": "dionysian-idle",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.0.1",
|
"@hookform/resolvers": "^5.0.1",
|
||||||
|
|
@ -70,6 +70,7 @@
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "^18.3.12",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
"@wyw-in-js/vite": "^0.6.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^9.15.0",
|
"eslint": "^9.15.0",
|
||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
|
|
@ -4863,6 +4864,72 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@wyw-in-js/transform": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@wyw-in-js/transform/-/transform-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-/Rxw8e3KcmSjnqWs/6flmpcNTa4jLw8NViIyNwqem498AfSWXrPnYf3RyjWed9zDVL72q7Xjei6TcRqMupl3Eg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/core": "^7.23.5",
|
||||||
|
"@babel/generator": "^7.23.5",
|
||||||
|
"@babel/helper-module-imports": "^7.22.15",
|
||||||
|
"@babel/plugin-transform-modules-commonjs": "^7.23.3",
|
||||||
|
"@babel/template": "^7.22.15",
|
||||||
|
"@babel/traverse": "^7.23.5",
|
||||||
|
"@babel/types": "^7.23.5",
|
||||||
|
"@wyw-in-js/processor-utils": "0.6.0",
|
||||||
|
"@wyw-in-js/shared": "0.6.0",
|
||||||
|
"babel-merge": "^3.0.0",
|
||||||
|
"cosmiconfig": "^8.0.0",
|
||||||
|
"happy-dom": "^15.11.0",
|
||||||
|
"source-map": "^0.7.4",
|
||||||
|
"stylis": "^4.3.0",
|
||||||
|
"ts-invariant": "^0.10.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@wyw-in-js/transform/node_modules/happy-dom": {
|
||||||
|
"version": "15.11.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-15.11.7.tgz",
|
||||||
|
"integrity": "sha512-KyrFvnl+J9US63TEzwoiJOQzZBJY7KgBushJA8X61DMbNsH+2ONkDuLDnCnwUiPTF42tLoEmrPyoqbenVA5zrg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"entities": "^4.5.0",
|
||||||
|
"webidl-conversions": "^7.0.0",
|
||||||
|
"whatwg-mimetype": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@wyw-in-js/transform/node_modules/stylis": {
|
||||||
|
"version": "4.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz",
|
||||||
|
"integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@wyw-in-js/vite": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@wyw-in-js/vite/-/vite-0.6.0.tgz",
|
||||||
|
"integrity": "sha512-nGeH/dFrjecHRJfxd5/71cJu4V2YWakUmnEoAUpS0iTnVVC4GWjKqt1dLtsJvtKZIm2OeNoTzzdFrP4bxyXYxQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@wyw-in-js/shared": "0.6.0",
|
||||||
|
"@wyw-in-js/transform": "0.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vite": ">=3.2.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/acorn": {
|
"node_modules/acorn": {
|
||||||
"version": "8.14.1",
|
"version": "8.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@
|
||||||
"@types/react": "^18.3.12",
|
"@types/react": "^18.3.12",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@types/react-dom": "^18.3.1",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
|
"@wyw-in-js/vite": "^0.6.0",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^9.15.0",
|
"eslint": "^9.15.0",
|
||||||
"eslint-plugin-react-hooks": "^5.0.0",
|
"eslint-plugin-react-hooks": "^5.0.0",
|
||||||
|
|
|
||||||
54
src/App.tsx
54
src/App.tsx
|
|
@ -3,6 +3,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from './components/CustomTab
|
||||||
import { useGameTick } from './hooks/useGameTick';
|
import { useGameTick } from './hooks/useGameTick';
|
||||||
import Field from './components/Field';
|
import Field from './components/Field';
|
||||||
import Warehouse from './components/Warehouse';
|
import Warehouse from './components/Warehouse';
|
||||||
|
import { ActionCooldown } from './components/ActionCooldown';
|
||||||
|
|
||||||
const appContainerStyle: React.CSSProperties = {
|
const appContainerStyle: React.CSSProperties = {
|
||||||
maxWidth: '1200px',
|
maxWidth: '1200px',
|
||||||
|
|
@ -10,21 +11,6 @@ const appContainerStyle: React.CSSProperties = {
|
||||||
padding: '2rem'
|
padding: '2rem'
|
||||||
};
|
};
|
||||||
|
|
||||||
const headerStyle: React.CSSProperties = {
|
|
||||||
textAlign: 'center',
|
|
||||||
marginBottom: '2rem'
|
|
||||||
};
|
|
||||||
|
|
||||||
const titleStyle: React.CSSProperties = {
|
|
||||||
fontSize: '2.25rem',
|
|
||||||
fontWeight: 'bold',
|
|
||||||
marginBottom: '0.5rem'
|
|
||||||
};
|
|
||||||
|
|
||||||
const subtitleStyle: React.CSSProperties = {
|
|
||||||
color: '#6b7280'
|
|
||||||
};
|
|
||||||
|
|
||||||
const tabsListStyles: React.CSSProperties = {
|
const tabsListStyles: React.CSSProperties = {
|
||||||
display: 'grid',
|
display: 'grid',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|
@ -35,26 +21,24 @@ function App() {
|
||||||
useGameTick();
|
useGameTick();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={appContainerStyle}>
|
<div>
|
||||||
<header style={headerStyle}>
|
<ActionCooldown />
|
||||||
<h1 style={titleStyle}>Idle Farm Game</h1>
|
<div style={appContainerStyle}>
|
||||||
<p style={subtitleStyle}>Grow crops, harvest, and expand your farm!</p>
|
<Tabs defaultValue="fields">
|
||||||
</header>
|
<TabsList style={tabsListStyles}>
|
||||||
|
<TabsTrigger value="fields">Fields</TabsTrigger>
|
||||||
<Tabs defaultValue="fields">
|
<TabsTrigger value="warehouse">Warehouse</TabsTrigger>
|
||||||
<TabsList style={tabsListStyles}>
|
<TabsTrigger value="market" disabled>Market</TabsTrigger>
|
||||||
<TabsTrigger value="fields">Fields</TabsTrigger>
|
<TabsTrigger value="temple" disabled>Temple</TabsTrigger>
|
||||||
<TabsTrigger value="warehouse">Warehouse</TabsTrigger>
|
</TabsList>
|
||||||
<TabsTrigger value="market" disabled>Market</TabsTrigger>
|
<TabsContent value="fields">
|
||||||
<TabsTrigger value="temple" disabled>Temple</TabsTrigger>
|
<Field />
|
||||||
</TabsList>
|
</TabsContent>
|
||||||
<TabsContent value="fields">
|
<TabsContent value="warehouse">
|
||||||
<Field />
|
<Warehouse />
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="warehouse">
|
</Tabs>
|
||||||
<Warehouse />
|
</div>
|
||||||
</TabsContent>
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
59
src/components/ActionCooldown.tsx
Normal file
59
src/components/ActionCooldown.tsx
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { styled } from '@linaria/react';
|
||||||
|
|
||||||
|
import { useGameStore } from '../store/useGameStore';
|
||||||
|
|
||||||
|
const CooldownContainer = styled.div`
|
||||||
|
position: relative;
|
||||||
|
height: 1rem;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #e5e7eb;
|
||||||
|
overflow: hidden;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ProgressBar = styled.div<{ progress: string }>`
|
||||||
|
height: 100%;
|
||||||
|
background-color: #3b82f6;
|
||||||
|
width: ${props => props.progress};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const ActionCooldown = () => {
|
||||||
|
const { actionCooldown, setActionCooldown } = useGameStore();
|
||||||
|
const [progress, setProgress] = useState(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (actionCooldown <= 0) {
|
||||||
|
setProgress(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const startTime = Date.now();
|
||||||
|
const duration = actionCooldown;
|
||||||
|
|
||||||
|
const updateProgress = () => {
|
||||||
|
const elapsed = Date.now() - startTime;
|
||||||
|
const newProgress = Math.min(100, (elapsed / duration) * 100);
|
||||||
|
|
||||||
|
if (newProgress >= 100) {
|
||||||
|
setProgress(0);
|
||||||
|
setActionCooldown(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setProgress(newProgress);
|
||||||
|
requestAnimationFrame(updateProgress);
|
||||||
|
};
|
||||||
|
|
||||||
|
const animationFrame = requestAnimationFrame(updateProgress);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelAnimationFrame(animationFrame);
|
||||||
|
};
|
||||||
|
}, [actionCooldown, setActionCooldown]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CooldownContainer>
|
||||||
|
<ProgressBar progress={`${progress}%`} />
|
||||||
|
</CooldownContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -148,32 +148,12 @@ const FieldComponent: React.FC = () => {
|
||||||
water,
|
water,
|
||||||
harvest,
|
harvest,
|
||||||
assignCrop,
|
assignCrop,
|
||||||
lastPlantTime,
|
|
||||||
lastWaterTime,
|
|
||||||
lastHarvestTime,
|
|
||||||
gameSpeed,
|
gameSpeed,
|
||||||
setGameSpeed
|
setGameSpeed,
|
||||||
|
actionCooldown
|
||||||
} = useGameStore();
|
} = useGameStore();
|
||||||
|
|
||||||
const [selectedCrop, setSelectedCrop] = useState<string | null>(null);
|
const [selectedCrop, setSelectedCrop] = useState<string | null>(null);
|
||||||
const [cooldowns, setCooldowns] = useState({
|
|
||||||
plant: false,
|
|
||||||
water: false,
|
|
||||||
harvest: false
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const interval = setInterval(() => {
|
|
||||||
const now = Date.now();
|
|
||||||
setCooldowns({
|
|
||||||
plant: now - lastPlantTime < 2000,
|
|
||||||
water: now - lastWaterTime < 2000,
|
|
||||||
harvest: now - lastHarvestTime < 2000
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
|
||||||
}, [lastPlantTime, lastWaterTime, lastHarvestTime]);
|
|
||||||
|
|
||||||
const handlePlotClick = (row: number, col: number) => {
|
const handlePlotClick = (row: number, col: number) => {
|
||||||
if (selectedCrop) {
|
if (selectedCrop) {
|
||||||
|
|
@ -187,6 +167,8 @@ const FieldComponent: React.FC = () => {
|
||||||
return "#92400e";
|
return "#92400e";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const availableSpeeds = [1, 2, 4, 8, 16, 32, 64]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={fieldContainerStyle}>
|
<div style={fieldContainerStyle}>
|
||||||
<h2 style={titleStyle}>Fields</h2>
|
<h2 style={titleStyle}>Fields</h2>
|
||||||
|
|
@ -194,24 +176,15 @@ const FieldComponent: React.FC = () => {
|
||||||
<div style={speedSelectorContainerStyle}>
|
<div style={speedSelectorContainerStyle}>
|
||||||
<p style={speedSelectorLabelStyle}>Game Speed:</p>
|
<p style={speedSelectorLabelStyle}>Game Speed:</p>
|
||||||
<div style={speedButtonsContainerStyle}>
|
<div style={speedButtonsContainerStyle}>
|
||||||
<button
|
{availableSpeeds.map(speed => (
|
||||||
style={getSpeedButtonStyle(gameSpeed === 1)}
|
<button
|
||||||
onClick={() => setGameSpeed(1)}
|
style={getSpeedButtonStyle(gameSpeed === speed)}
|
||||||
>
|
onClick={() => setGameSpeed(speed)}
|
||||||
1x
|
key={speed}
|
||||||
</button>
|
>
|
||||||
<button
|
{speed}x
|
||||||
style={getSpeedButtonStyle(gameSpeed === 5)}
|
</button>
|
||||||
onClick={() => setGameSpeed(5)}
|
))}
|
||||||
>
|
|
||||||
5x
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
style={getSpeedButtonStyle(gameSpeed === 10)}
|
|
||||||
onClick={() => setGameSpeed(10)}
|
|
||||||
>
|
|
||||||
10x
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -230,23 +203,23 @@ const FieldComponent: React.FC = () => {
|
||||||
|
|
||||||
<div style={actionsContainerStyle}>
|
<div style={actionsContainerStyle}>
|
||||||
<button
|
<button
|
||||||
style={getActionButtonStyle(cooldowns.plant)}
|
style={getActionButtonStyle(actionCooldown > 0)}
|
||||||
onClick={plant}
|
onClick={plant}
|
||||||
disabled={cooldowns.plant}
|
disabled={actionCooldown > 0}
|
||||||
>
|
>
|
||||||
Plant Crop
|
Plant Crop
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
style={getActionButtonStyle(cooldowns.water)}
|
style={getActionButtonStyle(actionCooldown > 0)}
|
||||||
onClick={water}
|
onClick={water}
|
||||||
disabled={cooldowns.water}
|
disabled={actionCooldown > 0}
|
||||||
>
|
>
|
||||||
Water Crop
|
Water Crop
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
style={getActionButtonStyle(cooldowns.harvest)}
|
style={getActionButtonStyle(actionCooldown > 0)}
|
||||||
onClick={harvest}
|
onClick={harvest}
|
||||||
disabled={cooldowns.harvest}
|
disabled={actionCooldown > 0}
|
||||||
>
|
>
|
||||||
Harvest Crop
|
Harvest Crop
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,26 @@
|
||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef } from 'react'
|
||||||
import { useGameStore } from '../store/useGameStore';
|
import { useGameStore } from '../store/useGameStore'
|
||||||
import { TICK_INTERVAL } from '../constants';
|
import { TICK_INTERVAL } from '../constants'
|
||||||
|
|
||||||
export const useGameTick = () => {
|
export const useGameTick = () => {
|
||||||
const tick = useGameStore(state => state.tick);
|
const tick = useGameStore(state => state.tick)
|
||||||
const gameSpeed = useGameStore(state => state.gameSpeed);
|
const gameSpeed = useGameStore(state => state.gameSpeed)
|
||||||
const intervalRef = useRef<number | null>(null);
|
const intervalRef = useRef<number | null>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (intervalRef.current !== null) {
|
if (intervalRef.current !== null) {
|
||||||
clearInterval(intervalRef.current);
|
clearInterval(intervalRef.current)
|
||||||
}
|
}
|
||||||
|
|
||||||
const adjustedInterval = TICK_INTERVAL / gameSpeed;
|
const adjustedInterval = TICK_INTERVAL / gameSpeed;
|
||||||
intervalRef.current = window.setInterval(() => {
|
intervalRef.current = window.setInterval(() => {
|
||||||
tick();
|
tick()
|
||||||
}, adjustedInterval);
|
}, adjustedInterval)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (intervalRef.current !== null) {
|
if (intervalRef.current !== null) {
|
||||||
clearInterval(intervalRef.current);
|
clearInterval(intervalRef.current)
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}, [tick, gameSpeed]); // Add gameSpeed as dependency
|
}, [tick, gameSpeed])
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ import {
|
||||||
FIELD_UPGRADE_COSTS,
|
FIELD_UPGRADE_COSTS,
|
||||||
INITIAL_INVENTORY,
|
INITIAL_INVENTORY,
|
||||||
CROPS,
|
CROPS,
|
||||||
INITIAL_GAME_SPEED
|
INITIAL_GAME_SPEED,
|
||||||
|
COOLDOWN_DURATION
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { GameState, PlotState } from '../types';
|
import { GameState, PlotState } from '../types';
|
||||||
|
|
||||||
|
|
@ -26,6 +27,7 @@ export const useGameStore = create<GameState & {
|
||||||
assignCrop: (row: number, col: number, cropId: string) => void;
|
assignCrop: (row: number, col: number, cropId: string) => void;
|
||||||
upgradeField: () => void;
|
upgradeField: () => void;
|
||||||
setGameSpeed: (speed: number) => void;
|
setGameSpeed: (speed: number) => void;
|
||||||
|
setActionCooldown: (cooldown: number) => void;
|
||||||
}>((set, get) => ({
|
}>((set, get) => ({
|
||||||
cash: INITIAL_CASH,
|
cash: INITIAL_CASH,
|
||||||
inventory: INITIAL_INVENTORY,
|
inventory: INITIAL_INVENTORY,
|
||||||
|
|
@ -33,10 +35,8 @@ export const useGameStore = create<GameState & {
|
||||||
maxFieldSize: INITIAL_FIELD_SIZE + FIELD_UPGRADE_COSTS.length,
|
maxFieldSize: INITIAL_FIELD_SIZE + FIELD_UPGRADE_COSTS.length,
|
||||||
fieldUpgradeCosts: FIELD_UPGRADE_COSTS,
|
fieldUpgradeCosts: FIELD_UPGRADE_COSTS,
|
||||||
plots: initializeField(INITIAL_FIELD_SIZE),
|
plots: initializeField(INITIAL_FIELD_SIZE),
|
||||||
lastPlantTime: 0,
|
|
||||||
lastWaterTime: 0,
|
|
||||||
lastHarvestTime: 0,
|
|
||||||
gameSpeed: INITIAL_GAME_SPEED,
|
gameSpeed: INITIAL_GAME_SPEED,
|
||||||
|
actionCooldown: 0,
|
||||||
|
|
||||||
assignCrop: (row, col, cropId) => {
|
assignCrop: (row, col, cropId) => {
|
||||||
set(produce(state => {
|
set(produce(state => {
|
||||||
|
|
@ -45,10 +45,9 @@ export const useGameStore = create<GameState & {
|
||||||
},
|
},
|
||||||
|
|
||||||
plant: () => {
|
plant: () => {
|
||||||
const now = Date.now();
|
const { plots, inventory, actionCooldown } = get();
|
||||||
const { lastPlantTime, plots, inventory } = get();
|
|
||||||
|
|
||||||
if (now - lastPlantTime < 2000) {
|
if (actionCooldown > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,7 +67,7 @@ export const useGameStore = create<GameState & {
|
||||||
};
|
};
|
||||||
|
|
||||||
state.inventory[seedId] = state.inventory[seedId] - 1;
|
state.inventory[seedId] = state.inventory[seedId] - 1;
|
||||||
state.lastPlantTime = now;
|
state.actionCooldown = COOLDOWN_DURATION;
|
||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -78,10 +77,9 @@ export const useGameStore = create<GameState & {
|
||||||
},
|
},
|
||||||
|
|
||||||
water: () => {
|
water: () => {
|
||||||
const now = Date.now();
|
const { plots, actionCooldown } = get();
|
||||||
const { lastWaterTime, plots } = get();
|
|
||||||
|
|
||||||
if (now - lastWaterTime < 2000) {
|
if (actionCooldown > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,16 +100,15 @@ export const useGameStore = create<GameState & {
|
||||||
if (driestRow >= 0 && driestCol >= 0) {
|
if (driestRow >= 0 && driestCol >= 0) {
|
||||||
set(produce(state => {
|
set(produce(state => {
|
||||||
state.plots[driestRow][driestCol].moisture = 1;
|
state.plots[driestRow][driestCol].moisture = 1;
|
||||||
state.lastWaterTime = now;
|
state.actionCooldown = COOLDOWN_DURATION;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
harvest: () => {
|
harvest: () => {
|
||||||
const now = Date.now();
|
const { plots, actionCooldown } = get();
|
||||||
const { lastHarvestTime, plots } = get();
|
|
||||||
|
|
||||||
if (now - lastHarvestTime < 2000) {
|
if (actionCooldown > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +124,7 @@ export const useGameStore = create<GameState & {
|
||||||
set(produce(state => {
|
set(produce(state => {
|
||||||
state.plots[row][col].current = undefined;
|
state.plots[row][col].current = undefined;
|
||||||
state.inventory[yieldItem] = (state.inventory[yieldItem] || 0) + yieldAmount;
|
state.inventory[yieldItem] = (state.inventory[yieldItem] || 0) + yieldAmount;
|
||||||
state.lastHarvestTime = now;
|
state.actionCooldown = COOLDOWN_DURATION;
|
||||||
}));
|
}));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +133,15 @@ export const useGameStore = create<GameState & {
|
||||||
},
|
},
|
||||||
|
|
||||||
tick: () => {
|
tick: () => {
|
||||||
|
const { actionCooldown } = get();
|
||||||
|
|
||||||
set(produce(state => {
|
set(produce(state => {
|
||||||
|
// Update cooldown
|
||||||
|
if (state.actionCooldown > 0) {
|
||||||
|
state.actionCooldown = Math.max(0, state.actionCooldown - (COOLDOWN_DURATION / 20));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update plots
|
||||||
state.plots.forEach((row: PlotState[], rowIndex: number) => {
|
state.plots.forEach((row: PlotState[], rowIndex: number) => {
|
||||||
row.forEach((plot: PlotState, colIndex: number) => {
|
row.forEach((plot: PlotState, colIndex: number) => {
|
||||||
if (!plot.current || plot.current.mature) {
|
if (!plot.current || plot.current.mature) {
|
||||||
|
|
@ -184,5 +189,11 @@ export const useGameStore = create<GameState & {
|
||||||
set(produce(state => {
|
set(produce(state => {
|
||||||
state.gameSpeed = speed;
|
state.gameSpeed = speed;
|
||||||
}));
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
setActionCooldown: (cooldown) => {
|
||||||
|
set(produce(state => {
|
||||||
|
state.actionCooldown = cooldown;
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -33,8 +33,6 @@ export interface GameState {
|
||||||
maxFieldSize: number;
|
maxFieldSize: number;
|
||||||
fieldUpgradeCosts: number[];
|
fieldUpgradeCosts: number[];
|
||||||
plots: PlotState[][];
|
plots: PlotState[][];
|
||||||
lastPlantTime: number;
|
|
||||||
lastWaterTime: number;
|
|
||||||
lastHarvestTime: number;
|
|
||||||
gameSpeed: number;
|
gameSpeed: number;
|
||||||
|
actionCooldown: number;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import path from "path"
|
import path from "path"
|
||||||
import react from "@vitejs/plugin-react"
|
|
||||||
import { defineConfig } from "vite"
|
import { defineConfig } from "vite"
|
||||||
import linaria from "@linaria/vite"
|
import react from "@vitejs/plugin-react"
|
||||||
|
import wyw from '@wyw-in-js/vite'
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
react(),
|
react(),
|
||||||
linaria({
|
wyw({
|
||||||
include: ['**/*.{ts,tsx}'],
|
include: ['**/*.{ts,tsx}'],
|
||||||
babelOptions: {
|
babelOptions: {
|
||||||
presets: ['@babel/preset-typescript', '@babel/preset-react'],
|
presets: ['@babel/preset-typescript', '@babel/preset-react'],
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue