COrrections, WIP

This commit is contained in:
2026-04-24 22:04:09 +02:00
parent d75b6cb945
commit e200b5f7b0
126 changed files with 768 additions and 5805 deletions

View File

@@ -10,6 +10,8 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
static types = [
{ id: "ring", label: "l5r5e.rings.label" },
{ id: "skill", label: "l5r5e.skills.label" },
{ id: "arcane", label: "l5r5e.chiaroscuro.arcane.label" },
{ id: "mot_invocation", label: "l5r5e.chiaroscuro.technique.mot_invocation" },
// others have theirs own xp count
];
@@ -27,6 +29,12 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
sheetData.data.subTypesList = AdvancementSheetL5r5e.types;
sheetData.data.skillsList = game.l5r5e.HelpersL5r5e.getSkillsList(true);
// Invocation sub-types (Général / Neutre / Précis)
const invTypes = game.l5r5e.HelpersL5r5e.getLocalizedRawObject("l5r5e.chiaroscuro.technique.invocation_types") ?? {};
sheetData.data.invocationTypesList = [{ id: "", label: "—" }].concat(
Object.entries(invTypes).map(([id, label]) => ({ id, label }))
);
return sheetData;
}
@@ -49,15 +57,22 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
html.find("#advancement_type").on("change", (event) => {
const targetEvt = $(event.target);
targetEvt.prop("disabled", true);
const val = targetEvt.val();
if (targetEvt.val() === "skill") {
if (val === "skill") {
this._updateChoice({ ring: currentRing }, { skill: currentSkill }).then(
targetEvt.prop("disabled", false)
);
} else if (targetEvt.val() === "ring") {
} else if (val === "ring") {
this._updateChoice({ skill: currentSkill }, { ring: currentRing }).then(
targetEvt.prop("disabled", false)
);
} else {
// arcane or mot_invocation: just save the type, no auto-calc
this.object.update({ system: { advancement_type: val } }).then(() => {
targetEvt.prop("disabled", false);
this.render(true);
});
}
});

View File

@@ -10,7 +10,8 @@ export class ArcaneSheetL5r5e extends BaseItemSheetL5r5e {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "arcane"],
template: CONFIG.l5r5e.paths.templates + "items/arcane/arcane-sheet.html",
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "attributes" }],
width: 500,
height: 400,
});
}

View File

@@ -1,137 +0,0 @@
import { ItemSheetL5r5e } from "./item-sheet.js";
/**
* @extends {ItemSheetL5r5e}
*/
export class ArmyCohortSheetL5r5e extends ItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "army-cohort"],
template: CONFIG.l5r5e.paths.templates + "items/army-cohort/army-cohort-sheet.html",
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "infos" }],
dragDrop: [{ dragSelector: ".item", dropSelector: null }],
});
}
/** @override */
constructor(options = {}) {
super(options);
this._initialize();
}
/**
* Initialize once
* @private
*/
_initialize() {
const data = this.object.system;
// update linked actor datas
if (data.leader_actor_id) {
const actor = game.actors.get(data.leader_actor_id);
if (actor) {
this._updateLinkedActorData(actor);
} else {
this._removeLinkedActor();
}
}
}
/**
* @return {Object|Promise}
*/
async getData(options = {}) {
const sheetData = await super.getData(options);
// Editors enrichment
sheetData.data.enrichedHtml.abilities = await foundry.applications.ux.TextEditor.implementation.enrichHTML(sheetData.data.system.abilities, {
async: true,
});
return sheetData;
}
/**
* Activate a named TinyMCE text editor
* @param {string} name The named data field which the editor modifies.
* @param {object} options TinyMCE initialization options passed to TextEditor.create
* @param {string} initialContent Initial text content for the editor area.
* @override
*/
activateEditor(name, options = {}, initialContent = "") {
// Symbols Compatibility with old compendium modules (PRE l5r v1.7.2)
if (name === "system.abilities" && initialContent) {
initialContent = game.l5r5e.HelpersL5r5e.convertSymbols(initialContent, false);
}
return super.activateEditor(name, options, initialContent);
}
/**
* Subscribe to events from the sheet.
* @param {jQuery} html HTML content of the sheet.
*/
activateListeners(html) {
super.activateListeners(html);
// *** Everything below here is only needed if the sheet is editable ***
if (!this.isEditable) {
return;
}
// Delete the linked Actor
html.find(".actor-remove-control").on("click", (event) => {
event.preventDefault();
event.stopPropagation();
this._removeLinkedActor();
});
}
/**
* Handle dropped Item data on the Actor sheet (cohort, fortification)
* @param {DragEvent} event
*/
async _onDrop(event) {
// *** Everything below here is only needed if the sheet is editable ***
if (!this.isEditable) {
return;
}
const droppedActor = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
return this._updateLinkedActorData(droppedActor);
}
/**
* Update actor datas for this army sheet
* @param {ActorL5r5e} actor actor object
* @return {Promise<abstract.Document>}
* @private
*/
async _updateLinkedActorData(actor) {
if (!actor || actor.documentName !== "Actor" || !actor.isCharacterType) {
console.warn("L5R5E | Army Cohort | Wrong actor type", actor?.type, actor);
return;
}
return this.object.update({
img: actor.img,
system: {
leader: actor.name,
leader_actor_id: actor._id,
},
});
}
/**
* Remove the linked actor (commander/warlord)
* @return {Promise<void>}
* @private
*/
async _removeLinkedActor() {
return this.object.update({
system: {
leader_actor_id: null,
},
});
}
}

