mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-04-21 23:13:39 +02:00
Reworked summon action and clowncar functionality to work with levels (#1791)
This commit is contained in:
parent
94f1fbdd9b
commit
3ec013ff50
4 changed files with 79 additions and 130 deletions
|
|
@ -1,104 +1,68 @@
|
|||
/**
|
||||
* A singleton class that handles preview tokens.
|
||||
* A singleton class that handles creating tokens.
|
||||
*/
|
||||
|
||||
export default class DhTokenManager {
|
||||
#activePreview;
|
||||
#actor;
|
||||
#resolve;
|
||||
|
||||
/**
|
||||
* Create a template preview, deactivating any existing ones.
|
||||
* @param {object} data
|
||||
* Create a token previer
|
||||
* @param {Actor} actor
|
||||
* @param {object} tokenData
|
||||
*/
|
||||
async createPreview(actor, tokenData) {
|
||||
this.#actor = actor;
|
||||
const token = await canvas.tokens._createPreview(
|
||||
{
|
||||
...actor.prototypeToken,
|
||||
displayName: 50,
|
||||
...tokenData
|
||||
},
|
||||
{ renderSheet: false, actor }
|
||||
const tokenSizes = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes;
|
||||
if (actor?.system.metadata.usesSize) {
|
||||
const tokenSize = tokenSizes[actor.system.size];
|
||||
if (tokenSize && actor.system.size !== CONFIG.DH.ACTOR.tokenSize.custom.id) {
|
||||
tokenData.width = tokenSize;
|
||||
tokenData.height = tokenSize;
|
||||
}
|
||||
}
|
||||
|
||||
return await canvas.tokens.placeTokens(
|
||||
[
|
||||
{
|
||||
...actor.prototypeToken.toObject(),
|
||||
actorId: actor.id,
|
||||
displayName: 50,
|
||||
...tokenData
|
||||
}
|
||||
],
|
||||
{ create: false }
|
||||
);
|
||||
|
||||
this.#activePreview = {
|
||||
document: token.document,
|
||||
object: token,
|
||||
origin: { x: token.document.x, y: token.document.y }
|
||||
};
|
||||
|
||||
this.#activePreview.events = {
|
||||
contextmenu: this.#cancelTemplate.bind(this),
|
||||
mousedown: this.#confirmTemplate.bind(this),
|
||||
mousemove: this.#onDragMouseMove.bind(this)
|
||||
};
|
||||
|
||||
canvas.stage.on('mousemove', this.#activePreview.events.mousemove);
|
||||
canvas.stage.on('mousedown', this.#activePreview.events.mousedown);
|
||||
canvas.app.view.addEventListener('contextmenu', this.#activePreview.events.contextmenu);
|
||||
}
|
||||
|
||||
/* Currently intended for using as a preview of where to create a token. (note the flag) */
|
||||
async createPreviewAsync(actor, tokenData = {}) {
|
||||
return new Promise(resolve => {
|
||||
this.#resolve = resolve;
|
||||
this.createPreview(actor, { ...tokenData, flags: { daggerheart: { createPlacement: true } } });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the movement of the token preview on mousedrag.
|
||||
* @param {mousemove Event} event
|
||||
* Creates new tokens on the canvas by placing previews.
|
||||
* @param {object} tokenData
|
||||
* @param {object} options
|
||||
*/
|
||||
#onDragMouseMove(event) {
|
||||
event.stopPropagation();
|
||||
const { moveTime, object } = this.#activePreview;
|
||||
const update = {};
|
||||
async createTokensWithPreview(tokensData, { elevation } = {}) {
|
||||
const scene = game.scenes.get(game.user.viewedScene);
|
||||
if (!scene) return;
|
||||
|
||||
const now = Date.now();
|
||||
if (now - (moveTime || 0) <= 16) return;
|
||||
this.#activePreview.moveTime = now;
|
||||
const level = scene.levels.get(game.user.viewedLevel);
|
||||
if (!level) return;
|
||||
|
||||
let cursor = event.getLocalPosition(canvas.templates);
|
||||
const createElevation = elevation ?? level.elevation.bottom;
|
||||
for (const tokenData of tokensData) {
|
||||
const previewTokens = await this.createPreview(tokenData.actor, {
|
||||
name: tokenData.tokenPreviewName,
|
||||
level: game.user.viewedLevel,
|
||||
elevation: createElevation,
|
||||
flags: { daggerheart: { createPlacement: true } }
|
||||
});
|
||||
if (!previewTokens?.length) return null;
|
||||
|
||||
Object.assign(update, canvas.grid.getTopLeftPoint(cursor));
|
||||
|
||||
object.document.updateSource(update);
|
||||
object.renderFlags.set({ refresh: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the preview token on right-click.
|
||||
* @param {contextmenu Event} event
|
||||
*/
|
||||
#cancelTemplate(_event, resolved) {
|
||||
const { mousemove, mousedown, contextmenu } = this.#activePreview.events;
|
||||
this.#activePreview.object.destroy();
|
||||
|
||||
canvas.stage.off('mousemove', mousemove);
|
||||
canvas.stage.off('mousedown', mousedown);
|
||||
canvas.app.view.removeEventListener('contextmenu', contextmenu);
|
||||
if (this.#resolve && !resolved) this.#resolve(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a real Actor and token at the preview location and cancels the preview.
|
||||
* @param {click Event} event
|
||||
*/
|
||||
async #confirmTemplate(event) {
|
||||
event.stopPropagation();
|
||||
this.#cancelTemplate(event, true);
|
||||
|
||||
const actor = this.#actor.inCompendium
|
||||
? await game.system.api.documents.DhpActor.create(this.#actor.toObject())
|
||||
: this.#actor;
|
||||
const tokenData = await actor.getTokenDocument();
|
||||
const result = await canvas.scene.createEmbeddedDocuments('Token', [
|
||||
{ ...tokenData.toObject(), x: this.#activePreview.document.x, y: this.#activePreview.document.y }
|
||||
]);
|
||||
|
||||
this.#activePreview = undefined;
|
||||
if (this.#resolve && result.length) this.#resolve(result[0]);
|
||||
await canvas.scene.createEmbeddedDocuments(
|
||||
'Token',
|
||||
previewTokens.map(x => ({
|
||||
...x.toObject(),
|
||||
name: tokenData.actor.prototypeToken.name,
|
||||
displayName: tokenData.actor.prototypeToken.displayName,
|
||||
flags: tokenData.actor.prototypeToken.flags
|
||||
})),
|
||||
{ controlObject: true, parent: canvas.scene }
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue