You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cardGame/public/effect.js

445 lines
11 KiB
JavaScript

// 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);
}
}