forked from GitHub-Mirrors/foundry-sw5e

System main update to be inline with dnd5e 1.1.1 Added active effects to as many sheets as I thought applicable. Please check loot, I made an attempt but it may be broken All .less .css and actor .html updates were made to the old actors. New actors may be broken with this update removed templates\actors\oldActor\parts\actor-effects.html for newer templates\actors\parts\active-effects.html removed module\apps\cast-dialog, templates\apps\cast-cast.html, and templates\items\cast.html. I do not think they are used, I think they were deprecated when powers were treated as items, if not we can add them back in. **NOTE** REQUIRES Foundry 0.7.6
126 lines
4 KiB
JavaScript
126 lines
4 KiB
JavaScript
import { SW5E } from "../config.js";
|
|
|
|
/**
|
|
* A helper class for building MeasuredTemplates for 5e powers and abilities
|
|
* @extends {MeasuredTemplate}
|
|
*/
|
|
export default class AbilityTemplate extends MeasuredTemplate {
|
|
|
|
/**
|
|
* A factory method to create an AbilityTemplate instance using provided data from an Item5e instance
|
|
* @param {Item5e} item The Item object for which to construct the template
|
|
* @return {AbilityTemplate|null} The template object, or null if the item does not produce a template
|
|
*/
|
|
static fromItem(item) {
|
|
const target = getProperty(item.data, "data.target") || {};
|
|
const templateShape = SW5E.areaTargetTypes[target.type];
|
|
if ( !templateShape ) return null;
|
|
|
|
// Prepare template data
|
|
const templateData = {
|
|
t: templateShape,
|
|
user: game.user._id,
|
|
distance: target.value,
|
|
direction: 0,
|
|
x: 0,
|
|
y: 0,
|
|
fillColor: game.user.color
|
|
};
|
|
|
|
// Additional type-specific data
|
|
switch ( templateShape ) {
|
|
case "cone": // 5e cone RAW should be 53.13 degrees
|
|
templateData.angle = 53.13;
|
|
break;
|
|
case "rect": // 5e rectangular AoEs are always cubes
|
|
templateData.distance = Math.hypot(target.value, target.value);
|
|
templateData.width = target.value;
|
|
templateData.direction = 45;
|
|
break;
|
|
case "ray": // 5e rays are most commonly 1 square (5 ft) in width
|
|
templateData.width = target.width ?? canvas.dimensions.distance;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Return the template constructed from the item data
|
|
return new this(templateData);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Creates a preview of the power template
|
|
*/
|
|
drawPreview() {
|
|
const initialLayer = canvas.activeLayer;
|
|
this.draw();
|
|
this.layer.activate();
|
|
this.layer.preview.addChild(this);
|
|
this.activatePreviewListeners(initialLayer);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Activate listeners for the template preview
|
|
* @param {CanvasLayer} initialLayer The initially active CanvasLayer to re-activate after the workflow is complete
|
|
*/
|
|
activatePreviewListeners(initialLayer) {
|
|
const handlers = {};
|
|
let moveTime = 0;
|
|
|
|
// Update placement (mouse-move)
|
|
handlers.mm = event => {
|
|
event.stopPropagation();
|
|
let now = Date.now(); // Apply a 20ms throttle
|
|
if ( now - moveTime <= 20 ) return;
|
|
const center = event.data.getLocalPosition(this.layer);
|
|
const snapped = canvas.grid.getSnappedPosition(center.x, center.y, 2);
|
|
this.data.x = snapped.x;
|
|
this.data.y = snapped.y;
|
|
this.refresh();
|
|
moveTime = now;
|
|
};
|
|
|
|
// Cancel the workflow (right-click)
|
|
handlers.rc = event => {
|
|
this.layer.preview.removeChildren();
|
|
canvas.stage.off("mousemove", handlers.mm);
|
|
canvas.stage.off("mousedown", handlers.lc);
|
|
canvas.app.view.oncontextmenu = null;
|
|
canvas.app.view.onwheel = null;
|
|
initialLayer.activate();
|
|
};
|
|
|
|
// Confirm the workflow (left-click)
|
|
handlers.lc = event => {
|
|
handlers.rc(event);
|
|
|
|
// Confirm final snapped position
|
|
const destination = canvas.grid.getSnappedPosition(this.x, this.y, 2);
|
|
this.data.x = destination.x;
|
|
this.data.y = destination.y;
|
|
|
|
// Create the template
|
|
canvas.scene.createEmbeddedEntity("MeasuredTemplate", this.data);
|
|
};
|
|
|
|
// Rotate the template by 3 degree increments (mouse-wheel)
|
|
handlers.mw = event => {
|
|
if ( event.ctrlKey ) event.preventDefault(); // Avoid zooming the browser window
|
|
event.stopPropagation();
|
|
let delta = canvas.grid.type > CONST.GRID_TYPES.SQUARE ? 30 : 15;
|
|
let snap = event.shiftKey ? delta : 5;
|
|
this.data.direction += (snap * Math.sign(event.deltaY));
|
|
this.refresh();
|
|
};
|
|
|
|
// Activate listeners
|
|
canvas.stage.on("mousemove", handlers.mm);
|
|
canvas.stage.on("mousedown", handlers.lc);
|
|
canvas.app.view.oncontextmenu = handlers.rc;
|
|
canvas.app.view.onwheel = handlers.mw;
|
|
}
|
|
}
|