import { SoSCardDeck } from "./sos-card-deck.js"; import { SoSUtility } from "./sos-utility.js"; import { SoSFlipDialog } from "./sos-flip-dialog.js"; import { SoSDialogCombatActions } from "./sos-dialog-combat-actions.js"; /* -------------------------------------------- */ export class SoSCombat extends Combat { /* -------------------------------------------- */ requestActions() { if ( game.user.isGM && !this.actionsRequested) { console.log("REQUEST ACTIONS !!!"); this.actionsRequested = true; this.phaseSetup = {}; // Reset each new round/update for( let combatant of this.combatants) { this.setInitiative(combatant._id, -1 ); // Reset init let uniq = randomID(16); if ( combatant.players[0]) { // A player controls this combatant -> message ! ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${combatant.actor.data.name} for round ${this.round} !
Declare actions`, whisper: [ combatant.players[0].data._id] } ); } else { ChatMessage.create( { content: `New round ! Click on the button below to declare the actions of ${combatant.actor.data.name} for round ${this.round} !
Declare actions`, whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); } } } } /* -------------------------------------------- */ async nextRound() { this.actionsRequested = false; super.nextRound(); } /* -------------------------------------------- */ gotoNextTurn() { this.phaseNumber -= 1; if ( this.phaseNumber <= 0) { this.applyConsequences(); this.nextRound(); // Auto-switch to next round } else { this.nextTurn(); } } /* -------------------------------------------- */ async nextTurn() { console.log("Going to phase !", this.phaseNumber ); // Get all actions for this phase let phaseIndex = this.phaseNumber - 1; let actionList = []; let actionMsg = `

Actions for phase ${this.phaseNumber}

`; for (let combatantId in this.phaseSetup ) { let actionData = this.phaseSetup[combatantId]; if ( actionData.phaseArray[phaseIndex].name != 'No Action' ) { let combatant = this.combatants.find( comb => comb._id == actionData.combatantId); actionList.push( { combatant: combatant, action: actionData.phaseArray[phaseIndex], isDone: false }); actionMsg += `
${combatant.actor.name} is going to : ${actionData.phaseArray[phaseIndex].name}`; } } if ( actionList.length == 0) { actionMsg += "
No actions for the phase !"; this.gotoNextTurn(); } // Display a nice message ChatMessage.create( { content: actionMsg }); // Now push specific messages for ( let action of actionList) { let uniq = randomID(16); action.uniqId = uniq; // Easy tracking with chat messages if ( action.combatant.players[0]) { // A player controls this combatant -> message ! ChatMessage.create( { content: `Phase ${this.phaseNumber} ! ${action.combatant.actor.data.name} must perform a ${action.action.name} action. When done, click on the button below to close the action. Action is done !`, whisper: [ action.combatant.players[0].data._id] } ); } else { ChatMessage.create( { content: `Phase ${this.phaseNumber} ! ${action.combatant.actor.data.name} must perform a ${action.action.name} action.
When done, click on the button below to close the action. Action is done !`, whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); } } // Save for easy access this.currentActions = actionList; } /* -------------------------------------------- */ applyConsequences( ) { if (game.user.isGM ) { for( let combatant of this.combatants) { let bleeding = combatant.actor.data.items.find( item => item.type == 'consequence' && item.name == 'Bleeding'); combatant.actor.applyConsequenceWound( bleeding.data.severity, "bleeding" ); } } } /* -------------------------------------------- */ closeAction( uniqId) { // Delete message ! const toDelete = game.messages.filter(it => it.data.content.includes( uniqId )); toDelete.forEach(it => it.delete()); let action = this.currentActions.find( _action => _action.uniqId == uniqId ); if (action) { action.isDone = true; let filtered = this.currentActions.filter( _action => action.isDone ); if ( filtered.length == this.currentActions.length) { // All actions closed ! console.log("Going next turn !!!"); this.gotoNextTurn(); } } } /* -------------------------------------------- */ getPhaseRank( actionConf) { for (let i=2; i>=0; i--) { let action = actionConf.phaseArray[i]; if (action.name != "No Action") { return i+1; } } return 0; } /* -------------------------------------------- */ getAPFromActor( actorId ) { for( let combatant of this.combatants) { //console.log(combatant); if ( combatant.actor.data._id == actorId ) { let phase = this.phaseSetup[combatant._id]; return phase.remainingAP; } } return 0; } /* -------------------------------------------- */ decreaseAPFromActor( actorId ) { for( let combatant of this.combatants) { //console.log(combatant); if ( combatant.actor.data._id == actorId ) { let phase = this.phaseSetup[combatant._id]; phase.remainingAP -= 1; if ( phase.remainingAP < 0 ) phase.remainingAP = 0; } } } /* -------------------------------------------- */ async setupActorActions(actionConf) { console.log("Setting combat for phase : ", actionConf, actionConf.uniqId); // Delete message ! const toDelete = game.messages.filter(it => it.data.content.includes( actionConf.uniqId )); console.log("MESSAGE : ", toDelete); toDelete.forEach(it => it.delete()); if ( !this.phaseSetup) this.phaseSetup = {}; // Opportunistic init // Keep track this.phaseSetup[actionConf.combatantId] = actionConf; console.log( this.combatants ); //let combatant = this.combatants.find( comb => comb._id == actionConf.combatantId); await this.setInitiative( actionConf.combatantId, this.getPhaseRank( actionConf ) ); let actionsDone = true for( let combatant of this.combatants) { if ( combatant.initiative == -1 ) actionsDone = false; } if ( actionsDone ) { this.actionsRequested = false; ChatMessage.create( { content: `Action declaration has been completed ! Now proceeding with actions.`, whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); this.phaseNumber = 3; this.nextTurn(); } } }