converting advancement to dynamic list skills
This commit is contained in:
@@ -216,38 +216,51 @@ export class ActorL5r5e extends Actor {
|
||||
* @private
|
||||
*/
|
||||
async _updateActorFromAdvancement(item, isAdd) {
|
||||
if (item && item.type === "advancement") {
|
||||
const actor = foundry.utils.duplicate(this.system);
|
||||
const itemData = item.system;
|
||||
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);
|
||||
}
|
||||
if (!item || item.type !== "advancement") {
|
||||
return;
|
||||
}
|
||||
|
||||
const actorSystem = foundry.utils.duplicate(this.system);
|
||||
const itemData = item.system;
|
||||
if (itemData.advancement_type === "ring") {
|
||||
// Ring
|
||||
if (isAdd) {
|
||||
actorSystem.rings[itemData.ring] = Math.min(9, actorSystem.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
|
||||
);
|
||||
}
|
||||
}
|
||||
actorSystem.rings[itemData.ring] = Math.max(1, actorSystem.rings[itemData.ring] - 1);
|
||||
}
|
||||
|
||||
// Update Actor
|
||||
await this.update({
|
||||
system: foundry.utils.diffObject(this.system, actor),
|
||||
system: foundry.utils.diffObject(this.system, actorSystem),
|
||||
});
|
||||
|
||||
} else {
|
||||
// Skill
|
||||
let skillItem = await fromUuid(itemData.skill); // Skill itemUuid
|
||||
if (!skillItem) {
|
||||
console.warn("L5R5E | Unknown skill item uuid", itemData.skill);
|
||||
return;
|
||||
}
|
||||
// Out of actor item ?
|
||||
if (!skillItem.actor || skillItem.actor._id !== this._id) {
|
||||
const checkItem = this.items.getName(skillItem.name);
|
||||
if (checkItem) {
|
||||
skillItem = checkItem;
|
||||
} else {
|
||||
throw new Error(`Unable to find "${skillItem.name}" on this actor`);
|
||||
}
|
||||
}
|
||||
|
||||
const newRank = isAdd
|
||||
? Math.min(9, skillItem.system.rank + 1)
|
||||
: Math.max(0, skillItem.system.rank - 1);
|
||||
if (skillItem.system.rank === newRank) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update Item
|
||||
await skillItem.update({ "system.rank": newRank });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -133,146 +133,151 @@ export class BaseCharacterSheetL5r5e extends BaseSheetL5r5e {
|
||||
* @param {DragEvent} event
|
||||
*/
|
||||
async _onDrop(event) {
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.isEditable || this.actor.system.soft_locked) {
|
||||
console.log("L5R5E | This sheet is not editable");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check item type and subtype
|
||||
const item = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
|
||||
if (!item || !["Item", "JournalEntry"].includes(item.documentName) || item.type === "property") {
|
||||
console.log(`L5R5E | Wrong subtype ${item?.type}`, item);
|
||||
return;
|
||||
}
|
||||
|
||||
// Specific curriculum journal drop
|
||||
if (item.documentName === "JournalEntry") {
|
||||
// npc does not have this
|
||||
if (!this.actor.system.identity?.school_curriculum_journal) {
|
||||
console.log("L5R5E | NPC won't go to school :'(");
|
||||
return;
|
||||
}
|
||||
this.actor.system.identity.school_curriculum_journal = {
|
||||
id: item._id,
|
||||
name: item.name,
|
||||
pack: item.pack || null,
|
||||
};
|
||||
await this.actor.update({
|
||||
system: {
|
||||
identity: {
|
||||
school_curriculum_journal: this.actor.system.identity.school_curriculum_journal,
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Dropped an item with same "id" as one owned
|
||||
if (this.actor.items) {
|
||||
// Exit if we already owned exactly this id (drag a personal item on our own sheet)
|
||||
if (
|
||||
this.actor.items.some((embedItem) => {
|
||||
// Search in children
|
||||
if (embedItem.items instanceof Map && embedItem.items.has(item._id)) {
|
||||
return true;
|
||||
}
|
||||
return embedItem._id === item._id;
|
||||
})
|
||||
) {
|
||||
console.log("L5R5E | This element has been ignored because it already exists in this actor", item.uuid);
|
||||
try {
|
||||
// *** Everything below here is only needed if the sheet is editable ***
|
||||
if (!this.isEditable || this.actor.system.soft_locked) {
|
||||
console.log("L5R5E | This sheet is not editable");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add quantity instead if they have (id is different so use type and name)
|
||||
if (item.system.quantity) {
|
||||
const tmpItem = this.actor.items.find(
|
||||
(embedItem) => embedItem.name === item.name && embedItem.type === item.type
|
||||
);
|
||||
if (tmpItem && this._modifyQuantity(tmpItem.id, 1)) {
|
||||
// Check item type and subtype
|
||||
const item = await game.l5r5e.HelpersL5r5e.getDragnDropTargetObject(event);
|
||||
if (!item || !["Item", "JournalEntry"].includes(item.documentName) || item.type === "property") {
|
||||
console.log(`L5R5E | Wrong subtype ${item?.type}`, item);
|
||||
return;
|
||||
}
|
||||
|
||||
// Specific curriculum journal drop
|
||||
if (item.documentName === "JournalEntry") {
|
||||
// npc does not have this
|
||||
if (!this.actor.system.identity?.school_curriculum_journal) {
|
||||
console.log("L5R5E | NPC won't go to school :'(");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can add the item - Foundry override cause props
|
||||
const allowed = Hooks.call("dropActorSheetData", this.actor, this, item);
|
||||
if (allowed === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
let itemData = item.toObject(true);
|
||||
|
||||
// Item subtype specific
|
||||
switch (itemData.type) {
|
||||
case "army_cohort":
|
||||
case "army_fortification":
|
||||
console.warn("L5R5E | Army items are not allowed", item?.type, item);
|
||||
this.actor.system.identity.school_curriculum_journal = {
|
||||
id: item._id,
|
||||
name: item.name,
|
||||
pack: item.pack || null,
|
||||
};
|
||||
await this.actor.update({
|
||||
system: {
|
||||
identity: {
|
||||
school_curriculum_journal: this.actor.system.identity.school_curriculum_journal,
|
||||
},
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
case "advancement":
|
||||
// Specific advancements, remove 1 to selected ring/skill
|
||||
await this.actor.addBonus(item);
|
||||
break;
|
||||
|
||||
case "title":
|
||||
// Generate new Ids for the embed items
|
||||
await item.generateNewIdsForAllEmbedItems();
|
||||
|
||||
// Add embed advancements bonus
|
||||
for (let [embedId, embedItem] of item.system.items) {
|
||||
if (embedItem.type === "advancement") {
|
||||
await this.actor.addBonus(embedItem);
|
||||
}
|
||||
// Dropped an item with same "id" as one owned
|
||||
if (this.actor.items) {
|
||||
// Exit if we already owned exactly this id (drag a personal item on our own sheet)
|
||||
if (
|
||||
this.actor.items.some((embedItem) => {
|
||||
// Search in children
|
||||
if (embedItem.items instanceof Map && embedItem.items.has(item._id)) {
|
||||
return true;
|
||||
}
|
||||
return embedItem._id === item._id;
|
||||
})
|
||||
) {
|
||||
console.log("L5R5E | This element has been ignored because it already exists in this actor", item.uuid);
|
||||
return;
|
||||
}
|
||||
|
||||
// refresh data
|
||||
itemData = item.toObject(true);
|
||||
break;
|
||||
|
||||
case "skill":
|
||||
itemData.system.rank = 0;
|
||||
itemData.system.modifier = 0;
|
||||
break;
|
||||
|
||||
case "technique":
|
||||
// School_ability and mastery_ability, allow only 1 per type
|
||||
if (CONFIG.l5r5e.techniques.get(itemData.system.technique_type)?.type === "school") {
|
||||
if (
|
||||
Array.from(this.actor.items).some((e) => {
|
||||
return e.type === "technique" && e.system.technique_type === itemData.system.technique_type;
|
||||
})
|
||||
) {
|
||||
ui.notifications.info(game.i18n.localize("l5r5e.techniques.only_one"));
|
||||
// Add quantity instead if they have (id is different so use type and name)
|
||||
if (item.system.quantity) {
|
||||
const tmpItem = this.actor.items.find(
|
||||
(embedItem) => embedItem.name === item.name && embedItem.type === item.type
|
||||
);
|
||||
if (tmpItem && this._modifyQuantity(tmpItem.id, 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No cost for schools
|
||||
itemData.system.xp_cost = 0;
|
||||
itemData.system.xp_used = 0;
|
||||
itemData.system.in_curriculum = true;
|
||||
} else {
|
||||
// Check if technique is allowed for this character
|
||||
// if (!game.user.isGM && !this.actor.system.techniques[itemData.system.technique_type]) {
|
||||
// ui.notifications.info(game.i18n.localize("l5r5e.techniques.not_allowed"));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Verify cost
|
||||
itemData.system.xp_cost =
|
||||
itemData.system.xp_cost > 0 ? itemData.system.xp_cost : CONFIG.l5r5e.xp.techniqueCost;
|
||||
itemData.system.xp_used = itemData.system.xp_cost;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Modify the bought at rank to the current actor rank
|
||||
if (itemData.system.bought_at_rank !== undefined && this.actor.system.identity?.school_rank) {
|
||||
itemData.system.bought_at_rank = this.actor.system.identity.school_rank;
|
||||
}
|
||||
// Can add the item - Foundry override cause props
|
||||
const allowed = Hooks.call("dropActorSheetData", this.actor, this, item);
|
||||
if (allowed === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Finally create the embed
|
||||
return this.actor.createEmbeddedDocuments("Item", [itemData]);
|
||||
let itemData = item.toObject(true);
|
||||
|
||||
// Item subtype specific
|
||||
switch (itemData.type) {
|
||||
case "army_cohort":
|
||||
case "army_fortification":
|
||||
console.warn("L5R5E | Army items are not allowed", item?.type, item);
|
||||
return;
|
||||
|
||||
case "advancement":
|
||||
// Specific advancements, add x to selected ring/skill
|
||||
await this.actor.addBonus(item);
|
||||
break;
|
||||
|
||||
case "title":
|
||||
// Generate new Ids for the embed items
|
||||
await item.generateNewIdsForAllEmbedItems();
|
||||
|
||||
// Add embed advancements bonus
|
||||
for (let [embedId, embedItem] of item.system.items) {
|
||||
if (embedItem.type === "advancement") {
|
||||
await this.actor.addBonus(embedItem);
|
||||
}
|
||||
}
|
||||
|
||||
// refresh data
|
||||
itemData = item.toObject(true);
|
||||
break;
|
||||
|
||||
case "skill":
|
||||
itemData.system.rank = 0;
|
||||
itemData.system.modifier = 0;
|
||||
break;
|
||||
|
||||
case "technique":
|
||||
// School_ability and mastery_ability, allow only 1 per type
|
||||
if (CONFIG.l5r5e.techniques.get(itemData.system.technique_type)?.type === "school") {
|
||||
if (
|
||||
Array.from(this.actor.items).some((e) => {
|
||||
return e.type === "technique" && e.system.technique_type === itemData.system.technique_type;
|
||||
})
|
||||
) {
|
||||
ui.notifications.info(game.i18n.localize("l5r5e.techniques.only_one"));
|
||||
return;
|
||||
}
|
||||
|
||||
// No cost for schools
|
||||
itemData.system.xp_cost = 0;
|
||||
itemData.system.xp_used = 0;
|
||||
itemData.system.in_curriculum = true;
|
||||
} else {
|
||||
// Check if technique is allowed for this character
|
||||
// if (!game.user.isGM && !this.actor.system.techniques[itemData.system.technique_type]) {
|
||||
// ui.notifications.info(game.i18n.localize("l5r5e.techniques.not_allowed"));
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Verify cost
|
||||
itemData.system.xp_cost =
|
||||
itemData.system.xp_cost > 0 ? itemData.system.xp_cost : CONFIG.l5r5e.xp.techniqueCost;
|
||||
itemData.system.xp_used = itemData.system.xp_cost;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Modify the bought at rank to the current actor rank
|
||||
if (itemData.system.bought_at_rank !== undefined && this.actor.system.identity?.school_rank) {
|
||||
itemData.system.bought_at_rank = this.actor.system.identity.school_rank;
|
||||
}
|
||||
|
||||
// Finally create the embed
|
||||
return this.actor.createEmbeddedDocuments("Item", [itemData]);
|
||||
|
||||
} catch (ex) {
|
||||
console.warn("L5R5E |", ex.message);
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
|
||||
@@ -47,7 +47,7 @@ L5R5E.techniques.set("title_ability", { type: "title", displayInTypes: false });
|
||||
L5R5E.techniques.set("specificity", { type: "custom", displayInTypes: false });
|
||||
|
||||
// *** SkillId - CategoryId ***
|
||||
// TODO @deprecated hardcoded skills
|
||||
// Hardcoded skills are still required for compatibility (migration & olds worlds)
|
||||
L5R5E.skills = new Map();
|
||||
L5R5E.skills.set("aesthetics", "artisan");
|
||||
L5R5E.skills.set("composition", "artisan");
|
||||
|
||||
@@ -90,7 +90,7 @@ export class HelpersL5r5e {
|
||||
* @return {{cat: any, id: any, label: *}[]}
|
||||
*/
|
||||
static getSkillsList(useGroup = false) {
|
||||
console.warn('@deprecated hardcoded skills - helpers.getSkillsList()'); // TODO @deprecated hardcoded skills
|
||||
console.warn('@deprecated hardcoded skills - helpers.getSkillsList() - Use getSkillsItemsList() + splitSkillByCategory() instead'); // TODO @deprecated hardcoded skills
|
||||
|
||||
if (!useGroup) {
|
||||
return Array.from(CONFIG.l5r5e.skills).map(([id, cat]) => ({
|
||||
|
||||
@@ -242,7 +242,11 @@ export class ItemL5r5e extends Item {
|
||||
if (addBonusToActor) {
|
||||
const actor = this.actor;
|
||||
if (item instanceof Item && actor instanceof Actor) {
|
||||
actor.addBonus(item);
|
||||
try {
|
||||
await actor.addBonus(item);
|
||||
} catch (ex) {
|
||||
console.warn("L5R5E |", ex.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
|
||||
const sheetData = await super.getData(options);
|
||||
|
||||
sheetData.data.subTypesList = AdvancementSheetL5r5e.types;
|
||||
sheetData.data.skillsList = game.l5r5e.HelpersL5r5e.getSkillsList(true);
|
||||
sheetData.data.skillsList = game.l5r5e.HelpersL5r5e.splitSkillByCategory(await game.l5r5e.HelpersL5r5e.getSkillsItemsList(this.actor));
|
||||
|
||||
return sheetData;
|
||||
}
|
||||
@@ -82,33 +82,45 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
|
||||
let name = this.object.name;
|
||||
let img = this.object.img;
|
||||
|
||||
const getLocalItemByUuid = async (uuid) => {
|
||||
const item = await fromUuid(uuid);
|
||||
if (!item) {
|
||||
return null;
|
||||
}
|
||||
if (item?.actor?._id === this.actor._id) {
|
||||
return item;
|
||||
}
|
||||
return this.items.getName(item.name);
|
||||
}
|
||||
const skillItemNew = newChoice.skill ? (await getLocalItemByUuid(newChoice.skill)) : null;
|
||||
const skillItemOld = oldChoice.skill ? (await getLocalItemByUuid(oldChoice.skill)) : null;
|
||||
|
||||
// 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";
|
||||
|
||||
} else if (newChoice.skill && skillItemNew) {
|
||||
name = skillItemNew.name +"+1";
|
||||
img = `systems/l5r5e/assets/dices/default/skill_blank.svg`;
|
||||
}
|
||||
|
||||
// Object embed in actor ?
|
||||
const actor = this.document.actor;
|
||||
if (actor) {
|
||||
if (newChoice.skill && !skillItemNew.actor) {
|
||||
ui.notifications.warn(`Unable to find "${skillItemNew?.name}" on this actor`);
|
||||
return;
|
||||
}
|
||||
|
||||
const actorData = foundry.utils.duplicate(actor.system);
|
||||
let skillCatId = null;
|
||||
|
||||
// Old choices
|
||||
if (oldChoice.ring) {
|
||||
actorData.rings[oldChoice.ring] = Math.max(1, actorData.rings[oldChoice.ring] - 1);
|
||||
}
|
||||
if (oldChoice.skill) {
|
||||
skillCatId = CONFIG.l5r5e.skills.get(oldChoice.skill);
|
||||
actorData.skills[skillCatId][oldChoice.skill] = Math.max(
|
||||
0,
|
||||
actorData.skills[skillCatId][oldChoice.skill] - 1
|
||||
);
|
||||
if (oldChoice.skill && skillItemOld) {
|
||||
await skillItemOld.update({ "system.rank": Math.max(0, skillItemOld.system.rank - 1) });
|
||||
}
|
||||
|
||||
// new choices
|
||||
@@ -119,15 +131,11 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
|
||||
game.i18n.localize(`l5r5e.rings.${newChoice.ring}`) +
|
||||
` +1 (${actorData.rings[newChoice.ring] - 1} -> ${actorData.rings[newChoice.ring]})`;
|
||||
}
|
||||
if (newChoice.skill) {
|
||||
skillCatId = CONFIG.l5r5e.skills.get(newChoice.skill);
|
||||
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 (${actorData.skills[skillCatId][newChoice.skill] - 1} -> ${
|
||||
actorData.skills[skillCatId][newChoice.skill]
|
||||
})`;
|
||||
if (newChoice.skill && skillItemNew) {
|
||||
const newRank = Math.min(9, skillItemNew.system.rank + 1);
|
||||
await skillItemNew.update({ "system.rank": newRank });
|
||||
xp_used = newRank * CONFIG.l5r5e.xp.skillCostMultiplier;
|
||||
name = `${skillItemNew.name} +1 (${newRank - 1} -> ${newRank})`;
|
||||
}
|
||||
|
||||
// Update Actor
|
||||
@@ -141,7 +149,7 @@ export class AdvancementSheetL5r5e extends ItemSheetL5r5e {
|
||||
name: name,
|
||||
img: img,
|
||||
system: {
|
||||
xp_used: xp_used,
|
||||
xp_used,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -160,18 +160,6 @@ export class TechniqueSheetL5r5e extends ItemSheetL5r5e {
|
||||
}
|
||||
});
|
||||
|
||||
// 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];
|
||||
return [...unqCatList];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
{{#each data.skillsList as |skills catId|}}
|
||||
<optgroup label="{{localizeSkill catId 'title'}}">
|
||||
{{#each skills as |obj|}}
|
||||
<option value="{{obj.id}}">{{obj.label}}</option>
|
||||
<option value="{{obj.uuid}}">{{obj.name}}</option>
|
||||
{{/each}}
|
||||
</optgroup>
|
||||
{{/each}}
|
||||
|
||||
Reference in New Issue
Block a user