View File

@@ -1,14 +0,0 @@
import { ItemSheetL5r5e } from "./item-sheet.js";
/**
* @extends {ItemSheetL5r5e}
*/
export class ArmyFortificationSheetL5r5e extends ItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "army-fortification"],
template: CONFIG.l5r5e.paths.templates + "items/army-fortification/army-fortification-sheet.html",
});
}
}

View File

@@ -1,14 +0,0 @@
import { ItemSheetL5r5e } from "./item-sheet.js";
/**
* @extends {ItemSheet}
*/
export class BondSheetL5r5e extends ItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "bond"],
template: CONFIG.l5r5e.paths.templates + "items/bond/bond-sheet.html",
});
}
}

View File

@@ -1,128 +0,0 @@
import { ItemSheetL5r5e } from "./item-sheet.js";
/**
* @extends {ItemSheet}
*/
export class ItemPatternSheetL5r5e extends ItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "item-pattern"],
template: CONFIG.l5r5e.paths.templates + "items/item-pattern/item-pattern-sheet.html",
});
}
/**
* @return {Object|Promise}
*/
async getData(options = {}) {
const sheetData = await super.getData(options);
// Linked Property
sheetData.data.linkedProperty = await this.getLinkedProperty(sheetData);
return sheetData;
}
/**
* Get the linked property name
* @param sheetData
* @return {Promise<null|{name, id}>}
*/
async getLinkedProperty(sheetData) {
if (sheetData.data.system.linked_property_id) {
const linkedProperty = await game.l5r5e.HelpersL5r5e.getObjectGameOrPack({
id: sheetData.data.system.linked_property_id,
type: "Item",
});
if (linkedProperty) {
return {
id: linkedProperty._id,
name: linkedProperty.name,
};
}
}
return null;
}
/**
* Subscribe to events from the sheet.
* @param {jQuery} html HTML content of the sheet.
*/
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) {
return;
}
// Delete the linked property
html.find(`.linked-property-delete`).on("click", this._deleteLinkedProperty.bind(this));
}
/**
* Callback actions which occur when a dragged element is dropped on a target.
* @param {DragEvent} event The originating DragEvent
* @private
*/
async _onDrop(event) {
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) {
return;
}
// Only property allowed here
let item = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
if (!item || item.documentName !== "Item" || item.type !== "property") {
return;
}
// Set the new property, and update
this.document.system.linked_property_id = item.id;
this.document.update({
system: {
linked_property_id: this.document.system.linked_property_id,
},
});
}
/**
* Remove the link to a property for the current item
* @param {Event} event
* @return {Promise<void>}
* @private
*/
async _deleteLinkedProperty(event) {
event.preventDefault();
event.stopPropagation();
let name;
const linkedProperty = await game.l5r5e.HelpersL5r5e.getObjectGameOrPack({
id: this.document.system.linked_property_id,
type: "Item",
});
if (linkedProperty) {
name = linkedProperty.name;
}
const callback = async () => {
this.document.system.linked_property_id = null;
this.document.update({
system: {
linked_property_id: this.document.system.linked_property_id,
},
});
};
// Holing Ctrl = without confirm
if (event.ctrlKey || !name) {
return callback();
}
game.l5r5e.HelpersL5r5e.confirmDeleteDialog(
game.i18n.format("l5r5e.global.delete_confirm", { name }),
callback
);
}
}

