Added Velocirobber
Fixed several robber and admin related commands Signed-off-by: James Ketrenos <james_eikona@ketrenos.com>
This commit is contained in:
parent
1e51512ee8
commit
54e1a51c04
@ -43,14 +43,30 @@
|
|||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Pip.Option {
|
||||||
|
filter: brightness(150%);
|
||||||
|
}
|
||||||
|
|
||||||
.Pip.Active {
|
.Pip.Active {
|
||||||
filter: drop-shadow(0px 0px 10px rgba(255, 0, 255, 1));
|
filter: drop-shadow(0px 0px 10px rgba(255, 0, 255, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.Pip.Option:hover,
|
||||||
|
.Pip:hover {
|
||||||
|
filter: brightness(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.Pip.Active:hover {
|
||||||
|
filter: drop-shadow(0px 0px 10px rgba(255, 0, 255, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.Pip.Active.Option {
|
.Pip.Active.Option {
|
||||||
filter: brightness(150%) drop-shadow(0px 0px 10px rgba(255, 0, 255, 1));
|
filter: brightness(150%) drop-shadow(0px 0px 10px rgba(255, 0, 255, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.Pips[disabled],
|
.Pips[disabled],
|
||||||
.Tiles[disabled],
|
.Tiles[disabled],
|
||||||
.Roads[disabled],
|
.Roads[disabled],
|
||||||
@ -121,6 +137,7 @@
|
|||||||
top: 0px;
|
top: 0px;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
clip-path: circle(50%);
|
clip-path: circle(50%);
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Tile-Shape {
|
.Tile-Shape {
|
||||||
@ -139,37 +156,38 @@
|
|||||||
filter: brightness(115%);
|
filter: brightness(115%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.Option .Pip-Shape,
|
|
||||||
.Option .Tile-Shape,
|
.Option .Tile-Shape,
|
||||||
.Option .Corner-Shape,
|
.Option .Corner-Shape,
|
||||||
.Option .Road-Shape {
|
.Option .Road-Shape {
|
||||||
background-color: rgba(255, 255, 255, 0.5);
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.Robber .Pip-Shape,
|
.Robber .Pip-Shape {
|
||||||
.Pip-Shape:hover {
|
top: -2em;
|
||||||
clip-path: circle(45%); /* show through the border */
|
left: -2em;
|
||||||
|
clip-path: circle(50%);
|
||||||
|
transform: scale(0.45);
|
||||||
background-color:#e7c099;
|
background-color:#e7c099;
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
border: 0.2em solid #8c471f;
|
||||||
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Roberta .Pip-Shape:hover,
|
||||||
.Roberta .Pip-Shape {
|
.Roberta .Pip-Shape {
|
||||||
top: -2em;
|
|
||||||
left: -2em;
|
|
||||||
clip-path: circle(50%);
|
|
||||||
transform: scale(0.45);
|
|
||||||
background-image:url("./assets/woman-robber.png");
|
background-image:url("./assets/woman-robber.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Robert .Pip-Shape:hover,
|
||||||
.Robert .Pip-Shape {
|
.Robert .Pip-Shape {
|
||||||
top: -2em;
|
|
||||||
left: -2em;
|
|
||||||
clip-path: circle(50%);
|
|
||||||
transform: scale(0.45);
|
|
||||||
background-image:url("./assets/man-robber.png");
|
background-image:url("./assets/man-robber.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Velocirobber .Pip-Shape {
|
||||||
|
background-image:url("./assets/raptor-robber.png");
|
||||||
|
}
|
||||||
|
|
||||||
.Tile-Shape:hover,
|
.Tile-Shape:hover,
|
||||||
.Corner-Shape:hover,
|
.Corner-Shape:hover,
|
||||||
.Road-Shape:hover {
|
.Road-Shape:hover {
|
||||||
|
@ -481,18 +481,19 @@ const Board = ({ table, game }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (game) {
|
if (game) {
|
||||||
let robberClass = game.gender === 'female' ? 'Roberta' : 'Robert';
|
|
||||||
let nodes = document.querySelectorAll(`.Pip.Robber`);
|
let nodes = document.querySelectorAll(`.Pip.Robber`);
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
nodes[i].classList.remove('Robber');
|
nodes[i].classList.remove('Robber');
|
||||||
nodes[i].classList.remove(robberClass);
|
[ 'Robert', 'Roberta', 'Velocirobber' ].forEach(robberName =>
|
||||||
|
nodes[i].classList.remove(robberName)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game.robber) {
|
if (game.robber !== undefined) {
|
||||||
const el = document.querySelector(`.Pip[data-index="${game.robber}"]`);
|
const el = document.querySelector(`.Pip[data-index="${game.robber}"]`);
|
||||||
if (el) {
|
if (el) {
|
||||||
el.classList.add('Robber');
|
el.classList.add('Robber');
|
||||||
el.classList.add(robberClass);
|
el.classList.add(game.robberName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
client/src/assets/raptor-robber.png
Executable file
BIN
client/src/assets/raptor-robber.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
@ -304,7 +304,7 @@ const distributeResources = (game, roll) => {
|
|||||||
let index = game.pipOrder[i];
|
let index = game.pipOrder[i];
|
||||||
if (assetData.pips[index].roll === roll) {
|
if (assetData.pips[index].roll === roll) {
|
||||||
if (game.robber === i) {
|
if (game.robber === i) {
|
||||||
addChatMessage(game, null, `That pesky Robber stole resources!`);
|
addChatMessage(game, null, `That pesky ${game.robberName} Roberson stole resources!`);
|
||||||
} else {
|
} else {
|
||||||
tiles.push(i);
|
tiles.push(i);
|
||||||
}
|
}
|
||||||
@ -350,6 +350,21 @@ const distributeResources = (game, roll) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const pickRobber = (game) => {
|
||||||
|
const selection = Math.floor(Math.random() * 3);
|
||||||
|
switch (selection) {
|
||||||
|
case 0:
|
||||||
|
game.robberName = 'Robert';
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
game.robberName = 'Roberta';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
game.robberName = 'Velocirobber';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const processRoll = (game, dice) => {
|
const processRoll = (game, dice) => {
|
||||||
let session;
|
let session;
|
||||||
for (let id in game.sessions) {
|
for (let id in game.sessions) {
|
||||||
@ -365,38 +380,40 @@ const processRoll = (game, dice) => {
|
|||||||
addChatMessage(game, session, `${session.name} rolled ${game.dice[0]}, ${game.dice[1]}.`);
|
addChatMessage(game, session, `${session.name} rolled ${game.dice[0]}, ${game.dice[1]}.`);
|
||||||
game.turn.roll = game.dice[0] + game.dice[1];
|
game.turn.roll = game.dice[0] + game.dice[1];
|
||||||
if (game.turn.roll === 7) {
|
if (game.turn.roll === 7) {
|
||||||
addChatMessage(game, null, `ROBBER! ${game.gender === 'female' ? 'Roberta' : 'Robert'} Robber Roberson!`);
|
|
||||||
game.turn.robberInAction = true;
|
game.turn.robberInAction = true;
|
||||||
delete game.turn.placedRobber;
|
delete game.turn.placedRobber;
|
||||||
|
const mustDiscard = [];
|
||||||
|
|
||||||
for (let id in game.sessions) {
|
for (let id in game.sessions) {
|
||||||
const player = game.sessions[id].player;
|
const player = game.sessions[id].player;
|
||||||
if (player) {
|
if (player) {
|
||||||
let discard = player.stone + player.wheat + player.brick + player.wood + player.sheep;
|
let discard = player.stone + player.wheat + player.brick + player.wood + player.sheep;
|
||||||
if (discard > 7) {
|
if (discard > 7) {
|
||||||
discard = Math.floor(discard / 2);
|
discard = Math.floor(discard / 2);
|
||||||
|
|
||||||
player.mustDiscard = discard;
|
player.mustDiscard = discard;
|
||||||
addChatMessage(game, null, `${game.sessions[id].name} must discard ${discard} resource cards.`);
|
mustDiscard.push(player);
|
||||||
} else {
|
} else {
|
||||||
delete player.mustDiscard;
|
delete player.mustDiscard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
if you roll a 7, no one receives any resource cards.
|
if (mustDiscard.length === 0) {
|
||||||
instead, every player who has more than 7 resource cards must select
|
addChatMessage(game, null, `ROBBER! ${game.robberName} Robber Roberson has fled, and no one had to discard!`);
|
||||||
half (rounded down) of their
|
addChatMessage(game, null, `But drat! A new robber has arrived and must be placed by ${game.turn.name}.`);
|
||||||
resource cards and return them to the bank.
|
game.turn.actions = [ 'place-robber' ];
|
||||||
then you muyst move the robber:
|
game.turn.limits = { pips: [] };
|
||||||
1. you must move the robber immediately to the number token of any other
|
for (let i = 0; i < 19; i++) {
|
||||||
terrain ohex or to the desert hex,
|
if (i === game.robber) {
|
||||||
2. you then steal 1 (random) resourcde card from an opponent who has a settlement or city
|
continue;
|
||||||
adjacent to the target terrain hex. the player who is robbed holds their resource cards
|
}
|
||||||
face down. you then take 1 card at random. if the target hex is adjacent to 2 or
|
game.turn.limits.pips.push(i);
|
||||||
more player's settlements or cities, you choose which one you want to steal from.
|
}
|
||||||
If the production number for the hex containing the robber is rolled, the owners of
|
} else {
|
||||||
adjacent settlements and citieis do not receive resourcres. The robber prevents it.
|
mustDiscard.forEach(player =>
|
||||||
*/
|
addChatMessage(game, null, `${getPlayerName(game, player)} must discard ${player.mustDiscard} resource cards the robber steals while fleeing!`)
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
distributeResources(game, game.turn.roll);
|
distributeResources(game, game.turn.roll);
|
||||||
}
|
}
|
||||||
@ -582,20 +599,22 @@ const adminActions = (game, action, value) => {
|
|||||||
if (!session) {
|
if (!session) {
|
||||||
return `Unable to determine current player turn to give resources.`;
|
return `Unable to determine current player turn to give resources.`;
|
||||||
}
|
}
|
||||||
if (type in session.player) {
|
|
||||||
|
if ([ 'wheat', 'sheep', 'wood', 'stone', 'brick' ].indexOf(type) !== -1) {
|
||||||
const count = parseInt(card);
|
const count = parseInt(card);
|
||||||
session.player[card] += count;
|
session.player[type] += count;
|
||||||
addChatMessage(game, null, `Admin gave ${count} ${type} to ${game.turn.name}.`);
|
addChatMessage(game, null, `Admin gave ${count} ${type} to ${game.turn.name}.`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = game.developmentCards.findIndex(item =>
|
const index = game.developmentCards.findIndex(item =>
|
||||||
item.card === card && item.type === type);
|
item.card.toString() === card && item.type === type);
|
||||||
|
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
console.log({ card, type}, game.developmentCards);
|
console.log({ card, type}, game.developmentCards);
|
||||||
return `Unable to find ${type}-${card} in the current deck of development cards.`;
|
return `Unable to find ${type}-${card} in the current deck of development cards.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmp = game.developmentCards.splice(index, 1)[0];
|
let tmp = game.developmentCards.splice(index, 1)[0];
|
||||||
tmp.turn = game.turns ? game.turns - 1 : 0;
|
tmp.turn = game.turns ? game.turns - 1 : 0;
|
||||||
session.player.development.push(tmp);
|
session.player.development.push(tmp);
|
||||||
@ -1203,7 +1222,7 @@ const getValidRoads = (game, color) => {
|
|||||||
return limits;
|
return limits;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isCompatibleOffer = (player, offer) => {
|
const isCompatibleOffer = (game, player, offer) => {
|
||||||
const isBank = offer.name === 'The bank';
|
const isBank = offer.name === 'The bank';
|
||||||
let valid = player.gets.length === offer.gives.length &&
|
let valid = player.gets.length === offer.gives.length &&
|
||||||
player.gives.length === offer.gets.length;
|
player.gives.length === offer.gets.length;
|
||||||
@ -1214,7 +1233,7 @@ const isCompatibleOffer = (player, offer) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log({
|
console.log({
|
||||||
player: getPlayerName(player),
|
player: getPlayerName(game, player),
|
||||||
gets: player.gets,
|
gets: player.gets,
|
||||||
gives: player.gives
|
gives: player.gives
|
||||||
}, {
|
}, {
|
||||||
@ -1274,11 +1293,11 @@ const isSameOffer = (player, offer) => {
|
|||||||
return same;
|
return same;
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkOffer = (player, offer) => {
|
const checkOffer = (game, player, offer) => {
|
||||||
let error = undefined;
|
let error = undefined;
|
||||||
|
|
||||||
console.log({
|
console.log({
|
||||||
player: getPlayerName(player),
|
player: getPlayerName(game, player),
|
||||||
gets: player.gets,
|
gets: player.gets,
|
||||||
gives: player.gives
|
gives: player.gives
|
||||||
}, {
|
}, {
|
||||||
@ -1476,7 +1495,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
if (value === 'offer') {
|
if (value === 'offer') {
|
||||||
const offer = req.body;
|
const offer = req.body;
|
||||||
|
|
||||||
error = checkOffer(session.player, offer);
|
error = checkOffer(game, session.player, offer);
|
||||||
if (error) {
|
if (error) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1519,7 +1538,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
const offer = req.body;
|
const offer = req.body;
|
||||||
let target;
|
let target;
|
||||||
|
|
||||||
error = checkOffer(session.player, offer);
|
error = checkOffer(game, session.player, offer);
|
||||||
if (error) {
|
if (error) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1553,7 +1572,7 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
|
|
||||||
/* Verify the requesting offer wasn't jacked --\
|
/* Verify the requesting offer wasn't jacked --\
|
||||||
* make sure the target.gives === player.gets and target.gives === player.gets */
|
* make sure the target.gives === player.gets and target.gives === player.gets */
|
||||||
if (!isCompatibleOffer(player, target)) {
|
if (!isCompatibleOffer(game, player, target)) {
|
||||||
error = `The requested offer does not match the negotiated terms!`;
|
error = `The requested offer does not match the negotiated terms!`;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1662,7 +1681,9 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
}
|
}
|
||||||
game.robber = robber;
|
game.robber = robber;
|
||||||
game.turn.placedRobber = true;
|
game.turn.placedRobber = true;
|
||||||
addChatMessage(game, session, `Robber has been moved!`);
|
|
||||||
|
pickRobber(game);
|
||||||
|
addChatMessage(game, session, `${game.robberName} Robber Robinson entered the scene as the nefarious robber!`);
|
||||||
|
|
||||||
let colors = [];
|
let colors = [];
|
||||||
layout.tiles[robber].corners.forEach(cornerIndex => {
|
layout.tiles[robber].corners.forEach(cornerIndex => {
|
||||||
@ -1680,7 +1701,8 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
game.turn.actions = [];
|
game.turn.actions = [];
|
||||||
game.turn.robberInAction = false;
|
game.turn.robberInAction = false;
|
||||||
delete game.turn.limits;
|
delete game.turn.limits;
|
||||||
addChatMessage(game, session, `The Robber was moved to a terrain with no other players.`);
|
addChatMessage(game, session, `The dread robber ${game.robberName} was placed on a terrain with no other players, ` +
|
||||||
|
`so ${game.turn.name} does not steal resources from anyone.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -1855,7 +1877,16 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
|
|
||||||
game.turn.robberInAction = true;
|
game.turn.robberInAction = true;
|
||||||
delete game.turn.placedRobber;
|
delete game.turn.placedRobber;
|
||||||
addChatMessage(game, session, `${session.name} must now move the robber.`);
|
addChatMessage(game, session, `The robber ${game.robberName} has fled before the power of the Knight, ` +
|
||||||
|
`but a new robber has returned and ${session.name} must now place them.`);
|
||||||
|
game.turn.actions = [ 'place-robber' ];
|
||||||
|
game.turn.limits = { pips: [] };
|
||||||
|
for (let i = 0; i < 19; i++) {
|
||||||
|
if (i === game.robber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
game.turn.limits.pips.push(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -2323,7 +2354,29 @@ router.put("/:id/:action/:value?", async (req, res) => {
|
|||||||
addChatMessage(game, null, `${session.name} discarded ${sum} resource cards.`);
|
addChatMessage(game, null, `${session.name} discarded ${sum} resource cards.`);
|
||||||
if (player.mustDiscard) {
|
if (player.mustDiscard) {
|
||||||
addChatMessage(game, null, `${session.name} must discard ${player.mustDiscard} more cards.`);
|
addChatMessage(game, null, `${session.name} must discard ${player.mustDiscard} more cards.`);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let move = true;
|
||||||
|
for (let color in game.players) {
|
||||||
|
const discard = game.players[color].mustDiscard;
|
||||||
|
if (discard) {
|
||||||
|
move = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (move) {
|
||||||
|
addChatMessage(game, null, `Drat! A new robber has arrived and must be placed by ${game.turn.name}!`);
|
||||||
|
game.turn.actions = [ 'place-robber' ];
|
||||||
|
game.turn.limits = { pips: [] };
|
||||||
|
for (let i = 0; i < 19; i++) {
|
||||||
|
if (i === game.robber) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
game.turn.limits.pips.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "state":
|
case "state":
|
||||||
@ -2423,28 +2476,6 @@ const sendGame = async (req, res, game, error) => {
|
|||||||
}
|
}
|
||||||
game.active = active;
|
game.active = active;
|
||||||
|
|
||||||
/* If the current turn is a robber placement, and everyone has
|
|
||||||
* discarded, set the limits for where the robber can be placed */
|
|
||||||
if (game.turn && game.turn.robberInAction) {
|
|
||||||
let move = true;
|
|
||||||
for (let color in game.players) {
|
|
||||||
const discard = game.players[color].mustDiscard;
|
|
||||||
if (discard) {
|
|
||||||
move = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (move && !game.turn.placedRobber) {
|
|
||||||
game.turn.actions = [ 'place-robber' ];
|
|
||||||
game.turn.limits = { pips: [] };
|
|
||||||
for (let i = 0; i < 19; i++) {
|
|
||||||
if (i === game.robber) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
game.turn.limits.pips.push(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the session lastActive clock */
|
/* Update the session lastActive clock */
|
||||||
let session;
|
let session;
|
||||||
if (req.session) {
|
if (req.session) {
|
||||||
@ -2708,7 +2739,7 @@ router.post("/:id?", (req, res/*, next*/) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const setBeginnerGame = (game) => {
|
const setBeginnerGame = (game) => {
|
||||||
game.gender = Math.random() > 0.5 ? 'male' : 'female';
|
pickRobber(game);
|
||||||
shuffle(game.developmentCards);
|
shuffle(game.developmentCards);
|
||||||
game.borderOrder = [];
|
game.borderOrder = [];
|
||||||
for (let i = 0; i < 6; i++) {
|
for (let i = 0; i < 6; i++) {
|
||||||
@ -2721,6 +2752,8 @@ const setBeginnerGame = (game) => {
|
|||||||
4, 11, 7, 14,
|
4, 11, 7, 14,
|
||||||
18, 8, 15
|
18, 8, 15
|
||||||
];
|
];
|
||||||
|
game.robber = 9;
|
||||||
|
|
||||||
game.pipOrder = [
|
game.pipOrder = [
|
||||||
5, 1, 6,
|
5, 1, 6,
|
||||||
7, 2, 9, 11,
|
7, 2, 9, 11,
|
||||||
@ -2732,7 +2765,7 @@ const setBeginnerGame = (game) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const shuffleBoard = (game, beginnersGame) => {
|
const shuffleBoard = (game, beginnersGame) => {
|
||||||
game.gender = Math.random() > 0.5 ? 'male' : 'female';
|
pickRobber(game);
|
||||||
|
|
||||||
const seq = [];
|
const seq = [];
|
||||||
for (let i = 0; i < 6; i++) {
|
for (let i = 0; i < 6; i++) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user