Working on 0.8.x

- Title's Advancements are now reflected on actor
- Migration update
This commit is contained in:
Vlyan
2021-05-22 17:20:17 +02:00
parent 4f9b72c63f
commit 53f04e6cef
33 changed files with 423 additions and 281 deletions

View File

@@ -108,4 +108,65 @@ export class ActorL5r5e extends Actor {
}
}
}
/**
* Add a Ring/Skill point to the current actor if the item is a advancement
* @param {Item} item
* @return {Promise<void>}
*/
async addBonus(item) {
return this._updateActorFromAdvancement(item, true);
}
/**
* Remove a Ring/Skill point to the current actor if the item is a advancement
* @param {Item} item
* @return {Promise<void>}
*/
async removeBonus(item) {
return this._updateActorFromAdvancement(item, false);
}
/**
* Alter Actor skill/ring from a advancement
* @param {Item} item
* @param {boolean} isAdd True=add, false=remove
* @return {Promise<void>}
* @private
*/
async _updateActorFromAdvancement(item, isAdd) {
if (item && item.type === "advancement") {
const actor = foundry.utils.duplicate(this.data.data);
const itemData = item.data.data;
if (itemData.advancement_type === "ring") {
// Ring
if (isAdd) {
actor.rings[itemData.ring] = Math.min(9, actor.rings[itemData.ring] + 1);
} else {
actor.rings[itemData.ring] = Math.max(1, actor.rings[itemData.ring] - 1);
}
} else {
// Skill
const skillCatId = CONFIG.l5r5e.skills.get(itemData.skill);
if (skillCatId) {
if (isAdd) {
actor.skills[skillCatId][itemData.skill] = Math.min(
9,
actor.skills[skillCatId][itemData.skill] + 1
);
} else {
actor.skills[skillCatId][itemData.skill] = Math.max(
0,
actor.skills[skillCatId][itemData.skill] - 1
);
}
}
}
// Update Actor
await this.update({
data: foundry.utils.diffObject(this.data.data, actor),
});
}
}
}

View File

