Compare commits

..

5 Commits

8 changed files with 129 additions and 52 deletions

View File

@@ -29,6 +29,8 @@ module.exports = {
}, },
globals: { globals: {
foundry: "readonly", foundry: "readonly",
TokenDocument: "readonly",
Babele: "readonly",
AudioHelper: "readonly", AudioHelper: "readonly",
Collection: "readonly", Collection: "readonly",
Hooks: "readonly", Hooks: "readonly",

View File

@@ -1,38 +1,46 @@
# Changelog # Changelog
Date format : day/month/year Date format : day/month/year
## 1.7.1 - 01/04/2022 - Spring fixes
- PC/NPC sheet :
- 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).
- Added "changelog" and "readme" properties in system.json
## 1.7.0 - 28/03/2022 - Strife, DiceRoller for Techniques & Npc Generator ## 1.7.0 - 28/03/2022 - Strife, DiceRoller for Techniques & Npc Generator
- NPC Sheet : - NPC Sheet :
- Added a random generator feature (Demeanor, Clan and Families names courteously authorized by Edge). - 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. - This is random by design, don't expect clan/school logic in values.
- Added collapsible techniques groupes. - Added collapsible techniques groupes.
- PC sheet : - PC sheet :
- Added collapsible skill/techniques groupes. - Added collapsible skill/techniques groupes.
- Army sheet : - 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 : - PC/NPC sheet :
- Added a volatile storage to keep collapsible (Skills/Inventory) in theirs state on sheet update. - 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. - 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. - 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. - 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. - Trying an autocomplete on some fields : clan, family, school, roles, demeanor.
- Techniques Sheet & Compendiums : - Techniques Sheet & Compendiums :
- Added difficulty and skill values (not to all techniques). - Added difficulty and skill values (not to all techniques).
- Trying an autocomplete on skill field. - Trying an autocomplete on skill field.
- DicePicker : - DicePicker :
- Added TN hidden difficulty visibility for GM (ex: ?2?). - Added TN hidden difficulty visibility for GM (ex: ?2?).
- Added a selection for techniques with skill list. - Added a selection for techniques with skill list.
- RnK : - 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. - 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. - 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. - You need to keep them after the step was validated.
- This way you can do step by step for disadvantages, advantages, techniques swaps... - This way you can do step by step for disadvantages, advantages, techniques swaps...
- Roll chat message : - Roll chat message :
- Added Target information. - Added Target information.
- Properties sheet: - Properties sheet:
- Fixed loading properties from custom compendiums. - Fixed loading properties from custom compendiums.
- Added a line strike on removed/unknown property and ability to remove them. - Added a line strike on removed/unknown property and ability to remove them.
- Added Inversion and Mantra icon and tag symbols (thanks to TesserWract). - Added Inversion and Mantra icon and tag symbols (thanks to TesserWract).
- Added a Changelog link in system tab.
- Fixed image following the technique_type on technique sheet. - Fixed image following the technique_type on technique sheet.
- Fixed linked actor image compatibility with Tokenizer. - Fixed linked actor image compatibility with Tokenizer.
- Fixed svg height/width for firefox. - Fixed svg height/width for firefox.
@@ -40,26 +48,26 @@ Date format : day/month/year
Technique syntaxe "quick" explanation : Technique syntaxe "quick" explanation :
- Difficulty can be : - Difficulty can be :
- Number : 1-9 - Number : 1-9
- Or specific syntaxe "@`S`:`prop1`" or "@`T`:`prop1`|`max`" or "@`T`:`prop1`|`max`(`prop2`)" : - Or specific syntaxe "@`S`:`prop1`" or "@`T`:`prop1`|`max`" or "@`T`:`prop1`|`max`(`prop2`)" :
- `@` fixed, trigger the parser - `@` fixed, trigger the parser
- `T` or `S` : `T`arget or `S`elf, define the actor to get the value. - `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). - `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. - `|` 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`). - `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`. - `(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.
- Exemples : - Exemples :
- `theology` - `@S:vigilance` : Difficulty will be my own `vigilance`.
- `melee,ranged,unarmed` - `@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)`.
- `martial,fitness,performance` - `@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 ## 1.6.1 - 13/02/2022 - Little Bugfixes
- PC sheet : fixed the "Complete this rank" button who stayed hidden in experience tab. - PC sheet : fixed the "Complete this rank" button who stayed hidden in experience tab.

View File

@@ -268,6 +268,30 @@ export class BaseCharacterSheetL5r5e extends BaseSheetL5r5e {
return this.actor.createEmbeddedDocuments("Item", [itemData]); return this.actor.createEmbeddedDocuments("Item", [itemData]);
} }
/** @inheritdoc */
_onDragStart(event) {
// Patch Owned Items
const li = event.currentTarget;
if (li.dataset.itemParentId && li.dataset.itemId) {
const item = this.actor.items.get(li.dataset.itemParentId)?.items.get(li.dataset.itemId);
if (item) {
const dragData = {
actorId: this.actor.id,
sceneId: this.actor.isToken ? canvas.scene?.id : null,
tokenId: this.actor.isToken ? this.actor.token.id : null,
pack: this.actor.pack,
type: "Item",
data: foundry.utils.duplicate(item.data),
};
dragData.data.data.parent_id = null;
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
return;
}
}
// Else regular
super._onDragStart(event);
}
/** /**
* Subscribe to events from the sheet. * Subscribe to events from the sheet.
* @param {jQuery} html HTML content of the sheet. * @param {jQuery} html HTML content of the sheet.
@@ -613,12 +637,12 @@ export class BaseCharacterSheetL5r5e extends BaseSheetL5r5e {
* @param {Event} event * @param {Event} event
* @private * @private
*/ */
_openDicePickerForTechnique(event) { async _openDicePickerForTechnique(event) {
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
const itemId = $(event.currentTarget).data("item-id") || null; // Required for tech in titles, search in sub items
const item = this.actor.items.get(itemId); const item = await game.l5r5e.HelpersL5r5e.getEmbedItemByEvent(event, this.actor);
if (!item || item.type !== "technique" || !item.data.data.skill) { if (!item || item.type !== "technique" || !item.data.data.skill) {
return; return;
} }

View File

@@ -370,13 +370,25 @@ export class RollL5r5e extends Roll {
roll.data = foundry.utils.duplicate(data.data); roll.data = foundry.utils.duplicate(data.data);
roll.l5r5e = foundry.utils.duplicate(data.l5r5e); roll.l5r5e = foundry.utils.duplicate(data.l5r5e);
// get real Actor object // Get real Actor object
if (data.l5r5e.actor) { if (data.l5r5e.actor) {
if (data.l5r5e.actor instanceof game.l5r5e.ActorL5r5e) { 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; roll.l5r5e.actor = data.l5r5e.actor;
} else { } else if (data.l5r5e.actor.uuid) {
// only id, get the object // 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); const actor = game.actors.get(data.l5r5e.actor.id);
if (actor) { if (actor) {
roll.l5r5e.actor = actor; roll.l5r5e.actor = actor;
@@ -398,9 +410,9 @@ export class RollL5r5e extends Roll {
json.l5r5e = foundry.utils.duplicate(this.l5r5e); json.l5r5e = foundry.utils.duplicate(this.l5r5e);
// lightweight the Actor // lightweight the Actor
if (json.l5r5e.actor) { if (json.l5r5e.actor && this.l5r5e.actor?.uuid) {
json.l5r5e.actor = { json.l5r5e.actor = {
id: json.l5r5e.actor._id, // method "id" not exist in json, need to use "_id" here uuid: this.l5r5e.actor.uuid,
}; };
} }

View File

@@ -109,6 +109,36 @@ export class HelpersL5r5e {
return CONFIG.l5r5e.roles.map((e) => game.i18n.localize(`l5r5e.roles.${e}`)); 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 * Return the target object on a drag n drop event, or null if not found
* @param {DragEvent} event * @param {DragEvent} event

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-undef */
export default class HooksL5r5e { export default class HooksL5r5e {
/** /**
* Do anything after initialization but before ready * Do anything after initialization but before ready
@@ -59,7 +58,7 @@ export default class HooksL5r5e {
case "settings": case "settings":
// Add Changelog link // Add Changelog link
html.find("#game-details .system").append( html.find("#game-details .system").append(
`<p><a href="${game.system.data.url}/-/blob/master/CHANGELOG.md" target="_blank">Changelog</a></p>` `<p><a href="${game.system.data.changelog}" target="_blank">Changelog</a></p>`
); );
break; break;
} }

View File

@@ -3,9 +3,11 @@
"title": "Legend of the Five Rings (5th Edition)", "title": "Legend of the Five Rings (5th Edition)",
"description": "This is an authorised multilingual game system En|Fr|Es, for Legend of the Five Rings (5th Edition) by <a href='https://edge-studio.net/'>Edge Studio</a> <p> - Join the official Discord server: <a href='https://discord.gg/foundryvtt'> Official Discord</a></p><p> - Rejoignez la communauté Francophone: <a href='https://discord.gg/pPSDNJk'>Francophone Discord</a></p>", "description": "This is an authorised multilingual game system En|Fr|Es, for Legend of the Five Rings (5th Edition) by <a href='https://edge-studio.net/'>Edge Studio</a> <p> - Join the official Discord server: <a href='https://discord.gg/foundryvtt'> Official Discord</a></p><p> - Rejoignez la communauté Francophone: <a href='https://discord.gg/pPSDNJk'>Francophone Discord</a></p>",
"url": "https://gitlab.com/teaml5r/l5r5e", "url": "https://gitlab.com/teaml5r/l5r5e",
"readme": "https://gitlab.com/teaml5r/l5r5e/-/blob/master/README.md",
"changelog": "https://gitlab.com/teaml5r/l5r5e/-/blob/master/CHANGELOG.md",
"manifest": "https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json", "manifest": "https://gitlab.com/teaml5r/l5r5e/-/raw/master/system/system.json",
"download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v1.7.0/raw/l5r5e.zip?job=build", "download": "https://gitlab.com/teaml5r/l5r5e/-/jobs/artifacts/v1.7.1/raw/l5r5e.zip?job=build",
"version": "1.7.0", "version": "1.7.1",
"minimumCoreVersion": "9", "minimumCoreVersion": "9",
"compatibleCoreVersion": "9", "compatibleCoreVersion": "9",
"manifestPlusVersion": "1.0.0", "manifestPlusVersion": "1.0.0",

View File

@@ -1,4 +1,4 @@
<li class="item technique flexcol" data-item-id="{{technique._id}}"> <li class="item technique flexcol" data-item-id="{{technique._id}}" {{#if technique.data.parent_id.item_id}}data-item-parent-id="{{technique.data.parent_id.item_id}}"{{/if}}>
<ul class="item-header technique-controls"> <ul class="item-header technique-controls">
<li class="item-img"><img src="{{technique.img}}" title="{{technique.name}}" width="32px" height="32px"/></li> <li class="item-img"><img src="{{technique.img}}" title="{{technique.name}}" width="32px" height="32px"/></li>
<li class="item-name l5r5e-tooltip {{#if technique.data.skill}}dice-picker-tech{{/if}}" data-item-id="{{technique._id}}" {{#if technique.data.parent_id.item_id}}data-item-parent-id="{{technique.data.parent_id.item_id}}"{{/if}}>{{technique.name}}</li> <li class="item-name l5r5e-tooltip {{#if technique.data.skill}}dice-picker-tech{{/if}}" data-item-id="{{technique._id}}" {{#if technique.data.parent_id.item_id}}data-item-parent-id="{{technique.data.parent_id.item_id}}"{{/if}}>{{technique.name}}</li>