View File

@@ -108,19 +108,12 @@ export class ItemSheetL5r5e extends BaseItemSheetL5r5e {
}
// If we are a property, the child id need to be different to parent
// (property type removed — guard kept for legacy data safety)
if (this.item.type === "property" && this.item.id === item._id) {
return;
}
// Specific ItemPattern's drop, get the associated props instead
if (item.type === "item_pattern" && item.system.linked_property_id) {
item = await game.l5r5e.HelpersL5r5e.getObjectGameOrPack({
id: item.system.linked_property_id,
type: "Item",
});
}
// Final object has to be a property
// Final object has to be a property (type removed — no more drops possible)
if (item.type !== "property") {
return;
}

View File

@@ -0,0 +1,59 @@
import { BaseItemSheetL5r5e } from "./base-item-sheet.js";
/** Mode Invocation values per invocation type */
const INVOCATION_MODE = {
general: 3,
neutre: 0,
precis: -3,
};
/**
* Sheet for Mot d'Invocation items (Chiaroscuro).
* @extends {BaseItemSheetL5r5e}
*/
export class MotInvocationSheetL5r5e extends BaseItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "mot-invocation"],
template: CONFIG.l5r5e.paths.templates + "items/mot_invocation/mot-invocation-sheet.html",
width: 500,
height: 360,
});
}
/** @override */
async getData(options = {}) {
const sheetData = await super.getData(options);
// Build invocation types list from i18n
const invTypes = game.l5r5e.HelpersL5r5e.getLocalizedRawObject("l5r5e.chiaroscuro.technique.invocation_types") ?? {};
sheetData.data.invocationTypesList = [{ id: "", label: "—" }].concat(
Object.entries(invTypes).map(([id, label]) => ({ id, label }))
);
sheetData.data.enrichedHtml = {
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
sheetData.data.system.description ?? "",
{ async: true }
),
};
return sheetData;
}
/** @override */
activateListeners(html) {
super.activateListeners(html);
if (!this.isEditable) return;
html.find("#mot_invocation_type").on("change", async (event) => {
const type = event.target.value;
const mode = INVOCATION_MODE[type] ?? 0;
// Update stored value and refresh display
await this.object.update({ system: { invocation_type: type, mode_invocation: mode } });
this.render(true);
});
}
}

View File

@@ -10,7 +10,8 @@ export class MystereSheetL5r5e extends BaseItemSheetL5r5e {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "mystere"],
template: CONFIG.l5r5e.paths.templates + "items/mystere/mystere-sheet.html",
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "attributes" }],
width: 500,
height: 380,
});
}

View File

@@ -1,14 +0,0 @@
import { ItemSheetL5r5e } from "./item-sheet.js";
/**
* @extends {ItemSheet}
*/
export class PropertySheetL5r5e extends ItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "property"],
template: CONFIG.l5r5e.paths.templates + "items/property/property-sheet.html",
});
}
}

View File

@@ -1,14 +0,0 @@
import { ItemSheetL5r5e } from "./item-sheet.js";
/**
* @extends {ItemSheet}
*/
export class SignatureScrollSheetL5r5e extends ItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "signature-scroll"],
template: CONFIG.l5r5e.paths.templates + "items/signature-scroll/signature-scroll-sheet.html",
});
}
}

View File