@@ -58,9 +58,19 @@ export class BaseSheetL5r5e extends ActorSheet {
// Add tech the character knows
sheetData.items.forEach((item) => {
if (item.type === "technique") {
out[item.data.technique_type].push(item);
}
switch (item.type) {
case "technique":
out[item.data.technique_type].push(item);
break;
case "title":
Array.from(item.data.items).forEach(([id, embedItem]) => {
if (embedItem.data.type === "technique") {
out[embedItem.data.data.technique_type].push(embedItem.data);
}
});
break;
} //swi
});
// Remove unused techs
@@ -170,35 +180,44 @@ export class BaseSheetL5r5e extends ActorSheet {
) {
return;
}
item = item.toJSON();
// Dropped a item with same "id" as one owned, add qte instead
if (item.data.quantity && this.actor.data.items) {
const tmpItem = this.actor.data.items.find((e) => e.name === item.name && e.type === item.type);
if (item.data.data.quantity && this.actor.data.items) {
const tmpItem = this.actor.data.items.find((e) => e.name === item.data.name && e.type === item.data.type);
if (tmpItem && this._modifyQuantity(tmpItem.id, 1)) {
return;
}
}
// Item subtype specific
switch (item.type) {
switch (item.data.type) {
case "bond": // no break
case "advancement": // no break
case "peculiarity": // no break
case "item_pattern": // no break
case "signature_scroll":
// Modify the bought at rank to the current actor rank
if (this.actor.data.data.identity?.school_rank) {
item.data.bought_at_rank = this.actor.data.data.identity.school_rank;
item.data.data.bought_at_rank = this.actor.data.data.identity.school_rank;
}
break;
case "advancement":
// Modify the bought at rank to the current actor rank
if (this.actor.data.data.identity?.school_rank) {
item.data.data.bought_at_rank = this.actor.data.data.identity.school_rank;
}
// Specific advancements, remove 1 to selected ring/skill
await this.actor.addBonus(item);
break;
case "technique":
// School_ability and mastery_ability, allow only 1 per type
if (CONFIG.l5r5e.techniques.get(item.data.technique_type)?.type === "school") {
if (CONFIG.l5r5e.techniques.get(item.data.data.technique_type)?.type === "school") {
if (
Array.from(this.actor.items).some(
(e) => e.type === "technique" && e.data.data.technique_type === item.data.technique_type
(e) =>
e.type === "technique" && e.data.data.technique_type === item.data.data.technique_type
)
) {
ui.notifications.info(game.i18n.localize("l5r5e.techniques.only_one"));
@@ -206,24 +225,25 @@ export class BaseSheetL5r5e extends ActorSheet {
}
// No cost for schools
item.data.xp_cost = 0;
item.data.xp_used = 0;
item.data.in_curriculum = true;
item.data.data.xp_cost = 0;
item.data.data.xp_used = 0;
item.data.data.in_curriculum = true;
} else {
// Check if technique is allowed for this character
if (!game.user.isGM && !this.actor.data.data.techniques[item.data.technique_type]) {
if (!game.user.isGM && !this.actor.data.data.techniques[item.data.data.technique_type]) {
ui.notifications.info(game.i18n.localize("l5r5e.techniques.not_allowed"));
return;
}
// Verify cost
item.data.xp_cost = item.data.xp_cost > 0 ? item.data.xp_cost : CONFIG.l5r5e.xp.techniqueCost;
item.data.xp_used = item.data.xp_cost;
item.data.data.xp_cost =
item.data.data.xp_cost > 0 ? item.data.data.xp_cost : CONFIG.l5r5e.xp.techniqueCost;
item.data.data.xp_used = item.data.data.xp_cost;
}
// Modify the bought at rank to the current actor rank
if (this.actor.data.data.identity?.school_rank) {
item.data.bought_at_rank = this.actor.data.data.identity.school_rank;
item.data.data.bought_at_rank = this.actor.data.data.identity.school_rank;
}
break;
}
@@ -234,7 +254,7 @@ export class BaseSheetL5r5e extends ActorSheet {
return;
}
return this._onDropItemCreate(item);
return this._onDropItemCreate(item.data.toObject(false));
}
/**
@@ -395,12 +415,25 @@ export class BaseSheetL5r5e extends ActorSheet {
event.preventDefault();
event.stopPropagation();
let item;
const itemId = $(event.currentTarget).data("item-id");
if (!itemId) {
return;
}
const item = this.actor.items.get(itemId);
const itemParentId = $(event.currentTarget).data("item-parent-id");
if (itemParentId) {
// Embed Item
const parentItem = this.actor.items.get(itemParentId);
if (!parentItem) {
return;
}
item = parentItem.items.get(itemId);
} else {
// Regular item
item = this.actor.items.get(itemId);
}
if (!item) {
return;
}
@@ -421,35 +454,20 @@ export class BaseSheetL5r5e extends ActorSheet {
return;
}
// Remove 1 qty if possible
const tmpItem = this.actor.items.get(itemId);
if (tmpItem && tmpItem.data.data.quantity > 1 && this._modifyQuantity(tmpItem.id, -1)) {
if (!tmpItem) {
return;
}
// Remove 1 qty if possible
if (tmpItem.data.data.quantity > 1 && this._modifyQuantity(tmpItem.id, -1)) {
return;
}
const callback = async () => {
// Specific advancements, remove 1 to selected ring/skill
if (tmpItem.type === "advancement") {
const actor = duplicate(this.actor.data.data);
const itmData = tmpItem.data.data;
if (itmData.advancement_type === "ring") {
// Ring
actor.rings[itmData.ring] = Math.max(1, actor.rings[itmData.ring] - 1);
} else {
// Skill
const skillCatId = CONFIG.l5r5e.skills.get(itmData.skill);
if (skillCatId) {
actor.skills[skillCatId][itmData.skill] = Math.max(
0,
actor.skills[skillCatId][itmData.skill] - 1
);
}
}
// Update Actor
this.actor.update({
data: diffObject(this.actor.data.data, actor),
});
await this.actor.removeBonus(tmpItem);
}
return this.actor.deleteEmbeddedDocuments("Item", [itemId]);
};

View File

@@ -49,13 +49,10 @@ export class CharacterSheetL5r5e extends BaseSheetL5r5e {
// Split Money
sheetData.data.data.money = this._zeniToMoney(this.actor.data.data.zeni);
// Split school advancements by rank, and calculate xp spent
// Split school advancements by rank, and calculate xp spent and add it to total
this._prepareSchoolAdvancement(sheetData);
// Titles
this._prepareTitles(sheetData);
// Others
// Split Others advancements, and calculate xp spent and add it to total
this._prepareOthersAdvancement(sheetData);
// Total
@@ -105,13 +102,6 @@ export class CharacterSheetL5r5e extends BaseSheetL5r5e {
.activate("advancement_rank_" + (this.actor.data.data.identity.school_rank || 0));
}
/**
* Prepare Titles, and get xp spend
*/
_prepareTitles(sheetData) {
// TODO
}
/**
* Split the school advancement, calculate the total xp spent and the current total xp spent by rank
*/
@@ -148,12 +138,23 @@ export class CharacterSheetL5r5e extends BaseSheetL5r5e {
* Prepare Bonds, Item Pattern, Signature Scroll and get xp spend
*/
_prepareOthersAdvancement(sheetData) {
// Split OthersAdvancement from items
sheetData.data.advancementsOthers = sheetData.items.filter((item) =>
["bond", "item_pattern", "title", "signature_scroll"].includes(item.type)
);
// Sort by rank desc
// sheetData.data.bondsList.sort((a, b) => (b.data.rank || 0) - (a.data.rank || 0));
sheetData.data.advancementsOthers.sort((a, b) => (b.data.rank || 0) - (a.data.rank || 0));
// Total xp spent
sheetData.data.advancementsOthersTotalXp = sheetData.data.advancementsOthers.reduce(
(acc, item) => acc + (item.data.xp_used || 0),
0
);
// Update the total spent
sheetData.data.data.xp_spent =
parseInt(sheetData.data.data.xp_spent) + sheetData.data.advancementsOthersTotalXp;
}
/**
@@ -177,6 +178,12 @@ export class CharacterSheetL5r5e extends BaseSheetL5r5e {
return super._updateObject(event, formData);
}
/**
* Convert a sum in Zeni to Zeni, Bu and Koku
* @param {number} zeni
* @return {{bu: number, koku: number, zeni: number}}
* @private
*/
_zeniToMoney(zeni) {
const money = {
koku: 0,
@@ -196,6 +203,14 @@ export class CharacterSheetL5r5e extends BaseSheetL5r5e {
return money;
}
/**
* Convert a sum in Zeni, Bu and Koku to Zeni
* @param {number} koku
* @param {number} bu
* @param {number} zeni
* @return {number}
* @private
*/
_moneyToZeni(koku, bu, zeni) {
return Math.floor(koku * CONFIG.l5r5e.money[0]) + Math.floor(bu * CONFIG.l5r5e.money[1]) + Math.floor(zeni);
}

View File

@@ -287,11 +287,14 @@ export class TwentyQuestions {
// Clear and add items to actor
const deleteIds = actor.data.items.map((e) => e.id);
await actor.deleteEmbeddedDocuments("Item", deleteIds);
if (deleteIds.length > 0) {
await actor.deleteEmbeddedDocuments("Item", deleteIds);
}
// Add items in 20Q to actor
for (const types of Object.values(itemsCache)) {
for (const item of types) {
const newItemsData = [];
Object.values(itemsCache).forEach((types) => {
types.forEach((item) => {
const itemData = foundry.utils.duplicate(item.data);
if (itemData.data?.bought_at_rank) {
itemData.data.bought_at_rank = 0;
@@ -299,8 +302,11 @@ export class TwentyQuestions {
if (itemData.data?.xp_spent) {
itemData.data.xp_spent = 0;
}
await actor.createEmbeddedDocuments("Item", [itemData]);
}
newItemsData.push(itemData);
});
});
if (newItemsData.length > 0) {
await actor.createEmbeddedDocuments("Item", newItemsData);
}
// Update actor

View File

@@ -23,7 +23,7 @@ L5R5E.techniques.set("ninjutsu", { type: "core", displayInTypes: true });
L5R5E.techniques.set("school_ability", { type: "school", displayInTypes: false });
L5R5E.techniques.set("mastery_ability", { type: "school", displayInTypes: false });
// Title
// L5R5E.techniques.set("title_ability", { type: "title", displayInTypes: false });
L5R5E.techniques.set("title_ability", { type: "title", displayInTypes: false });
// Custom
L5R5E.techniques.set("specificity", { type: "custom", displayInTypes: false });

View File

@@ -71,14 +71,14 @@ export class L5rBaseDie extends DiceTerm {
* Evaluate the roll term, populating the results Array
* @override
*/
evaluate({ minimize = false, maximize = false } = {}) {
evaluate({ minimize = false, maximize = false, async = false } = {}) {
if (this._evaluated) {
throw new Error(`This ${this.constructor.name} has already been evaluated and is immutable`);
}
// Roll the initial number of dice
for (let n = 1; n <= this.number; n++) {
this.roll({ minimize, maximize });
this.roll({ minimize, maximize, async });
}
// Apply modifiers

View File

@@ -294,14 +294,6 @@ export class RollL5r5e extends Roll {
return renderTemplate(chatOptions.template, chatData);
}
/**
* Render the HTML for the ChatMessage which should be added to the log
* @return {Promise<jQuery>}
*/
async getHTML() {
console.log(" --------- getHTML");
}
/**
* Transform a Roll instance into a ChatMessage, displaying the roll result.
* This function can either create the ChatMessage directly, or return the data object that will be used to create.

View File

@@ -7,6 +7,14 @@ export class ItemL5r5e extends Item {
return this.data.data.items || null;
}
/**
* Return the linked Actor instance if any (current or embed)
* @return {Actor|null}
*/
get actor() {
return super.actor || game.actors.get(this.data.data.parent_id?.actor_id) || null;
}
/**
* Create a new entity using provided input data
* @override
@@ -27,7 +35,7 @@ export class ItemL5r5e extends Item {
*/
async update(data = {}, context = {}) {
// Regular
if (!this.data.data.parentId) {
if (!this.data.data.parent_id) {
return super.update(data, context);
}
@@ -67,7 +75,7 @@ export class ItemL5r5e extends Item {
this.data.data.items = new Map();
itemsData.forEach((item) => {
this.addEmbedItem(item, { save: false, newId: false });
this.addEmbedItem(item, { save: false, newId: false, addBonusToActor: false });
});
}
}
@@ -75,10 +83,16 @@ export class ItemL5r5e extends Item {
// ***** parent ids management *****
/**
* Return a string with idemId + actorId if any
* @return {string} itemId|actor
* @return {{item_id: (string|null), actor_id?: (string|null)}}
*/
getParentsIds() {
return this.id + (this.actor?.data?._id ? `|${this.actor.data._id}` : "");
const parent = {
item_id: this.id,
};
if (this.actor?.data?._id) {
parent.actor_id = this.actor.data._id;
}
return parent;
}
/**
@@ -86,17 +100,18 @@ export class ItemL5r5e extends Item {
* @return {ItemL5r5e|null}
*/
getItemFromParentId() {
const parentIds = this.data.data.parent_id;
let parentItem;
let [parentItemId, parentActorId] = this.data.data.parentId.split("|");
if (parentActorId) {
if (parentIds?.actor_id) {
// Actor item object
const parentActor = parentActorId ? game.actors.get(parentActorId) : null;
parentItem = parentActor?.items.get(parentItemId);
} else {
const parentActor = parentIds.actor_id ? game.actors.get(parentIds.actor_id) : null;
parentItem = parentActor?.items.get(parentIds.item_id);
} else if (parentIds?.item_id) {
// World Object
parentItem = game.items.get(parentItemId);
parentItem = game.items.get(parentIds.item_id);
}
return parentItem;
}
@@ -115,9 +130,10 @@ export class ItemL5r5e extends Item {
* @param {ItemL5r5e} item Object to add
* @param {boolean} save if we save in db or not (used internally)
* @param {boolean} newId if we change the id
* @param {boolean} addBonusToActor if we update the actor bonus for advancements
* @return {Promise<void>}
*/
async addEmbedItem(item, { save = true, newId = true } = {}) {
async addEmbedItem(item, { save = true, newId = true, addBonusToActor = true } = {}) {
if (!item) {
return;
}
@@ -133,14 +149,17 @@ export class ItemL5r5e extends Item {
}
// Tag parent (flags won't work as we have no id in db)
item.data.data.parentId = this.getParentsIds();
item.data.data.parent_id = this.getParentsIds();
// Object
this.data.data.items.set(item.data._id, item);
// TODO add bonus from actor
if (this.actor instanceof Actor) {
// const item = this.data.data.items.get(id);
// Add bonus to actor
if (addBonusToActor) {
const actor = this.actor;
if (item instanceof Item && actor instanceof Actor) {
actor.addBonus(item);
}
}
if (save) {
@@ -155,23 +174,28 @@ export class ItemL5r5e extends Item {
* @return {Promise<void>}
*/
async updateEmbedItem(item, { save = true } = {}) {
await this.addEmbedItem(item, { save, newId: false });
await this.addEmbedItem(item, { save, newId: false, addBonusToActor: false });
}
/**
* Delete the Embed Item and clear the actor bonus if any
* @param {ItemL5r5e} item Object to add
* @param id Item id
* @param {boolean} save if we save in db or not (used internally)
* @param {boolean} removeBonusFromActor if we update the actor bonus for advancements
* @return {Promise<void>}
*/
async deleteEmbedItem(id, { save = true } = {}) {
async deleteEmbedItem(id, { save = true, removeBonusFromActor = true } = {}) {
if (!this.data.data.items.has(id)) {
return;
}
// TODO remove bonus from actor
if (this.actor instanceof Actor) {
// const item = this.data.data.items.get(id);
// Remove bonus from actor
if (removeBonusFromActor) {
const actor = this.actor;
const item = this.data.data.items.get(id);
if (item instanceof Item && actor instanceof Actor) {
actor.removeBonus(item);
}
}
// Remove the embed item

View File

@@ -7,7 +7,7 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
/**
* Sub Types of advancements
*/
static types = ["ring", "skill"]; // "peculiarity" and "technique" have theirs own xp count
static types = ["ring", "skill"]; // others have theirs own xp count
/** @override */
static get defaultOptions() {
@@ -73,47 +73,55 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
// Modify image to reflect choice
if (newChoice.ring) {
name = game.i18n.localize(`l5r5e.rings.${newChoice.ring}`) + "+1";
img = `systems/l5r5e/assets/icons/rings/${newChoice.ring}.svg`;
} else if (newChoice.skill) {
name =
game.i18n.localize(`l5r5e.skills.${CONFIG.l5r5e.skills.get(newChoice.skill)}.${newChoice.skill}`) +
"+1";
img = `systems/l5r5e/assets/dices/default/skill_blank.svg`;
}
// Object embed in actor ?
if (this.actor) {
const actor = duplicate(this.actor.data.data);
const actor = this.document.actor;
if (actor) {
const actorData = foundry.utils.duplicate(actor.data.data);
let skillCatId = null;
// Old choices
if (oldChoice.ring) {
actor.rings[oldChoice.ring] = Math.max(1, actor.rings[oldChoice.ring] - 1);
actorData.rings[oldChoice.ring] = Math.max(1, actorData.rings[oldChoice.ring] - 1);
}
if (oldChoice.skill) {
skillCatId = CONFIG.l5r5e.skills.get(oldChoice.skill);
actor.skills[skillCatId][oldChoice.skill] = Math.max(0, actor.skills[skillCatId][oldChoice.skill] - 1);
actorData.skills[skillCatId][oldChoice.skill] = Math.max(
0,
actorData.skills[skillCatId][oldChoice.skill] - 1
);
}
// new choices
if (newChoice.ring) {
actor.rings[newChoice.ring] = actor.rings[newChoice.ring] + 1;
xp_used = actor.rings[newChoice.ring] * CONFIG.l5r5e.xp.ringCostMultiplier;
actorData.rings[newChoice.ring] = actorData.rings[newChoice.ring] + 1;
xp_used = actorData.rings[newChoice.ring] * CONFIG.l5r5e.xp.ringCostMultiplier;
name =
game.i18n.localize(`l5r5e.rings.${newChoice.ring}`) +
` +1 (${actor.rings[newChoice.ring] - 1} -> ${actor.rings[newChoice.ring]})`;
` +1 (${actorData.rings[newChoice.ring] - 1} -> ${actorData.rings[newChoice.ring]})`;
}
if (newChoice.skill) {
skillCatId = CONFIG.l5r5e.skills.get(newChoice.skill);
actor.skills[skillCatId][newChoice.skill] = actor.skills[skillCatId][newChoice.skill] + 1;
xp_used = actor.skills[skillCatId][newChoice.skill] * CONFIG.l5r5e.xp.skillCostMultiplier;
actorData.skills[skillCatId][newChoice.skill] = actorData.skills[skillCatId][newChoice.skill] + 1;
xp_used = actorData.skills[skillCatId][newChoice.skill] * CONFIG.l5r5e.xp.skillCostMultiplier;
name =
game.i18n.localize(`l5r5e.skills.${skillCatId}.${newChoice.skill}`) +
` +1 (${actor.skills[skillCatId][newChoice.skill] - 1} -> ${
actor.skills[skillCatId][newChoice.skill]
` +1 (${actorData.skills[skillCatId][newChoice.skill] - 1} -> ${
actorData.skills[skillCatId][newChoice.skill]
})`;
}
// Update Actor
await this.actor.update({
data: diffObject(this.actor.data.data, actor),
await actor.update({
data: foundry.utils.diffObject(actor.data.data, actorData),
});
}

View File

@@ -21,9 +21,6 @@ export class ItemPatternSheetL5r5e extends ItemSheetL5r5e {
async getData(options = {}) {
const sheetData = await super.getData(options);
sheetData.data.dtypes = ["String", "Number", "Boolean"];
sheetData.data.ringsList = game.l5r5e.HelpersL5r5e.getRingsList();
// Linked Property
sheetData.data.linkedProperty = await this.getLinkedProperty(sheetData);

View File

@@ -256,6 +256,23 @@ export class ItemSheetL5r5e extends ItemSheet {
event.preventDefault();
event.stopPropagation();
const itemId = $(event.currentTarget).data("item-id");
this.document.deleteEmbedItem(itemId);
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
);
}
}

View File

@@ -21,14 +21,15 @@ export class TitleSheetL5r5e extends ItemSheetL5r5e {
async getData(options = {}) {
const sheetData = await super.getData(options);
sheetData.data.dtypes = ["String", "Number", "Boolean"];
sheetData.data.ringsList = game.l5r5e.HelpersL5r5e.getRingsList();
console.log(sheetData.data.data.items); // todo tmp
// Prepare OwnedItems
sheetData.data.embedItemsList = this._prepareEmbedItems(sheetData.data.data.items);
console.log(sheetData); // todo tmp
// Automatically compute the xp cost
sheetData.data.data.xp_used = sheetData.data.embedItemsList.reduce(
(acc, item) => acc + (+item.data.xp_used || 0),
0
);
return sheetData;
}
@@ -63,17 +64,19 @@ export class TitleSheetL5r5e extends ItemSheetL5r5e {
// Check item type and subtype
let item = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
if (!item || (item.documentName !== "Item" && !["technique", "advancement"].includes(item.data.type))) {
if (!item || item.documentName !== "Item" || !["technique", "advancement"].includes(item.data.type)) {
return;
}
const data = item.data.toJSON();
const data = item.data.toObject(false);
console.log("------ data", data); // todo tmp
// Check xp for techs
if (item.data.type === "technique") {
data.data.xp_cost = data.data.xp_cost > 0 ? data.data.xp_cost : CONFIG.l5r5e.xp.techniqueCost;
data.data.xp_used = data.data.xp_cost;
}
this.document.addEmbedItem(data);
console.log(this.document); // todo tmp
}
/**
@@ -93,16 +96,4 @@ export class TitleSheetL5r5e extends ItemSheetL5r5e {
html.find(`.item-edit`).on("click", this._editSubItem.bind(this));
html.find(`.item-delete`).on("click", this._deleteSubItem.bind(this));
}
/**
* 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
* @abstract
*/
// async _updateObject(event, formData) {
// console.log("------- _updateObject.", formData); // todo TMP
// return super._updateObject(event, formData);
// }
}

View File

@@ -3,10 +3,10 @@
*/
export class MigrationL5r5e {
/**
* Version needed for migration stuff to trigger
* Minimum Version needed for migration stuff to trigger
* @type {string}
*/
static NEEDED_VERSION = "1.1.0";
static NEEDED_VERSION = "1.3.0";
/**
* Return true if the current world need some updates
@@ -14,7 +14,7 @@ export class MigrationL5r5e {
*/
static needUpdate() {
const currentVersion = game.settings.get("l5r5e", "systemMigrationVersion");
return currentVersion && isNewerVersion(MigrationL5r5e.NEEDED_VERSION, currentVersion);
return currentVersion && foundry.utils.isNewerVersion(MigrationL5r5e.NEEDED_VERSION, currentVersion);
}
/**
@@ -26,6 +26,7 @@ export class MigrationL5r5e {
return;
}
// Warn the users
ui.notifications.info(
`Applying L5R5e System Migration for version ${game.system.data.version}.` +
` Please be patient and do not close your game or shut down your server.`,
@@ -33,56 +34,53 @@ export class MigrationL5r5e {
);
// Migrate World Actors
for (let a of game.actors.contents) {
for (let actor of game.actors.contents) {
try {
const updateData = MigrationL5r5e._migrateActorData(a.data);
if (!isObjectEmpty(updateData)) {
console.log(`Migrating Actor entity ${a.name}`);
await a.update(updateData, { enforceTypes: false }); // TODO use Actor.updateDocuments(data, context) for multiple actors
const updateData = MigrationL5r5e._migrateActorData(actor.data);
if (!foundry.utils.isObjectEmpty(updateData)) {
console.log(`L5R5E | Migrating Actor entity ${actor.name}`);
await actor.update(updateData);
}
} catch (err) {
err.message = `Failed L5R5e system migration for Actor ${a.name}: ${err.message}`;
err.message = `L5R5E | Failed L5R5e system migration for Actor ${actor.name}: ${err.message}`;
console.error(err);
}
}
// Migrate World Items
for (let i of game.items.contents) {
for (let item of game.items.contents) {
try {
const updateData = MigrationL5r5e._migrateItemData(i.data);
if (!isObjectEmpty(updateData)) {
console.log(`Migrating Item entity ${i.name}`);
await i.update(updateData, { enforceTypes: false }); // TODO use Item.updateDocuments(data, context) for multiple actors
const updateData = MigrationL5r5e._migrateItemData(item.data);
if (!foundry.utils.isObjectEmpty(updateData)) {
console.log(`L5R5E | Migrating Item entity ${item.name}`);
await item.update(updateData);
}
} catch (err) {
err.message = `Failed L5R5e system migration for Item ${i.name}: ${err.message}`;
err.message = `L5R5E | Failed L5R5e system migration for Item ${item.name}: ${err.message}`;
console.error(err);
}
}
// Migrate Actor Override Tokens
for (let s of game.scenes.contents) {
for (let scene of game.scenes.contents) {
try {
const updateData = MigrationL5r5e._migrateSceneData(s.data);
if (!isObjectEmpty(updateData)) {
console.log(`Migrating Scene entity ${s.name}`);
await s.update(updateData, { enforceTypes: false }); // TODO use Scene.updateDocuments(data, context) for multiple actors
const updateData = MigrationL5r5e._migrateSceneData(scene.data);
if (!foundry.utils.isObjectEmpty(updateData)) {
console.log(`L5R5E | Migrating Scene entity ${scene.name}`);
await scene.update(updateData);
}
} catch (err) {
err.message = `Failed L5R5e system migration for Scene ${s.name}: ${err.message}`;
err.message = `L5R5E | Failed L5R5e system migration for Scene ${scene.name}: ${err.message}`;
console.error(err);
}
}
// Migrate World Compendium Packs
for (let p of game.packs) {
if (p.metadata.package !== "world") {
for (let pack of game.packs) {
if (pack.metadata.package !== "world" || !["Actor", "Item", "Scene"].includes(pack.metadata.entity)) {
continue;
}
if (!["Actor", "Item", "Scene"].includes(p.metadata.entity)) {
continue;
}
await MigrationL5r5e._migrateCompendium(p);
await MigrationL5r5e._migrateCompendium(pack);
}
// Set the migration as complete
@@ -94,7 +92,7 @@ export class MigrationL5r5e {
/**
* Apply migration rules to all Entities within a single Compendium pack
* @param pack
* @param {Compendium} pack
* @return {Promise}
*/
static async _migrateCompendium(pack) {
@@ -103,18 +101,20 @@ export class MigrationL5r5e {
return;
}
// Unlock the pack for editing
const wasLocked = pack.locked;
await pack.configure({ locked: false });
try {
// Unlock the pack for editing
await pack.configure({ locked: false });
// Begin by requesting server-side data model migration and get the migrated content
await pack.migrate();
const content = await pack.getContent();
// Begin by requesting server-side data model migration and get the migrated content
await pack.migrate();
const documents = await pack.getDocuments();
// Iterate over compendium entries - applying fine-tuned migration functions
const updateDatasList = [];
for (let ent of documents) {
let updateData = {};
// Iterate over compendium entries - applying fine-tuned migration functions
for (let ent of content) {
let updateData = {};
try {
switch (entity) {
case "Actor":
updateData = MigrationL5r5e._migrateActorData(ent.data);
@@ -126,24 +126,30 @@ export class MigrationL5r5e {
updateData = MigrationL5r5e._migrateSceneData(ent.data);
break;
}
if (isObjectEmpty(updateData)) {
if (foundry.utils.isObjectEmpty(updateData)) {
continue;
}
// Save the entry, if data was changed
updateData["_id"] = ent._id;
await pack.updateEntity(updateData); // TODO use Item/Actor.updateDocuments(data, context) for multiple actors
console.log(`Migrated ${entity} entity ${ent.name} in Compendium ${pack.collection}`);
} catch (err) {
// Handle migration failures
err.message = `Failed L5R5e system migration for entity ${ent.name} in pack ${pack.collection}: ${err.message}`;
console.error(err);
// Add the entry, if data was changed
updateData["_id"] = ent.data._id;
updateDatasList.push(updateData);
console.log(`L5R5E | Migrating ${entity} entity ${ent.name} in Compendium ${pack.collection}`);
}
// Save the modified entries
if (updateDatasList.length > 0) {
await pack.documentClass.updateDocuments(updateDatasList, { pack: pack.collection });
}
} catch (err) {
// Handle migration failures
err.message = `L5R5E | Failed system migration for entities ${entity} in pack ${pack.collection}: ${err.message}`;
console.error(err);
}
// Apply the original locked status for the pack
pack.configure({ locked: wasLocked });
console.log(`Migrated all ${entity} contents from Compendium ${pack.collection}`);
console.log(`L5R5E | Migrated all ${entity} contents from Compendium ${pack.collection}`);
}
/**
@@ -153,7 +159,7 @@ export class MigrationL5r5e {
* @return {Object} The updateData to apply
*/
static _migrateSceneData(scene) {
const tokens = duplicate(scene.tokens);
const tokens = foundry.utils.duplicate(scene.tokens);
return {
tokens: tokens.map((t) => {
if (!t.actorId || t.actorLink || !t.actorData.data) {
@@ -183,8 +189,6 @@ export class MigrationL5r5e {
const updateData = {};
const actorData = actor.data;
console.log(actorData); // TODO TMP data.data ? à vérifier
// ***** Start of 1.1.0 *****
// Add "Prepared" in actor
if (actorData.prepared === undefined) {
@@ -211,6 +215,10 @@ export class MigrationL5r5e {
actorData.rings_affinities.strength.value;
updateData["data.rings_affinities." + actorData.rings_affinities.weakness.ring] =
actorData.rings_affinities.weakness.value;
// Delete old keys : not working :'(
updateData["-=data.rings_affinities.strength"] = null;
updateData["-=data.rings_affinities.weakness"] = null;
}
// ***** End of 1.3.0 *****
@@ -224,7 +232,7 @@ export class MigrationL5r5e {
*/
static cleanActorData(actorData) {
const model = game.system.model.Actor[actorData.type];
actorData.data = filterObject(actorData.data, model);
actorData.data = foundry.utils.filterObject(actorData.data, model);
return actorData;
}

View File

@@ -6,8 +6,8 @@
"manifest": "https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json",
"download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v1.3.0/raw/l5r5e.zip?job=build",
"version": "1.3.0",
"minimumCoreVersion": "0.8.2",
"compatibleCoreVersion": "0.8.2",
"minimumCoreVersion": "0.8.5",
"compatibleCoreVersion": "0.8.5",
"manifestPlusVersion": "1.0.0",
"socket": true,
"author": "Team L5R",
@@ -22,12 +22,6 @@
},
{
"name": "Carter"
},
{
"name": "Hrunh"
},
{
"name": "Sasmira"
}
],
"background": "L5R-Header.webp",

View File

@@ -1,9 +1,9 @@
<form class="{{cssClass}}" data-lang="{{localize 'I18N.Language'}}" autocomplete="off">
{{!-- Sheet Header --}}
<header class="sheet-header">
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}"/>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<div class="header-fields identity-wrapper">
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
{{> 'systems/l5r5e/templates/actors/character/identity.html'}}
</div>
<div class="header-fields">
@@ -28,7 +28,7 @@
{{!-- Skills Tab --}}
<article class="tab skills" data-group="primary" data-tab="skills">
<ul class="skills-wrapper">
{{#each actor.data.data.skills as |category id|}}
{{#each data.data.skills as |category id|}}
{{> 'systems/l5r5e/templates/actors/character/category.html' category=category categoryId=id}}
{{/each}}
</ul>

View File

@@ -1,5 +1,5 @@
<tr class="flexrow row advancement">
<td class="name" name="advancement.name"><img src="{{ advancement.img }}" title="{{advancement.name}}"> {{advancement.name}}{{#if advancement.data.bond_type}} ({{advancement.data.bond_type}}){{/if}}</td>
<td class="name" name="advancement.name"><img src="{{advancement.img}}" title="{{advancement.name}}"> {{advancement.name}}{{#if advancement.data.bond_type}} ({{advancement.data.bond_type}}){{/if}}</td>
<td class="xp" name="advancement.xp">{{advancement.data.xp_used}}</td>
<td class="rank" name="advancement.rank">{{advancement.data.rank}}</td>
{{#if editable}}

View File

@@ -1,15 +1,15 @@
<li class="skill-category-wrapper skill-category-content">
<h4 class="section-header">{{ localizeSkill categoryId 'title' }}</h4>
<h4 class="section-header">{{localizeSkill categoryId 'title'}}</h4>
<ul class="skill-category-skills-list">
{{#each category as |skill id| }}
{{> 'systems/l5r5e/templates/actors/character/skill.html' categoryId=../categoryId skill=skill skillId=id }}
{{#each category as |skill id|}}
{{> 'systems/l5r5e/templates/actors/character/skill.html' categoryId=../categoryId skill=skill skillId=id}}
{{/each}}
</ul>
<ul class="skill-category-ring-actions">
<li name="air" class="air"><i class="i_air"></i> {{ localizeSkill categoryId 'air' }} </li>
<li name="earth" class="earth"><i class="i_earth"></i> {{ localizeSkill categoryId 'earth' }} </li>
<li name="fire" class="fire"><i class="i_fire"></i> {{ localizeSkill categoryId 'fire' }} </li>
<li name="water" class="water"><i class="i_water"></i> {{ localizeSkill categoryId 'water' }} </li>
<li name="void" class="void"><i class="i_void"></i> {{ localizeSkill categoryId 'void' }} </li>
<li name="air" class="air"><i class="i_air"></i> {{localizeSkill categoryId 'air'}} </li>
<li name="earth" class="earth"><i class="i_earth"></i> {{localizeSkill categoryId 'earth'}} </li>
<li name="fire" class="fire"><i class="i_fire"></i> {{localizeSkill categoryId 'fire'}} </li>
<li name="water" class="water"><i class="i_water"></i> {{localizeSkill categoryId 'water'}} </li>
<li name="void" class="void"><i class="i_void"></i> {{localizeSkill categoryId 'void'}} </li>
</ul>
</li>

View File

@@ -1,8 +1,8 @@
<fieldset class="initiative initiative-wrapper">
<legend class="section-header">
{{localize 'l5r5e.conflict.initiative.title'}}
<a class="encounter prepared-control" data-id="{{entity.type}}">
<i class="fa fas prepared-icon prepared-icon-{{data.data.prepared}} prepared-{{entity.type}}" title="{{localize (localize 'l5r5e.conflict.initiative.prepared_{value}' value=data.data.prepared)}}"></i>
<a class="encounter prepared-control" data-id="{{data.type}}">
<i class="fa fas prepared-icon prepared-icon-{{data.data.prepared}} prepared-{{data.type}}" title="{{localize (localize 'l5r5e.conflict.initiative.prepared_{value}' value=data.data.prepared)}}"></i>
</a>
</legend>
<button class="initiative dice-picker" data-initiative="true" data-skill="sentiment">{{localize 'l5r5e.conflict.initiative.intrigue'}}</button>

View File

@@ -70,7 +70,7 @@
<th class="name">{{localize 'l5r5e.name'}}</th>
<th class="xp">{{localize 'l5r5e.advancements.spent'}}</th>
<th class="rank">{{localize 'l5r5e.rank'}}</th>
{{#if editable}}
{{#if options.editable}}
<th class="actions"></th>
{{/if}}
</tr>
@@ -80,5 +80,12 @@
{{> 'systems/l5r5e/templates/actors/character/advancement-others.html' advancement=advancement editable=../options.editable}}
{{/each}}
</tbody>
<tfoot class="flex">
<tr>
<th>
{{localize 'l5r5e.advancements.total_xp_rank'}} : {{data.advancementsOthersTotalXp}}
</th>
</tr>
</tfoot>
</table>
</fieldset>

View File

@@ -1,8 +1,8 @@
<form class="{{cssClass}} flexcol limited" data-lang="{{localize 'I18N.Language'}}" autocomplete="off">
<img class="profile-img full" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" />
<img class="profile-img full" src="{{data.img}}" data-edit="img" title="{{data.name}}" />
{{!-- Sheet Header --}}
<div class="sheet-header">
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
{{!-- Sheet identity --}}
<ul class="identity-content">
<li>

View File

@@ -2,8 +2,8 @@
{{!-- Sheet Header --}}
<header class="sheet-header">
<div class="header-fields identity-wrapper">
<img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
{{> 'systems/l5r5e/templates/actors/npc/identity.html'}}
</div>
<fieldset class="npc-note">

View File

@@ -1,23 +1,23 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Attributes Tab --}}
<article class="attributes" data-group="primary" data-tab="attributes">
<select name="data.advancement_type" id="advancement_type">
{{#select document.data.data.advancement_type}}
{{#select data.data.advancement_type}}
{{#each data.subTypesList as |type|}}
<option value="{{type}}">{{type}}</option>
{{/each}}
{{/select}}
</select>
{{#ifCond document.data.data.advancement_type '==' 'ring' }}
{{#ifCond data.data.advancement_type '==' 'ring' }}
<select name="data.ring" id="advancement_ring">
{{#select document.data.data.ring}}
{{#select data.data.ring}}
{{#each data.ringsList as |obj|}}
<option value="{{obj.id}}">{{obj.label}}</option>
{{/each}}
@@ -25,10 +25,10 @@
</select>
{{/ifCond}}
{{#ifCond document.data.data.advancement_type '==' 'skill' }}
{{#ifCond data.data.advancement_type '==' 'skill' }}
<select name="data.skill" id="advancement_skill">
<option value="">{{localize 'l5r5e.twenty_questions.choose_one_skill'}}</option>
{{#select document.data.data.skill}}
{{#select data.data.skill}}
{{#each data.skillsList as |skills catId|}}
<optgroup label="{{localizeSkill catId 'title'}}">
{{#each skills as |obj|}}
@@ -40,7 +40,7 @@
</select>
{{/ifCond}}
<label class="cursus attribute-value checkbox">
<input type="checkbox" name="data.in_curriculum" {{checked document.data.data.in_curriculum}} />
<input type="checkbox" name="data.in_curriculum" {{checked data.data.in_curriculum}} />
{{ localize 'l5r5e.advancements.curriculum' }}
</label>
<label class="attribute">

View File

@@ -1,31 +1,31 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- attributes --}}
<article class="attributes" data-group="primary" data-tab="description">
<label class="equipped checkbox">
<input type="checkbox" name="data.equipped" {{checked document.data.data.equipped}} />
<input type="checkbox" name="data.equipped" {{checked data.data.equipped}} />
{{ localize 'l5r5e.armors.equipped' }}
</label>
{{> 'systems/l5r5e/templates/items/item/item-value.html' }}
<fieldset class="attribute type">
<legend class="text-header">{{ localize 'l5r5e.armors.type' }}</legend>
<legend class="text-header">{{localize 'l5r5e.armors.type'}}</legend>
<label>
{{ localize 'l5r5e.armors.physical' }}
{{localize 'l5r5e.armors.physical'}}
<input class="select-on-focus" type="number" name="data.armor.physical" value="{{data.data.armor.physical}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label>
{{ localize 'l5r5e.armors.supernatural' }}
{{localize 'l5r5e.armors.supernatural'}}
<input class="select-on-focus" type="number" name="data.armor.supernatural" value="{{data.data.armor.supernatural}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
</fieldset>
</article>
<article class="properties" data-group="primary" data-tab="properties">
{{> 'systems/l5r5e/templates/items/property/properties.html' properties=data.propertiesList }}
{{> 'systems/l5r5e/templates/items/property/properties.html' properties=data.propertiesList}}
</article>
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}
</section>

View File

@@ -1,7 +1,7 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
@@ -9,23 +9,23 @@
<article class="attributes" data-group="primary" data-tab="attributes">
<label class="attribute">
{{ localize 'l5r5e.types' }}
<input class="select-on-focus" type="text" name="data.bond_type" value="{{document.data.data.bond_type}}" data-dtype="String"/>
<input class="select-on-focus" type="text" name="data.bond_type" value="{{data.data.bond_type}}" data-dtype="String"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.advancements.cost' }}
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{document.data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.advancements.spent' }}
<input class="select-on-focus" type="number" name="data.xp_used" value="{{document.data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.xp_used" value="{{data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.rank' }}
<input class="select-on-focus" type="number" name="data.rank" value="{{document.data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.rank" value="{{data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.bought_at_rank' }}
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{document.data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
</article>
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}

View File

@@ -1,7 +1,7 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
@@ -9,23 +9,23 @@
<article class="attributes" data-group="primary" data-tab="attributes">
<label class="attribute">
{{ localize 'l5r5e.advancements.rarity_modifier' }}
<input class="select-on-focus" type="number" name="data.rarity_modifier" value="{{document.data.data.rarity_modifier}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.rarity_modifier" value="{{data.data.rarity_modifier}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.advancements.cost' }}
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{document.data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.advancements.spent' }}
<input class="select-on-focus" type="number" name="data.xp_used" value="{{document.data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.xp_used" value="{{data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.rank' }}
<input class="select-on-focus" type="number" name="data.rank" value="{{document.data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.rank" value="{{data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.bought_at_rank' }}
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{document.data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.linked_property' }}

View File

@@ -1,14 +1,14 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- properties Tab --}}
<article class="attributes" data-group="primary" data-tab="checkbox">
<label class="equipped checkbox">
<input type="checkbox" name="data.equipped" {{checked document.data.data.equipped}} />
<input type="checkbox" name="data.equipped" {{checked data.data.equipped}} />
{{ localize 'l5r5e.armors.equipped' }}
</label>
{{> 'systems/l5r5e/templates/items/item/item-value.html' }}

View File

@@ -1,45 +1,45 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}" />
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name" /></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}" />
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name" /></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Attributes Tab --}}
<article class="tab attributes" data-group="primary" data-tab="attributes">
<select name="data.ring">
{{#select document.data.data.ring}}
{{#select data.data.ring}}
{{#each data.ringsList as |obj|}}
<option value="{{obj.id}}">{{obj.label}}</option>
{{/each}}
{{/select}}
</select>
<select class="attribute" name="data.peculiarity_type">
{{#select document.data.data.peculiarity_type}}
{{#select data.data.peculiarity_type}}
{{#each data.subTypesList as |type|}}
<option value="{{type.id}}">{{type.label}}</option>
{{/each}}
{{/select}}
</select>
<label class="cursus attribute-value checkbox">
<input type="checkbox" name="data.in_curriculum" {{checked document.data.data.in_curriculum}} />
<input type="checkbox" name="data.in_curriculum" {{checked data.data.in_curriculum}} />
{{localize 'l5r5e.advancements.curriculum'}}
</label>
<label class="attribute">
{{localize 'l5r5e.advancements.spent'}}
<input class="select-on-focus" type="number" name="data.xp_used" value="{{document.data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0" />
<input class="select-on-focus" type="number" name="data.xp_used" value="{{data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0" />
</label>
<label class="attribute">
{{localize 'l5r5e.rank' }}
<input class="select-on-focus" type="number" name="data.rank" value="{{document.data.data.rank}}" data-dtype="Number" min="0" placeholder="0" />
<input class="select-on-focus" type="number" name="data.rank" value="{{data.data.rank}}" data-dtype="Number" min="0" placeholder="0" />
</label>
<label class="attribute">
{{localize 'l5r5e.bought_at_rank'}}
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{document.data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0" />
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0" />
</label>
<label class="attribute full">
{{localize 'l5r5e.types' }}
<input type="text" name="data.types" value="{{document.data.data.types}}" />
<input type="text" name="data.types" value="{{data.data.types}}" />
</label>
</article>
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}

View File

@@ -1,7 +1,7 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">

View File

@@ -1,7 +1,7 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
@@ -9,19 +9,19 @@
<article class="attributes" data-group="primary" data-tab="attributes">
<label class="attribute">
{{ localize 'l5r5e.advancements.cost' }}
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{document.data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.advancements.spent' }}
<input class="select-on-focus" type="number" name="data.xp_used" value="{{document.data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.xp_used" value="{{data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.rank' }}
<input class="select-on-focus" type="number" name="data.rank" value="{{document.data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.rank" value="{{data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.bought_at_rank' }}
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{document.data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
</article>
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}

View File

@@ -3,8 +3,10 @@
<li class="item-img"><img src="{{technique.img}}" title="{{technique.name}}" width="32px" height="32px"/></li>
<li class="item-name">{{technique.name}}</li>
{{#if editable}}
<li data-item-id="{{technique._id}}" class="item-control item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
<li data-item-id="{{technique._id}}" {{#if technique.data.parent_id.item_id}}data-item-parent-id="{{technique.data.parent_id.item_id}}"{{/if}} class="item-control item-edit" title="{{localize 'l5r5e.global.edit'}}"><i class="fas fa-edit"></i></li>
{{^if technique.data.parent_id.item_id}}
<li data-item-id="{{technique._id}}" class="item-control item-delete" title="{{localize 'Delete'}}"><i class="fas fa-trash"></i></li>
{{/if}}
{{/if}}
</ul>
{{#if technique.data.description}}

View File

@@ -1,45 +1,45 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
{{!-- Attributes Tab --}}
<article class="attributes" data-group="primary" data-tab="attributes">
<select name="data.ring">
{{#select document.data.data.ring}}
{{#select data.data.ring}}
{{#each data.ringsList as |obj|}}
<option value="{{obj.id}}">{{obj.label}}</option>
{{/each}}
{{/select}}
</select>
<select name="data.technique_type">
{{#select document.data.data.technique_type}}
{{#select data.data.technique_type}}
{{#each data.techniquesList as |obj|}}
<option value="{{obj.id}}">{{obj.label}}</option>
{{/each}}
{{/select}}
</select>
<label class="cursus attribute-value checkbox">
<input type="checkbox" name="data.in_curriculum" {{checked document.data.data.in_curriculum}} />
<input type="checkbox" name="data.in_curriculum" {{checked data.data.in_curriculum}} />
{{ localize 'l5r5e.advancements.curriculum' }}
</label>
<label class="attribute">
{{ localize 'l5r5e.advancements.cost' }}
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{document.data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.advancements.spent' }}
<input class="select-on-focus" type="number" name="data.xp_used" value="{{document.data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.xp_used" value="{{data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.rank' }}
<input class="select-on-focus" type="number" name="data.rank" value="{{document.data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.rank" value="{{data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.bought_at_rank' }}
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{document.data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
</article>
{{> 'systems/l5r5e/templates/items/item/item-infos.html'}}

View File

@@ -1,7 +1,7 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="profile-img" src="{{document.img}}" data-edit="img" title="{{document.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{document.name}}" placeholder="Name"/></h1>
<img class="profile-img" src="{{data.img}}" data-edit="img" title="{{data.name}}"/>
<h1 class="charname"><input name="name" type="text" value="{{data.name}}" placeholder="Name"/></h1>
</header>
{{!-- Sheet Navigation --}}
<nav class="sheet-tabs tabs" data-group="primary">
@@ -13,20 +13,20 @@
{{!-- Attributes Tab --}}
<article class="tab attributes" data-group="primary" data-tab="attributes">
<label class="attribute">
{{ localize 'l5r5e.advancements.cost' }}
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{document.data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
{{localize 'l5r5e.advancements.cost'}}
<input class="select-on-focus" type="number" name="data.xp_cost" value="{{data.data.xp_cost}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.advancements.spent' }}
<input class="select-on-focus" type="number" name="data.xp_used" value="{{document.data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0"/>
{{localize 'l5r5e.advancements.spent'}}
<input class="select-on-focus" type="number" name="data.xp_used" value="{{data.data.xp_used}}" data-dtype="Number" min="0" placeholder="0" readonly/>
</label>
<label class="attribute">
{{ localize 'l5r5e.rank' }}
<input class="select-on-focus" type="number" name="data.rank" value="{{document.data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
{{localize 'l5r5e.rank'}}
<input class="select-on-focus" type="number" name="data.rank" value="{{data.data.rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
<label class="attribute">
{{ localize 'l5r5e.bought_at_rank' }}
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{document.data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
{{localize 'l5r5e.bought_at_rank'}}
<input class="select-on-focus" type="number" name="data.bought_at_rank" value="{{data.data.bought_at_rank}}" data-dtype="Number" min="0" placeholder="0"/>
</label>
</article>