Add play Shield and Mana

feature/clientSideSimplify
Nathan Steel 1 year ago
parent 55b85dae1a
commit 77bef59558

@ -578,6 +578,10 @@ function requestDeck(itemData = null){
//itemData.component.deck[deckItem].handSize = 0;
itemData.component.cardCount.hand[forPlayer] = 0;
itemData.component.cardCount.board[forPlayer] = 0;
itemData.component.cardCount.shield[forPlayer] = 0;
itemData.component.cardCount.mana[forPlayer] = 0;
itemData.component.cardCount.grave[forPlayer] = 0;
itemData.component.cardCount.void[forPlayer] = 0;
itemCount++; // Increment item to not overwrite
}

@ -16,6 +16,10 @@ const component = {
deck : {},
hand : {},
board : {},
shield : {},
mana : {}, // For some of these, the length of object/array would be better...
grave : {},
void : {},
},
// Card Stuff

@ -10,6 +10,40 @@ const gameHelper = require('./gameHelper');
// actual Id would be better, but the player should be passed correctly
// from the client. They can edit data, but server-side validation SHOULD prevent
// in the future
function gameStart(roomId){
// Each player shuffles
for(const player of roomData[roomId].playerData){
// TODO: Make sure this only does for players, not spectators (in fut.)
shuffleDeck(roomId, player.playerDataId);
}
// Each player plays X shield
for(const player of roomData[roomId].playerData){
// TODO: Make sure this only does for players, not spectators (in fut.)
// If shieldCount is less than the 'most' shield at start of game
for(let shieldCount = 0; shieldCount < 4; shieldCount++){
playShield(roomId, player.playerDataId);
}
}
// Each player draws X cards to hand
for(const player of roomData[roomId].playerData){
// TODO: Make sure this only does for players, not spectators (in fut.)
//
for(let handCount = 0; handCount < 1; handCount++){
drawACard(roomId, player.playerDataId);
}
}
}
function passTurn(roomId, playerId){
// TODO:Check playerId and roomId before doing the stuff, to verify the user
@ -45,6 +79,49 @@ function passTurn(roomId, playerId){
}
function playShield(roomId, playerId){
if(global.roomData[roomId].itemData.component.shield[playerId] >= 2){
global.socketAlert(roomData[roomId].playerData[playerId].socketId, 'Shield full; cannot play shield', 'alert');
return false;
}
// Change position to last position available in shield zone
let fromPosition = global.roomData[roomId].itemData.component.cardCount.deck[playerId]; // 'top' of deck
let toPosition = global.roomData[roomId].itemData.component.cardCount.shield[playerId]+1; // newest shield pos.
// TODO: This is essential the same as in drawACard() so should be normalised into a function
// Get each card from the deck
for (const [key, value] of Object.entries(global.roomData[roomId].itemData.component.inDeck)) {
// Key is the entity here
// If the card inDeck does not belongs to the player, skip over it
if(global.roomData[roomId].itemData.component.player[key] != playerId){
continue;
}
// If the card isn't the last (bottom) card of deck, skip over it
// TODO: -1 is jank, sort so listPositions all start from 1..x
if(global.roomData[roomId].itemData.component.listPosition[key] != fromPosition){
continue;
}
// The main man
// Move positions in hand/deck, and put the item from the deck into the shield
gameHelper.setCardPosition(roomId, playerId, key, toPosition, global.roomData[roomId].itemData.component.shield, fromPosition, global.roomData[roomId].itemData.component.inDeck);
}
// Reduce deckSize by 1 for the player that drew
global.roomData[roomId].itemData.component.cardCount.deck[playerId]--;
// And increase the shield size by 1
global.roomData[roomId].itemData.component.cardCount.shield[playerId]++;
// Then emit the deckSize and hand size to all the player's sockets
global.socketResponsePlayedShield(roomId, playerId);
}
function drawACard(roomId, playerId){
if(global.roomData[roomId].itemData.component.cardCount.hand[playerId] >= 2){
@ -103,8 +180,11 @@ function drawACard(roomId, playerId){
}
function playManaFromHand(roomId, playerId, position){
playFromHand(roomId, playerId, position, true);
}
// TODO: Rename and rejig the 3 play from hand functions
function playFromHand(roomId, playerId, position){
function playFromHand(roomId, playerId, position, mana = false){
let cardId = null;
// Get the cardId of the card from position within players hand
@ -129,21 +209,28 @@ function playFromHand(roomId, playerId, position){
}
// Attempt to play the card from hand
if(!playACardFromHand(roomId, playerId, cardId)){
if(!playACardFromHand(roomId, playerId, cardId, mana)){
return false;
}
}
function playACardFromHand(roomId, playerId, cardId){
function playACardFromHand(roomId, playerId, cardId, mana = false){
// Add the card to field (and its effect to 'stack') or spell to the 'stack'
if(playACard(roomId, playerId, cardId, 'hand') !== true){
if(playACard(roomId, playerId, cardId, 'hand', mana) !== true){
// TODO: Return socket to player about 'illegal move' and why
return false;
}
if(mana){
global.socketResponsePlayManaFromHand(roomId, playerId, cardId);
return true;
}
// TODO: Maybe update with 'location played to' so animations, draws, etc. are correct
global.socketResponsePlayFromHand(roomId, playerId, cardId);
// TODO: Above can probably be the same/similar to what is added to the roomData on
// client-end (when it's fully done)
@ -154,8 +241,14 @@ function playACardFromHand(roomId, playerId, cardId){
// 'Play' a card is activation with cost (triggering play events)
// 'Summon' puts it onto the board without play events
// yada yada to think about in future
function playACard(roomId, playerId, cardId, playedFrom){
function playACard(roomId, playerId, cardId, playedFrom, mana = false){
// Play a mana (a card that was played as mana, loses it's normal card data)
if(mana){
// Play to board. If there's a 'onPlay' effect, add that to the 'stack'
return playMana(roomId, playerId, cardId, playedFrom);
}
// Play a unit
if(cardId in global.roomData[roomId].itemData.component.type.unit){
// Play to board. If there's a 'onPlay' effect, add that to the 'stack'
@ -256,6 +349,40 @@ function playAToken(roomId, playerId, cardId, playedFrom){
return false;
return true;
}
function playMana(roomId, playerId, cardId, playedFrom){
console.log('playMana');
// TODO: Check if mana can be played (default 10 max)
// TODO: Check if a mana has already been played this turn (default 1 per turn per player)
if(playedFrom == 'hand'){
// Remove from hand
removeFromHand(roomId, playerId, cardId);
// Add card to mana zone
global.roomData[roomId].itemData.component.mana[cardId] = cardId;
global.roomData[roomId].itemData.component.cardCount.mana[playerId]++;
console.log(global.roomData[roomId].itemData.component.mana);
console.log(global.roomData[roomId].itemData.component.cardCount.mana[playerId]);
// Change list positions of hand and mana
gameHelper.setCardPosition(roomId, playerId, cardId
, global.roomData[roomId].itemData.component.cardCount.mana[playerId]
, global.roomData[roomId].itemData.component.mana
, global.roomData[roomId].itemData.component.listPosition[cardId]
, global.roomData[roomId].itemData.component.hand
);
// Mana has been played
return true;
}
return false;
}
// Not 100% sure how to implement the stack
// TODO: Make it better
@ -460,6 +587,8 @@ module.exports = {
,drawACard
,shuffleDeck
,playFromHand
,playManaFromHand
,acceptResolveStack
,gameStart
};

@ -7,6 +7,8 @@ function drawGameBoard(){
calculateDeckPositions();
calculateHandPositions();
calculateBoardPositions();
calculateShieldPositions();
calculateManaPositions();
drawEntities();
@ -146,6 +148,122 @@ function calculateBoardPositions(){
}
}
function calculateShieldPositions(){
for (const [key, value] of Object.entries(gameData.shield)) {
// key is entity Id here
let cardsOnBoard = 0;
let position = 0;
let fromX = 0;
let fromY = 0;
let split = 0;
let shieldScale = .5; // TODO: Make global (like handScale)
switch(gameData.player[key]){
// Set position for player hand (all the time at current)
case gameData.playerId:
position = gameData.listPosition[key];
fromX = 60;
fromY = 300;
// i-1 here as it's based on 0 being start, like array.
// TODO: Not sure if I want to start elements at 1 (for clienty) or 0 (for programmy)
if(position-1>=2){ split = 1; }
gameData.position[key] = [
(fromX+((position%2)*cardMargin)) +(position%2*(cardWidth*shieldScale))
,canvas.height-fromY+(split*(cardHeight*shieldScale)+(cardMargin*split))
];
gameData.size[key] = [cardWidth * shieldScale, cardHeight * shieldScale];
break;
// Opponent
case gameData.opponentId:
position = gameData.listPosition[key];
fromX = canvas.width-60;
fromY = 300;
if(position-1>=2){ split = 1; }
// i%2 0 = 0, 1 = 1, 2 = 0, 3 = 1 to prevent margin from X/Y axis, and just between cards
gameData.position[key] = [
(fromX+((position%2)*cardMargin)) +(position%2*(cardWidth*shieldScale)-(cardWidth*2*shieldScale))
,fromY+(split*(cardHeight*shieldScale)+(cardMargin*split)-((cardHeight*2*shieldScale) + cardMargin))
];
gameData.size[key] = [cardWidth * shieldScale, cardHeight * shieldScale];
break;
}
}
}
function calculateManaPositions(){
for (const [key, value] of Object.entries(gameData.mana)) {
// key is entity Id here
let cardsOnBoard = 0;
let position = 0;
let fromX = 0;
let fromY = 0;
let manaScale = .3;
switch(gameData.player[key]){
// Set position for player hand (all the time at current)
case gameData.playerId:
position = gameData.listPosition[key] - 1; // Position starts at 1
fromX = 60;
fromY = 60 + cardHeight*manaScale;
gameData.position[key] = [
(fromX)+(position*(cardWidth*manaScale)+cardMargin*position)
,canvas.height-fromY
];
gameData.size[key] = [cardWidth * manaScale, cardHeight * manaScale];
break;
// Opponent
case gameData.opponentId:
position = gameData.listPosition[key] - 1; // Position starts at 1
fromX = 60;
fromY = 60;// + cardHeight*manaScale;
gameData.position[key] = [
// TODO: correct (then again all position need correcting tbf)
canvas.width - fromX-cardWidth*manaScale-(position*(cardWidth*manaScale))-cardMargin*position
,fromY
];
gameData.size[key] = [cardWidth * manaScale, cardHeight * manaScale];
break;
}
}
}
// TODO: Move this function elsewhere, not really a draw function
function calculateCardSpacing(positionInt, size, standardSize){
@ -164,6 +282,7 @@ function drawEntities(){
// If the entity has a position AND a size, we can print it
if(gameData.size[key] !== undefined){
// Should prolly switch from ifs somehow, but it works for now
// If the entity is a deck
if(key in gameData.deck){
drawDeck(key);
@ -179,6 +298,16 @@ function drawEntities(){
drawCardOnBoard(key);
}
// If shield
if(key in gameData.shield){
drawShield(key);
}
// Mana
if(key in gameData.mana){
drawMana(key);
}
if(key in gameData.inInteractionMenu){
// Add the menu with 'play', 'activate effect', 'inspect', etc.
drawInteractionMenu(key);
@ -253,6 +382,22 @@ function drawCardOnBoard(entity){
drawCardDetails(entity);
}
function drawShield(entity){
// TODO: Tapped
drawCardBack(entity);
}
function drawMana(entity){
// TODO: Show the colour/Icon of the mana for ease when tapping, etc.
console.log('drawMana');
console.log(entity);
// TODO: Tapped
drawCardBack(entity);
}
// The draw all the card data, name, colour, etc.

@ -67,6 +67,10 @@ canvas.addEventListener('click', function(event) {
requestPlayFromHand(gameData.listPosition[gameData.inInteractionMenu[Object.keys(gameData.inInteractionMenu)[0]]])
}
if(key == 'Play as Mana'){
requestPlayManaFromHand(gameData.listPosition[gameData.inInteractionMenu[Object.keys(gameData.inInteractionMenu)[0]]])
}
console.log(key);
// After an interaction, clear the menu to prevent redraw

@ -16,6 +16,10 @@ let gameData = {
deck : {},
hand : {},
board : {},
shield : {},
mana : {},
grave : {},
void : {},
},
inInteractionMenu : {},
@ -29,6 +33,10 @@ let gameData = {
deck : {},
hand : {},
board : {},
shield : {},
mana : {},
grave : {},
void : {},
// Local components, not done on serverside
// calculated, etc. by client

@ -82,6 +82,21 @@ function updateBoard(data){
gameData.cardColours = data.cardColours;
//console.log(data);
}
function updateShield(data){
console.log('TODO: updateShield correctly');
console.log(data);
gameData.shield = data.shield;
gameData.listPosition = data.listPosition;
// TODO: Tapped
}
function updateMana(data){
console.log('TODO: updateMana correctly');
console.log(data);
gameData.mana = data.mana;
gameData.listPosition = data.listPosition;
gameData.cardData = data.cardData;
gameData.cardColours = data.cardColours;
}
// To prevent typical functionality (draw, etc.)
// if there's a stack in play.

@ -73,6 +73,28 @@ socket.on('responsePlayFromHand', function (data) {
console.log('<< playFromHand');
console.log(data);
});
function requestPlayManaFromHand(listPosition){
console.log('>> playManaFromHand');
socket.emit('playManaFromHand', gameData.roomId, gameData.playerId, listPosition);
}
socket.on('responseUpdateMana', function (data) {
// Return boardData, update hand
console.log('<< updateMana');
console.log(data);
updateMana(data);
drawGameBoard();
});
socket.on('responsePlayedShield', function (data) {
// The playerId that played it for animations
console.log('<< playedShield');
drawGameBoard();
});
socket.on('responseUpdateShield', function (data) {
console.log('<< updateShield');
console.log(data);
updateShield(data);
});
// Stack
socket.on('responseAddToStack', function (data) {

@ -1,4 +1,5 @@
const roomMod = require('./roomMod');
const gameMod = require('./gameMod');
// Variables for server overall
let numRooms = 0;
@ -205,6 +206,7 @@ async function startGame(roomId){
// Each player then gets sent the roomGeneration stuff
// TODO:They should recieve different data based on what they can see/interact
for (const clientId of clients) {
const clientSocket = global.io.sockets.sockets.get(clientId);
@ -230,6 +232,8 @@ async function startGame(roomId){
}
// Start game gameMod?
gameMod.gameStart(roomId);
}

@ -66,6 +66,9 @@ function onConnection(socket){
socket.on('playFromHand', function(roomId, playerId, listPosition) {
gameMod.playFromHand(roomId, playerId, listPosition);
});
socket.on('playManaFromHand', function(roomId, playerId, listPosition) {
gameMod.playManaFromHand(roomId, playerId, listPosition);
});
socket.on('requestResolveStack', function(roomId, playerId) {
gameMod.acceptResolveStack(roomId, playerId);
@ -170,6 +173,13 @@ global.socketResponseUpdateBoard = function(roomId){
// to the player who's side it's on
global.sendToEachSocket(roomId, 'responseUpdateBoard', data);
}
global.socketResponseUpdateMana = function(roomId){
// TODO: Only return the data that's needed, no everything
let data = global.roomData[roomId].itemData.component;
global.sendToEachSocket(roomId, 'responseUpdateMana', data);
}
global.socketResponsePlayFromHand = function(roomId, playerId, cardId){
@ -188,6 +198,35 @@ global.socketResponsePlayFromHand = function(roomId, playerId, cardId){
// So the animations can be played with the new cardData (in future)
global.sendToEachSocket(roomId, 'responsePlayFromHand', cardId);
}
global.socketResponsePlayManaFromHand = function(roomId, playerId, cardId){
console.log('>> '+roomData[roomId].playerData[playerId].playerId+' played mana from hand');
// Return the new cardCounts for hand/deck/grave, etc.
global.socketReturnCardCounts(roomId);
// Update hand of player that card's hand was played from (using existing logic)
global.socketResponsePlayerHandData(roomId, playerId);
// Update the mana (for both players)
global.socketResponseUpdateMana(roomId);
// So the animations can be played with the new cardData (in future)
//global.sendToEachSocket(roomId, 'responsePlayFromHand', cardId);
}
global.socketResponsePlayedShield = function(roomId, playerId){
//global.socketReturnCardCounts(roomId, 'responseDrawCard');
// Return playerId of who played a shield so it can be added then animated
global.sendToEachSocket(roomId, 'responsePlayedShield', playerId);
// Date for shield
let data = global.roomData[roomId].itemData.component;
global.sendToEachSocket(roomId, 'responseUpdateShield', data);
}
// Stack
global.socketResponseAddToStack = function(roomId){

Loading…
Cancel
Save