@@ -0,0 +1,31 @@
import { BaseItemSheetL5r5e } from "./base-item-sheet.js";
/**
* Sheet for Technique École items (Chiaroscuro).
* @extends {BaseItemSheetL5r5e}
*/
export class TechniqueEcoleSheetL5r5e extends BaseItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "technique-ecole"],
template: CONFIG.l5r5e.paths.templates + "items/technique_ecole/technique-ecole-sheet.html",
width: 500,
height: 380,
});
}
/** @override */
async getData(options = {}) {
const sheetData = await super.getData(options);
sheetData.data.enrichedHtml = {
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(
sheetData.data.system.description ?? "",
{ async: true }
),
};
return sheetData;
}
}

View File

@@ -1,195 +0,0 @@
import { ItemSheetL5r5e } from "./item-sheet.js";
/**
* @extends {ItemSheet}
*/
export class TechniqueSheetL5r5e extends ItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "technique"],
template: CONFIG.l5r5e.paths.templates + "items/technique/technique-sheet.html",
});
}
/** @override */
async getData(options = {}) {
const sheetData = await super.getData(options);
// List all available techniques type
const types = ["core", "school", "title", "chiaroscuro"];
if (game.settings.get(CONFIG.l5r5e.namespace, "techniques-customs")) {
types.push("custom");
}
sheetData.data.techniquesList = game.l5r5e.HelpersL5r5e.getTechniquesList({ types });
// Invocation sub-type fields (visible only for mot_invocation)
sheetData.data.isMotInvocation = sheetData.data.system.technique_type === "mot_invocation";
sheetData.data.invocationTypes = [
{ id: "general", label: game.i18n.localize("chiaroscuro.technique.invocation_types.general") },
{ id: "neutre", label: game.i18n.localize("chiaroscuro.technique.invocation_types.neutre") },
{ id: "precis", label: game.i18n.localize("chiaroscuro.technique.invocation_types.precis") },
];
sheetData.data.modeInvocationValues = [
{ id: "-3", label: "-3" },
{ id: "0", label: "0" },
{ id: "3", label: "+3" },
];
// Convert mode_invocation to string for selectOptions matching
sheetData.data.system.mode_invocation_str = String(sheetData.data.system.mode_invocation ?? 0);
// Sanitize Difficulty and Skill list
sheetData.data.system.difficulty = TechniqueSheetL5r5e.formatDifficulty(sheetData.data.system.difficulty);
sheetData.data.system.skill = TechniqueSheetL5r5e.translateSkillsList(
TechniqueSheetL5r5e.formatSkillList(sheetData.data.system.skill.split(",")),
false
).join(", ");
return sheetData;
}
/**
* This method is called upon form submission after form data is validated
* @param {Event} event The initial triggering submission event
* @param {Object} formData The object of validated form data with which to update the object
* @returns {Promise} A Promise which resolves once the update operation has completed
* @override
*/
async _updateObject(event, formData) {
// Change the image according to the type if this is already the case
if (
formData["system.technique_type"] &&
formData.img === `${CONFIG.l5r5e.paths.assets}icons/techs/${this.object.system.technique_type}.svg`
) {
formData.img = `${CONFIG.l5r5e.paths.assets}icons/techs/${formData["system.technique_type"]}.svg`;
}
// Sanitize Difficulty and Skill list
formData["system.difficulty"] = TechniqueSheetL5r5e.formatDifficulty(formData["system.difficulty"]);
formData["system.skill"] = TechniqueSheetL5r5e.formatSkillList(
TechniqueSheetL5r5e.translateSkillsList(formData["system.skill"].split(","), true)
).join(",");
// Convert mode_invocation_str back to number
if ("system.mode_invocation_str" in formData) {
formData["system.mode_invocation"] = parseInt(formData["system.mode_invocation_str"] ?? "0", 10);
delete formData["system.mode_invocation_str"];
}
return super._updateObject(event, formData);
}
/**
* Listen to html elements
* @param {jQuery} html HTML content of the sheet.
* @override
*/
activateListeners(html) {
super.activateListeners(html);
// *** Everything below here is only needed if the sheet is editable ***
if (!this.isEditable) {
return;
}
// Autocomplete
game.l5r5e.HelpersL5r5e.autocomplete(
html,
"system.difficulty",
[
"@T:intrigueRank",
"@T:focus",
"@T:martialRank",
"@T:statusRank|max",
"@T:strife.value|max",
"@T:vigilance",
"@T:vigilance|max",
"@T:vigilance|min",
"@T:vigilance|max(@T:statusRank)",
],
","
);
game.l5r5e.HelpersL5r5e.autocomplete(
html,
"system.skill",
Object.values(TechniqueSheetL5r5e.getSkillsTranslationMap(false)),
","
);
}
/**
* Sanitize the technique difficulty
* @param {string} str
* @return {string}
*/
static formatDifficulty(str) {
if (str && !Number.isNumeric(str) && !CONFIG.l5r5e.regex.techniqueDifficulty.test(str)) {
return "";
}
return str;
}
/**
* Get a flat map for skill translation
* @param {boolean} bToSkillId if true flip props/values
* @return {Object}
*/
static getSkillsTranslationMap(bToSkillId) {
return Array.from(CONFIG.l5r5e.skills).reduce((acc, [id, cat]) => {
if (bToSkillId) {
acc[game.l5r5e.HelpersL5r5e.normalize(game.i18n.localize(`l5r5e.skills.${cat}.${id}`))] = id;
acc[game.l5r5e.HelpersL5r5e.normalize(game.i18n.localize(`l5r5e.skills.${cat}.title`))] = cat;
} else {
acc[id] = game.i18n.localize(`l5r5e.skills.${cat}.${id}`);
acc[cat] = game.i18n.localize(`l5r5e.skills.${cat}.title`);
}
return acc;
}, {});
}
/**
* Translate a list of skill and category
* @param {string[]} aIn
* @param {boolean} bToSkillId
* @return {string[]}
*/
static translateSkillsList(aIn, bToSkillId) {
const map = TechniqueSheetL5r5e.getSkillsTranslationMap(bToSkillId);
return aIn.map((skill) => map[game.l5r5e.HelpersL5r5e.normalize(skill)]);
}
/**
* Sanitize the technique skill list
* @param {string[]} skillList
* @return {string[]}
*/
static formatSkillList(skillList) {
if (!skillList) {
return "";
}
const categories = game.l5r5e.HelpersL5r5e.getCategoriesSkillsList();
// List categories
const unqCatList = new Set();
skillList.forEach((s) => {
s = s?.trim();
if (!!s && categories.has(s)) {
unqCatList.add(s);
}
});
// List skill (not include in cat)
const unqSkillList = new Set();
skillList.forEach((s) => {
s = s?.trim();
if (!!s && CONFIG.l5r5e.skills.has(s)) {
const cat = CONFIG.l5r5e.skills.get(s);
if (!unqCatList.has(cat)) {
unqSkillList.add(s);
}
}
});
return [...unqCatList, ...unqSkillList];
}
}

