From ccb86df970c8bb93cc60f30b472b8a519cc5b986 Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 24 Oct 2024 14:20:22 +0100 Subject: [PATCH 01/18] Start of basic effect functionality --- public/effect.js | 112 ++++++++++++++++++++++++++++++++++++++++++++++ public/helper.js | 6 +++ public/index.html | 2 + 3 files changed, 120 insertions(+) create mode 100644 public/effect.js create mode 100644 public/helper.js diff --git a/public/effect.js b/public/effect.js new file mode 100644 index 0000000..44b6b85 --- /dev/null +++ b/public/effect.js @@ -0,0 +1,112 @@ +// Passive effects (just does stuff) +let flight = {}; +let reach = {}; +let equipped = {}; // Entity x has [a,b,c] equipped to it + + +// Actives to add passives +function giveFlight(card){ + flight[card] = true; +} +function removeFlight(card){ + // If the card has flight delete entity component + if(card in flight){ + delete flight[card]; + return true; + } + return false; +} + +// Active +function equip(){ + // Equip card to another unit + +} +function unequip(){ + // Remove card from its equipped to unit + +} + +function heal(healAmount, healPlayer){ + // For each heal 1..4 + for(let i = 0; i < healAmount; i++){ + // Loop shield + let items = this.getItems('shield', healPlayer, null, null); + for(let item = 0; item < items.length; item++){ + + let itemKey = items[item]; + // If a shield is tapped, untap it to 'heal' + if(board.isTapped(itemKey)){ + board.untapCard(itemKey); + } + + } + } +} + +function hurt(hurtDamage, hurtTarget = null, hurtPlayer = null){ + // Deal X000 damage to unit this turn, or deal Y to opponent's shield + + // Set player/element + if(hurtPlayer == null && hurtTarget != null){ + hurtPlayer = player[hurtTarget]; + hurtElement = boardElement[hurtTarget]; + }else{ + hurtElement = 'shield' + } + + switch(hurtElement){ + case 'board': + // TODO: Make temp damage this turn as well + if(hurtDamage >= cardAttack[hurtTarget][0]){ + board.sendToGrave(hurtTarget); + } + break; + + case 'shield': + let destroyCount = cardAttackToShieldDamage(hurtDamage); + console.log(destroyCount); + // TODO: loop player's shield, tap if they can be tapped, destroy + // if all already tapped + + // While there's still damage to deal + while(destroyCount > 0){ + + // Keep looping through the shield belonging to target user + let items = board.getItems('shield', hurtPlayer, null, null); + let tappedItems = board.getItems('shield', hurtPlayer, 'tapped', null); + + for(let item = 0; item < items.length; item++){ + + // If nothing more to destroy, exit loop + if(destroyCount <= 0){ break; } + + let itemKey = items[item]; + console.log(itemKey); + console.log(cardStatus[itemKey]); + + // If there's anything to tap, tap it + if(cardStatus[itemKey] == null){ + console.log('been tapped'); + board.tapCard(itemKey); + destroyCount--; + continue; + } + + // If there's nothing to tap, destroy it + if(items.length == tappedItems.length){ + console.log('been destroyed'); + board.destroyShield(itemKey); + destroyCount--; + continue; + } + + } + } + + board.drawBoard(); + break; // end case 'shield' + + } +} + diff --git a/public/helper.js b/public/helper.js new file mode 100644 index 0000000..bb995ac --- /dev/null +++ b/public/helper.js @@ -0,0 +1,6 @@ +function cardAttackToShieldDamage(attack){ + if (attack >= 10000){ return 3; } + if (attack >= 5001){ return 2; } + if (attack >= 1){ return 1; } +} + diff --git a/public/index.html b/public/index.html index d0ccafc..1bed34f 100644 --- a/public/index.html +++ b/public/index.html @@ -69,6 +69,8 @@ + + From 916c0f2dcba8dd0027033087b9306c125544e00e Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 24 Oct 2024 14:44:38 +0100 Subject: [PATCH 02/18] Add debug tool for effects --- public/board.js | 1 + public/debug.js | 52 +++++++++++++++++++++++++++++++++++++++++++++++ public/index.html | 28 +++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 public/debug.js diff --git a/public/board.js b/public/board.js index b2d9a75..444d9a8 100644 --- a/public/board.js +++ b/public/board.js @@ -1243,6 +1243,7 @@ canvas.addEventListener('contextmenu', function(event) { if(itemKey in size && itemKey in position){ // Compare the event XY position to the item if(clickableCheck(x,y,itemKey)){ + console.log('itemId: '+itemKey); // Only want to happen once (for now) // Maybe in future add to hand would trigger another event if there's an effect? diff --git a/public/debug.js b/public/debug.js new file mode 100644 index 0000000..9269e0e --- /dev/null +++ b/public/debug.js @@ -0,0 +1,52 @@ +// For front-end debugging +// Anything to be tested that would otherwise need server logs, etc. +// should go here + +function debugEffect(){ + + let damageAmount = document.getElementById("effectDamageAmount").value; + if(damageAmount == ""){ damageAmount = null; } + + let targetId = document.getElementById("effectTargetId").value; + if(targetId == ""){ targetId = null; } + + let targetId2 = document.getElementById("effectTargetId2").value; + if(targetId2 == ""){ targetId2 = null; } + + let targetPlayer = document.getElementById("effectTargetPlayer").value; + if(targetPlayer == ""){ targetPlayer = null; } + + let effectAddRemove = document.getElementById("effectAddRemove").value; + if(effectAddRemove == ""){ effectAddRemove = null; } + + let effect = document.getElementById("effect").value; + if(effect == ""){ effect = null; } + + debugEffectFunction(damageAmount, targetId, targetId2, targetPlayer, effectAddRemove, effect); + +} + +function debugEffectFunction(damageAmount = null, targetId = null, targetId2 = null, targetPlayer = null, effectAddRemove = null, effect = null){ + + if(effect == 'hurt'){ + hurt(damageAmount, targetId, targetPlayer); + } + if(effect == 'heal'){ + heal(damageAmount, targetPlayer); + } + if(effect == 'flight'){ + console.log(targetId+' Flight: '+flight[targetId]); + + console.log(effectAddRemove); + + if(effectAddRemove == 'remove'){ + removeFlight(targetId); + }else{ + giveFlight(targetId); + } + + console.log(targetId+' Flight: '+flight[targetId]); + } + if(effect == 'equip'){} +} + diff --git a/public/index.html b/public/index.html index 1bed34f..509d2e7 100644 --- a/public/index.html +++ b/public/index.html @@ -58,6 +58,33 @@ +
+
+ + + + + + + + + + + +
+
@@ -71,6 +98,7 @@ + From 87e91d4a6da53e31425ce8bd7c0f563a439c1178 Mon Sep 17 00:00:00 2001 From: Nathan Date: Thu, 24 Oct 2024 14:58:22 +0100 Subject: [PATCH 03/18] Add draw/reach to effect/debug --- public/debug.js | 16 ++++++++++++++++ public/effect.js | 14 ++++++++++++++ public/index.html | 2 ++ 3 files changed, 32 insertions(+) diff --git a/public/debug.js b/public/debug.js index 9269e0e..6eed83f 100644 --- a/public/debug.js +++ b/public/debug.js @@ -47,6 +47,22 @@ function debugEffectFunction(damageAmount = null, targetId = null, targetId2 = n console.log(targetId+' Flight: '+flight[targetId]); } + if(effect == 'reach'){ + console.log(targetId+' Reach: '+reach[targetId]); + + console.log(effectAddRemove); + + if(effectAddRemove == 'remove'){ + removeReach(targetId); + }else{ + giveReach(targetId); + } + + console.log(targetId+' Reach: '+reach[targetId]); + } + if(effect == 'draw'){ + drawCard(damageAmount, targetPlayer); + } if(effect == 'equip'){} } diff --git a/public/effect.js b/public/effect.js index 44b6b85..60062d0 100644 --- a/public/effect.js +++ b/public/effect.js @@ -16,6 +16,16 @@ function removeFlight(card){ } return false; } +function giveReach(card){ + reach[card] = true; +} +function removeReach(card){ + if(card in reach){ + delete reach[card]; + return true; + } + return false; +} // Active function equip(){ @@ -27,6 +37,10 @@ function unequip(){ } +function drawCard(drawAmount, player){ + board.drawACard(player, drawAmount); +} + function heal(healAmount, healPlayer){ // For each heal 1..4 for(let i = 0; i < healAmount; i++){ diff --git a/public/index.html b/public/index.html index 509d2e7..d0d3f57 100644 --- a/public/index.html +++ b/public/index.html @@ -75,9 +75,11 @@ + + + + +
+
From 876b705407f8225a68dece60ee14c045cad7f6cb Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 25 Oct 2024 02:30:30 +0100 Subject: [PATCH 11/18] Start 'pay' trigger + amend tapManaRequired --- public/board.js | 43 +++++++++++++++++++++++++++++-------------- public/debug.js | 2 +- public/effect.js | 24 +++++++++++++++++++++--- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/public/board.js b/public/board.js index 3dcb565..d3da392 100644 --- a/public/board.js +++ b/public/board.js @@ -698,10 +698,15 @@ class Board{ this.drawBoard(); } - tapManaRequired(itemToPayCost, playerId){ + // TODO: Make to check mana, and actually do it. + // also make work for effects + tapManaRequired(itemToPayCost, playerId, checkOnly = false, effectCosts = null){ // TODO: Look at combining or normalising this and canPayMana() - let manaRequired = this.getManaTotalOf(itemToPayCost); + let manaRequired = []; + if(effectCosts !== null){ manaRequired = effectCosts; } + else{ manaRequired = this.getManaTotalOf(itemToPayCost); } + let noManaReq = {1:0, 2:0, 3:0, 4:0}; let manaToTap = []; @@ -723,7 +728,6 @@ class Board{ console.log(JSON.stringify(manaRequired[0])); // Loop the requirements of the cost to pay for (const manaColour in manaRequired[0]) { - //console.log(manaColour+' '+manaRequired[manaColour]+', '+colourId); // If the colour of the mana is in the requirements // of the cost to pay, reduce the cost for that colour by // 1 and tap the mana @@ -745,17 +749,25 @@ class Board{ // For 3 cost cards that only require 1 red, two more mana (any colour) // need to be tapped // TODO: Better more efficiently and let user select... - let itemCostRemaining = cardData[itemToPayCost].cost - manaRequired[1]; - if(itemCostRemaining > 0){ - /* - let tapRequirement = (cardData[itemToPayCost].cost - manaRequired[1]); - alert('Tap: '+(tapRequirement)+' more mana to play'); + let itemCostRemaining = 0; + let itemCost = 0; + if(itemToPayCost !== null){ + itemCostRemaining = cardData[itemToPayCost].cost - manaRequired[1]; + itemCost = cardData[itemToPayCost].cost; + } + else if(effectCosts !== null){ + itemCostRemaining = manaRequired[1]; + itemCost = manaRequired[1]; + } - // start mana tap event - */ + if(itemCostRemaining > 0){ // TODO: decide 100% how cards are to be played/payed for // don't want to slam time into a mana system if it'll be nuked. + if(items.length < itemCostRemaining){ + return false; + } + // For now, reloop and tap first available mana so that card // payment is satiated // Using same items from above @@ -772,18 +784,21 @@ class Board{ } manaToTap.push(mana); + itemCostRemaining--; // TODO: ?????? } } - if(cardData[itemToPayCost].cost - manaToTap.length > 0){ + if(itemCost - manaToTap.length > 0){ return 'itemCostRemaining: '+itemCostRemaining; // Didn't find another mana to tap so cost not satiated } // If the mana to tap has been satitated then tap the mana selected - manaToTap.forEach(manaId => { - this.tapCard(manaId); - }); + if(checkOnly == false){ // Tap the mana if this isn't a check + manaToTap.forEach(manaId => { + this.tapCard(manaId); + }); + } // And continue with whatever we were doing return true; diff --git a/public/debug.js b/public/debug.js index 327f37d..98a97ca 100644 --- a/public/debug.js +++ b/public/debug.js @@ -87,7 +87,7 @@ function debugTriggerFunction(targetId = null, trigger = null, triggerAmount = n triggerTap(targetId); } if(trigger == 'pay'){ - triggerPay(targetId, triggerAmount); + triggerPay(triggerAmount); } } diff --git a/public/effect.js b/public/effect.js index 509d270..f10c2c6 100644 --- a/public/effect.js +++ b/public/effect.js @@ -130,7 +130,7 @@ function hurt(hurtDamage, hurtTarget = null, hurtPlayer = null){ // When card has been actively tapped function triggerTap(card){ - if(!canTriggerTap(card)){ return false; } + if(canTriggerTap(card) == false){ return false; } board.tapCard(card); @@ -152,11 +152,29 @@ function canTriggerTap(card){ } // Pay the mana cost(s) to trigger event -function triggerPay(){ +function triggerPay(triggerAmount){ + if(canTriggerPay(triggerAmount) == false){ + return false; + } + + let effectCosts = [{1:0,2:0,3:0,4:0}, triggerAmount]; + board.tapManaRequired(null, 0, false, effectCosts); + + console.log('triggerPay'); + return true; } // Check the mana cost(s) can be paid, otherwise don't start trigger -function canTriggerPay(){ +function canTriggerPay(triggerAmount){ + // For player0 only at the mo. and with no specific colour costs + let effectCosts = [{1:0,2:0,3:0,4:0}, triggerAmount]; + if(board.tapManaRequired(null, 0, true, effectCosts) == false){ + console.log('cannot trigger pay'); + return false; + } + + console.log('Can trigger pay'); + return true; } From f9919bde0ede691a1ba158f5114a8a86977c9bab Mon Sep 17 00:00:00 2001 From: Nathan Date: Fri, 25 Oct 2024 20:55:30 +0100 Subject: [PATCH 12/18] Add console debug for cardEffect --- public/board.js | 1 + public/debug.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ public/effect.js | 16 +++++++++++++ 3 files changed, 77 insertions(+) diff --git a/public/board.js b/public/board.js index d3da392..89ad5ab 100644 --- a/public/board.js +++ b/public/board.js @@ -1285,6 +1285,7 @@ canvas.addEventListener('contextmenu', function(event) { console.log('itemId: '+itemKey); document.getElementById('effectTargetId').value = itemKey; document.getElementById('triggerTargetId').value = itemKey; + debugGetCardEffects(itemKey); // Only want to happen once (for now) // Maybe in future add to hand would trigger another event if there's an effect? diff --git a/public/debug.js b/public/debug.js index 98a97ca..bbc76b7 100644 --- a/public/debug.js +++ b/public/debug.js @@ -91,3 +91,63 @@ function debugTriggerFunction(targetId = null, trigger = null, triggerAmount = n } } +// Builds console log for card effect (inc. +// all triggers, etc) +function debugGetCardEffects(itemKey){ + + let effectData = cardEffect[itemKey]; + console.log(effectData); + if(effectData === undefined){ return false; } + + effectData.forEach((effect, effectIndex) => { + + console.log('--- Effect '+ effectIndex +' ---'); + console.log(effect['description']); + + // Loop the triggers + for (const [key, value] of Object.entries(effect['trigger'])) { + + console.log('--- Trigger ---'); + let effectTrigger = effect['trigger'][key]; + console.log(triggerTypes[effectTrigger['triggerTypeId']]); + + console.log('--- Trigger Amount ---'); + console.log(effectTrigger['amount']); + + // Loop targets for said trigger + effectTrigger['target'].forEach((effectTriggerTarget) => { + console.log('--- Trigger Target ---'); + console.log(effectTriggerTarget.classId); + console.log(effectTriggerTarget.colourId); + console.log(effectTriggerTarget.passiveId); + console.log(effectTriggerTarget.typeId); + }); + } + + // Loop the effects + for (const [key, value] of Object.entries(effect['step'])) { + // amoutn, basicEffectId, stepOrder, target (also itemfromstep) + console.log(effect['step'][key]); + + console.log('--- Effect Step ---'); + let effectStep = effect['step'][key]; + console.log(basicEffects[effectStep['basicEffectId']]); + + console.log('--- Effect Step Amount ---'); + console.log(effectStep['amount']); + + // Loop targets for effectStep + effectStep['target'].forEach((effectStepTarget) => { + console.log('--- Effect Step Target ---'); + console.log(effectStepTarget.classId); + console.log(effectStepTarget.colourId); + console.log(effectStepTarget.passiveId); + console.log(effectStepTarget.typeId); + console.log(effectStepTarget.itemFromStep); + }); + + } + + }); + +} diff --git a/public/effect.js b/public/effect.js index f10c2c6..5140ddc 100644 --- a/public/effect.js +++ b/public/effect.js @@ -4,6 +4,22 @@ let reach = {}; let equipped = {}; // Entity x has [a,b,c] equipped to it +// Trigger types +const triggerTypes = { + 1: 'Tap', + 2: 'Pay', +}; +// Basic effects +// TODO: Pull display name/description from DB? +const basicEffects = { + 1: 'Equip', + 2: 'Heal', + 3: 'Hurt', + 4: 'Recruit', + 5: 'Give Flight', +}; + + // Actives to add passives function giveFlight(card){ flight[card] = true; From 4fb1a2694d6bb7e859820cceb10e4d3dcf0f47ee Mon Sep 17 00:00:00 2001 From: Nathan Date: Sat, 26 Oct 2024 23:04:42 +0100 Subject: [PATCH 13/18] Add functionality to trigger effect(s) Currently takes the trigger conditions, but doesn't start the effects --- public/board.js | 2 +- public/debug.js | 19 ++++++++++++ public/effect.js | 76 +++++++++++++++++++++++++++++++++++++++++++++-- public/index.html | 9 ++++++ 4 files changed, 103 insertions(+), 3 deletions(-) diff --git a/public/board.js b/public/board.js index 89ad5ab..2db6ae7 100644 --- a/public/board.js +++ b/public/board.js @@ -704,7 +704,7 @@ class Board{ // TODO: Look at combining or normalising this and canPayMana() let manaRequired = []; - if(effectCosts !== null){ manaRequired = effectCosts; } + if(effectCosts != null){ manaRequired = effectCosts; } else{ manaRequired = this.getManaTotalOf(itemToPayCost); } let noManaReq = {1:0, 2:0, 3:0, 4:0}; diff --git a/public/debug.js b/public/debug.js index bbc76b7..1a47973 100644 --- a/public/debug.js +++ b/public/debug.js @@ -151,3 +151,22 @@ function debugGetCardEffects(itemKey){ }); } + +function debugEffectCanTrigger(){ + + let ecTriggerTargetId = document.getElementById("ecTriggerTargetId").value; + if(ecTriggerTargetId == ""){ ecTriggerTargetId = null; } + + let ecTriggerIndex = document.getElementById("ecTriggerIndex").value; + if(ecTriggerIndex == ""){ ecTriggerIndex = 0; } + + if(triggerEffect(ecTriggerTargetId, ecTriggerIndex, true) != true){ + console.log('Effect cannot be triggered'); + return false; + } + + console.log('Effect CAN be triggered'); + triggerEffect(ecTriggerTargetId, ecTriggerIndex); + +} + diff --git a/public/effect.js b/public/effect.js index 5140ddc..cbba37d 100644 --- a/public/effect.js +++ b/public/effect.js @@ -6,8 +6,8 @@ let equipped = {}; // Entity x has [a,b,c] equipped to it // Trigger types const triggerTypes = { - 1: 'Tap', - 2: 'Pay', + 'tap': 1, + 'pay': 2, }; // Basic effects // TODO: Pull display name/description from DB? @@ -194,3 +194,75 @@ function canTriggerPay(triggerAmount){ } +// Pay/Activate (all) the triggers +function triggerEffect(itemKey, effectIndex, checkOnly = false){ + + // Check card has effectData + let effectData = cardEffect[itemKey]; + if(effectData === undefined){ return false; } // No effect + + // Check effectData contains target effect + let effect = effectData[effectIndex]; + if(effect === undefined){ return false; } // No effect + + // Loop each trigger, AND activate them + for (const [key, value] of Object.entries(effect['trigger'])) { + + let effectTrigger = effect['trigger'][key]; + console.log('--- Trigger '+key+' ---'); + console.log(effectTrigger['triggerTypeId']); + + // TAP TRIGGER + if(effectTrigger['triggerTypeId'] == triggerTypes.tap){ + if(canTriggerTap(itemKey) == false){ + console.log('Tap trigger, cannot be triggered'); + return false; + } + + // Do the trigger, then continue to next trigger + if(!checkOnly){board.tapCard(itemKey);} + continue; + + } + + + // PAY TRIGGER + if(effectTrigger['triggerTypeId'] == triggerTypes.pay){ + + // To build the colourReq TODO: Change as could be 1 of either red/blue + // for instance + let colourReq = {1:0,2:0,3:0,4:0}; + + // Loop pay required (colours) for said trigger + // BUILD the colourReq loop needed for tapMana check + effectTrigger['target'].forEach((effectTriggerTarget) => { + + // Increment colourReq by one of that colour + // THIS WILL NEED REDOING, AS MAYBE IT'S 2 OF RED OR BLUE!! + colourReq[effectTriggerTarget.colourId]++; + + }); + + // Check if the cost (and colour req.) can be paid + canPay = board.tapManaRequired(null, null, true, [colourReq, effectTrigger['amount']]); + if(canPay !== true){ + console.log('Pay trigger, cannot be triggered'); + return false; + } + + // Pay trigger costs, then continue to next trigger + if(!checkOnly){ + board.tapManaRequired(null, null, false, [colourReq, effectTrigger['amount']]); + } + continue; + + } + + // OTHER TRIGGERS + + } + + return true; + +} + diff --git a/public/index.html b/public/index.html index fd1bbd7..0d650ff 100644 --- a/public/index.html +++ b/public/index.html @@ -101,6 +101,15 @@
+
+
+ + + + + +
+
From 6a6c9ffb83902ab3a3f7d978a908e24686739183 Mon Sep 17 00:00:00 2001 From: Nathan Date: Sun, 27 Oct 2024 18:52:07 +0000 Subject: [PATCH 14/18] WIP: Actual effect check/doing Needs lots of work, perhaps splitting into a function per step to prevent loops, etc in case of chains, and counterspells, etc. --- public/debug.js | 15 +++- public/effect.js | 178 +++++++++++++++++++++++++++++++++++++++++++++- public/index.html | 4 ++ 3 files changed, 194 insertions(+), 3 deletions(-) diff --git a/public/debug.js b/public/debug.js index 1a47973..da47f48 100644 --- a/public/debug.js +++ b/public/debug.js @@ -160,13 +160,24 @@ function debugEffectCanTrigger(){ let ecTriggerIndex = document.getElementById("ecTriggerIndex").value; if(ecTriggerIndex == ""){ ecTriggerIndex = 0; } - if(triggerEffect(ecTriggerTargetId, ecTriggerIndex, true) != true){ + let ecDoTrigger = document.getElementById("ecDoTrigger").value; + if(ecDoTrigger == ""){ ecDoTrigger = 0; } + + if(doEffectTriggers(ecTriggerTargetId, ecTriggerIndex, true) != true){ console.log('Effect cannot be triggered'); + doEffect(ecTriggerTargetId, ecTriggerIndex, 1); return false; } console.log('Effect CAN be triggered'); - triggerEffect(ecTriggerTargetId, ecTriggerIndex); + + if(ecDoTrigger){ + // Do everything needed in triggers + doEffectTriggers(ecTriggerTargetId, ecTriggerIndex); + + // Then do the actual effects + doEffect(ecTriggerTargetId, ecTriggerIndex); // also step = 1,2,3 + } } diff --git a/public/effect.js b/public/effect.js index cbba37d..ae3805f 100644 --- a/public/effect.js +++ b/public/effect.js @@ -195,7 +195,7 @@ function canTriggerPay(triggerAmount){ } // Pay/Activate (all) the triggers -function triggerEffect(itemKey, effectIndex, checkOnly = false){ +function doEffectTriggers(itemKey, effectIndex, checkOnly = false){ // Check card has effectData let effectData = cardEffect[itemKey]; @@ -266,3 +266,179 @@ function triggerEffect(itemKey, effectIndex, checkOnly = false){ } +function activateEffect(){ + // Do effect triggers, then doEffect once payed +} + +function getEffect(itemKey, effectIndex){ + // Check card has effectData + let effectData = cardEffect[itemKey]; + if(effectData === undefined){ return false; } // No effect + + // Check effectData contains target effect + let effect = effectData[effectIndex]; + if(effect === undefined){ return false; } // No effect + + return effect; +} +// Get all the targets for effect step, so they can be targgeted +// by the effect/selected by the player +function getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement, playerId){ + + // Get Effect + let effect = getEffect(itemKey, effectIndex); + if(effect == false){ return false; } + + // Get the step + let step = effect['step'][effectStep]; + if(step == undefined){ return false; } + + // The items that can be targetted with the effectStep + let itemsToSelectFrom = []; + + // Loop the target location (or all locations) + // Check which cards meet the criteria in the DB + + + // TODO: Not 100% sure how to keep track. May need a var for each item in previous steps + // or previous chains so they can be accessed, and used + // If itemFromStep, return the itemKeys of the items selected from a previous step + /* + if(target['itemFromStep'] == null){ + // So something from step 1 needs to be selected by this. + } + */ + + + // boardElement, playerId, cardStatus, listPosition + let items = board.getItems(fromBoardElement, playerId, null, null); // TODO: maybe 'from top of deck, or if tapped' + for(let item = 0; item < items.length; item++){ + // TODO: MAYBE ADD THE COLOUR/PASSIVE CHECKS to the getItems itself + + let itemKey = items[item]; + console.log(cardColours[itemKey]); + + // If the item from getItems meets the criterias of target DB + step['target'].forEach((target) => { + + // Check the class the same for target, and item + // If targetDB has null this means 'any' so is always correct + // Check Class (TODO: mixed classes, colours, etc ie select 1 red+blue card) + /* + if(class[itemKey] == target['classId'] || target['classId'] == null){ + + } + */ + + // Check colour + // If not null check the colours, otherwise null means any colour is ok + if(target['colourId'] !== null){ + // Check the colours to see if one is of requirement + cardColours[itemKey].forEach((colour) => { + // If the colour doesn't match, continue to next target (forEach) + if(colour[0] != target['colourId']){ + // The return below is just a 'continue' in forEach terms + return; // forEach jank. forEach executes the 'function' 'target' each loop + } + // If the colour is correct, keep checking requirements + }); + } + + // Check passive (If hasPassive(id)) + /* + if(cardColours[itemKey] == target['passiveId'] || target['passiveId'] == null){ + + } + */ + + /* + if(cardType[itemKey] == target['typeId'] || target['typeId'] == null){ + + } + */ + + // Once all the target Req. have been checked against the item + // and they match, add to selectable list + itemsToSelectFrom.push(itemKey); + + }); + + } + + return itemsToSelectFrom; + + +} + + +// Recusively call doEffect until each is done? +// Once recruit (play from hand) is triggered, need to allow user to select +// then when done move to next step +function doEffect(itemKey, effectIndex, effectStep = 1){ + + let effect = getEffect(itemKey, effectIndex); + if(effect == false){ return false; } + + // Get the step + let step = effect['step'][effectStep]; + if(step == undefined){ return false; } + + + // For each step, activate the correct effect type on + // the correct targets. + + switch (step['basicEffectId']){ + + // Recruit + case 4: + recruitCard(itemKey, effectIndex, effectStep, step['amount']); + break; + + // Give Flight + case 5: + console.log('GIVE FLIGHT'); + break; + + } + + // Now do the next step, if there's another in the effect + if(effect['step'][effectStep++] !== undefined){ + doEffect(itemKey, effectIndex, effectStep++); + } +} + +function recruitCard(itemKey, effectIndex, effectStep, targetAmount){ + console.log('RECRUIT'); + + let fromBoardElement = 'hand'; // FOR NOW, JUST TO TEST, THIS WILL BE PER BASIC EFFECT + let playerId = 0; + + let targets = getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement, playerId); + console.log(targets); + + if(targetAmount > 0 && targets.length > 0){ + + let selectedTarget = prompt("Select a card to recruit: \n"+targets, targets[0]); + // User didn't select anything + if (selectedTarget == null || selectedTarget == "") { + alert('No card recruited, c ya'); + return false; + } + // User inputted card not in ID (obv temp, as will be done in game UI) + if (!selectedTarget.includes(selectedTarget)){ + alert('Not in selection'); + return false; + } + + // Remove the card from the selection + targets.splice(targets.indexOf(selectedTarget), 1); + + // Play recruited card + // TODO: Maybe needs a new function 'playRecruitedCard' for different event triggers + board.playCardToBoard(listPosition[itemKey], boardElement[itemKey], 'board', 0, 0, 1); + + } + + +} + diff --git a/public/index.html b/public/index.html index 0d650ff..b2cfa00 100644 --- a/public/index.html +++ b/public/index.html @@ -107,6 +107,10 @@ +
From 5f89925a92c9ca999c20c44bc273a33db54cfe36 Mon Sep 17 00:00:00 2001 From: Nathan Date: Mon, 28 Oct 2024 20:00:19 +0000 Subject: [PATCH 15/18] Effect changes --- public/board.js | 31 +++++- public/debug.js | 8 +- public/effect.js | 252 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 269 insertions(+), 22 deletions(-) diff --git a/public/board.js b/public/board.js index 2db6ae7..8023be2 100644 --- a/public/board.js +++ b/public/board.js @@ -651,6 +651,34 @@ class Board{ } } + playRecruitedCard(player, fromPositionInHand){ + + // Check there's space on the board/mana zone/shield/etc + if(!this.hasSpaceInBoardElement('board', player)){ + alert('No space on board'); + return false; + } + + // Summon card to board from... + this.summonCard(player, fromPositionInHand, 'hand', player); + + // TODO: Check triggers for 'when X recruits' and add to queue + + this.drawBoard(); + + } + + summonCard(fromPlayer, positionFrom, fromElement, toPlayer){ + + // Summon card to board from... + this.addFromBoardElement(fromPlayer, positionFrom, fromElement, 'board', null, toPlayer); + + // TODO: Check triggers on 'when X summons'/'when a X is summoned' and add to queue + + this.drawBoard(); + + } + // Currently only functionality in hand playCardToBoard(positionFrom, fromElement, toElement, fromPlayer, toPlayer = null, cardsToPlay = 1){ @@ -691,8 +719,7 @@ class Board{ } } - // Move from player0, position 0 (top) of deck, to hand, to pos(null/auto) for toPlayer - this.addFromBoardElement(fromPlayer, positionFrom, fromElement, toElement, null, toPlayer); + this.summonCard(fromPlayer, positionFrom, fromElement, toPlayer); } this.drawBoard(); diff --git a/public/debug.js b/public/debug.js index da47f48..6074130 100644 --- a/public/debug.js +++ b/public/debug.js @@ -165,7 +165,9 @@ function debugEffectCanTrigger(){ if(doEffectTriggers(ecTriggerTargetId, ecTriggerIndex, true) != true){ console.log('Effect cannot be triggered'); - doEffect(ecTriggerTargetId, ecTriggerIndex, 1); + queueEffect(ecTriggerTargetId, ecTriggerIndex); + //doNextInQueue(); + loopTriggerQueue(); return false; } @@ -175,8 +177,8 @@ function debugEffectCanTrigger(){ // Do everything needed in triggers doEffectTriggers(ecTriggerTargetId, ecTriggerIndex); - // Then do the actual effects - doEffect(ecTriggerTargetId, ecTriggerIndex); // also step = 1,2,3 + // Then queue the effects to happen (queued so they can be chained/countered) + queueEffect(ecTriggerTargetId, ecTriggerIndex); } } diff --git a/public/effect.js b/public/effect.js index ae3805f..a006713 100644 --- a/public/effect.js +++ b/public/effect.js @@ -1,9 +1,22 @@ +// Theorising, if this is what's wanted then will need doing for everything +// not just in effects. eg. 'attack', 'effect1p1', 'flip', yadda yadda +let triggerQueue = []; +let triggerId = 1; // So any other effects, etc. queued for a destroyed card can be removed at once +let triggerDone = []; // The triggers that have completed +let triggerQueueTargets = []; // Whatever was targetted by the effect, etc. in triggerQueue (for ref by effectStep, etc) + // Passive effects (just does stuff) let flight = {}; let reach = {}; let equipped = {}; // Entity x has [a,b,c] equipped to it +// Events (when these occur check if this is part of an effect trigger) +// startOfGame, startOfTurn, endOfTurn +// cardSummoned, cardRecruited, effectTriggered +// etc. + + // Trigger types const triggerTypes = { 'tap': 1, @@ -283,7 +296,7 @@ function getEffect(itemKey, effectIndex){ } // Get all the targets for effect step, so they can be targgeted // by the effect/selected by the player -function getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement, playerId){ +function getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement, playerId, effectTriggerId = null){ // Get Effect let effect = getEffect(itemKey, effectIndex); @@ -303,24 +316,71 @@ function getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement // TODO: Not 100% sure how to keep track. May need a var for each item in previous steps // or previous chains so they can be accessed, and used // If itemFromStep, return the itemKeys of the items selected from a previous step - /* - if(target['itemFromStep'] == null){ - // So something from step 1 needs to be selected by this. + + console.log('HELLOO'); + console.log(step['target']); + + // TODO: If target is 'itemFromStep', then get whatever item(s) were selected in + // said step, and add them to the thing + // TODO TODO + + // If the target requirement is something from a previous step + // Check if target criteria is something from another step + let isFromStep = false; + step['target'].forEach((target) => { + if(target['itemFromStep'] != null){ + + console.log(target['itemFromStep']); + console.log(effectTriggerId); + //console.log(triggerQueue); + //console.log(triggerDone); + + // Loop all triggers that have been done (completed) + triggerDone.forEach((oldTrigger) => { + + // If not same triggerId, or the effectStep is not that of itemFromStep + if(oldTrigger['triggerId'] != effectTriggerId || target['itemFromStep'] != oldTrigger['effectStep']){ + return isFromStep = false; + } + + console.log(oldTrigger); + return isFromStep = oldTrigger['targets']; + + }); + + } + + }); + // If above returns a step, need to get the target(s) from that prior step to use a targets now + if(isFromStep){ + console.log(isFromStep); + console.log('AAAAAAAAAAAAAAAAAAAAAA'); } - */ - + + let items = []; + // If from a previous step, loop those + if(isFromStep !== null && isFromStep !== undefined && isFromStep !== false){ items = isFromStep; } + // If not, get all the related doodads + else{ + items = board.getItems(fromBoardElement, playerId, null, null); + } + + // Loop the boardlements and compare the colours, classes, etc. to match effect target criteria // boardElement, playerId, cardStatus, listPosition - let items = board.getItems(fromBoardElement, playerId, null, null); // TODO: maybe 'from top of deck, or if tapped' for(let item = 0; item < items.length; item++){ // TODO: MAYBE ADD THE COLOUR/PASSIVE CHECKS to the getItems itself let itemKey = items[item]; - console.log(cardColours[itemKey]); + //console.log(cardColours[itemKey]); // If the item from getItems meets the criterias of target DB step['target'].forEach((target) => { + //console.log(target); + //console.log(triggerDone); + + // Check the class the same for target, and item // If targetDB has null this means 'any' so is always correct // Check Class (TODO: mixed classes, colours, etc ie select 1 red+blue card) @@ -370,11 +430,102 @@ function getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement } +function addTargettedCardsToQueueEvent(queueTriggerId, triggerStep, targets){ + + console.log('ADD TARGETTED TO QUEUED TRIGGER'); + console.log(queueTriggerId); + console.log(triggerStep); + console.log(targets); + + //console.log(triggerQueue[queueTriggerId]); + //console.log(targets); + + console.log(triggerQueue); + + triggerQueue.forEach((queued) => { + console.log(queued); + if( + queued.triggerId == queueTriggerId + && + queued.effectStep == triggerStep + ){ + console.log('THIS SHOULD HAVE TARGETS ADDED'); + queued['targets'] = targets; + } + }); + + console.log(triggerQueue); + +} + + +function queueEffect(itemKey, effectIndex){ + + let effect = getEffect(itemKey, effectIndex); + if(effect == false){ return false; } + + // TODO: Sort steps by stepOrder incase wrong in DB, etc. + for (const [stepKey, step] of Object.entries(effect['step'])) { + triggerQueue.push( + // event, item, effectId, target, triggerId (commented atop) + { + 'event': 'effect' // Which event. attack, destroy, effect, etc. + ,'item': itemKey // Which card is doing event + ,'effectIndex': effectIndex // Which effect (if effect) + ,'effectStep': stepKey // Which effect (if effect) + ,'target': null // ? + ,'triggerId': triggerId + ,'targets': null // ? + } + ); + } + // Increment triggerId + triggerId++; + console.log(triggerQueue); +} + +function doNextInQueue(){ + + if(triggerQueue.length <= 0){ + console.log('Nothing in queue, doing next phase/event/whatever'); + } + + // If effect, trigger it (should already have paid the trigger costs) + switch(triggerQueue[0].event){ + case 'effect': + // Do the effect + doEffect(triggerQueue[0].item, triggerQueue[0].effectIndex, triggerQueue[0].effectStep, triggerQueue[0].triggerId); + break; + + default: + alert('Error in doNextInQueue'); + return 0; + break; + + + } + + // Add to completed triggers + triggerDone.push(triggerQueue[0]); + + // And remove from the triggerQueue (first index) + triggerQueue.shift(); + +} +function loopTriggerQueue(){ + + while(triggerQueue.length > 0){ + doNextInQueue(); + } + +} // Recusively call doEffect until each is done? // Once recruit (play from hand) is triggered, need to allow user to select // then when done move to next step -function doEffect(itemKey, effectIndex, effectStep = 1){ +function doEffect(itemKey, effectIndex, effectStep, effectTriggerId){ + + console.log('doEffect'); let effect = getEffect(itemKey, effectIndex); if(effect == false){ return false; } @@ -386,35 +537,98 @@ function doEffect(itemKey, effectIndex, effectStep = 1){ // For each step, activate the correct effect type on // the correct targets. + + + // Get targets TODO: Use this instead of each case having it + //let targets = getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement, playerId, effectTriggerId); switch (step['basicEffectId']){ // Recruit case 4: - recruitCard(itemKey, effectIndex, effectStep, step['amount']); + recruitCard(itemKey, effectIndex, effectStep, step['amount'], effectTriggerId); break; // Give Flight case 5: - console.log('GIVE FLIGHT'); + givePassive(itemKey, effectIndex, effectStep, step['amount'], effectTriggerId, 'flight'); break; } + // Add the selected targets to the queuedItem so it can be referred to in future + // Now do the next step, if there's another in the effect + // Commented out while testing triggerQueue + /* if(effect['step'][effectStep++] !== undefined){ doEffect(itemKey, effectIndex, effectStep++); } + */ +} + +function givePassive(itemKey, effectIndex, effectStep, targetAmount, effectTriggerId, passive){ + + console.log('GIVE PASSIVE: '+passive); + + let effect = getEffect(itemKey, effectIndex); + if(effect == false){ return false; } + + // Get the step + let step = effect['step'][effectStep]; + if(step == undefined){ return false; } + + console.log(step); + //return false; + + // TODO: null, 0 are boardElement/playerId (for now) need to redo, rethink + console.log('HELP ME'); + let targets = getEffectStepTargets(itemKey, effectIndex, effectStep, null, 0, effectTriggerId); + console.log(targets); + + if(targetAmount > 0 && targets.length > 0){ + + // TODO: better, and if just one thing omit, and do automatically + let selectedTarget = prompt("Select a card to gain flight: \n"+targets, targets[0]); + // User didn't select anything + if (selectedTarget == null || selectedTarget == "") { + alert('No card recruited, c ya'); + return false; + } + // User inputted card not in ID (obv temp, as will be done in game UI) + // Huh I forgot why this is written like this, maybe it doens't work? + if (!selectedTarget.includes(selectedTarget)){ + alert('Not in selection'); + return false; + } + + + // Remove the card from the selection (in case there's another in this loop) + targets.splice(targets.indexOf(selectedTarget), 1); + + // Give the passive + if(passive == 'flight'){ + giveFlight(selectedTarget); + } + + } + + } -function recruitCard(itemKey, effectIndex, effectStep, targetAmount){ +function removePassive(){} +function hasPassive(){} + +function recruitCard(itemKey, effectIndex, effectStep, targetAmount, effectTriggerId = null){ console.log('RECRUIT'); let fromBoardElement = 'hand'; // FOR NOW, JUST TO TEST, THIS WILL BE PER BASIC EFFECT let playerId = 0; - let targets = getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement, playerId); - console.log(targets); + let targets = getEffectStepTargets(itemKey, effectIndex, effectStep, fromBoardElement, playerId, effectTriggerId); + let targettedCards = []; + + //console.log(targets); if(targetAmount > 0 && targets.length > 0){ @@ -430,15 +644,19 @@ function recruitCard(itemKey, effectIndex, effectStep, targetAmount){ return false; } - // Remove the card from the selection + // Remove the card from the selection (in case there's another) targets.splice(targets.indexOf(selectedTarget), 1); + // Add to targetted (for future ref) + targettedCards.push(selectedTarget); + // Play recruited card - // TODO: Maybe needs a new function 'playRecruitedCard' for different event triggers - board.playCardToBoard(listPosition[itemKey], boardElement[itemKey], 'board', 0, 0, 1); + // TODO: Need to pass player/listPosition better? + board.playRecruitedCard(player[selectedTarget], listPosition[selectedTarget]); } + addTargettedCardsToQueueEvent(effectTriggerId, effectStep, targettedCards); } From 3e512459cf5ddc66304f162e57fb0000e9808e15 Mon Sep 17 00:00:00 2001 From: Nathan Date: Mon, 28 Oct 2024 20:36:51 +0000 Subject: [PATCH 16/18] Add passives to cards via DB --- cardGen.js | 68 ++++++++++++++++++++++++++++++++++-- database.js | 18 ++++++++++ db/281024_2036_migration.sql | 3 ++ public/board.js | 4 +++ 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 db/281024_2036_migration.sql diff --git a/cardGen.js b/cardGen.js index eac3737..9adaf11 100644 --- a/cardGen.js +++ b/cardGen.js @@ -251,6 +251,28 @@ function buildCardEffects(effects, effectSteps, effectTriggers){ } +function getCardPassive(){ + const cPromise = new Promise((resolve, reject) => { + database.dbGetPassive().then(data => { + + let passives = []; + + data.forEach((passive) => { + + passives.push({ + 'cardId': passive.cardId, + 'passiveId': passive.passiveId, + }); + + }); + console.log(passives); + resolve(passives); + + }) + .catch(err => { throw err; }) + }); + return cPromise; +} //getCardColourRequirement(); // Then effects which will have effects with parent triggers, and unit type checks @@ -299,12 +321,13 @@ function requestDeck(itemData = null){ // Change SQL to accept for just the cards passed // Get each cards data, colourReqs, and classes - const [cards, cardClasses, cardColourRequirements, cardManaColours] = + const [cards, cardClasses, cardColourRequirements, cardManaColours, cardPassives] = await Promise.all([ getCards(), getCardClasses(), getCardColourRequirement(), getCardManaColour(), + getCardPassive(), ]); // ^^^^ Classes async? Can pass the cardsIds, then loop classes, if the class cardId @@ -336,7 +359,7 @@ function requestDeck(itemData = null){ // Build the cardData (maybe do all the components here too) const [builtCards] = await Promise.all([ - buildCards(cards, cardClasses, cardColourRequirements, cardManaColours, cardEffects), + buildCards(cards, cardClasses, cardColourRequirements, cardManaColours, cardEffects, cardPassives), ]); //console.log(builtCards); @@ -395,6 +418,9 @@ function requestDeck(itemData = null){ let cardSprite = {}; // Maybe from DB? let cardManaColour = {}; // The card colour value when played in mana zone let cardEffect = {}; + // Passive + let flight = {}; + let reach = {}; // TODO: Set the player. For now will do this in front-end as testing currently @@ -465,6 +491,28 @@ function requestDeck(itemData = null){ if(cardData[itemCount].effect.length > 0){ cardEffect[itemCount] = cardData[itemCount].effect; } + + // Add each passive + if(cardData[itemCount].passive.length > 0){ + //console.log(cardData[itemCount].passive); + for(let i = 0; i < cardData[itemCount].passive.length; i++){ + + switch (cardData[itemCount].passive[i]){ + + // Flight + case 1: + flight[itemCount] = itemCount; + break; + + // Reach + case 2: + reach[itemCount] = itemCount; + break; + + } + + } + } itemCount++; // Increment item to not overwrite @@ -489,6 +537,8 @@ function requestDeck(itemData = null){ itemData.cardSprite = cardSprite; itemData.cardManaColour = cardManaColour; itemData.cardEffect = cardEffect; + itemData.flight = flight; + itemData.reach = reach; // item, itemCount, deckData, cardData, boardElement //console.log(cardData); @@ -514,7 +564,7 @@ function requestDeck(itemData = null){ // point to see. For now DB, and generating is ok, as still working on it } -function buildCards(cards, cardClasses, cardColourRequirements, cardManaColours, cardEffects){ +function buildCards(cards, cardClasses, cardColourRequirements, cardManaColours, cardEffects, cardPassives){ console.log(cardColourRequirements); const dPromise = new Promise((resolve, reject) => { @@ -537,6 +587,7 @@ function buildCards(cards, cardClasses, cardColourRequirements, cardManaColours, rarity: card.cardRarity, effect: [], cardClass: [], + passive: [], }; // Give the card an easily accessible Id for compares // and to add to the cardItem being built @@ -608,6 +659,17 @@ function buildCards(cards, cardClasses, cardColourRequirements, cardManaColours, } + // Add card mana colours (colour value when played in mana zone) + cardPassives.forEach((passive) => { + + // Check the card exists (it should always, but don't want jank) + if(passive.cardId in builtCards){ + // Add the colours to the class array (cards can have multiple) + builtCards[passive.cardId]['passive'].push(passive.passiveId); + } + + }); + resolve(builtCards); }); diff --git a/database.js b/database.js index 54a99d2..8f89c93 100644 --- a/database.js +++ b/database.js @@ -205,6 +205,23 @@ function dbGetEffectTrigger(){ return ePromise; } +// Passive stuff +function dbGetPassive(){ + const pPromise = new Promise((resolve, reject) => { + let sql = `SELECT + cardId + ,passiveId + FROM card_passive + `; + + con.query(sql, function (err, result, fields) { + if (err) { throw err; reject(new Error(err)); } + resolve(result); + }); + }); + return pPromise; +} + module.exports = { connect, disconnect // Testing, and trailing @@ -217,4 +234,5 @@ module.exports = { , dbGetEffect , dbGetEffectStep , dbGetEffectTrigger + , dbGetPassive }; diff --git a/db/281024_2036_migration.sql b/db/281024_2036_migration.sql new file mode 100644 index 0000000..5b5b09e --- /dev/null +++ b/db/281024_2036_migration.sql @@ -0,0 +1,3 @@ +INSERT INTO `card_passive` (`id`, `cardId`, `passiveId`) VALUES (1, 1, 1); +INSERT INTO `card_passive` (`id`, `cardId`, `passiveId`) VALUES (2, 5, 2); + diff --git a/public/board.js b/public/board.js index 8023be2..afc3449 100644 --- a/public/board.js +++ b/public/board.js @@ -1236,6 +1236,10 @@ function loadBoard(data) { cardManaColour = data.cardManaColour; cardEffect = data.cardEffect; + // Passives + flight = data.flight; + reach = data.reach; + // TODO: JANK IN, CHANGE CODE TO USE NEW ARRAY!! // Temp jank, set colour to first colour req. for(let i = 0; i < itemCount; i++){ From a70f052780cd1a2e3184afc6c578c8dda250374b Mon Sep 17 00:00:00 2001 From: Nathan Date: Mon, 28 Oct 2024 22:58:49 +0000 Subject: [PATCH 17/18] Add taunt passive --- db/281024_2257_migration.sql | 2 ++ public/board.js | 4 ++++ public/debug.js | 26 ++++++++++++++++++++++++-- public/effect.js | 18 ++++++++++++++++++ public/index.html | 1 + 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 db/281024_2257_migration.sql diff --git a/db/281024_2257_migration.sql b/db/281024_2257_migration.sql new file mode 100644 index 0000000..508c0e9 --- /dev/null +++ b/db/281024_2257_migration.sql @@ -0,0 +1,2 @@ +INSERT INTO `passive` (`id`, `passiveName`, `passiveDescription`) VALUES (3, 'Taunt', 'Must be targetted by attacks'); + diff --git a/public/board.js b/public/board.js index afc3449..f71ec43 100644 --- a/public/board.js +++ b/public/board.js @@ -368,6 +368,10 @@ class Board{ this.printCenterText('R', positionX + (10*passiveCount), positionY); passiveCount++; } + if(itemKey in taunt){ + this.printCenterText('T', positionX + (10*passiveCount), positionY); + passiveCount++; + } } printColourRequirements(itemKey){ // Set the size(s) diff --git a/public/debug.js b/public/debug.js index 6074130..a71caf4 100644 --- a/public/debug.js +++ b/public/debug.js @@ -60,10 +60,25 @@ function debugEffectFunction(damageAmount = null, targetId = null, targetId2 = n console.log(targetId+' Reach: '+reach[targetId]); } + if(effect == 'taunt'){ + console.log(targetId+' Taunt: '+taunt[targetId]); + + console.log(effectAddRemove); + + if(effectAddRemove == 'remove'){ + removeTaunt(targetId); + }else{ + giveTaunt(targetId); + } + + console.log(targetId+' Taunt: '+reach[targetId]); + } if(effect == 'draw'){ drawCard(damageAmount, targetPlayer); } if(effect == 'equip'){} + + board.drawBoard(); } @@ -89,6 +104,8 @@ function debugTriggerFunction(targetId = null, trigger = null, triggerAmount = n if(trigger == 'pay'){ triggerPay(triggerAmount); } + + board.drawBoard(); } // Builds console log for card effect (inc. @@ -165,9 +182,9 @@ function debugEffectCanTrigger(){ if(doEffectTriggers(ecTriggerTargetId, ecTriggerIndex, true) != true){ console.log('Effect cannot be triggered'); - queueEffect(ecTriggerTargetId, ecTriggerIndex); + //queueEffect(ecTriggerTargetId, ecTriggerIndex); //doNextInQueue(); - loopTriggerQueue(); + //loopTriggerQueue(); return false; } @@ -179,7 +196,12 @@ function debugEffectCanTrigger(){ // Then queue the effects to happen (queued so they can be chained/countered) queueEffect(ecTriggerTargetId, ecTriggerIndex); + + // Do all effects in queue (for debug), in actual will do one, then allow chain triggers, etc. + loopTriggerQueue(); } + board.drawBoard(); + } diff --git a/public/effect.js b/public/effect.js index a006713..beaa3be 100644 --- a/public/effect.js +++ b/public/effect.js @@ -8,6 +8,7 @@ let triggerQueueTargets = []; // Whatever was targetted by the effect, etc. in t // Passive effects (just does stuff) let flight = {}; let reach = {}; +let taunt = {}; let equipped = {}; // Entity x has [a,b,c] equipped to it @@ -30,6 +31,7 @@ const basicEffects = { 3: 'Hurt', 4: 'Recruit', 5: 'Give Flight', + 6: 'Taunt', }; @@ -55,6 +57,17 @@ function removeReach(card){ } return false; } +function giveTaunt(card){ + taunt[card] = true; +} +function removeTaunt(card){ + // If the card has flight delete entity component + if(card in taunt){ + delete taunt[card]; + return true; + } + return false; +} // Active function equip(){ @@ -554,6 +567,11 @@ function doEffect(itemKey, effectIndex, effectStep, effectTriggerId){ givePassive(itemKey, effectIndex, effectStep, step['amount'], effectTriggerId, 'flight'); break; + // Give Taunt + case 6: + givePassive(itemKey, effectIndex, effectStep, step['amount'], effectTriggerId, 'taunt'); + break; + } // Add the selected targets to the queuedItem so it can be referred to in future diff --git a/public/index.html b/public/index.html index b2cfa00..e34efda 100644 --- a/public/index.html +++ b/public/index.html @@ -80,6 +80,7 @@ + From 1e82ae04b948515d5d9c189f89e51b82690425e6 Mon Sep 17 00:00:00 2001 From: Nathan Date: Tue, 29 Oct 2024 00:12:02 +0000 Subject: [PATCH 18/18] Add combat logic for taunt/flight/reach passives --- public/board.js | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/public/board.js b/public/board.js index f71ec43..e3c0d4f 100644 --- a/public/board.js +++ b/public/board.js @@ -1045,6 +1045,12 @@ class Board{ let atkAttacker = this.attackOf(itemAttacking); let atkDefender = this.attackOf(itemDefending); + // Check if the attack can target the defender + if(!this.canAttackDefender(itemAttacking, itemDefending)){ + alert('Cannot target card.'); + break; + } + // Does Attacker kill Defender if(atkDefender <= atkAttacker){ this.sendToGrave(itemDefending); @@ -1062,6 +1068,13 @@ class Board{ break; case 'shield': + + // Check shield can be targetted (not defended by taunt/block unit) + if(!this.canAttackDirect(itemAttacking, player[itemDefending])){ + alert('Cannot attack shield for some reason'); + break; + } + // If the shield is tapped 'destroy' it if(this.isTapped(itemDefending)){ if(!this.destroyShield(itemDefending)){ @@ -1081,6 +1094,58 @@ class Board{ this.drawBoard(); } + canAttackDefender(itemAttacking, itemDefending){ + + // Currently all there is is that flight cannot + // be attacked by anything but flight and reach + + // If defender has flight + if(flight[itemDefending]){ + // And attack doesn't have either flight or reach + if(flight[itemAttacking] === undefined && reach[itemAttacking] === undefined){ + return false; + } + } + + return true; + + + } + canAttackDirect(itemAttacking, playerDefending){ + + // Defender must not be tapped, as you can ignore tapped units + let itemsToBlock = this.getItems('board', playerDefending, null, null); + for(let item = 0; item < itemsToBlock.length; item++){ + + let defender = itemsToBlock[item]; + + // Defender cannot block if tapped + if(this.isTapped(defender)){ + continue; + } + + // If the defender doesn't have taunt, direct attacks can occur + if(taunt[defender] == undefined){ + continue; + } + + // If the attacked doesn't have flight (or another means of bypassing taunt) + // it can't attack direct + if(!flight[itemAttacking]){ + return false; + } + + // If the unitAttacking has flight, it can be blocked by a taunt+flight + // or giant+flight + if(flight[itemAttacking] && flight[defender]){ + return false; + } + + } + + return true; + + } attackOf(itemKey){ // TODO: Change this to ECSey element when added return cardData[itemKey];