Rebuilding Trade menu
Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
46182e453a
commit
c6b29ff580
@ -4,8 +4,13 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"proxy": "http://localhost:8930",
|
"proxy": "http://localhost:8930",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@emotion/react": "^11.8.1",
|
||||||
|
"@emotion/styled": "^11.8.1",
|
||||||
"@material-ui/core": "^4.12.3",
|
"@material-ui/core": "^4.12.3",
|
||||||
"@material-ui/lab": "^4.0.0-alpha.60",
|
"@material-ui/lab": "^4.0.0-alpha.60",
|
||||||
|
"@mui/icons-material": "^5.4.4",
|
||||||
|
"@mui/material": "^5.4.4",
|
||||||
|
"@mui/utils": "^5.4.4",
|
||||||
"@testing-library/jest-dom": "^5.16.1",
|
"@testing-library/jest-dom": "^5.16.1",
|
||||||
"@testing-library/react": "^12.1.2",
|
"@testing-library/react": "^12.1.2",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
@ -63,8 +63,8 @@ const Activities = ({ table }) => {
|
|||||||
normalPlay = (game.state === 'initial-placement' || game.state === 'normal'),
|
normalPlay = (game.state === 'initial-placement' || game.state === 'normal'),
|
||||||
mustDiscard = game.player ? parseInt(game.player.mustDiscard ? game.player.mustDiscard : 0) : 0,
|
mustDiscard = game.player ? parseInt(game.player.mustDiscard ? game.player.mustDiscard : 0) : 0,
|
||||||
mustPlaceRobber = (game.turn && !game.turn.placedRobber && game.turn.robberInAction),
|
mustPlaceRobber = (game.turn && !game.turn.placedRobber && game.turn.robberInAction),
|
||||||
isInitialPlacement = (game.state === 'initial-placement'),
|
placement = (game.state === 'initial-placement' || game.turn.active === 'road-building'),
|
||||||
placeRoad = isInitialPlacement && game.turn && game.turn.actions && game.turn.actions.indexOf('place-road') !== -1,
|
placeRoad = placement && game.turn && game.turn.actions && game.turn.actions.indexOf('place-road') !== -1,
|
||||||
mustStealResource = game.turn && game.turn.actions && game.turn.actions.indexOf('steal-resource') !== -1;
|
mustStealResource = game.turn && game.turn.actions && game.turn.actions.indexOf('steal-resource') !== -1;
|
||||||
|
|
||||||
const list = game.activities
|
const list = game.activities
|
||||||
@ -86,7 +86,7 @@ const Activities = ({ table }) => {
|
|||||||
<div className="Requirement">{who} must move the Robber.</div>
|
<div className="Requirement">{who} must move the Robber.</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
{ isInitialPlacement &&
|
{ placement &&
|
||||||
<div className="Requirement">{who} must place a {placeRoad ? 'road' : 'settlement'}.</div>
|
<div className="Requirement">{who} must place a {placeRoad ? 'road' : 'settlement'}.</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Resource[disabled] {
|
||||||
|
filter: grayscale(75%);
|
||||||
|
}
|
||||||
|
|
||||||
.Resource:hover {
|
.Resource:hover {
|
||||||
filter: brightness(150%);
|
filter: brightness(150%);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import React from "react";
|
|||||||
import "./Resource.css";
|
import "./Resource.css";
|
||||||
import { assetsPath } from './Common.js';
|
import { assetsPath } from './Common.js';
|
||||||
|
|
||||||
const Resource = ({ type, select, disabled, count, label }) => {
|
const Resource = ({ type, select, disabled, available, count, label, onClick }) => {
|
||||||
const array = new Array(Number(count ? count : 0));
|
const array = new Array(Number(count ? count : 0));
|
||||||
const click = select ? select : (event) => {
|
const click = select ? select : (event) => {
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
@ -12,10 +12,12 @@ const Resource = ({ type, select, disabled, count, label }) => {
|
|||||||
|
|
||||||
if (label) {
|
if (label) {
|
||||||
return <div className="Resource"
|
return <div className="Resource"
|
||||||
|
disabled={disabled}
|
||||||
data-type={type}
|
data-type={type}
|
||||||
onClick={click}
|
onClick={onClick ? onClick : click}
|
||||||
style={{backgroundImage:`url(${assetsPath}/gfx/card-${type}.png)`}}>
|
style={{backgroundImage:`url(${assetsPath}/gfx/card-${type}.png)`}}>
|
||||||
<div>{count}</div>
|
{ available !== undefined && <div className="Left">{available}</div> }
|
||||||
|
<div className="Right">{count}</div>
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +28,8 @@ const Resource = ({ type, select, disabled, count, label }) => {
|
|||||||
{ React.Children.map(array, i => (
|
{ React.Children.map(array, i => (
|
||||||
<div className="Resource"
|
<div className="Resource"
|
||||||
data-type={type}
|
data-type={type}
|
||||||
onClick={click}
|
disabled={disabled}
|
||||||
|
onClick={onClick ? onClick : click}
|
||||||
style={{backgroundImage:`url(${assetsPath}/gfx/card-${type}.png)`}}>
|
style={{backgroundImage:`url(${assetsPath}/gfx/card-${type}.png)`}}>
|
||||||
</div>
|
</div>
|
||||||
)) }
|
)) }
|
||||||
|
@ -271,7 +271,10 @@ const Action = ({ table }) => {
|
|||||||
hasRolled = (game && game.turn && game.turn.roll) ? true : false,
|
hasRolled = (game && game.turn && game.turn.roll) ? true : false,
|
||||||
isTurn = (game && game.turn && game.turn.color === game.color) ? true : false,
|
isTurn = (game && game.turn && game.turn.color === game.color) ? true : false,
|
||||||
robberActions = (game && game.turn && game.turn.robberInAction),
|
robberActions = (game && game.turn && game.turn.robberInAction),
|
||||||
haveResources = player ? player.haveResources : false;
|
haveResources = player ? player.haveResources : false,
|
||||||
|
placement = (game.state === 'initial-placement' || game.turn.active === 'road-building'),
|
||||||
|
placeRoad = placement && game.turn && game.turn.actions && game.turn.actions.indexOf('place-road') !== -1,
|
||||||
|
mustStealResource = game.turn && game.turn.actions && game.turn.actions.indexOf('steal-resource') !== -1;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className="Action">
|
<Paper className="Action">
|
||||||
@ -281,12 +284,12 @@ const Action = ({ table }) => {
|
|||||||
<Button disabled={game.color ? true : false} onClick={() => {table.setState({ pickName: true})}}>Change name</Button> </> }
|
<Button disabled={game.color ? true : false} onClick={() => {table.setState({ pickName: true})}}>Change name</Button> </> }
|
||||||
{ !inLobby && <>
|
{ !inLobby && <>
|
||||||
<Button disabled={robberActions || !isTurn || hasRolled || !inGame} onClick={rollClick}>Roll Dice</Button>
|
<Button disabled={robberActions || !isTurn || hasRolled || !inGame} onClick={rollClick}>Roll Dice</Button>
|
||||||
<Button disabled={robberActions || !isTurn || !hasRolled || !haveResources} onClick={tradeClick}>Trade</Button>
|
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled || !haveResources} onClick={tradeClick}>Trade</Button>
|
||||||
<Button disabled={robberActions || !isTurn || !hasRolled || !haveResources} onClick={buildClicked}>Build</Button>
|
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled || !haveResources} onClick={buildClicked}>Build</Button>
|
||||||
{ game.turn.roll === 7 && player && player.mustDiscard > 0 &&
|
{ game.turn.roll === 7 && player && player.mustDiscard > 0 &&
|
||||||
<Button onClick={discardClick}>Discard</Button>
|
<Button onClick={discardClick}>Discard</Button>
|
||||||
}
|
}
|
||||||
<Button disabled={robberActions || !isTurn || !hasRolled} onClick={passClick}>Done</Button>
|
<Button disabled={placeRoad || robberActions || !isTurn || !hasRolled} onClick={passClick}>Done</Button>
|
||||||
</> }
|
</> }
|
||||||
{ /* inLobby &&
|
{ /* inLobby &&
|
||||||
<Button onClick={quitClick}>Quit</Button>
|
<Button onClick={quitClick}>Quit</Button>
|
||||||
@ -647,8 +650,10 @@ class Table extends React.Component {
|
|||||||
if (this.state.signature !== game.signature) {
|
if (this.state.signature !== game.signature) {
|
||||||
this.setState( { signature: game.signature });
|
this.setState( { signature: game.signature });
|
||||||
}
|
}
|
||||||
// console.log("Update Game", game);
|
console.log("Update Game", game);
|
||||||
this.setState( { game });
|
|
||||||
|
this.setState( { game } );
|
||||||
|
this.setState(this.state);
|
||||||
this.game = game;
|
this.game = game;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,6 +806,7 @@ class Table extends React.Component {
|
|||||||
let update;
|
let update;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case 'game-update':
|
case 'game-update':
|
||||||
|
console.log(`Game update received`);
|
||||||
update = data.update;
|
update = data.update;
|
||||||
const error = (update.status !== 'success') ? update.status : undefined;
|
const error = (update.status !== 'success') ? update.status : undefined;
|
||||||
this.updateGame(update);
|
this.updateGame(update);
|
||||||
|
@ -33,8 +33,68 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.Trade .Resource {
|
.Trade .Resource {
|
||||||
|
cursor: pointer;
|
||||||
width: 3.75em; /* 5x7 aspect ratio */
|
width: 3.75em; /* 5x7 aspect ratio */
|
||||||
height: 5.25em;
|
height: 3.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .Resource {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
width: 3.75em; /* 5x7 aspect ratio */
|
||||||
|
height: 3.75em;
|
||||||
|
min-width: 3.75em; /* 5x7 aspect ratio */
|
||||||
|
min-height: 3.75em;
|
||||||
|
margin: 0 0.125rem;
|
||||||
|
background-size: 130%;
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
margin: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .Direction {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
|
height: 2em;
|
||||||
|
width: 2em;
|
||||||
|
line-height: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .Resource:hover {
|
||||||
|
filter: brightness(125%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .Resource > div.Right {
|
||||||
|
user-select: none;
|
||||||
|
position: absolute;
|
||||||
|
top: -0.75rem;
|
||||||
|
right: -0.75rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid white;
|
||||||
|
background-color: rgb(36, 148, 46);
|
||||||
|
font-size: 1rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .Resource > div.Left {
|
||||||
|
user-select: none;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -0.75rem;
|
||||||
|
left: -0.75rem;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid white;
|
||||||
|
background-color: #444;
|
||||||
|
font-size: 1rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Trade .PlayerColor {
|
.Trade .PlayerColor {
|
||||||
@ -43,6 +103,13 @@
|
|||||||
margin: 0 0.25em 0 0;
|
margin: 0 0.25em 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Trade .Transfer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
.TradePlayer {
|
.TradePlayer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -55,7 +122,19 @@
|
|||||||
margin-right: 0.25em;
|
margin-right: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Trade .Transfers {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Trade .ResourceCounter {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.TradeLine {
|
.TradeLine {
|
||||||
|
user-select: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -70,7 +149,3 @@
|
|||||||
.TradeLine > div > div {
|
.TradeLine > div > div {
|
||||||
margin-left: 0.25em;
|
margin-left: 0.25em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.TradeLine *:last-child {
|
|
||||||
/* align-self: flex-end;*/
|
|
||||||
}
|
|
@ -1,121 +1,86 @@
|
|||||||
import React, { useState, useCallback } from "react";
|
import React, { useState, useCallback, useEffect } from "react";
|
||||||
import "./Trade.css";
|
import "./Trade.css";
|
||||||
import { getPlayerName } from './Common.js';
|
import { getPlayerName } from './Common.js';
|
||||||
import PlayerColor from './PlayerColor.js';
|
import PlayerColor from './PlayerColor.js';
|
||||||
import Paper from '@material-ui/core/Paper';
|
import Paper from '@material-ui/core/Paper';
|
||||||
import Button from '@material-ui/core/Button';
|
import Button from '@material-ui/core/Button';
|
||||||
import Resource from './Resource.js';
|
import Resource from './Resource.js';
|
||||||
|
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'
|
||||||
|
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'
|
||||||
|
|
||||||
const ResourceCounter = ({type, count, onCount, max}) => {
|
const empty = {
|
||||||
count = count ? count : 0;
|
wheat: 0,
|
||||||
const plusClicked = (event) => {
|
brick: 0,
|
||||||
if (max === undefined || max > count) {
|
wood: 0,
|
||||||
if (onCount) {
|
stone: 0,
|
||||||
onCount(type, count+1);
|
sheep: 0
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const minusClicked = (event) => {
|
|
||||||
if (count > 0) {
|
|
||||||
if (onCount) {
|
|
||||||
onCount(type, count-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="ResourceCounter" style={{
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column'
|
|
||||||
}}>
|
|
||||||
<Resource disabled type={type} count={1}/>
|
|
||||||
<div style={{
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-around',
|
|
||||||
width: '100%',
|
|
||||||
alignItems: 'center',
|
|
||||||
flexDirection: 'column'
|
|
||||||
}}>
|
|
||||||
<div style={{userSelect: 'none'}}>{count}</div>
|
|
||||||
<div>
|
|
||||||
<Button style={{
|
|
||||||
flexShrink: 1,
|
|
||||||
minWidth: 0
|
|
||||||
}}
|
|
||||||
disabled={count>=max}
|
|
||||||
onClick={plusClicked}>+</Button>
|
|
||||||
<Button style={{
|
|
||||||
flexShrink: 1,
|
|
||||||
minWidth: 0
|
|
||||||
}}
|
|
||||||
disabled={count===0}
|
|
||||||
onClick={minusClicked}>-</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const Trade = ({table}) => {
|
const Trade = ({table}) => {
|
||||||
const [giveLine, setGiveLine] = useState('nothing');
|
const [gives, setGives] = useState(Object.assign({}, empty));
|
||||||
const [getLine, setGetLine] = useState('nothing');
|
const [gets, setGets] = useState(Object.assign({}, empty));
|
||||||
|
const player = (table.game && table.game.player) ? table.game.player : undefined;
|
||||||
|
|
||||||
const [gives, setGives] = useState([]);
|
const transfer = useCallback((type, direction) => {
|
||||||
const [gets, setGets] = useState([]);
|
if (direction === 'give') { /* give clicked */
|
||||||
|
if (gets[type]) {
|
||||||
const giveCount = useCallback((type, count) => {
|
gets[type]--;
|
||||||
gives[type] = count;
|
gives[type] = 0;
|
||||||
if (!count) {
|
|
||||||
delete gives[type];
|
|
||||||
}
|
|
||||||
setGives(gives);
|
|
||||||
const items = [];
|
|
||||||
for (let key in gives) {
|
|
||||||
items.push(`${gives[key]} ${key}`);
|
|
||||||
}
|
|
||||||
if (items.length === 0) {
|
|
||||||
setGiveLine('nothing');
|
|
||||||
} else {
|
} else {
|
||||||
setGiveLine(items.join(', '));
|
if (gives[type] < player[type]) {
|
||||||
|
gives[type]++;
|
||||||
}
|
}
|
||||||
}, [setGiveLine, setGives, gives]);
|
gets[type] = 0;
|
||||||
|
|
||||||
const getCount = useCallback((type, count) => {
|
|
||||||
gets[type] = count;
|
|
||||||
if (!count) {
|
|
||||||
delete gets[type];
|
|
||||||
}
|
}
|
||||||
setGets(gets);
|
} else if (direction === 'get') { /* get clicked */
|
||||||
const items = [];
|
if (gives[type]) {
|
||||||
for (let key in gets) {
|
gives[type]--;
|
||||||
items.push(`${gets[key]} ${key}`);
|
gets[type] = 0;
|
||||||
}
|
|
||||||
if (items.length === 0) {
|
|
||||||
setGetLine('nothing');
|
|
||||||
} else {
|
} else {
|
||||||
setGetLine(items.join(', '));
|
if (gets[type] < 15) {
|
||||||
|
gets[type]++;
|
||||||
}
|
}
|
||||||
}, [setGetLine, setGets, gets]);
|
gives[type] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setGets({...gets});
|
||||||
|
setGives({...gives});
|
||||||
|
}, [setGets, setGives, gets, gives, player]);
|
||||||
|
|
||||||
|
const createTransfer = useCallback(resource => {
|
||||||
|
return <div key={resource} className="Transfer">
|
||||||
|
<Resource
|
||||||
|
onClick={() => transfer(resource, 'give')}
|
||||||
|
label={true}
|
||||||
|
type={resource}
|
||||||
|
count={gives[resource]}/>
|
||||||
|
<div className="Direction">{ gets[resource] === gives[resource] ? '' : (gets[resource] > gives[resource] ? <ArrowDownwardIcon/> : <ArrowUpwardIcon/>)}</div>
|
||||||
|
<Resource
|
||||||
|
onClick={() => transfer(resource, 'get')}
|
||||||
|
label={true}
|
||||||
|
available={player ? player[resource] - gives[resource] : undefined}
|
||||||
|
type={resource}
|
||||||
|
count={gets[resource]}/>
|
||||||
|
</div>;
|
||||||
|
}, [ gives, gets, transfer]);
|
||||||
|
|
||||||
const agreeClicked = useCallback((offer) => {
|
const agreeClicked = useCallback((offer) => {
|
||||||
const trade = {
|
const trade = {
|
||||||
gives: offer.gets.slice(),
|
gives: offer.gets.slice(),
|
||||||
gets: offer.gives.slice()
|
gets: offer.gives.slice()
|
||||||
};
|
};
|
||||||
trade.gives.forEach(give => giveCount(give.type, give.count));
|
let _gives = {}, _gets = {};
|
||||||
trade.gets.forEach(get => getCount(get.type, get.count));
|
trade.gives.forEach(give => _gives[give.type] = give.count);
|
||||||
|
trade.gets.forEach(get => _gets[get.type] = get.count);
|
||||||
table.offerTrade(trade);
|
table.offerTrade(trade);
|
||||||
let tmp = {};
|
setGives(_gives);
|
||||||
trade.gives.forEach(give => {
|
setGets(_gets);
|
||||||
tmp[give.type] = give.count;
|
}, [setGives, setGets, table]);
|
||||||
});
|
|
||||||
setGives(tmp);
|
let transfers = [];
|
||||||
tmp = {};
|
|
||||||
trade.gets.forEach(get => {
|
transfers = [ 'brick', 'wood', 'wheat', 'sheep', 'stone' ].map(resource => { return createTransfer(resource); });
|
||||||
tmp[get.type] = get.count;
|
|
||||||
});
|
|
||||||
setGets(tmp);
|
|
||||||
}, [giveCount, getCount, setGives, setGets, table]);
|
|
||||||
|
|
||||||
if (!table.game) {
|
if (!table.game) {
|
||||||
return (<></>);
|
return (<></>);
|
||||||
@ -131,11 +96,15 @@ const Trade = ({table}) => {
|
|||||||
gets: []
|
gets: []
|
||||||
};
|
};
|
||||||
for (let key in gives) {
|
for (let key in gives) {
|
||||||
|
if (gives[key] !== 0) {
|
||||||
trade.gives.push({type: key, count: gives[key]});
|
trade.gives.push({type: key, count: gives[key]});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
for (let key in gets) {
|
for (let key in gets) {
|
||||||
|
if (gets[key] !== 0) {
|
||||||
trade.gets.push({type: key, count: gets[key]});
|
trade.gets.push({type: key, count: gets[key]});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
table.offerTrade(trade);
|
table.offerTrade(trade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +163,6 @@ const Trade = ({table}) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const player = (table.game && table.game.player) ? table.game.player : undefined;
|
|
||||||
if (!player) {
|
if (!player) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
@ -266,10 +234,10 @@ const Trade = ({table}) => {
|
|||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gets = item.gets.map(get =>
|
const _gets = item.gets.map(get =>
|
||||||
`${get.count} ${(get.type === 'bank') ? 'of any one resource' : get.type}`)
|
`${get.count} ${(get.type === 'bank') ? 'of any one resource' : get.type}`)
|
||||||
.join(', '),
|
.join(', '),
|
||||||
gives = item.gives.map(give =>
|
_gives = item.gives.map(give =>
|
||||||
`${give.count} ${(give.type === '*') ? 'of any resource' : give.type}`)
|
`${give.count} ${(give.type === '*') ? 'of any resource' : give.type}`)
|
||||||
.join(', ');
|
.join(', ');
|
||||||
return (
|
return (
|
||||||
@ -277,11 +245,11 @@ const Trade = ({table}) => {
|
|||||||
<PlayerColor color={item.color}/>
|
<PlayerColor color={item.color}/>
|
||||||
<div>{item.name}</div>
|
<div>{item.name}</div>
|
||||||
<div className='TradeLine'>
|
<div className='TradeLine'>
|
||||||
{ gets !== '' && gives !== '' &&
|
{ _gets !== '' && _gives !== '' &&
|
||||||
<div>wants {gets} and will give {gives}.
|
<div>wants {_gets} and will give {_gives}.
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{ (gets === '' || gives === '') &&
|
{ (_gets === '' || _gives === '') &&
|
||||||
<div>has not submitted a trade offer.
|
<div>has not submitted a trade offer.
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
@ -309,35 +277,12 @@ const Trade = ({table}) => {
|
|||||||
{ players }
|
{ players }
|
||||||
</div>
|
</div>
|
||||||
{ !player.haveResources && <b>You have no resources to participate in this trade.</b> }
|
{ !player.haveResources && <b>You have no resources to participate in this trade.</b> }
|
||||||
<Button disabled={getLine === 'nothing' || giveLine === 'nothing'}
|
<Button
|
||||||
onClick={offerClicked}>Offer to give {giveLine} in exchange for {getLine}</Button>
|
onClick={offerClicked}>Offer to give giveLine in exchange for getLine</Button>
|
||||||
|
|
||||||
{ player.haveResources &&
|
{ player.haveResources &&
|
||||||
<div className='TradeLine'
|
<div className="Transfers">
|
||||||
style={{
|
{ transfers }
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'flex-start'
|
|
||||||
}}>
|
|
||||||
<div style={{display: 'flex' }}>
|
|
||||||
<b>You want to receive {getLine}:</b>
|
|
||||||
</div>
|
|
||||||
<div style={{display: 'flex' }}>
|
|
||||||
<ResourceCounter count={gets.brick} onCount={getCount} type='brick'/>
|
|
||||||
<ResourceCounter count={gets.wood} onCount={getCount} type='wood'/>
|
|
||||||
<ResourceCounter count={gets.wheat} onCount={getCount} type='wheat'/>
|
|
||||||
<ResourceCounter count={gets.sheep} onCount={getCount} type='sheep'/>
|
|
||||||
<ResourceCounter count={gets.stone} onCount={getCount} type='stone'/>
|
|
||||||
</div>
|
|
||||||
<div style={{display: 'flex' }}>
|
|
||||||
<b>You are willing to give {giveLine}:</b>
|
|
||||||
</div>
|
|
||||||
<div style={{display: 'flex' }}>
|
|
||||||
{ player.brick > 0 && <ResourceCounter count={gives.brick} onCount={giveCount} type='brick' max={player.brick}/> }
|
|
||||||
{ player.wood > 0 && <ResourceCounter count={gives.wood} onCount={giveCount} type='wood' max={player.wood}/> }
|
|
||||||
{ player.wheat > 0 && <ResourceCounter count={gives.wheat} onCount={giveCount} type='wheat' max={player.wheat}/> }
|
|
||||||
{ player.sheep > 0 && <ResourceCounter count={gives.sheep} onCount={giveCount} type='sheep' max={player.sheep}/> }
|
|
||||||
{ player.stone > 0 && <ResourceCounter count={gives.stone} onCount={giveCount} type='stone' max={player.stone}/> }
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{ isTurn && <Button onClick={cancelClicked}>cancel</Button> }
|
{ isTurn && <Button onClick={cancelClicked}>cancel</Button> }
|
||||||
|
@ -29,10 +29,13 @@
|
|||||||
|
|
||||||
.ViewCard .Description {
|
.ViewCard .Description {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
max-width: 20vw;
|
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ViewCard .Description p:first-of-type {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.ViewCard .Resource {
|
.ViewCard .Resource {
|
||||||
width: 10em; /* 5x7 aspect ratio */
|
width: 10em; /* 5x7 aspect ratio */
|
||||||
height: 14em;
|
height: 14em;
|
||||||
|
@ -27,57 +27,53 @@ const ViewCard = ({table, card}) => {
|
|||||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const descriptions = {
|
let description, lookup;
|
||||||
army: <>When played, you <b>must</b> move the robber.
|
if (card.type == 'progress') {
|
||||||
|
lookup = `${card.type}-${card.card}`;
|
||||||
|
} else {
|
||||||
|
lookup = card.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (lookup) {
|
||||||
|
case 'army':
|
||||||
|
description = <>When played, you <b>must</b> move the robber.
|
||||||
<p>Steal <b>1</b> resource card from the owner of an adjacent settlement or city.</p>
|
<p>Steal <b>1</b> resource card from the owner of an adjacent settlement or city.</p>
|
||||||
<p>You may only play one development card during your turn -- either one
|
<p>You may only play one development card during your turn -- either one
|
||||||
knight or one progress card.</p></>,
|
knight or one progress card.</p></>;
|
||||||
vp: <><b>1</b> victory point.
|
break;
|
||||||
|
case 'vp':
|
||||||
|
description = <><b>1</b> victory point.
|
||||||
<p>You only reveal your victory point cards when the game is over, either
|
<p>You only reveal your victory point cards when the game is over, either
|
||||||
when you or an opponent
|
when you or an opponent
|
||||||
reaches <b>10+</b> victory points on their turn and declares
|
reaches <b>10+</b> victory points on their turn and declares
|
||||||
victory!</p></>,
|
victory!</p></>;
|
||||||
'progress-road-1': <>
|
break;
|
||||||
|
case 'progress-road-1':
|
||||||
|
case 'progress-road-2':
|
||||||
|
description = <>
|
||||||
<p>Play <b>2</b> new roads as if you had just built them.</p>
|
<p>Play <b>2</b> new roads as if you had just built them.</p>
|
||||||
<p>This is still limited by the number of roads you have (a maximum of 15.)</p>
|
<p>This is still limited by the number of roads you have. If you do not have enough roads
|
||||||
<p><b>NOTE:</b> This card is not yet implemented. The server will give you <b>2</b> wood
|
remaining, or if there are no valid road building locations, the number of roads
|
||||||
and <b>2</b> brick and we trust you will use them to build <b>2</b> roads.</p>
|
you can place will be reduced.</p>
|
||||||
<p>If
|
<p>You currently have <b>{table.game.player.roads}</b> roads remaining.</p>
|
||||||
you do not have enough roads remaining, you may end up with extra resources...
|
</>;
|
||||||
but the game is in beta, so... be happy :)
|
break;
|
||||||
</p>
|
case 'progress-monopoly':
|
||||||
<p>As an FYI, you currently have {15 - table.game.player.roads} roads remaining.</p>
|
description = <>
|
||||||
</>,
|
|
||||||
'progress-road-2': <>
|
|
||||||
<p>Play <b>2</b> new roads as if you had just built them.</p>
|
|
||||||
<p>This is still limited by the number of roads you have (a maximum of 15.)</p>
|
|
||||||
<p><b>NOTE:</b> This card is not yet implemented. The server will give you <b>2</b> wood
|
|
||||||
and <b>2</b> brick and we trust you will use them to build <b>2</b> roads.</p>
|
|
||||||
<p>If
|
|
||||||
you do not have enough roads remaining, you may end up with extra resources...
|
|
||||||
but the game is in beta, so... be happy :)
|
|
||||||
</p>
|
|
||||||
<p>As an FYI, you currently have {15 - table.game.player.roads} roads remaining.</p>
|
|
||||||
</>,
|
|
||||||
'progress-monopoly': <>
|
|
||||||
When you play this card, you will select <b>1</b> type of resource.
|
When you play this card, you will select <b>1</b> type of resource.
|
||||||
All other players must give you all their resource cards of that type.
|
All other players must give you all their resource cards of that type.
|
||||||
</>,
|
</>;
|
||||||
'progress-year-of-plenty': <>
|
break;
|
||||||
|
case 'progress-year-of-plenty':
|
||||||
|
description = <>
|
||||||
Take any <b>2</b> resources from the bank. Add them to your hand. They can be
|
Take any <b>2</b> resources from the bank. Add them to your hand. They can be
|
||||||
<b>2</b> of the same resource or <b>2</b> different resources.
|
<b>2</b> of the same resource or <b>2</b> different resources.
|
||||||
<p><b>Unfortunately</b> the current implementation only lets you pick a single
|
<p><b>Unfortunately</b> the current implementation only lets you pick a single
|
||||||
resource and you will then get <b>2</b> of those.</p>
|
resource and you will then get <b>2</b> of those.</p>
|
||||||
</>
|
</>;
|
||||||
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
let description;
|
|
||||||
if (card.type == 'progress') {
|
|
||||||
description = descriptions[`${card.type}-${card.card}`];
|
|
||||||
} else {
|
|
||||||
description = descriptions[card.type];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (description === undefined) {
|
if (description === undefined) {
|
||||||
console.log(`No description for ${card.type}-${card.card}`);
|
console.log(`No description for ${card.type}-${card.card}`);
|
||||||
}
|
}
|
||||||
|
@ -1598,7 +1598,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
}
|
}
|
||||||
game.turn.offer = offer;
|
game.turn.offer = offer;
|
||||||
}
|
}
|
||||||
// addActivity(game, session, `${session.name} submitted an offer to give ${offerToString(offer)}.`);
|
addActivity(game, session, `${session.name} submitted an offer to give ${offerToString(offer)}.`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1674,8 +1674,8 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
player[item.type] -= item.count;
|
player[item.type] -= item.count;
|
||||||
});
|
});
|
||||||
|
|
||||||
addChatMessage(game, session, `${session.name} has accepted a trade ` +
|
addChatMessage(game, session, `${session.name} traded ` +
|
||||||
`offer to give ${offerToString(session.player)} ` +
|
` ${offerToString(session.player)} ` +
|
||||||
`from ${(offer.name === 'The bank') ? 'the bank' : offer.name}.`);
|
`from ${(offer.name === 'The bank') ? 'the bank' : offer.name}.`);
|
||||||
|
|
||||||
delete game.turn.offer;
|
delete game.turn.offer;
|
||||||
@ -1923,10 +1923,21 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
switch (card.card) {
|
switch (card.card) {
|
||||||
case 'road-1':
|
case 'road-1':
|
||||||
case 'road-2':
|
case 'road-2':
|
||||||
addActivity(game, session, `${session.name} played a Road Building card. The server is giving them 2 brick and 2 wood to build those roads!`);
|
const allowed = Math.min(player.roads, 2);
|
||||||
addChatMessage(game, session, `${server.name} received 2 wood, 2 brick from the bank.`);
|
if (!allowed) {
|
||||||
player.brick += 2;
|
addActivity(game, session, `${session.name} played a Road Building card, but has no roads to build.`);
|
||||||
player.wood += 2;
|
break;
|
||||||
|
}
|
||||||
|
let roads = getValidRoads(game, session.color);
|
||||||
|
if (roads.length === 0) {
|
||||||
|
addActivity(game, session, `${session.name} played a Road Building card, but they do not have any valid locations to place them.`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
game.turn.active = 'road-building';
|
||||||
|
game.turn.free = true;
|
||||||
|
game.turn.freeRoads = allowed;
|
||||||
|
addActivity(game, session, `${session.name} played a Road Building card. They now place ${allowed} roads for free.`);
|
||||||
|
placeRoad(game, roads);
|
||||||
break;
|
break;
|
||||||
case 'monopoly':
|
case 'monopoly':
|
||||||
game.turn.actions = [ 'select-resource' ];
|
game.turn.actions = [ 'select-resource' ];
|
||||||
@ -2369,18 +2380,39 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
|
|
||||||
player.roads--;
|
player.roads--;
|
||||||
if (!game.turn.free) {
|
if (!game.turn.free) {
|
||||||
addChatMessage(game, session, `${session.name} spent 1 brick, 1 wood to purchase a road.`)
|
addChatMessage(game, session, `${name} spent 1 brick, 1 wood to purchase a road.`)
|
||||||
player.brick--;
|
player.brick--;
|
||||||
player.wood--;
|
player.wood--;
|
||||||
}
|
}
|
||||||
delete game.turn.free;
|
|
||||||
debugChat(game, 'After road purchase');
|
debugChat(game, 'After road purchase');
|
||||||
|
|
||||||
road.color = session.color;
|
road.color = session.color;
|
||||||
game.turn.actions = [];
|
|
||||||
game.turn.limits = {};
|
|
||||||
addActivity(game, session, `${name} placed a road.`);
|
addActivity(game, session, `${name} placed a road.`);
|
||||||
calculateRoadLengths(game, session);
|
calculateRoadLengths(game, session);
|
||||||
|
|
||||||
|
if (game.turn.active === 'road-building') {
|
||||||
|
game.turn.freeRoads--;
|
||||||
|
if (game.turn.freeRoads === 0) {
|
||||||
|
delete game.turn.free;
|
||||||
|
delete game.turn.active;
|
||||||
|
delete game.turn.freeRaods;
|
||||||
|
}
|
||||||
|
|
||||||
|
let roads = getValidRoads(game, session.color);
|
||||||
|
if (roads.length === 0) {
|
||||||
|
delete game.turn.active;
|
||||||
|
delete game.turn.freeRaods;
|
||||||
|
addActivity(game, session, `${name} has another road to play, but there are no more valid locations.`);
|
||||||
|
} else if (game.turn.freeRoads !== 0) {
|
||||||
|
game.turn.free = true;
|
||||||
|
placeRoad(game, roads);
|
||||||
|
break; /* do not reset actions or limits -- player has another road to place! */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete game.turn.free;
|
||||||
|
game.turn.actions = [];
|
||||||
|
game.turn.limits = {};
|
||||||
} else if (game.state === 'initial-placement') {
|
} else if (game.state === 'initial-placement') {
|
||||||
road.color = session.color;
|
road.color = session.color;
|
||||||
addActivity(game, session, `${name} placed a road.`);
|
addActivity(game, session, `${name} placed a road.`);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user