}
*/
static async getEmbedItemByEvent(event, actor) {
const current = $(event.currentTarget);
diff --git a/system/scripts/items/army-cohort-sheet.js b/system/scripts/items/army-cohort-sheet.js
new file mode 100644
index 0000000..1f8aac5
--- /dev/null
+++ b/system/scripts/items/army-cohort-sheet.js
@@ -0,0 +1,17 @@
+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",
+ width: 520,
+ height: 480,
+ tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
+ });
+ }
+}
diff --git a/system/scripts/items/army-fortification-sheet.js b/system/scripts/items/army-fortification-sheet.js
new file mode 100644
index 0000000..24b09de
--- /dev/null
+++ b/system/scripts/items/army-fortification-sheet.js
@@ -0,0 +1,17 @@
+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",
+ width: 520,
+ height: 480,
+ tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
+ });
+ }
+}
diff --git a/system/scripts/items/base-item-sheet.js b/system/scripts/items/base-item-sheet.js
new file mode 100644
index 0000000..9243fed
--- /dev/null
+++ b/system/scripts/items/base-item-sheet.js
@@ -0,0 +1,166 @@
+/**
+ * Extend the basic ItemSheet with some very simple modifications
+ * @extends {ItemSheet}
+ */
+export class BaseItemSheetL5r5e extends ItemSheet {
+ /** @override */
+ static get defaultOptions() {
+ return foundry.utils.mergeObject(super.defaultOptions, {
+ classes: ["l5r5e", "sheet", "item"],
+ //template: CONFIG.l5r5e.paths.templates + "items/item/item-sheet.html",
+ width: 520,
+ height: 480,
+ tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
+ });
+ }
+
+ /**
+ * Add the SendToChat button on top of sheet
+ * @override
+ */
+ _getHeaderButtons() {
+ let buttons = super._getHeaderButtons();
+
+ // Send To Chat
+ buttons.unshift({
+ label: game.i18n.localize("l5r5e.global.send_to_chat"),
+ class: "send-to-chat",
+ icon: "fas fa-comment-dots",
+ onclick: () =>
+ game.l5r5e.HelpersL5r5e.debounce(
+ "send2chat-" + this.object.id,
+ () => game.l5r5e.HelpersL5r5e.sendToChat(this.object),
+ 2000,
+ true
+ )(),
+ });
+
+ return buttons;
+ }
+
+ /**
+ * @return {Object|Promise}
+ */
+ async getData(options = {}) {
+ const sheetData = await super.getData(options);
+
+ sheetData.data.dtypes = ["String", "Number", "Boolean"];
+
+ // Fix editable
+ sheetData.editable = this.isEditable;
+ sheetData.options.editable = sheetData.editable;
+
+ 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 = "") {
+ if (name === "data.description" && initialContent) {
+ initialContent = game.l5r5e.HelpersL5r5e.convertSymbols(initialContent, false);
+ }
+ super.activateEditor(name, options, initialContent);
+ }
+
+ /**
+ * This method is called upon form submission after form data is validated
+ * @param event {Event} The initial triggering submission event
+ * @param formData {Object} 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) {
+ if (formData["data.description"]) {
+ // Base links (Journal, compendiums...)
+ formData["data.description"] = TextEditor.enrichHTML(formData["data.description"]);
+ // L5R Symbols
+ formData["data.description"] = game.l5r5e.HelpersL5r5e.convertSymbols(formData["data.description"], true);
+ }
+ return super._updateObject(event, formData);
+ }
+
+ /**
+ * Subscribe to events from the sheet.
+ * @param {jQuery} html HTML content of the sheet.
+ * @override
+ */
+ activateListeners(html) {
+ super.activateListeners(html);
+
+ // Commons
+ game.l5r5e.HelpersL5r5e.commonListeners(html, this.actor);
+
+ // Everything below here is only needed if the sheet is editable
+ if (!this.isEditable) {
+ return;
+ }
+
+ // On focus on one numeric element, select all text for better experience
+ html.find(".select-on-focus").on("focus", (event) => {
+ event.preventDefault();
+ event.stopPropagation();
+ event.target.select();
+ });
+ }
+
+ /**
+ * Add a embed item
+ * @param {Event} event
+ * @private
+ */
+ _addSubItem(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ const itemId = $(event.currentTarget).data("item-id");
+ console.warn("L5R5E | TODO ItemSheetL5r5e._addSubItem()", itemId); // TODO _addSubItem Currently not used, title override it
+ }
+
+ /**
+ * Add a embed item
+ * @param {Event} event
+ * @private
+ */
+ _editSubItem(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ const itemId = $(event.currentTarget).data("item-id");
+ const item = this.document.items.get(itemId);
+ if (item) {
+ item.sheet.render(true);
+ }
+ }
+
+ /**
+ * Delete a embed item
+ * @param {Event} event
+ * @private
+ */
+ _deleteSubItem(event) {
+ event.preventDefault();
+ event.stopPropagation();
+ const itemId = $(event.currentTarget).data("item-id");
+ const item = this.document.getEmbedItem(itemId);
+ if (!item) {
+ return;
+ }
+
+ const callback = async () => {
+ this.document.deleteEmbedItem(itemId);
+ };
+
+ // Holing Ctrl = without confirm
+ if (event.ctrlKey) {
+ return callback();
+ }
+
+ game.l5r5e.HelpersL5r5e.confirmDeleteDialog(
+ game.i18n.format("l5r5e.global.delete_confirm", { name: item.name }),
+ callback
+ );
+ }
+}
diff --git a/system/scripts/items/item-sheet.js b/system/scripts/items/item-sheet.js
index 9edb579..ab1024e 100644
--- a/system/scripts/items/item-sheet.js
+++ b/system/scripts/items/item-sheet.js
@@ -1,8 +1,10 @@
+import { BaseItemSheetL5r5e } from "./base-item-sheet.js";
+
/**
- * Extend the basic ItemSheet with some very simple modifications
+ * Extend BaseItemSheetL5r5e with modifications for objects
* @extends {ItemSheet}
*/
-export class ItemSheetL5r5e extends ItemSheet {
+export class ItemSheetL5r5e extends BaseItemSheetL5r5e {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
@@ -14,46 +16,17 @@ export class ItemSheetL5r5e extends ItemSheet {
});
}
- /**
- * Add the SendToChat button on top of sheet
- * @override
- */
- _getHeaderButtons() {
- let buttons = super._getHeaderButtons();
-
- // Send To Chat
- buttons.unshift({
- label: game.i18n.localize("l5r5e.global.send_to_chat"),
- class: "send-to-chat",
- icon: "fas fa-comment-dots",
- onclick: () =>
- game.l5r5e.HelpersL5r5e.debounce(
- "send2chat-" + this.object.id,
- () => game.l5r5e.HelpersL5r5e.sendToChat(this.object),
- 2000,
- true
- )(),
- });
-
- return buttons;
- }
-
/**
* @return {Object|Promise}
*/
async getData(options = {}) {
const sheetData = await super.getData(options);
- sheetData.data.dtypes = ["String", "Number", "Boolean"];
sheetData.data.ringsList = game.l5r5e.HelpersL5r5e.getRingsList();
// Prepare Properties (id/name => object)
await this._prepareProperties(sheetData);
- // Fix editable
- sheetData.editable = this.isEditable;
- sheetData.options.editable = sheetData.editable;
-
return sheetData;
}
@@ -79,37 +52,6 @@ export class ItemSheetL5r5e extends ItemSheet {
}
}
- /**
- * 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 = "") {
- if (name === "data.description" && initialContent) {
- initialContent = game.l5r5e.HelpersL5r5e.convertSymbols(initialContent, false);
- }
- super.activateEditor(name, options, initialContent);
- }
-
- /**
- * This method is called upon form submission after form data is validated
- * @param event {Event} The initial triggering submission event
- * @param formData {Object} 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) {
- if (formData["data.description"]) {
- // Base links (Journal, compendiums...)
- formData["data.description"] = TextEditor.enrichHTML(formData["data.description"]);
- // L5R Symbols
- formData["data.description"] = game.l5r5e.HelpersL5r5e.convertSymbols(formData["data.description"], true);
- }
- return super._updateObject(event, formData);
- }
-
/**
* Subscribe to events from the sheet.
* @param {jQuery} html HTML content of the sheet.
@@ -118,21 +60,11 @@ export class ItemSheetL5r5e extends ItemSheet {
activateListeners(html) {
super.activateListeners(html);
- // Commons
- game.l5r5e.HelpersL5r5e.commonListeners(html, this.actor);
-
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) {
return;
}
- // On focus on one numeric element, select all text for better experience
- html.find(".select-on-focus").on("focus", (event) => {
- event.preventDefault();
- event.stopPropagation();
- event.target.select();
- });
-
// Delete a property
html.find(`.property-delete`).on("click", this._deleteProperty.bind(this));
}
@@ -260,60 +192,4 @@ export class ItemSheetL5r5e extends ItemSheet {
callback
);
}
-
- /**
- * Add a embed item
- * @param {Event} event
- * @private
- */
- _addSubItem(event) {
- event.preventDefault();
- event.stopPropagation();
- const itemId = $(event.currentTarget).data("item-id");
- console.warn("L5R5E | TODO ItemSheetL5r5e._addSubItem()", itemId); // TODO _addSubItem Currently not used, title override it
- }
-
- /**
- * Add a embed item
- * @param {Event} event
- * @private
- */
- _editSubItem(event) {
- event.preventDefault();
- event.stopPropagation();
- const itemId = $(event.currentTarget).data("item-id");
- const item = this.document.items.get(itemId);
- if (item) {
- item.sheet.render(true);
- }
- }
-
- /**
- * Delete a embed item
- * @param {Event} event
- * @private
- */
- _deleteSubItem(event) {
- event.preventDefault();
- event.stopPropagation();
- const itemId = $(event.currentTarget).data("item-id");
- const item = this.document.getEmbedItem(itemId);
- if (!item) {
- return;
- }
-
- const callback = async () => {
- this.document.deleteEmbedItem(itemId);
- };
-
- // Holing Ctrl = without confirm
- if (event.ctrlKey) {
- return callback();
- }
-
- game.l5r5e.HelpersL5r5e.confirmDeleteDialog(
- game.i18n.format("l5r5e.global.delete_confirm", { name: item.name }),
- callback
- );
- }
}
diff --git a/system/scripts/main-l5r5e.js b/system/scripts/main-l5r5e.js
index 0b9cdf6..a1e50f5 100644
--- a/system/scripts/main-l5r5e.js
+++ b/system/scripts/main-l5r5e.js
@@ -11,6 +11,7 @@ import HooksL5r5e from "./hooks.js";
import { ActorL5r5e } from "./actor.js";
import { CharacterSheetL5r5e } from "./actors/character-sheet.js";
import { NpcSheetL5r5e } from "./actors/npc-sheet.js";
+import { ArmySheetL5r5e } from "./actors/army-sheet.js";
// Dice and rolls
import { L5rBaseDie } from "./dice/dietype/l5r-base-die.js";
import { AbilityDie } from "./dice/dietype/ability-die.js";
@@ -32,6 +33,8 @@ import { TitleSheetL5r5e } from "./items/title-sheet.js";
import { BondSheetL5r5e } from "./items/bond-sheet.js";
import { SignatureScrollSheetL5r5e } from "./items/signature-scroll-sheet.js";
import { ItemPatternSheetL5r5e } from "./items/item-pattern-sheet.js";
+import { ArmyCohortSheetL5r5e } from "./items/army-cohort-sheet.js";
+import { ArmyFortificationSheetL5r5e } from "./items/army-fortification-sheet.js";
// JournalEntry
import { JournalL5r5e } from "./journal.js";
import { BaseJournalSheetL5r5e } from "./journals/base-journal-sheet.js";
@@ -106,6 +109,7 @@ Hooks.once("init", async () => {
Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("l5r5e", CharacterSheetL5r5e, { types: ["character"], makeDefault: true });
Actors.registerSheet("l5r5e", NpcSheetL5r5e, { types: ["npc"], makeDefault: true });
+ Actors.registerSheet("l5r5e", ArmySheetL5r5e, { types: ["army"], makeDefault: true });
// Items
Items.unregisterSheet("core", ItemSheet);
@@ -120,6 +124,8 @@ Hooks.once("init", async () => {
Items.registerSheet("l5r5e", BondSheetL5r5e, { types: ["bond"], makeDefault: true });
Items.registerSheet("l5r5e", SignatureScrollSheetL5r5e, { types: ["signature_scroll"], makeDefault: true });
Items.registerSheet("l5r5e", ItemPatternSheetL5r5e, { types: ["item_pattern"], makeDefault: true });
+ Items.registerSheet("l5r5e", ArmyCohortSheetL5r5e, { types: ["army_cohort"], makeDefault: true });
+ Items.registerSheet("l5r5e", ArmyFortificationSheetL5r5e, { types: ["army_fortification"], makeDefault: true });
// Journal
Items.unregisterSheet("core", JournalSheet);
diff --git a/system/scripts/preloadTemplates.js b/system/scripts/preloadTemplates.js
index fb02bce..7d9a4b3 100644
--- a/system/scripts/preloadTemplates.js
+++ b/system/scripts/preloadTemplates.js
@@ -28,6 +28,10 @@ export const PreloadTemplates = async function () {
`${tpl}actors/npc/social.html`,
`${tpl}actors/npc/skill.html`,
`${tpl}actors/npc/techniques.html`,
+ // *** Actors : Army ***
+ `${tpl}actors/army/cohort.html`,
+ `${tpl}actors/army/fortification.html`,
+ `${tpl}actors/army/others.html`,
// *** Items ***
`${tpl}items/advancement/advancement-entry.html`,
`${tpl}items/advancement/advancement-sheet.html`,
@@ -57,5 +61,7 @@ export const PreloadTemplates = async function () {
`${tpl}items/weapon/weapons.html`,
`${tpl}items/weapon/weapon-entry.html`,
`${tpl}items/weapon/weapon-sheet.html`,
+ `${tpl}items/army-cohort/army-cohort-entry.html`,
+ `${tpl}items/army-fortification/army-fortification-entry.html`,
]);
};
diff --git a/system/system.json b/system/system.json
index 6f8e205..dd074a6 100644
--- a/system/system.json
+++ b/system/system.json
@@ -4,8 +4,8 @@
"description": "This is an authorised multilingual game system En|Fr|Es, for Legend of the Five Rings (5th Edition) by Edge Studio - Join the official Discord server: Official Discord
- Rejoignez la communauté Francophone: Francophone Discord
",
"url": "https://gitlab.com/teaml5r/l5r5e",
"manifest": "https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json",
- "download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v1.3.5/raw/l5r5e.zip?job=build",
- "version": "1.3.5",
+ "download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v1.4.0/raw/l5r5e.zip?job=build",
+ "version": "1.4.0",
"minimumCoreVersion": "0.8.5",
"compatibleCoreVersion": "0.8.9",
"manifestPlusVersion": "1.0.0",
diff --git a/system/template.json b/system/template.json
index bbcfcdc..5ba1041 100644
--- a/system/template.json
+++ b/system/template.json
@@ -1,6 +1,6 @@
{
"Actor": {
- "types": ["character", "npc"],
+ "types": ["character", "npc", "army"],
"templates": {
"identity": {
"identity": {
@@ -141,6 +141,33 @@
"social": 0,
"trade": 0
}
+ },
+ "army": {
+ "warlord": "",
+ "allies_backers": "",
+ "purpose_mustering": "",
+ "battle_readiness": {
+ "casualties_strength": {
+ "max": 0,
+ "value": 0
+ },
+ "panic_discipline": {
+ "max": 0,
+ "value": 0
+ }
+ },
+ "commander": "",
+ "commander_abilities": "",
+ "army_abilities": "",
+ "commander_standing": {
+ "honor": 0,
+ "glory": 0,
+ "status": 0
+ },
+ "supplies_logistics": "",
+ "notes": "",
+ "description": "",
+ "past_battles": ""
}
},
"Item": {
@@ -155,7 +182,9 @@
"title",
"bond",
"signature_scroll",
- "item_pattern"
+ "item_pattern",
+ "army_cohort",
+ "army_fortification"
],
"templates": {
"basics": {
@@ -236,6 +265,28 @@
},
"signature_scroll": {
"templates": ["basics", "advancement"]
+ },
+ "army_cohort": {
+ "templates": ["basics"],
+ "leader": "",
+ "equipment": "",
+ "abilities": "",
+ "battle_readiness": {
+ "casualties_strength": {
+ "max": 0,
+ "value": 0
+ },
+ "panic_discipline": {
+ "max": 0,
+ "value": 0
+ }
+ }
+ },
+ "army_fortification": {
+ "templates": ["basics"],
+ "difficulty": "",
+ "attrition_reduction": "",
+ "notes": ""
}
}
}
diff --git a/system/templates/actors/army-sheet.html b/system/templates/actors/army-sheet.html
new file mode 100644
index 0000000..5d59b54
--- /dev/null
+++ b/system/templates/actors/army-sheet.html
@@ -0,0 +1,99 @@
+
\ No newline at end of file
diff --git a/system/templates/actors/army/cohort.html b/system/templates/actors/army/cohort.html
new file mode 100644
index 0000000..92501db
--- /dev/null
+++ b/system/templates/actors/army/cohort.html
@@ -0,0 +1,13 @@
+
+
+
+ {{#each data.splitItemsList.army_cohort as |item|}}
+ {{> 'systems/l5r5e/templates/items/army-cohort/army-cohort-entry.html' cohort=item editable=../options.editable}}
+ {{/each}}
+
+
\ No newline at end of file
diff --git a/system/templates/actors/army/fortification.html b/system/templates/actors/army/fortification.html
new file mode 100644
index 0000000..9a3e033
--- /dev/null
+++ b/system/templates/actors/army/fortification.html
@@ -0,0 +1,13 @@
+
+
+
+ {{#each data.splitItemsList.army_fortification as |item|}}
+ {{> 'systems/l5r5e/templates/items/army-fortification/army-fortification-entry.html' fortification=item editable=../options.editable}}
+ {{/each}}
+
+
\ No newline at end of file
diff --git a/system/templates/actors/army/others.html b/system/templates/actors/army/others.html
new file mode 100644
index 0000000..5c24d56
--- /dev/null
+++ b/system/templates/actors/army/others.html
@@ -0,0 +1,25 @@
+
+ {{!-- Supplies and Logistics --}}
+
+
+ {{editor content=data.data.supplies_logistics target="data.supplies_logistics" button=true editable=options.editable}}
+
+
+ {{!-- Past Battles --}}
+
+
+ {{editor content=data.data.past_battles target="data.past_battles" button=true editable=options.editable}}
+
+
+ {{!-- Description (public) --}}
+
+
+ {{editor content=data.data.description target="data.description" button=true editable=options.editable}}
+
+
+ {{!-- Notes (private) --}}
+
+
+ {{editor content=data.data.notes target="data.notes" button=true editable=options.editable}}
+
+
\ No newline at end of file
diff --git a/system/templates/items/army-cohort/army-cohort-entry.html b/system/templates/items/army-cohort/army-cohort-entry.html
new file mode 100644
index 0000000..f81f452
--- /dev/null
+++ b/system/templates/items/army-cohort/army-cohort-entry.html
@@ -0,0 +1,22 @@
+
+
+
+ {{localize 'l5r5e.army.cohort.leader'}} : {{cohort.data.leader}}
+ {{localize 'l5r5e.equipment'}} : {{cohort.data.equipment}}
+ {{localize 'l5r5e.army.cohort.abilities'}} : {{cohort.data.abilities}}
+ {{localize 'l5r5e.description'}} : {{cohort.data.description}}
+
+
\ No newline at end of file
diff --git a/system/templates/items/army-cohort/army-cohort-sheet.html b/system/templates/items/army-cohort/army-cohort-sheet.html
new file mode 100644
index 0000000..c1ef502
--- /dev/null
+++ b/system/templates/items/army-cohort/army-cohort-sheet.html
@@ -0,0 +1,43 @@
+
diff --git a/system/templates/items/army-fortification/army-fortification-entry.html b/system/templates/items/army-fortification/army-fortification-entry.html
new file mode 100644
index 0000000..6a849bc
--- /dev/null
+++ b/system/templates/items/army-fortification/army-fortification-entry.html
@@ -0,0 +1,17 @@
+
+
+
+ {{localize 'l5r5e.description'}} : {{fortification.data.description}}
+
+
\ No newline at end of file
diff --git a/system/templates/items/army-fortification/army-fortification-sheet.html b/system/templates/items/army-fortification/army-fortification-sheet.html
new file mode 100644
index 0000000..4fb00f9
--- /dev/null
+++ b/system/templates/items/army-fortification/army-fortification-sheet.html
@@ -0,0 +1,22 @@
+