Add files via upload

This commit is contained in:
CK 2020-06-24 14:23:36 -04:00 committed by GitHub
parent ec71de4339
commit 8d1045325f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -0,0 +1,127 @@
import { SW5E } from "../config.js";
/**
* A helper class for building MeasuredTemplates for 5e powers and abilities
* @extends {MeasuredTemplate}
*/
export 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 5ft wide
templateData.width = 5;
break;
default:
break;
}
// Return the template constructed from the item data
return new this(templateData);
}
/* -------------------------------------------- */
/**
* Creates a preview of the power template
* @param {Event} event The initiating click event
*/
drawPreview(event) {
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;
}
}