Compare commits
5 commits
1358bfad93
...
2c4dbb2620
Author | SHA1 | Date | |
---|---|---|---|
2c4dbb2620 | |||
e021fedcdf | |||
7fcdcf8a5c | |||
f807b59c9a | |||
3eaf69f558 |
24 changed files with 128 additions and 138 deletions
|
@ -8,6 +8,6 @@ root = true
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 2
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
|
@ -184,7 +184,9 @@
|
||||||
"DS4.EffectFactor": "Faktor (wie oft der Effekt angewendet wird)",
|
"DS4.EffectFactor": "Faktor (wie oft der Effekt angewendet wird)",
|
||||||
"DS4.EffectFactorAbbr": "F",
|
"DS4.EffectFactorAbbr": "F",
|
||||||
"DS4.ActorName": "Name",
|
"DS4.ActorName": "Name",
|
||||||
|
"DS4.ActorSheet": "Aktorbogen",
|
||||||
"DS4.ActorImageAltText": "Bild des Aktors",
|
"DS4.ActorImageAltText": "Bild des Aktors",
|
||||||
|
"DS4.ItemSheet": "Itembogen",
|
||||||
"DS4.ActorTypeCharacter": "Charakter",
|
"DS4.ActorTypeCharacter": "Charakter",
|
||||||
"DS4.ActorTypeCreature": "Kreatur",
|
"DS4.ActorTypeCreature": "Kreatur",
|
||||||
"DS4.Attribute": "Attribut",
|
"DS4.Attribute": "Attribut",
|
||||||
|
|
|
@ -184,7 +184,9 @@
|
||||||
"DS4.EffectFactor": "Factor (the number of times the effect is being applied)",
|
"DS4.EffectFactor": "Factor (the number of times the effect is being applied)",
|
||||||
"DS4.EffectFactorAbbr": "F",
|
"DS4.EffectFactorAbbr": "F",
|
||||||
"DS4.ActorName": "Name",
|
"DS4.ActorName": "Name",
|
||||||
|
"DS4.ActorSheet": "Actor Sheet",
|
||||||
"DS4.ActorImageAltText": "Image of the Actor",
|
"DS4.ActorImageAltText": "Image of the Actor",
|
||||||
|
"DS4.ItemSheet": "Item Sheet",
|
||||||
"DS4.ActorTypeCharacter": "Character",
|
"DS4.ActorTypeCharacter": "Character",
|
||||||
"DS4.ActorTypeCreature": "Creature",
|
"DS4.ActorTypeCreature": "Creature",
|
||||||
"DS4.Attribute": "Attribute",
|
"DS4.Attribute": "Attribute",
|
||||||
|
|
|
@ -53,7 +53,8 @@
|
||||||
|
|
||||||
/* Icon animations */
|
/* Icon animations */
|
||||||
@keyframes pulse {
|
@keyframes pulse {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
@use "./colors";
|
@use "./colors";
|
||||||
|
|
||||||
|
|
||||||
$padding-sm: 5px;
|
$padding-sm: 5px;
|
||||||
$padding-md: 10px;
|
$padding-md: 10px;
|
||||||
$padding-lg: 20px;
|
$padding-lg: 20px;
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base sheet class for DS4 Actor Sheets
|
* The base sheet class for DS4 Actor Sheets
|
||||||
*/
|
*/
|
||||||
export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicationMixin(
|
||||||
|
foundry.applications.sheets.ActorSheetV2,
|
||||||
|
) {
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
classes: ["sheet", "ds4-actor-sheet", "themed"],
|
classes: ["sheet", "ds4-actor-sheet", "themed"],
|
||||||
tag: "form",
|
tag: "form",
|
||||||
|
@ -41,14 +41,7 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
changeEffect: DS4ActorSheet.prototype._onChangeEffect,
|
changeEffect: DS4ActorSheet.prototype._onChangeEffect,
|
||||||
sortItems: DS4ActorSheet.prototype._onSortItems,
|
sortItems: DS4ActorSheet.prototype._onSortItems,
|
||||||
changeTab: DS4ActorSheet.prototype._onChangeTab,
|
changeTab: DS4ActorSheet.prototype._onChangeTab,
|
||||||
edititem: DS4ActorSheet.prototype._onEditItem,
|
editImage: DS4ActorSheet.prototype._onEditImage,
|
||||||
deleteitem: DS4ActorSheet.prototype._onDeleteItem,
|
|
||||||
createitem: DS4ActorSheet.prototype._onCreateItem,
|
|
||||||
editeffect: DS4ActorSheet.prototype._onEditEffect,
|
|
||||||
deleteeffect: DS4ActorSheet.prototype._onDeleteEffect,
|
|
||||||
createeffect: DS4ActorSheet.prototype._onCreateEffect,
|
|
||||||
editImage: DS4ActorSheet._onEditImage,
|
|
||||||
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,14 +58,14 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
get template() {
|
get template() {
|
||||||
const templatePath = !game.user?.isGM && this.document.limited
|
const templatePath =
|
||||||
? "systems/ds4/templates/sheets/actor/limited-sheet.hbs"
|
!game.user?.isGM && this.document.limited
|
||||||
: `systems/ds4/templates/sheets/actor/${this.document.type}-sheet.hbs`;
|
? "systems/ds4/templates/sheets/actor/limited-sheet.hbs"
|
||||||
|
: `systems/ds4/templates/sheets/actor/${this.document.type}-sheet.hbs`;
|
||||||
|
|
||||||
return templatePath;
|
return templatePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async _renderHTML(context) {
|
async _renderHTML(context) {
|
||||||
return await foundry.applications.handlebars.renderTemplate(this.template, context);
|
return await foundry.applications.handlebars.renderTemplate(this.template, context);
|
||||||
|
@ -83,8 +76,6 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
content.innerHTML = result;
|
content.innerHTML = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async _prepareContext(options) {
|
async _prepareContext(options) {
|
||||||
const context = await super._prepareContext(options);
|
const context = await super._prepareContext(options);
|
||||||
|
@ -94,8 +85,6 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
throw new Error("Document not available for sheet rendering");
|
throw new Error("Document not available for sheet rendering");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Add document data
|
// Add document data
|
||||||
context.data = this.document;
|
context.data = this.document;
|
||||||
context.system = this.document.system;
|
context.system = this.document.system;
|
||||||
|
@ -111,8 +100,6 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
showSlayerPoints: game.settings.get("ds4", "showSlayerPoints") || false,
|
showSlayerPoints: game.settings.get("ds4", "showSlayerPoints") || false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Add items organized by type
|
// Add items organized by type
|
||||||
context.itemsByType = {};
|
context.itemsByType = {};
|
||||||
if (this.document.items && this.document.items.size > 0) {
|
if (this.document.items && this.document.items.size > 0) {
|
||||||
|
@ -352,7 +339,6 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle changing an item property
|
* Handle changing an item property
|
||||||
* @param {Event} event - The triggering event
|
* @param {Event} event - The triggering event
|
||||||
|
@ -484,8 +470,6 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle sorting items
|
* Handle sorting items
|
||||||
* @param {Event} event - The triggering event
|
* @param {Event} event - The triggering event
|
||||||
|
@ -497,7 +481,7 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
|
|
||||||
if (!dataPath || !itemType) return;
|
if (!dataPath || !itemType) return;
|
||||||
|
|
||||||
const items = this.document.items.filter(item => item.type === itemType);
|
const items = this.document.items.filter((item) => item.type === itemType);
|
||||||
const sortedItems = this.sortItems(items, dataPath);
|
const sortedItems = this.sortItems(items, dataPath);
|
||||||
|
|
||||||
const updates = sortedItems.map((item, index) => ({
|
const updates = sortedItems.map((item, index) => ({
|
||||||
|
@ -549,13 +533,13 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
if (!nav || !sheet) return;
|
if (!nav || !sheet) return;
|
||||||
|
|
||||||
// Update navigation active state
|
// Update navigation active state
|
||||||
nav.querySelectorAll(".ds4-sheet-tab-nav__item").forEach(item => {
|
nav.querySelectorAll(".ds4-sheet-tab-nav__item").forEach((item) => {
|
||||||
item.classList.remove("active");
|
item.classList.remove("active");
|
||||||
});
|
});
|
||||||
target.classList.add("active");
|
target.classList.add("active");
|
||||||
|
|
||||||
// Update tab content visibility
|
// Update tab content visibility
|
||||||
sheet.querySelectorAll(".ds4-sheet-tab").forEach(tabContent => {
|
sheet.querySelectorAll(".ds4-sheet-tab").forEach((tabContent) => {
|
||||||
tabContent.classList.remove("active");
|
tabContent.classList.remove("active");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -589,8 +573,8 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
const tabContents = sheet.querySelectorAll(".ds4-sheet-tab");
|
const tabContents = sheet.querySelectorAll(".ds4-sheet-tab");
|
||||||
|
|
||||||
// Remove active class from all items first
|
// Remove active class from all items first
|
||||||
navItems.forEach(item => item.classList.remove("active"));
|
navItems.forEach((item) => item.classList.remove("active"));
|
||||||
tabContents.forEach(content => content.classList.remove("active"));
|
tabContents.forEach((content) => content.classList.remove("active"));
|
||||||
|
|
||||||
// Find the currently active tab or default to first
|
// Find the currently active tab or default to first
|
||||||
let targetTab = this.activeTab;
|
let targetTab = this.activeTab;
|
||||||
|
@ -626,7 +610,7 @@ export class DS4ActorSheet extends foundry.applications.api.HandlebarsApplicatio
|
||||||
const fp = new foundry.applications.apps.FilePicker({
|
const fp = new foundry.applications.apps.FilePicker({
|
||||||
type: "image",
|
type: "image",
|
||||||
current: current,
|
current: current,
|
||||||
callback: (path) => this.document.update({ [field]: path })
|
callback: (path) => this.document.update({ [field]: path }),
|
||||||
});
|
});
|
||||||
|
|
||||||
return fp.browse();
|
return fp.browse();
|
||||||
|
|
|
@ -25,7 +25,7 @@ export class DS4CharacterActorSheet extends DS4ActorSheet {
|
||||||
{
|
{
|
||||||
async: true,
|
async: true,
|
||||||
relativeTo: this.document,
|
relativeTo: this.document,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ export class DS4CreatureActorSheet extends DS4ActorSheet {
|
||||||
{
|
{
|
||||||
async: true,
|
async: true,
|
||||||
relativeTo: this.document,
|
relativeTo: this.document,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ export class DialogWithListeners extends foundry.applications.api.DialogV2 {
|
||||||
await super._onRender(context, options);
|
await super._onRender(context, options);
|
||||||
|
|
||||||
// Attach additional listeners if provided
|
// Attach additional listeners if provided
|
||||||
if (this.activateAdditionalListeners && typeof this.activateAdditionalListeners === 'function') {
|
if (this.activateAdditionalListeners && typeof this.activateAdditionalListeners === "function") {
|
||||||
this.activateAdditionalListeners(this.element, this);
|
this.activateAdditionalListeners(this.element, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
/**
|
/**
|
||||||
* The Sheet class for DS4 Items
|
* The Sheet class for DS4 Items
|
||||||
*/
|
*/
|
||||||
export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplicationMixin(
|
||||||
|
foundry.applications.sheets.ItemSheetV2,
|
||||||
|
) {
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
classes: ["sheet", "ds4-item-sheet", "themed"],
|
classes: ["sheet", "ds4-item-sheet", "themed"],
|
||||||
tag: "form",
|
tag: "form",
|
||||||
|
@ -26,18 +28,13 @@ export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplication
|
||||||
actions: {
|
actions: {
|
||||||
controlEffect: DS4ItemSheet.prototype._onControlEffect,
|
controlEffect: DS4ItemSheet.prototype._onControlEffect,
|
||||||
createEffect: DS4ItemSheet.prototype._onCreateEffect,
|
createEffect: DS4ItemSheet.prototype._onCreateEffect,
|
||||||
createeffect: DS4ItemSheet.prototype._onCreateEffect,
|
|
||||||
editEffect: DS4ItemSheet.prototype._onEditEffect,
|
editEffect: DS4ItemSheet.prototype._onEditEffect,
|
||||||
editeffect: DS4ItemSheet.prototype._onEditEffect,
|
|
||||||
deleteEffect: DS4ItemSheet.prototype._onDeleteEffect,
|
deleteEffect: DS4ItemSheet.prototype._onDeleteEffect,
|
||||||
deleteeffect: DS4ItemSheet.prototype._onDeleteEffect,
|
|
||||||
changeTab: DS4ItemSheet.prototype._onChangeTab,
|
changeTab: DS4ItemSheet.prototype._onChangeTab,
|
||||||
editImage: DS4ItemSheet.prototype._onEditImage,
|
editImage: DS4ItemSheet.prototype._onEditImage,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static TABS = {};
|
static TABS = {};
|
||||||
|
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
|
@ -105,14 +102,13 @@ export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplication
|
||||||
this.item.system.description,
|
this.item.system.description,
|
||||||
{
|
{
|
||||||
secrets: this.item.isOwner,
|
secrets: this.item.isOwner,
|
||||||
relativeTo: this.item
|
relativeTo: this.item,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
context.enrichedDescription = "";
|
context.enrichedDescription = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,10 +179,12 @@ export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplication
|
||||||
|
|
||||||
const effect = this.item.effects.get(effectId);
|
const effect = this.item.effects.get(effectId);
|
||||||
if (!effect) {
|
if (!effect) {
|
||||||
throw new Error(game.i18n.format("DS4.ErrorItemDoesNotHaveEffect", {
|
throw new Error(
|
||||||
id: effectId,
|
game.i18n.format("DS4.ErrorItemDoesNotHaveEffect", {
|
||||||
item: this.item.name
|
id: effectId,
|
||||||
}));
|
item: this.item.name,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await effect.sheet.render(true);
|
await effect.sheet.render(true);
|
||||||
|
@ -235,13 +233,13 @@ export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplication
|
||||||
if (!nav || !sheet) return;
|
if (!nav || !sheet) return;
|
||||||
|
|
||||||
// Update navigation active state
|
// Update navigation active state
|
||||||
nav.querySelectorAll(".ds4-sheet-tab-nav__item").forEach(item => {
|
nav.querySelectorAll(".ds4-sheet-tab-nav__item").forEach((item) => {
|
||||||
item.classList.remove("active");
|
item.classList.remove("active");
|
||||||
});
|
});
|
||||||
target.classList.add("active");
|
target.classList.add("active");
|
||||||
|
|
||||||
// Update tab content visibility
|
// Update tab content visibility
|
||||||
sheet.querySelectorAll(".ds4-sheet-tab").forEach(tabContent => {
|
sheet.querySelectorAll(".ds4-sheet-tab").forEach((tabContent) => {
|
||||||
tabContent.classList.remove("active");
|
tabContent.classList.remove("active");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -263,7 +261,7 @@ export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplication
|
||||||
const fp = new foundry.applications.apps.FilePicker({
|
const fp = new foundry.applications.apps.FilePicker({
|
||||||
type: "image",
|
type: "image",
|
||||||
current: current,
|
current: current,
|
||||||
callback: (path) => this.item.update({ [field]: path })
|
callback: (path) => this.item.update({ [field]: path }),
|
||||||
});
|
});
|
||||||
return fp.browse();
|
return fp.browse();
|
||||||
}
|
}
|
||||||
|
@ -276,8 +274,6 @@ export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplication
|
||||||
this._initializeTabs();
|
this._initializeTabs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async _onClose(options) {
|
async _onClose(options) {
|
||||||
await super._onClose(options);
|
await super._onClose(options);
|
||||||
|
@ -299,8 +295,8 @@ export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplication
|
||||||
const tabContents = sheet.querySelectorAll(".ds4-sheet-tab");
|
const tabContents = sheet.querySelectorAll(".ds4-sheet-tab");
|
||||||
|
|
||||||
// Remove active class from all items first
|
// Remove active class from all items first
|
||||||
navItems.forEach(item => item.classList.remove("active"));
|
navItems.forEach((item) => item.classList.remove("active"));
|
||||||
tabContents.forEach(content => content.classList.remove("active"));
|
tabContents.forEach((content) => content.classList.remove("active"));
|
||||||
|
|
||||||
// Find the currently active tab or default to first
|
// Find the currently active tab or default to first
|
||||||
let targetTab = this.activeTab;
|
let targetTab = this.activeTab;
|
||||||
|
@ -312,8 +308,6 @@ export class DS4ItemSheet extends foundry.applications.api.HandlebarsApplication
|
||||||
targetTab = targetNavItem?.dataset.tab;
|
targetTab = targetNavItem?.dataset.tab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Set target tab navigation as active
|
// Set target tab navigation as active
|
||||||
if (targetNavItem && targetTab) {
|
if (targetNavItem && targetTab) {
|
||||||
targetNavItem.classList.add("active");
|
targetNavItem.classList.add("active");
|
||||||
|
|
|
@ -7,41 +7,38 @@
|
||||||
* Based on actor movement combat value
|
* Based on actor movement combat value
|
||||||
*/
|
*/
|
||||||
export class DS4TokenRuler extends foundry.canvas.placeables.tokens.TokenRuler {
|
export class DS4TokenRuler extends foundry.canvas.placeables.tokens.TokenRuler {
|
||||||
|
static WAYPOINT_LABEL_TEMPLATE = "systems/ds4/templates/partials/waypoint-label.hbs";
|
||||||
|
|
||||||
static WAYPOINT_LABEL_TEMPLATE = "systems/ds4/templates/partials/waypoint-label.hbs";
|
/**
|
||||||
|
* Enhance waypoint label context with movement range information
|
||||||
|
* @param {object} waypoint - The waypoint data
|
||||||
|
* @param {object} state - The current ruler state
|
||||||
|
* @returns {object} Enhanced context with range class
|
||||||
|
*/
|
||||||
|
_getWaypointLabelContext(waypoint, state) {
|
||||||
|
const context = super._getWaypointLabelContext(waypoint, state);
|
||||||
|
|
||||||
|
// Only apply movement coloring for distance measurements in meters
|
||||||
|
if (context?.cost?.units === "m" || context?.distance?.units === "m") {
|
||||||
|
const movement = this.token?.actor?.system?.combatValues?.movement?.total;
|
||||||
|
|
||||||
|
if (movement) {
|
||||||
|
const total = Number(context.cost?.total || context.distance?.total || 0);
|
||||||
|
|
||||||
/**
|
// DS4 movement rules:
|
||||||
* Enhance waypoint label context with movement range information
|
// - Normal movement: up to movement value
|
||||||
* @param {object} waypoint - The waypoint data
|
// - Dash: up to 2x movement value (requires action)
|
||||||
* @param {object} state - The current ruler state
|
// - Beyond 2x: impossible in single turn
|
||||||
* @returns {object} Enhanced context with range class
|
if (total > 2 * movement) {
|
||||||
*/
|
context.rangeClass = "out-of-range";
|
||||||
_getWaypointLabelContext(waypoint, state) {
|
} else if (total <= movement) {
|
||||||
const context = super._getWaypointLabelContext(waypoint, state);
|
context.rangeClass = "move-range";
|
||||||
|
} else {
|
||||||
// Only apply movement coloring for distance measurements in meters
|
context.rangeClass = "dash-range";
|
||||||
if (context?.cost?.units === "m" || context?.distance?.units === "m") {
|
|
||||||
const movement = this.token?.actor?.system?.combatValues?.movement?.total;
|
|
||||||
|
|
||||||
if (movement) {
|
|
||||||
const total = Number(context.cost?.total || context.distance?.total || 0);
|
|
||||||
|
|
||||||
// DS4 movement rules:
|
|
||||||
// - Normal movement: up to movement value
|
|
||||||
// - Dash: up to 2x movement value (requires action)
|
|
||||||
// - Beyond 2x: impossible in single turn
|
|
||||||
if (total > 2 * movement) {
|
|
||||||
context.rangeClass = "out-of-range";
|
|
||||||
} else if (total <= movement) {
|
|
||||||
context.rangeClass = "move-range";
|
|
||||||
} else {
|
|
||||||
context.rangeClass = "dash-range";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,7 +212,10 @@ async function askForInteractiveRollData(checkTargetNumber, options = {}, { temp
|
||||||
|
|
||||||
if (checkModifierSelect) {
|
if (checkModifierSelect) {
|
||||||
checkModifierSelect.addEventListener("change", (event) => {
|
checkModifierSelect.addEventListener("change", (event) => {
|
||||||
if (event.currentTarget.value === "custom" && checkModifierCustomFormGroup?.classList.contains("ds4-hidden")) {
|
if (
|
||||||
|
event.currentTarget.value === "custom" &&
|
||||||
|
checkModifierCustomFormGroup?.classList.contains("ds4-hidden")
|
||||||
|
) {
|
||||||
checkModifierCustomFormGroup.classList.remove("ds4-hidden");
|
checkModifierCustomFormGroup.classList.remove("ds4-hidden");
|
||||||
app.setPosition({ height: "auto" });
|
app.setPosition({ height: "auto" });
|
||||||
} else if (checkModifierCustomFormGroup && !checkModifierCustomFormGroup.classList.contains("ds4-hidden")) {
|
} else if (checkModifierCustomFormGroup && !checkModifierCustomFormGroup.classList.contains("ds4-hidden")) {
|
||||||
|
|
|
@ -466,30 +466,33 @@ export class DS4Actor extends Actor {
|
||||||
const traitIdentifier = "attribute-trait-selection-trait";
|
const traitIdentifier = "attribute-trait-selection-trait";
|
||||||
return foundry.applications.api.DialogV2.prompt({
|
return foundry.applications.api.DialogV2.prompt({
|
||||||
window: { title: getGame().i18n.localize("DS4.DialogAttributeTraitSelection") },
|
window: { title: getGame().i18n.localize("DS4.DialogAttributeTraitSelection") },
|
||||||
content: await foundry.applications.handlebars.renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
|
content: await foundry.applications.handlebars.renderTemplate(
|
||||||
selects: [
|
"systems/ds4/templates/dialogs/simple-select-form.hbs",
|
||||||
{
|
{
|
||||||
label: getGame().i18n.localize("DS4.Attribute"),
|
selects: [
|
||||||
identifier: attributeIdentifier,
|
{
|
||||||
options: Object.fromEntries(
|
label: getGame().i18n.localize("DS4.Attribute"),
|
||||||
Object.entries(DS4.i18n.attributes).map(([attribute, translation]) => [
|
identifier: attributeIdentifier,
|
||||||
attribute,
|
options: Object.fromEntries(
|
||||||
`${translation} (${this.system.attributes[attribute].total})`,
|
Object.entries(DS4.i18n.attributes).map(([attribute, translation]) => [
|
||||||
]),
|
attribute,
|
||||||
),
|
`${translation} (${this.system.attributes[attribute].total})`,
|
||||||
},
|
]),
|
||||||
{
|
),
|
||||||
label: getGame().i18n.localize("DS4.Trait"),
|
},
|
||||||
identifier: traitIdentifier,
|
{
|
||||||
options: Object.fromEntries(
|
label: getGame().i18n.localize("DS4.Trait"),
|
||||||
Object.entries(DS4.i18n.traits).map(([trait, translation]) => [
|
identifier: traitIdentifier,
|
||||||
trait,
|
options: Object.fromEntries(
|
||||||
`${translation} (${this.system.traits[trait].total})`,
|
Object.entries(DS4.i18n.traits).map(([trait, translation]) => [
|
||||||
]),
|
trait,
|
||||||
),
|
`${translation} (${this.system.traits[trait].total})`,
|
||||||
},
|
]),
|
||||||
],
|
),
|
||||||
}),
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
ok: {
|
ok: {
|
||||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
||||||
callback: (_event, button) => {
|
callback: (_event, button) => {
|
||||||
|
|
|
@ -86,18 +86,21 @@ export class DS4Weapon extends DS4Item {
|
||||||
const identifier = `attack-type-selection-${foundry.utils.randomID()}`;
|
const identifier = `attack-type-selection-${foundry.utils.randomID()}`;
|
||||||
return foundry.applications.api.DialogV2.prompt({
|
return foundry.applications.api.DialogV2.prompt({
|
||||||
window: { title: getGame().i18n.localize("DS4.DialogAttackTypeSelection") },
|
window: { title: getGame().i18n.localize("DS4.DialogAttackTypeSelection") },
|
||||||
content: await foundry.applications.handlebars.renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
|
content: await foundry.applications.handlebars.renderTemplate(
|
||||||
selects: [
|
"systems/ds4/templates/dialogs/simple-select-form.hbs",
|
||||||
{
|
{
|
||||||
label: getGame().i18n.localize("DS4.AttackType"),
|
selects: [
|
||||||
identifier,
|
{
|
||||||
options: { melee, ranged },
|
label: getGame().i18n.localize("DS4.AttackType"),
|
||||||
},
|
identifier,
|
||||||
],
|
options: { melee, ranged },
|
||||||
}),
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
ok: {
|
ok: {
|
||||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
||||||
callback: (_event, button, _dialog) => {
|
callback: (_event, button) => {
|
||||||
const selectedAttackType = button.form.elements[identifier].value;
|
const selectedAttackType = button.form.elements[identifier].value;
|
||||||
if (selectedAttackType !== "melee" && selectedAttackType !== "ranged") {
|
if (selectedAttackType !== "melee" && selectedAttackType !== "ranged") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
|
|
@ -14,6 +14,11 @@ const helpers = {
|
||||||
|
|
||||||
isEmpty: (input: Array<unknown> | null | undefined): boolean => (input?.length ?? 0) === 0,
|
isEmpty: (input: Array<unknown> | null | undefined): boolean => (input?.length ?? 0) === 0,
|
||||||
|
|
||||||
|
capitalize: (str: string): string => {
|
||||||
|
if (typeof str !== "string") return "";
|
||||||
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||||
|
},
|
||||||
|
|
||||||
toRomanNumerals,
|
toRomanNumerals,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,6 @@ import { registerForReadyHook } from "./ready";
|
||||||
import { registerForRenderHooks } from "./render";
|
import { registerForRenderHooks } from "./render";
|
||||||
import { registerForSetupHook } from "./setup";
|
import { registerForSetupHook } from "./setup";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export function registerForHooks(): void {
|
export function registerForHooks(): void {
|
||||||
registerForHotbarDropHook();
|
registerForHotbarDropHook();
|
||||||
registerForPreCreateItemHook();
|
registerForPreCreateItemHook();
|
||||||
|
|
|
@ -21,12 +21,12 @@ export function registerForRenderHooks() {
|
||||||
*/
|
*/
|
||||||
function selectTargetInputOnFocus(app, element) {
|
function selectTargetInputOnFocus(app, element) {
|
||||||
// V13: element is always a plain DOM element
|
// V13: element is always a plain DOM element
|
||||||
if (!element || typeof element.querySelectorAll !== 'function') {
|
if (!element || typeof element.querySelectorAll !== "function") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const inputs = element.querySelectorAll("input");
|
const inputs = element.querySelectorAll("input");
|
||||||
inputs.forEach(input => {
|
inputs.forEach((input) => {
|
||||||
input.addEventListener("focus", (ev) => {
|
input.addEventListener("focus", (ev) => {
|
||||||
ev.currentTarget.select();
|
ev.currentTarget.select();
|
||||||
});
|
});
|
||||||
|
|
|
@ -30,7 +30,10 @@ export function enforce(value, message) {
|
||||||
* @returns {Canvas}
|
* @returns {Canvas}
|
||||||
*/
|
*/
|
||||||
export function getCanvas() {
|
export function getCanvas() {
|
||||||
enforce(canvas instanceof foundry.canvas.Canvas && canvas.ready, getGame().i18n.localize("DS4.ErrorCanvasIsNotInitialized"));
|
enforce(
|
||||||
|
canvas instanceof foundry.canvas.Canvas && canvas.ready,
|
||||||
|
getGame().i18n.localize("DS4.ErrorCanvasIsNotInitialized"),
|
||||||
|
);
|
||||||
return canvas;
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ SPDX-License-Identifier: MIT
|
||||||
{{> systems/ds4/templates/sheets/actor/components/creature-properties.hbs}}
|
{{> systems/ds4/templates/sheets/actor/components/creature-properties.hbs}}
|
||||||
{{/systems/ds4/templates/sheets/actor/components/actor-header.hbs}}
|
{{/systems/ds4/templates/sheets/actor/components/actor-header.hbs}}
|
||||||
|
|
||||||
|
|
||||||
{{!-- Sheet Tab Navigation --}}
|
{{!-- Sheet Tab Navigation --}}
|
||||||
<nav class="ds4-sheet-tab-nav" data-group="primary">
|
<nav class="ds4-sheet-tab-nav" data-group="primary">
|
||||||
<a class="ds4-sheet-tab-nav__item" data-action="changeTab" data-tab="values">{{localize 'DS4.HeadingValues'}}</a>
|
<a class="ds4-sheet-tab-nav__item" data-action="changeTab" data-tab="values">{{localize 'DS4.HeadingValues'}}</a>
|
||||||
|
|
|
@ -9,7 +9,6 @@ SPDX-License-Identifier: MIT
|
||||||
{{#> systems/ds4/templates/sheets/actor/components/actor-header.hbs}}
|
{{#> systems/ds4/templates/sheets/actor/components/actor-header.hbs}}
|
||||||
{{/systems/ds4/templates/sheets/actor/components/actor-header.hbs}}
|
{{/systems/ds4/templates/sheets/actor/components/actor-header.hbs}}
|
||||||
|
|
||||||
|
|
||||||
{{!-- Sheet Body --}}
|
{{!-- Sheet Body --}}
|
||||||
<section class="ds4-sheet-body">
|
<section class="ds4-sheet-body">
|
||||||
{{#if (eq data.type 'character')}}
|
{{#if (eq data.type 'character')}}
|
||||||
|
|
|
@ -40,10 +40,8 @@ titleKey=titleKey}}
|
||||||
titleKey=titleKey}}
|
titleKey=titleKey}}
|
||||||
{{/inline}}
|
{{/inline}}
|
||||||
|
|
||||||
|
|
||||||
{{!-- ======================================================================== --}}
|
{{!-- ======================================================================== --}}
|
||||||
|
|
||||||
|
|
||||||
<div class="ds4-sheet-tab tab spells" data-group="primary" data-tab="spells">
|
<div class="ds4-sheet-tab tab spells" data-group="primary" data-tab="spells">
|
||||||
{{#unless (isEmpty itemsByType.spell)}}
|
{{#unless (isEmpty itemsByType.spell)}}
|
||||||
<ol class="ds4-embedded-document-list ds4-embedded-document-list--spell item-list">
|
<ol class="ds4-embedded-document-list ds4-embedded-document-list--spell item-list">
|
||||||
|
|
|
@ -5,10 +5,10 @@ SPDX-License-Identifier: MIT
|
||||||
--}}
|
--}}
|
||||||
|
|
||||||
<div class="ds4-sheet-tab tab effects" data-group="primary" data-tab="effects">
|
<div class="ds4-sheet-tab tab effects" data-group="primary" data-tab="effects">
|
||||||
{{#unless (isEmpty data.effects)}}
|
{{#unless (isEmpty enrichedEffects)}}
|
||||||
<ol class="ds4-embedded-document-list ds4-embedded-document-list--item-effect effect-list">
|
<ol class="ds4-embedded-document-list ds4-embedded-document-list--item-effect effect-list">
|
||||||
{{> systems/ds4/templates/sheets/item/components/effect-list-header.hbs}}
|
{{> systems/ds4/templates/sheets/item/components/effect-list-header.hbs}}
|
||||||
{{#each data.effects as |effectData id| }}
|
{{#each enrichedEffects as |effectData id| }}
|
||||||
{{> systems/ds4/templates/sheets/item/components/effect-list-entry.hbs effectData=effectData}}
|
{{> systems/ds4/templates/sheets/item/components/effect-list-entry.hbs effectData=effectData}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ol>
|
</ol>
|
||||||
|
|
|
@ -13,7 +13,7 @@ SPDX-License-Identifier: MIT
|
||||||
}}
|
}}
|
||||||
{{#if @root/editable}}
|
{{#if @root/editable}}
|
||||||
<div class="ds4-add-button">
|
<div class="ds4-add-button">
|
||||||
<a class="ds4-add-button__link" title="{{localize title}}" data-action="create{{documentType}}" {{#if type}}data-type="{{type}}"
|
<a class="ds4-add-button__link" title="{{localize title}}" data-action="{{concat 'create' (capitalize documentType)}}" {{#if type}}data-type="{{type}}"
|
||||||
{{/if}}>
|
{{/if}}>
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
{{localize "DS4.UserInteractionAdd"}}
|
{{localize "DS4.UserInteractionAdd"}}
|
||||||
|
|
|
@ -14,9 +14,9 @@ SPDX-License-Identifier: MIT
|
||||||
--}}
|
--}}
|
||||||
<div class="ds4-control-button-group">
|
<div class="ds4-control-button-group">
|
||||||
{{#if @root/editable}}
|
{{#if @root/editable}}
|
||||||
<a class="ds4-control-button-group__button" data-action="edit{{documentType}}" data-document-type="{{documentType}}"
|
<a class="ds4-control-button-group__button" data-action="{{concat 'edit' (capitalize documentType)}}" data-document-type="{{documentType}}"
|
||||||
title="{{localize editTitle}}"><i class="fas fa-edit"></i></a>
|
title="{{localize editTitle}}"><i class="fas fa-edit"></i></a>
|
||||||
<a class="ds4-control-button-group__button" data-action="delete{{documentType}}" data-document-type="{{documentType}}"
|
<a class="ds4-control-button-group__button" data-action="{{concat 'delete' (capitalize documentType)}}" data-document-type="{{documentType}}"
|
||||||
title="{{localize deleteTitle}}"><i class="fas fa-trash"></i></a>
|
title="{{localize deleteTitle}}"><i class="fas fa-trash"></i></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue