diff --git a/.eslintrc.js b/.eslintrc.js index 28e0a55..7c922a8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -29,6 +29,7 @@ module.exports = { }, globals: { foundry: "readonly", + TokenDocument: "readonly", AudioHelper: "readonly", Collection: "readonly", Hooks: "readonly", diff --git a/CHANGELOG.md b/CHANGELOG.md index dd3df56..6ae7d20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,36 +3,38 @@ Date format : day/month/year ## 1.7.1 - ??/04/2022 - Spring fixes - PC/NPC sheet : - - Fixed technique with a skill set, in a title, now open the DicePicker as intended. + - Fixed technique with a skill set, in a title, now open the DicePicker as intended. +- Roll/DP/RnK : + - Fixed the way an actor is lightweight and re-construct from chat message. This fix minions npc sync with multiple token (missing context). ## 1.7.0 - 28/03/2022 - Strife, DiceRoller for Techniques & Npc Generator - NPC Sheet : - - Added a random generator feature (Demeanor, Clan and Families names courteously authorized by Edge). - - This is random by design, don't expect clan/school logic in values. - - Added collapsible techniques groupes. + - Added a random generator feature (Demeanor, Clan and Families names courteously authorized by Edge). + - This is random by design, don't expect clan/school logic in values. + - Added collapsible techniques groupes. - PC sheet : - - Added collapsible skill/techniques groupes. + - Added collapsible skill/techniques groupes. - Army sheet : - - Image and token now follow the commander's on drop. + - Image and token now follow the commander's on drop. - PC/NPC sheet : - - Added a volatile storage to keep collapsible (Skills/Inventory) in theirs state on sheet update. - - Added the ability for technique with a skill set, to open the DicePicker with presets values. - - Some can interact with targets, but do the default difficulty if none. - - Notes : Techniques in sheet need to be re-imported from the compendium or manually updated for this to work. - - Trying an autocomplete on some fields : clan, family, school, roles, demeanor. + - Added a volatile storage to keep collapsible (Skills/Inventory) in theirs state on sheet update. + - Added the ability for technique with a skill set, to open the DicePicker with presets values. + - Some can interact with targets, but do the default difficulty if none. + - Notes : Techniques in sheet need to be re-imported from the compendium or manually updated for this to work. + - Trying an autocomplete on some fields : clan, family, school, roles, demeanor. - Techniques Sheet & Compendiums : - - Added difficulty and skill values (not to all techniques). - - Trying an autocomplete on skill field. + - Added difficulty and skill values (not to all techniques). + - Trying an autocomplete on skill field. - DicePicker : - - Added TN hidden difficulty visibility for GM (ex: ?2?). - - Added a selection for techniques with skill list. + - Added TN hidden difficulty visibility for GM (ex: ?2?). + - Added a selection for techniques with skill list. - RnK : - - Added ability to directly apply the strife to the actor on final step. The chat message show the value taken in gray aside the total strife. - - Changed the way the swap is handled, that now work the same as the reroll. - - You need to keep them after the step was validated. - - This way you can do step by step for disadvantages, advantages, techniques swaps... + - Added ability to directly apply the strife to the actor on final step. The chat message show the value taken in gray aside the total strife. + - Changed the way the swap is handled, that now work the same as the reroll. + - You need to keep them after the step was validated. + - This way you can do step by step for disadvantages, advantages, techniques swaps... - Roll chat message : - - Added Target information. + - Added Target information. - Properties sheet: - Fixed loading properties from custom compendiums. - Added a line strike on removed/unknown property and ability to remove them. @@ -44,26 +46,26 @@ Date format : day/month/year Technique syntaxe "quick" explanation : - Difficulty can be : - - Number : 1-9 - - Or specific syntaxe "@`S`:`prop1`" or "@`T`:`prop1`|`max`" or "@`T`:`prop1`|`max`(`prop2`)" : - - `@` fixed, trigger the parser - - `T` or `S` : `T`arget or `S`elf, define the actor to get the value. - - `prop1` / `prop2` : Can be any property in `actor` or `actor.data.data`. Limitations: currently no `size`, `distance` (range) or computation (a+b). - - `|` separator, optional if no min/max. - - `min` or `max` : Between the selected targets, search for the min/max of `prop2`. If no `prop2` provided, take `prop1` as `prop2` (irrelevant for `@S`). - - `(prop2)` : define the property for the actor selection in multiple target, can be omitted if same as `prop1`. - - Exemples : - - `@S:vigilance` : Difficulty will be my own `vigilance`. - - `@T:vigilance|min` : Difficulty will be the `vigilance` from the target with the minimum vigilance (implicit) value. it's the same to wrote `@T:vigilance|min(vigilance)`. - - `@T:vigilance|max(statusRank)` : Difficulty will be the `vigilance` from the target with the maximum `statusRank` value. -- Skill can be : - - Skill : `melee`, `fitness`... - - SkillCategory : `scholar`, `martial`... - - Or both in list, coma separated. + - Number : 1-9 + - Or specific syntaxe "@`S`:`prop1`" or "@`T`:`prop1`|`max`" or "@`T`:`prop1`|`max`(`prop2`)" : + - `@` fixed, trigger the parser + - `T` or `S` : `T`arget or `S`elf, define the actor to get the value. + - `prop1` / `prop2` : Can be any property in `actor` or `actor.data.data`. Limitations: currently no `size`, `distance` (range) or computation (a+b). + - `|` separator, optional if no min/max. + - `min` or `max` : Between the selected targets, search for the min/max of `prop2`. If no `prop2` provided, take `prop1` as `prop2` (irrelevant for `@S`). + - `(prop2)` : define the property for the actor selection in multiple target, can be omitted if same as `prop1`. - Exemples : - - `theology` - - `melee,ranged,unarmed` - - `martial,fitness,performance` + - `@S:vigilance` : Difficulty will be my own `vigilance`. + - `@T:vigilance|min` : Difficulty will be the `vigilance` from the target with the minimum vigilance (implicit) value. it's the same to wrote `@T:vigilance|min(vigilance)`. + - `@T:vigilance|max(statusRank)` : Difficulty will be the `vigilance` from the target with the maximum `statusRank` value. +- Skill can be : + - Skill : `melee`, `fitness`... + - SkillCategory : `scholar`, `martial`... + - Or both in list, coma separated. + - Exemples : + - `theology` + - `melee,ranged,unarmed` + - `martial,fitness,performance` ## 1.6.1 - 13/02/2022 - Little Bugfixes - PC sheet : fixed the "Complete this rank" button who stayed hidden in experience tab. diff --git a/system/scripts/dice/roll.js b/system/scripts/dice/roll.js index 8bdefbd..7324c1f 100644 --- a/system/scripts/dice/roll.js +++ b/system/scripts/dice/roll.js @@ -370,13 +370,25 @@ export class RollL5r5e extends Roll { roll.data = foundry.utils.duplicate(data.data); roll.l5r5e = foundry.utils.duplicate(data.l5r5e); - // get real Actor object + // Get real Actor object if (data.l5r5e.actor) { if (data.l5r5e.actor instanceof game.l5r5e.ActorL5r5e) { - // duplicate break the object, relink it + // Duplicate break the object, relink it roll.l5r5e.actor = data.l5r5e.actor; - } else { - // only id, get the object + } else if (data.l5r5e.actor.uuid) { + // Only uuid, get the object + let actor; + let tmpItem = game.l5r5e.HelpersL5r5e.fromUuidNoPack(data.l5r5e.actor.uuid); + if (tmpItem instanceof Actor) { + actor = tmpItem; + } else if (tmpItem instanceof TokenDocument) { + actor = tmpItem.actor; + } + if (actor) { + roll.l5r5e.actor = actor; + } + } else if (data.l5r5e.actor.id) { + // Compat old chat message : only id const actor = game.actors.get(data.l5r5e.actor.id); if (actor) { roll.l5r5e.actor = actor; @@ -398,9 +410,9 @@ export class RollL5r5e extends Roll { json.l5r5e = foundry.utils.duplicate(this.l5r5e); // lightweight the Actor - if (json.l5r5e.actor) { + if (json.l5r5e.actor && this.l5r5e.actor?.uuid) { json.l5r5e.actor = { - id: json.l5r5e.actor._id, // method "id" not exist in json, need to use "_id" here + uuid: this.l5r5e.actor.uuid, }; } diff --git a/system/scripts/helpers.js b/system/scripts/helpers.js index 616f145..42a9c22 100644 --- a/system/scripts/helpers.js +++ b/system/scripts/helpers.js @@ -109,6 +109,36 @@ export class HelpersL5r5e { return CONFIG.l5r5e.roles.map((e) => game.i18n.localize(`l5r5e.roles.${e}`)); } + /** + * Retrieve a Document by its Universally Unique Identifier (uuid). + * Exactly the same as fromUuid but without Compendium as it need async. + * @param {string} uuid The uuid of the Document to retrieve + * @return {Document|null} + */ + static fromUuidNoPack(uuid) { + let parts = uuid.split("."); + let doc; + + if (parts[0] === "Compendium") { + // Compendium Documents need asynchronous + return null; + } else { + // World Documents + const [docName, docId] = parts.slice(0, 2); + parts = parts.slice(2); + const collection = CONFIG[docName].collection.instance; + doc = collection.get(docId); + } + + // Embedded Documents + while (doc && parts.length > 1) { + const [embeddedName, embeddedId] = parts.slice(0, 2); + doc = doc.getEmbeddedDocument(embeddedName, embeddedId); + parts = parts.slice(2); + } + return doc || null; + } + /** * Return the target object on a drag n drop event, or null if not found * @param {DragEvent} event