import { Hero6Utility } from "./hero6-utility.js"; /* -------------------------------------------- */ export class Hero6CombatTracker extends CombatTracker { /* -------------------------------------------- */ static get defaultOptions() { let path = "systems/fvtt-hero-system-6/templates/apps/combat-tracker.hbs"; return foundry.utils.mergeObject(super.defaultOptions, { template: path, }); } } /* -------------------------------------------- */ export class Hero6Combat extends Combat { /* -------------------------------------------- */ static ready() { Hooks.on("getCombatTrackerEntryContext", (html, options) => { Hero6Combat.pushMenuOptions(html, options); }); game.combat.settings.resource = "characteristics.spd.value"; } /* -------------------------------------------- */ static pushMenuOptions(html, options) { let newOpt for (let i = 0; i < options.length; i++) { let option = options[i]; if (option.name == 'COMBAT.CombatantReroll') { // Replace ! option.name = "Hold/Unhold action"; option.condition = true; option.icon = ''; option.callback = target => { Hero6Combat.holdAction(target.data('combatant-id')); } //newOpt = duplicate(option) } } //options.push(newOpt) } /* -------------------------------------------- */ holdAction(combatantId) { this.rebuildInitiative() console.log("Rebuilding.....") /*const combatant = game.combat.combatants.get(combatantId) if (combatant.actor.holdAction()) { let id = combatant._id || combatant.id let name = combatant.actor.name + " (H)" await game.combat.updateEmbeddedDocuments("Combatant", [{ _id: id, name: name, holdAction: true }]); }*/ } /* -------------------------------------------- */ abortAction(actorId, abortState) { this.rebuildInitiative() /*const combatant = game.combat.combatants.find(c => c.actor.id == actorId) if (abortState) { let id = combatant._id || combatant.id let name = combatant.actor.name + " (A)" await game.combat.updateEmbeddedDocuments("Combatant", [{ _id: id, name: name }]); }*/ } /* -------------------------------------------- */ constructor(data, context) { super(data, context); this.turnNumber = 0; this.segmentNumber = 12; } /* -------------------------------------------- */ async startCombat() { game.combat.settings.resource = "characteristics.spd.value"; let updList = [] for (let c of this.combatants) { this.computeInitiative(c, updList) await c.actor.cleanCombat() } if (updList.length > 0) { await this.updateEmbeddedDocuments("Combatant", updList); } super.startCombat(); } /* -------------------------------------------- */ forceHold(actor, isHold) { let updList = [] let c = this.combatants.find(c => c.actor._id == actor.id) let name = actor.name + ((isHold) ? " (H)" : "") updList.push({ _id: c.id || c._id, name: name, initiative: actor.getBaseInit(this.segmentNumber) }) this.updateEmbeddedDocuments("Combatant", updList) } /* -------------------------------------------- */ forceAbort(actor, isAbort) { let updList = [] let c = this.combatants.find(c => c.actor._id == actor.id) let name = actor.name + ((isAbort) ? " (A)" : "") updList.push({ _id: c.id || c._id, name: name, initiative: actor.getBaseInit(this.segmentNumber) }) this.updateEmbeddedDocuments("Combatant", updList) } /* -------------------------------------------- */ computeInitiative(c, updList) { let id = c._id || c.id let hasSegment = c.actor.hasPhase(this.segmentNumber) let isOnHold = c.actor.getHoldAction() let isOnAbort = c.actor.getAbortAction() let name = c.actor.name if (hasSegment || isOnHold || isOnAbort) { let baseInit = c.actor ? c.actor.getBaseInit(this.segmentNumber) : 0; if (isOnHold) { if (hasSegment) { // On hold + current segment -> auto-disable on hold c.actor.disableHoldAction() } else { name = c.actor.name + " (H)" } } if (isOnAbort) { name = c.actor.name + " (A)" if ( hasSegment) { c.actor.disableAbortAction() } } updList.push({ _id: id, name: name, initiative: baseInit, holdAction: c.holdAction }) } else { updList.push({ _id: id, name: name, initiative: 0, holdAction: c.holdAction }) } } /* -------------------------------------------- */ async rollInitiative(ids, formula = undefined, messageOptions = {}) { ids = typeof ids === "string" ? [ids] : ids; let updList = [] for (let cId = 0; cId < ids.length; cId++) { const c = this.combatants.get(ids[cId]) this.computeInitiative(c, updList) } if (updList.length > 0) { await this.updateEmbeddedDocuments("Combatant", updList); } return this; } /* -------------------------------------------- */ async rebuildInitiative() { let updList = [] for (let c of this.combatants) { this.computeInitiative(c, updList) } if (updList.length > 0) { await this.updateEmbeddedDocuments("Combatant", updList); console.log("Rebuild INIT", updList) for (let c of updList) { if (c.initiative != 0) { return true } } } return false } /* -------------------------------------------- */ async nextRound() { let hasCombatants = false let nextRound = this.round let advanceTime = 0 let turn = this.turn === null ? null : 0; // Preserve the fact that it's no-one's turn currently. let turnData = this.getFlag("world", "hero6-turn-data") console.log("Next round called....", nextRound, turnData) while (!hasCombatants) { turn = turn; // Preserve the fact that it's no-one's turn currently. if (this.settings.skipDefeated && (turn !== null)) { turn = this.turns.findIndex(t => !t.isDefeated); if (turn === -1) { ui.notifications.warn("COMBAT.NoneRemaining", { localize: true }); turn = 0; } } advanceTime = Math.max(this.turns.length - this.turn, 0) * CONFIG.time.turnTime; advanceTime += CONFIG.time.roundTime; nextRound = nextRound + 1; console.log("Next round called....2", nextRound, turnData) turnData = this.getFlag("world", "hero6-turn-data") if (!turnData) { turnData = { turnNumber: 0, segmentNumber: 12 } this.setFlag("world", "hero6-turn-data", turnData) } turnData = duplicate(turnData) turnData.segmentNumber += 1 if (turnData.segmentNumber > 12) { turnData.segmentNumber = 1 turnData.turnNumber++ } await this.setFlag("world", "hero6-turn-data", turnData) this.turnNumber = turnData.turnNumber; this.segmentNumber = turnData.segmentNumber; console.log("Next round called....3", nextRound, turnData) // Re-compute init of actors hasCombatants = await this.rebuildInitiative() console.log("Going round....", nextRound, hasCombatants) } // Update the document, passing data through a hook first const updateData = { round: nextRound, turn: turn, segmentNumber: turnData.segmentNumber, turnNumber: turnData.turnNumber }; const updateOptions = { advanceTime, direction: 1 }; Hooks.callAll("combatRound", this, updateData, updateOptions); return this.update(updateData, updateOptions); } /* -------------------------------------------- */ async _onCreateEmbeddedDocuments(type, documents, result, options, userId) { //console.log("Added...") await super._onCreateEmbeddedDocuments(type, documents, result, options, userId) await this.rebuildInitiative() } /* -------------------------------------------- _onUpdate(changed, options, userId) { }*/ /* -------------------------------------------- */ static async checkTurnPosition() { while (game.combat.turn > 0) { await game.combat.previousTurn() } } }