126 lines
4.0 KiB
JavaScript
126 lines
4.0 KiB
JavaScript
|
|
import RegionBehaviorType from "./base.mjs";
|
||
|
|
import {REGION_EVENTS} from "../../../common/constants.mjs";
|
||
|
|
import * as fields from "../../../common/data/fields.mjs";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The data model for a behavior that displays scrolling text above a token when one of the subscribed events occurs.
|
||
|
|
*
|
||
|
|
* @property {boolean} once Disable the behavior after it triggers once
|
||
|
|
* @property {string} text The text to display
|
||
|
|
* @property {string} color Optional color setting for the text
|
||
|
|
* @property {number} visibility Which users the scrolling text will display for
|
||
|
|
(see {@link DisplayScrollingTextRegionBehaviorType.VISIBILITY_MODES})
|
||
|
|
*/
|
||
|
|
export default class DisplayScrollingTextRegionBehaviorType extends RegionBehaviorType {
|
||
|
|
|
||
|
|
/** @override */
|
||
|
|
static LOCALIZATION_PREFIXES = ["BEHAVIOR.TYPES.displayScrollingText", "BEHAVIOR.TYPES.base"];
|
||
|
|
|
||
|
|
/* ---------------------------------------- */
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Text visibility behavior modes.
|
||
|
|
* @enum {number}
|
||
|
|
*/
|
||
|
|
static get VISIBILITY_MODES() {
|
||
|
|
return DisplayScrollingTextRegionBehaviorType.#VISIBILITY_MODES;
|
||
|
|
}
|
||
|
|
|
||
|
|
static #VISIBILITY_MODES = Object.freeze({
|
||
|
|
/**
|
||
|
|
* Display only for gamemaster users
|
||
|
|
*/
|
||
|
|
GAMEMASTER: 0,
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Display only for users with observer permissions on the triggering token (and for the GM)
|
||
|
|
*/
|
||
|
|
OBSERVER: 1,
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Display for all users
|
||
|
|
*/
|
||
|
|
ANYONE: 2,
|
||
|
|
});
|
||
|
|
|
||
|
|
/* ---------------------------------------- */
|
||
|
|
|
||
|
|
/** @override */
|
||
|
|
static defineSchema() {
|
||
|
|
return {
|
||
|
|
events: this._createEventsField({events: [
|
||
|
|
REGION_EVENTS.TOKEN_ENTER,
|
||
|
|
REGION_EVENTS.TOKEN_EXIT,
|
||
|
|
REGION_EVENTS.TOKEN_MOVE,
|
||
|
|
REGION_EVENTS.TOKEN_MOVE_IN,
|
||
|
|
REGION_EVENTS.TOKEN_MOVE_OUT,
|
||
|
|
REGION_EVENTS.TOKEN_TURN_START,
|
||
|
|
REGION_EVENTS.TOKEN_TURN_END,
|
||
|
|
REGION_EVENTS.TOKEN_ROUND_START,
|
||
|
|
REGION_EVENTS.TOKEN_ROUND_END
|
||
|
|
]}),
|
||
|
|
text: new fields.StringField({required: true}),
|
||
|
|
color: new fields.ColorField({required: true, nullable: false, initial: "#ffffff"}),
|
||
|
|
visibility: new fields.NumberField({
|
||
|
|
required: true,
|
||
|
|
choices: Object.entries(this.VISIBILITY_MODES).reduce((obj, [key, value]) => {
|
||
|
|
obj[value] = `BEHAVIOR.TYPES.displayScrollingText.VISIBILITY_MODES.${key}.label`;
|
||
|
|
return obj;
|
||
|
|
}, {}),
|
||
|
|
initial: this.VISIBILITY_MODES.ANYONE,
|
||
|
|
validationError: "must be a value in DisplayScrollingTextRegionBehaviorType.VISIBILITY_MODES"}),
|
||
|
|
once: new fields.BooleanField()
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ---------------------------------------- */
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Display the scrolling text to the current User?
|
||
|
|
* @param {RegionEvent} event The Region event.
|
||
|
|
* @returns {boolean} Display the scrolling text to the current User?
|
||
|
|
*/
|
||
|
|
#canView(event) {
|
||
|
|
if ( !this.parent.scene.isView ) return false;
|
||
|
|
if ( game.user.isGM ) return true;
|
||
|
|
if ( event.data.token.isSecret ) return false;
|
||
|
|
|
||
|
|
const token = event.data.token.object;
|
||
|
|
if ( !token || !token.visible ) return false;
|
||
|
|
|
||
|
|
const M = DisplayScrollingTextRegionBehaviorType.VISIBILITY_MODES;
|
||
|
|
if ( this.visibility === M.ANYONE ) return true;
|
||
|
|
if ( this.visibility === M.OBSERVER ) return event.data.token.testUserPermission(game.user, "OBSERVER");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ---------------------------------------- */
|
||
|
|
|
||
|
|
/** @override */
|
||
|
|
async _handleRegionEvent(event) {
|
||
|
|
if ( this.once && game.users.activeGM?.isSelf ) {
|
||
|
|
// noinspection ES6MissingAwait
|
||
|
|
this.parent.update({disabled: true});
|
||
|
|
}
|
||
|
|
|
||
|
|
if ( !this.text ) return;
|
||
|
|
const canView = this.#canView(event);
|
||
|
|
if ( !canView ) return;
|
||
|
|
|
||
|
|
const token = event.data.token.object;
|
||
|
|
const animation = CanvasAnimation.getAnimation(token.animationName);
|
||
|
|
if ( animation ) await animation.promise;
|
||
|
|
await canvas.interface.createScrollingText(
|
||
|
|
token.center,
|
||
|
|
this.text,
|
||
|
|
{
|
||
|
|
distance: 2 * token.h,
|
||
|
|
fontSize: 28,
|
||
|
|
fill: this.color,
|
||
|
|
stroke: 0x000000,
|
||
|
|
strokeThickness: 4
|
||
|
|
}
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|