// Passive effects (just does stuff) let flight = {}; let reach = {}; let equipped = {}; // Entity x has [a,b,c] equipped to it // Trigger types const triggerTypes = { 'tap': 1, 'pay': 2, }; // 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; } function removeFlight(card){ // If the card has flight delete entity component if(card in flight){ delete flight[card]; return true; } 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(){ // Equip card to another unit } function unequip(){ // Remove card from its equipped to unit } function drawCard(drawAmount, player){ board.drawACard(player, drawAmount); } 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' } } // Effect Trigger(s) // Non-event triggers. i.e. these are activated triggers // rather than things such as 'On attack', 'When opponent draws' // When card has been actively tapped function triggerTap(card){ if(canTriggerTap(card) == false){ return false; } board.tapCard(card); console.log('triggerTap'); return true; } // Check a card can actively be tapped, otherwise don't start trigger function canTriggerTap(card){ if(board.isTapped(card)){ return false; } if(boardElement[card] != 'board'){ return false; } console.log('can triggerTap'); return true; } // Pay the mana cost(s) to trigger event 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(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; } // Pay/Activate (all) the triggers function doEffectTriggers(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; } 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); } }