View File

@@ -1,149 +0,0 @@
import { ItemSheetL5r5e } from "./item-sheet.js";
/**
* @extends {ItemSheet}
*/
export class TitleSheetL5r5e extends ItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["l5r5e", "sheet", "title"],
template: CONFIG.l5r5e.paths.templates + "items/title/title-sheet.html",
});
}
/**
* @return {Object|Promise}
*/
async getData(options = {}) {
const sheetData = await super.getData(options);
// Prepare OwnedItems
sheetData.data.embedItemsList = this._prepareEmbedItems(sheetData.data.system.items);
// Automatically compute the total xp cost (full price) and XP in title (cursus, some halved prices)
const { xp_used_total, xp_used } = game.l5r5e.HelpersL5r5e.getItemsXpCost(sheetData.data.embedItemsList);
sheetData.data.system.xp_used_total = xp_used_total;
sheetData.data.system.xp_used = xp_used;
return sheetData;
}
/**
* Prepare Embed items
* @param {[]|Map} itemsMap
* @return {[]}
* @private
*/
_prepareEmbedItems(itemsMap) {
let itemsList = itemsMap;
if (itemsMap instanceof Map) {
itemsList = Array.from(itemsMap).map(([id, item]) => item);
}
// Sort by rank desc
itemsList.sort((a, b) => (b.system.rank || 0) - (a.system.rank || 0));
return itemsList;
}
/**
* Callback actions which occur when a dragged element is dropped on a target.
* @param {DragEvent} event The originating DragEvent
* @private
*/
async _onDrop(event) {
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) {
return;
}
// Check item type and subtype
let item = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
if (!item || item.documentName !== "Item" || !["technique", "advancement"].includes(item.type)) {
return;
}
const data = item.toObject(false);
// Check xp for techs
if (item.type === "technique") {
data.system.xp_cost = data.system.xp_cost > 0 ? data.system.xp_cost : CONFIG.l5r5e.xp.techniqueCost;
data.system.xp_used = data.system.xp_cost;
}
this.document.addEmbedItem(data);
}
/**
* Subscribe to events from the sheet.
* @param {jQuery} html HTML content of the sheet.
*/
activateListeners(html) {
super.activateListeners(html);
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) {
return;
}
// *** Sub-Items management ***
html.find(".item-add").on("click", this._addSubItem.bind(this));
html.find(`.item-edit`).on("click", this._editSubItem.bind(this));
html.find(`.item-delete`).on("click", this._deleteSubItem.bind(this));
html.find(`.item-curriculum`).on("click", this._switchSubItemCurriculum.bind(this));
}
/**
* Display a dialog to choose what Item to add, and add it on this Item
* @param {Event} event
* @return {Promise<void>}
* @private
*/
async _addSubItem(event) {
event.preventDefault();
event.stopPropagation();
// Show Dialog
const selectedType = await game.l5r5e.HelpersL5r5e.showSubItemDialog(["advancement", "technique"]);
if (!selectedType) {
return;
}
// Create the new Item
const itemId = await this.document.addEmbedItem(
new game.l5r5e.ItemL5r5e({
name: game.i18n.localize(`TYPES.Item.${selectedType.toLowerCase()}`),
type: selectedType,
img: `${CONFIG.l5r5e.paths.assets}icons/items/${selectedType}.svg`,
})
);
// Get the store object and display it
const item = this.document.items.get(itemId);
if (item) {
item.sheet.render(true);
}
}
/**
* Toogle the curriculum for this embed item
* @param {Event} event
* @return {Promise<void>}
* @private
*/
async _switchSubItemCurriculum(event) {
event.preventDefault();
event.stopPropagation();
const itemId = $(event.currentTarget).data("item-id");
const item = this.document.getEmbedItem(itemId);
if (!item) {
return;
}
// Switch the state and update
item.system.in_curriculum = !item.system.in_curriculum;
return this.document.updateEmbedItem(item);
}
}

View File

@@ -15,18 +15,21 @@ export class WeaponSheetL5r5e extends ItemSheetL5r5e {
async getData(options = {}) {
const sheetData = await super.getData(options);
// Martial skills only
// Only these four skills are relevant for weapons
const allowedSkills = ["archery", "unarmed", "melee", "invocation"];
sheetData.data.skills = Array.from(CONFIG.l5r5e.skills)
.filter(([id, cat]) => cat === "martial")
.filter(([id]) => allowedSkills.includes(id))
.map(([id, cat]) => ({
id,
label: "l5r5e.skills." + cat.toLowerCase() + "." + id.toLowerCase(),
}));
// Weapon categories (Chiaroscuro)
// Weapon categories (Chiaroscuro) — sorted alphabetically
const catObj = game.l5r5e.HelpersL5r5e.getLocalizedRawObject("chiaroscuro.weapon.categories") ?? {};
sheetData.data.weaponCategories = [{ id: "", label: "—" }].concat(
Object.entries(catObj).map(([id, label]) => ({ id, label }))
Object.entries(catObj)
.map(([id, label]) => ({ id, label }))
.sort((a, b) => a.label.localeCompare(b.label, undefined, { sensitivity: "base" }))
);
return sheetData;