import { getWorldActor } from '../../../helpers/utils.mjs'; const fields = foundry.data.fields; /** * @import DHSummonAction from '../../action/summonAction.mjs' */ export default class DHSummonField extends fields.SchemaField { /** * Action Workflow order */ static order = 130; constructor(options = {}, context = {}) { const transformFields = { actorUUID: new fields.DocumentUUIDField({ type: 'Actor', required: true }), resourceRefresh: new fields.SchemaField({ hitPoints: new fields.BooleanField({ initial: true }), stress: new fields.BooleanField({ initial: true }) }) }; super(transformFields, options, context); } /** * Runs the execute. This is run on behalf of DHSummonAction. * @todo move this function to be on the summon action. * @this DHSummonAction */ static async execute() { if (!this.transform.actorUUID) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.noTransformActor')); return false; } const baseActor = await foundry.utils.fromUuid(this.transform.actorUUID); if (!baseActor) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.transformActorMissing')); return false; } if (!canvas.scene) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.canvasError')); return false; } const activeTokens = this.actor.getActiveTokens(false, true); const controlledMatchingTokens = canvas.tokens.controlled .filter(x => x.actor && x.actor.uuid === this.actor.uuid) .map(x => x.document); /** @type {typeof game.system.api.documents.DhToken | null} */ const token = this.actor.token ?? ( activeTokens.length === 1 ? activeTokens[0] : (controlledMatchingTokens.length === 1 ? controlledMatchingTokens[0] : null) ); if (!this.actor.token && !token) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.linkedSelectedError')); return false; } if (!token) { ui.notifications.warn(game.i18n.localize('DAGGERHEART.ACTIONS.TYPES.transform.prototypeError')); return false; } const actor = await getWorldActor(baseActor); const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes; const tokenSize = actor?.system.metadata.usesSize ? tokenSizes[actor.system.size] : actor.prototypeToken.width; const prototypeTokenData = actor.prototypeToken.toObject(); const createdToken = (await canvas.scene.createEmbeddedDocuments( 'Token', [{ ...prototypeTokenData, actorId: actor.id, x: token.x, y: token.y, width: tokenSize, height: tokenSize, level: game.user.viewedLevel, elevation: token.elevation }], { controlObject: true, parent: canvas.scene } ))[0]; /* Swap out previous combatant for a new one if applicable */ if (token.combatant) { const combatantWasSpotlighted = game.combat.turn === game.combat.combatants.contents .sort(game.combat._sortCombatants) .map(x => x.id) .indexOf(token.combatant.id); /* Batching combatants update to avoid jumpy UI with multiple rerenders */ const batch = [ { action: 'create', documentName: 'Combatant', data: [{ tokenId: createdToken.id, sceneId: createdToken.parent.id, actorId: createdToken.actorId, hidden: createdToken.hidden }], parent: game.combat }, { action: 'delete', documentName: 'Combatant', ids: [token.combatant.id], parent: game.combat } ]; await foundry.documents.modifyBatch(batch); if (combatantWasSpotlighted) { ui.combat.setCombatantSpotlight(createdToken.combatant.id); } } await token.delete(); const marks = { hitPoints: 0, stress: 0 }; if (!this.transform.resourceRefresh.hitPoints) { marks.hitPoints = Math.min( this.actor.system.resources.hitPoints.value, token.actor.system.resources.hitPoints.max - 1 ); } if (!this.transform.resourceRefresh.stress) { marks.stress = Math.min( this.actor.system.resources.stress.value, token.actor.system.resources.stress.max - 1 ); } if (marks.hitPoints || marks.stress) { createdToken.actor.update({ 'system.resources': { hitPoints: { value: marks.hitPoints }, stress: { value: marks.stress } } }); } const prevPosition = { ...this.actor.sheet.position }; this.actor.sheet.close(); createdToken.actor.sheet.render({ force: true, position: prevPosition }); } }