Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3890,6 +3890,8 @@
},
"Hover": "Hover",
"HoverSpeed": "{speed} (hover)",
"Reduced": "Normally {speed}",
"ReducedBy": "Reduced to 0 by {effect}",
"Speed": "Combat Speed",
"Type": {
"Burrow": "Burrow",
Expand Down
32 changes: 30 additions & 2 deletions module/applications/actor/npc-sheet.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { formatNumber, getPluralRules, simplifyBonus, splitSemicolons } from "../../utils.mjs";
import { formatLength, formatNumber, getPluralRules, simplifyBonus, splitSemicolons } from "../../utils.mjs";
import { createCheckboxInput } from "../fields.mjs";
import BaseActorSheet from "./api/base-actor-sheet.mjs";
import HabitatConfig from "./config/habitat-config.mjs";
Expand Down Expand Up @@ -370,14 +370,23 @@ export default class NPCActorSheet extends BaseActorSheet {
context.tools = this._prepareSkillsTools(context, "tools");

// Speed
const movementSource = this.actor._source.system.attributes.movement;
context.speed = [
...Object.entries(CONFIG.DND5E.movementTypes).filter(([, m]) => !m.hidden).map(([k, { label }]) => {
const value = attributes.movement[k];
if ( !value ) return null;
const base = movementSource[k];
if ( !value && !base ) return null;
const data = { label, value };
if ( (k === "fly") && attributes.movement.hover ) data.icons = [{
icon: "fas fa-cloud", label: _loc("DND5E.MOVEMENT.Hover")
}];
if ( !value ) {
data.displayZero = true;
const sources = this.#movementReducers(k);
data.tooltip = sources.length
? _loc("DND5E.MOVEMENT.ReducedBy", { effect: game.i18n.getListFormatter().format(sources) })
: _loc("DND5E.MOVEMENT.Reduced", { speed: formatLength(base, attributes.movement.units) });
}
return data;
}),
...splitSemicolons(attributes.movement.special).map(label => ({ label }))
Expand Down Expand Up @@ -474,6 +483,25 @@ export default class NPCActorSheet extends BaseActorSheet {

/* -------------------------------------------- */

/**
* Identify the active effects currently reducing a movement type to zero.
* @param {string} key The movement type key.
* @returns {string[]} Names of the responsible effects.
*/
#movementReducers(key) {
const statuses = new Set(CONFIG.DND5E.conditionEffects.noMovement);
if ( key !== "walk" ) CONFIG.DND5E.conditionEffects.crawl.forEach(s => statuses.add(s));
const path = `system.attributes.movement.${key}`;
const names = new Set();
for ( const effect of this.actor.appliedEffects ) {
// Conditions zero movement in code (keyed off statuses); custom effects may override the field directly.
if ( effect.statuses.intersects(statuses) || effect.changes.some(c => c.key === path) ) names.add(effect.name);
}
return Array.from(names);
}

/* -------------------------------------------- */

/** @inheritDoc */
async _renderFrame(options) {
const html = await super._renderFrame(options);
Expand Down
5 changes: 3 additions & 2 deletions templates/actors/parts/actor-trait-pills.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
</h3>
<ul class="pills">
{{#each values}}
<li class="pill {{ ../color }} {{ color }} {{~ifThen draggable ' draggable' ''}}">
<li class="pill {{ ../color }} {{ color }} {{~ifThen draggable ' draggable' ''}}"
{{~#if tooltip}} data-tooltip aria-label="{{ tooltip }}"{{/if}}>
{{#if link}}<a class="{{ @root.rollableClass }}" {{ dnd5e-dataset link }}>{{/if}}
{{#each icons}}
<i class="{{ icon }}" data-tooltip="{{ label }}" aria-label="{{ label }}"></i>
{{/each}}
<span class="label">{{ label }}</span>
{{#if value}}
{{#if (or value displayZero)}}
<span class="separator">&vert;</span>
<span class="value">{{ dnd5e-numberFormat value signDisplay=../signDisplay }}</span>
{{/if}}
Expand Down