Changed targetInfos (name/img) to target (TokenDocument)

Added item in dp/rnk/roll
This commit is contained in:
Vlyan
2022-07-29 12:32:38 +02:00
parent fb911a9bf0
commit 685c923667
10 changed files with 186 additions and 69 deletions

View File

@@ -9,8 +9,10 @@ __! Be certain to carefully back up any critical user data before installing thi
- Added socket API `openDicePicker` to remotely open the DicePicker (see usage below). - Added socket API `openDicePicker` to remotely open the DicePicker (see usage below).
- Added a distinction when clicking on the dice icon on Chat tab : - Added a distinction when clicking on the dice icon on Chat tab :
- Left clic, open the DP locally (as usual). - Left clic, open the DP locally (as usual).
- Right clic (GM only), now open the DP for players with all skill list. - Right clic (GM only), now open the DP for players with all skills in list.
- Added `itemUuid` to Roll/RnK for technique and weapons to be readable in ChatMessage (use `fromUuid()` / `fromUuidSync()` to get the object). - Added `itemUuid`/`item` to DP and `item` in RnK/Roll for the technique or weapon used to be readable in ChatMessage.
- Changed `targetInfos` (`name`/`img`) to `target` (`TokenDocument`) on DP/RnK/Roll for better access to the related token.
- Added @UUID link on target and weapon/technique in ChatMessage.
- Added wiki link in system tab. - Added wiki link in system tab.
- Removed restriction on technique types when dropping a technique (Sheet and 20Q. #39). - Removed restriction on technique types when dropping a technique (Sheet and 20Q. #39).
- Fixed sync between GM for Combat tracker `initiative encounter type` and `initiative prepared`. - Fixed sync between GM for Combat tracker `initiative encounter type` and `initiative prepared`.

View File

@@ -11,7 +11,7 @@ export class CombatL5r5e extends Combat {
/** /**
* Roll initiative for one or multiple Combatants within the Combat entity * Roll initiative for one or multiple Combatants within the Combat entity
* @param {string|string[]} ids A Combatant id or Array of ids for which to roll * @param {string|string[]} ids A Combatant id or Array of ids for which to roll
* @param {string|null} [formula] A non-default initiative formula to roll. Otherwise the system default is used. * @param {string|null} [formula] A non-default initiative formula to roll. Otherwise, the system default is used.
* @param {boolean} [updateTurn] Update the Combat turn after adding new initiative scores to keep the turn on * @param {boolean} [updateTurn] Update the Combat turn after adding new initiative scores to keep the turn on
* the same Combatant. * the same Combatant.
* @param {object} [messageOptions] Additional options with which to customize created Chat Messages * @param {object} [messageOptions] Additional options with which to customize created Chat Messages
@@ -118,6 +118,7 @@ export class CombatL5r5e extends Combat {
} else { } else {
// Regular // Regular
roll = new game.l5r5e.RollL5r5e(formula ?? createFormula.join("+")); roll = new game.l5r5e.RollL5r5e(formula ?? createFormula.join("+"));
roll.item = messageOptions.item;
roll.actor = combatant.actor; roll.actor = combatant.actor;
roll.l5r5e.isInitiativeRoll = true; roll.l5r5e.isInitiativeRoll = true;
roll.l5r5e.stance = actorSystem.stance; roll.l5r5e.stance = actorSystem.stance;

View File

@@ -5,11 +5,25 @@
export class DicePickerDialog extends FormApplication { export class DicePickerDialog extends FormApplication {
/** /**
* Current Actor * Current Actor
* @type {Actor} * @type {ActorL5r5e}
* @private * @private
*/ */
_actor = null; _actor = null;
/**
* Current used Item (Technique, Weapon)
* @type {ItemL5r5e}
* @private
*/
_item = null;
/**
* Current Target (Token)
* @type {TokenDocument}
* @private
*/
_target = null;
/** /**
* If GM or Constructor set to hidden, lock the player choice, so he cannot look the TN * If GM or Constructor set to hidden, lock the player choice, so he cannot look the TN
* @type {{gm: boolean, option: boolean}} * @type {{gm: boolean, option: boolean}}
@@ -42,10 +56,8 @@ export class DicePickerDialog extends FormApplication {
hidden: false, hidden: false,
addVoidPoint: false, addVoidPoint: false,
}, },
targetInfos: null,
useVoidPoint: false, useVoidPoint: false,
isInitiativeRoll: false, isInitiativeRoll: false,
itemUuid: null,
}; };
/** /**
@@ -98,19 +110,21 @@ export class DicePickerDialog extends FormApplication {
* ex: new game.l5r5e.DicePickerDialog({skillId: 'aesthetics', ringId: 'water', actor: game.user.character}).render(true); * ex: new game.l5r5e.DicePickerDialog({skillId: 'aesthetics', ringId: 'water', actor: game.user.character}).render(true);
* *
* Options : * Options :
* actor A instance of actor (game.user.character, canvas.tokens.controlled[0].actor, ...) * actor {Actor} Any `Actor` object instance. Ex : `game.user.character`, `canvas.tokens.controlled[0].actor`
* actorId string (AbYgKrNwWeAxa9jT) * actorId {string} This is the `id` not the `uuid` of an actor. Ex : "AbYgKrNwWeAxa9jT"
* actorName string (Isawa Aki) Careful this is case-sensitive * actorName {string} Careful this is case-sensitive. Ex : "Isawa Aki"
* ringId string (fire) * difficulty {number} `1` to `9`
* skillId string (design) * difficultyHidden {boolean} If `true`, hide the difficulty and lock the view for the player.
* skillCatId string (artisan) * isInitiativeRoll {boolean} `true` if this is an initiative roll
* skillsList string[] (artisan,fitness) * item {Item} The object of technique or weapon used for this roll.
* difficulty number (0-9) * itemUuid {string} The `uuid` of technique or weapon used for this roll. Can be anything retrieved by `fromUuid()` or `fromUuidSync()`
* difficultyHidden boolean * ringId {string} If not provided, take the current stance of the actor if any. Ex : "fire", "water"
* isInitiativeRoll boolean * skillId {string} Skill `id`. Ex : "design", "aesthetics", "courtesy"
* itemUuid string * skillCatId {string} Skill category `id`. Ex : "artisan", "scholar"
* skillsList {string[]} `skillId`/`skillCatId` list coma separated. Allow the player to select the skill used in a select. Ex : "artisan,design"
* target {TokenDocument} The targeted Token
* *
* @param options actor, actorId, ringId, actorName, skillId, skillCatId, difficulty, difficultyHidden, isInitiativeRoll, itemUuid * @param options actor, actorId, actorName, difficulty, difficultyHidden, isInitiativeRoll, item, itemUuid, ringId, skillId, skillCatId, skillsList, target
*/ */
constructor(options = {}) { constructor(options = {}) {
super({}, options); super({}, options);
@@ -148,10 +162,16 @@ export class DicePickerDialog extends FormApplication {
this.skillCatId = options.skillCatId; this.skillCatId = options.skillCatId;
} }
// Target Infos : get the 1st selected target // Target Infos
const targetToken = Array.from(game.user.targets).values().next()?.value?.document; if (options.target) {
if (targetToken) { this.target = options.target;
this.targetInfos = targetToken; }
if (!this._target) {
// Get the 1st selected target
const targetToken = Array.from(game.user.targets).values().next()?.value?.document;
if (targetToken) {
this.target = targetToken;
}
} }
// Difficulty // Difficulty
@@ -168,9 +188,11 @@ export class DicePickerDialog extends FormApplication {
// InitiativeRoll // InitiativeRoll
this.object.isInitiativeRoll = !!options.isInitiativeRoll; this.object.isInitiativeRoll = !!options.isInitiativeRoll;
// Item UUID (weapon/technique) // Item (weapon/technique)
if (options.itemUuid) { if (options.item) {
this.object.itemUuid = options.itemUuid; this.item = options.item;
} else if (options.itemUuid) {
this.item = fromUuidSync(options.itemUuid);
} }
} }
@@ -202,16 +224,36 @@ export class DicePickerDialog extends FormApplication {
} }
/** /**
* Set Target Infos (Name, Img) * Set used item
* @param {ItemL5r5e} item
*/
set item(item) {
if (!item) {
return;
}
if (!(item instanceof Item) || !item.isOwner) {
console.warn("L5R5E | DP | Item rejected : Not a valid Item instance or permission was denied", item);
return;
}
this._item = item;
}
/**
* Set Target Infos object
* @param {TokenDocument} targetToken * @param {TokenDocument} targetToken
*/ */
set targetInfos(targetToken) { set target(targetToken) {
this.object.targetInfos = targetToken if (!targetToken) {
? { return;
img: targetToken.texture.src || null, }
name: targetToken.name, if (!(targetToken instanceof TokenDocument) || !targetToken.isOwner) {
} console.warn(
: null; "L5R5E | DP | target rejected : Not a valid TokenDocument instance or permission was denied",
targetToken
);
return;
}
this._target = targetToken;
} }
/** /**
@@ -542,8 +584,8 @@ export class DicePickerDialog extends FormApplication {
if (this.object.isInitiativeRoll) { if (this.object.isInitiativeRoll) {
// Initiative roll // Initiative roll
let msgOptions = { let msgOptions = {
item: this._item,
skillId: this.object.skill.id, skillId: this.object.skill.id,
itemUuid: this.object.itemUuid,
rnkMessage: null, rnkMessage: null,
difficulty: this.object.difficulty.value, difficulty: this.object.difficulty.value,
useVoidPoint: this.object.useVoidPoint, useVoidPoint: this.object.useVoidPoint,
@@ -567,12 +609,12 @@ export class DicePickerDialog extends FormApplication {
const roll = await new game.l5r5e.RollL5r5e(formula.join("+")); const roll = await new game.l5r5e.RollL5r5e(formula.join("+"));
roll.actor = this._actor; roll.actor = this._actor;
roll.l5r5e.item = this._item;
roll.l5r5e.target = this._target;
roll.l5r5e.stance = this.object.ring.id; roll.l5r5e.stance = this.object.ring.id;
roll.l5r5e.skillId = this.object.skill.id; roll.l5r5e.skillId = this.object.skill.id;
roll.l5r5e.itemUuid = this.object.itemUuid;
roll.l5r5e.skillCatId = this.object.skill.cat; roll.l5r5e.skillCatId = this.object.skill.cat;
roll.l5r5e.difficulty = this.object.difficulty.value; roll.l5r5e.difficulty = this.object.difficulty.value;
roll.l5r5e.targetInfos = this.object.targetInfos;
roll.l5r5e.voidPointUsed = this.object.useVoidPoint; roll.l5r5e.voidPointUsed = this.object.useVoidPoint;
roll.l5r5e.skillAssistance = this.object.skill.assistance; roll.l5r5e.skillAssistance = this.object.skill.assistance;
roll.l5r5e.difficultyHidden = this.object.difficulty.hidden; roll.l5r5e.difficultyHidden = this.object.difficulty.hidden;
@@ -768,7 +810,7 @@ export class DicePickerDialog extends FormApplication {
if (infos[1] === "T") { if (infos[1] === "T") {
this.difficultyHidden = true; this.difficultyHidden = true;
this._difficultyHiddenIsLock.option = true; this._difficultyHiddenIsLock.option = true;
this.targetInfos = targetToken; this.target = targetToken;
} }
return true; return true;
} }

View File

@@ -19,13 +19,13 @@ export class RollL5r5e extends Roll {
history: null, history: null,
initialFormula: null, initialFormula: null,
isInitiativeRoll: false, isInitiativeRoll: false,
item: null,
keepLimit: null, keepLimit: null,
rnkEnded: false, rnkEnded: false,
skillAssistance: 0, skillAssistance: 0,
skillCatId: "", skillCatId: "",
skillId: "", skillId: "",
stance: "", stance: "",
itemUuid: null,
strifeApplied: 0, strifeApplied: 0,
summary: { summary: {
totalSuccess: 0, totalSuccess: 0,
@@ -35,7 +35,7 @@ export class RollL5r5e extends Roll {
opportunity: 0, opportunity: 0,
strife: 0, strife: 0,
}, },
targetInfos: null, target: null,
voidPointUsed: false, voidPointUsed: false,
}; };
@@ -56,7 +56,7 @@ export class RollL5r5e extends Roll {
// Target Infos : get the 1st selected target // Target Infos : get the 1st selected target
const targetToken = Array.from(game.user.targets).values().next()?.value?.document; const targetToken = Array.from(game.user.targets).values().next()?.value?.document;
if (targetToken) { if (targetToken) {
this.targetInfos = targetToken; this.target = targetToken;
} }
} }
@@ -72,13 +72,8 @@ export class RollL5r5e extends Roll {
* Set Target Infos (Name, Img) * Set Target Infos (Name, Img)
* @param {TokenDocument} targetToken * @param {TokenDocument} targetToken
*/ */
set targetInfos(targetToken) { set target(targetToken) {
this.l5r5e.targetInfos = targetToken this.l5r5e.target = targetToken || null;
? {
img: targetToken.texture.src || null,
name: targetToken.name,
}
: null;
} }
/** /**
@@ -361,6 +356,8 @@ export class RollL5r5e extends Roll {
); );
messageData.roll = this; messageData.roll = this;
console.log("toMessage", messageData); //todo tmp
// Either create the message or just return the chat data // Either create the message or just return the chat data
return ChatMessage.implementation.create(messageData, { return ChatMessage.implementation.create(messageData, {
rollMode: rMode, rollMode: rMode,
@@ -401,6 +398,34 @@ export class RollL5r5e extends Roll {
} }
} }
// Get real Item object
if (data.l5r5e.item) {
if (data.l5r5e.item instanceof game.l5r5e.ItemL5r5e) {
// Duplicate break the object, relink it
roll.l5r5e.item = data.l5r5e.item;
} else if (data.l5r5e.item.uuid) {
// Only uuid, get the object
const tmpItem = fromUuidSync(data.l5r5e.item.uuid);
if (tmpItem) {
roll.l5r5e.item = tmpItem;
}
}
}
// Get real Target object
if (data.l5r5e.target) {
if (data.l5r5e.target instanceof TokenDocument) {
// Duplicate break the object, relink it
roll.l5r5e.target = data.l5r5e.target;
} else if (data.l5r5e.target.uuid) {
// Only uuid, get the object
const tmpItem = fromUuidSync(data.l5r5e.target.uuid);
if (tmpItem) {
roll.l5r5e.target = tmpItem;
}
}
}
return roll; return roll;
} }
@@ -414,13 +439,27 @@ export class RollL5r5e extends Roll {
json.data = foundry.utils.duplicate(this.data); json.data = foundry.utils.duplicate(this.data);
json.l5r5e = foundry.utils.duplicate(this.l5r5e); json.l5r5e = foundry.utils.duplicate(this.l5r5e);
// lightweight the Actor // Lightweight the Actor
if (json.l5r5e.actor && this.l5r5e.actor?.uuid) { if (json.l5r5e.actor && this.l5r5e.actor?.uuid) {
json.l5r5e.actor = { json.l5r5e.actor = {
uuid: this.l5r5e.actor.uuid, uuid: this.l5r5e.actor.uuid,
}; };
} }
// Lightweight the Item
if (json.l5r5e.item && this.l5r5e.item?.uuid) {
json.l5r5e.item = {
uuid: this.l5r5e.item.uuid,
};
}
// Lightweight the Target Token
if (json.l5r5e.target && this.l5r5e.target?.uuid) {
json.l5r5e.target = {
uuid: this.l5r5e.target.uuid,
};
}
return json; return json;
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -71,7 +71,8 @@
color: rgba(155, 55, 55, 0.75); color: rgba(155, 55, 55, 0.75);
} }
} }
.target { .target,
.item-infos {
display: flex; display: flex;
align-items: center; align-items: center;
flex: 0 0 100%; flex: 0 0 100%;
@@ -87,12 +88,26 @@
.profile-img { .profile-img {
position: relative; position: relative;
border: none; border: none;
filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.66));
} }
} }
.name { .name {
flex: 6; flex: 6;
font-family: "BrushtipTexe", sans-serif; font-family: "BrushtipTexe", sans-serif;
} }
.content-link {
background: unset;
border: unset;
i {
display: none;
}
}
}
.item-infos {
border: solid 1px rgba(0, 78, 100, 0.75);
i {
font-size: var(--font-size-12);
}
} }
} }

View File

@@ -11,7 +11,7 @@
"version": "1.9.0", "version": "1.9.0",
"compatibility": { "compatibility": {
"minimum": 10, "minimum": 10,
"verified": "10.275" "verified": "10.276"
}, },
"manifestPlusVersion": "1.2.0", "manifestPlusVersion": "1.2.0",
"socket": true, "socket": true,

View File

@@ -37,10 +37,26 @@
</div> </div>
{{/if}} {{/if}}
{{#if l5r5e.targetInfos}} {{#if l5r5e.target.uuid}}
<div class="l5r5e target"> <div class="l5r5e target">
<div class="profile"><img class="profile-img" src="{{l5r5e.targetInfos.img}}" alt="{{l5r5e.targetInfos.name}}" /></div> <div class="profile"><img class="profile-img" src="{{l5r5e.target.texture.src}}" alt="{{l5r5e.target.name}}" /></div>
<div class="name"> &nbsp; {{l5r5e.targetInfos.name}}</div> <div class="name"> &nbsp; @UUID[{{l5r5e.target.actor.uuid}}]&#123;{{l5r5e.target.name}}&#125;</div>
</div>
{{/if}}
{{#if l5r5e.item.uuid}}
<div class="l5r5e item-infos">
<div class="profile"><img class="profile-img" src="{{l5r5e.item.img}}" alt="{{l5r5e.item.name}}" /></div>
<div class="name">
@UUID[{{l5r5e.item.uuid}}]
{{#ifCond l5r5e.item.type '==' 'weapon'}}
<p>
<i class="fas fa-arrows-alt-h" title="{{localize 'l5r5e.weapons.range'}}"> {{l5r5e.item.system.range}}</i>
/ <i class="fas fa-tint" title="{{localize 'l5r5e.weapons.damage'}}"> {{l5r5e.item.system.damage}}</i>
/ <i class="fas fa-skull" title="{{localize 'l5r5e.weapons.deadliness'}}"> {{l5r5e.item.system.deadliness}}</i>
</p>
{{/ifCond}}
</div>
</div> </div>
{{/if}} {{/if}}

View File

@@ -11,19 +11,21 @@ new game.l5r5e.DicePickerDialog({
``` ```
## Constructor Options ## Constructor Options
| Property | Type | Notes / Examples | | Property | Type | Notes / Examples |
|------------------|----------|------------------------------------------------------------------------------------------------------------------------------------------| |------------------|---------------|------------------------------------------------------------------------------------------------------------------------------------------|
| actor | Actor | Any `Actor` object instance.<br>ex : `game.user.character`, `canvas.tokens.controlled[0].actor` | | actor | Actor | Any `Actor` object instance.<br>ex : `game.user.character`, `canvas.tokens.controlled[0].actor` |
| actorId | string | This is the `id` not the `uuid` of an actor.<br>ex : "AbYgKrNwWeAxa9jT" | | actorId | string | This is the `id` not the `uuid` of an actor.<br>ex : "AbYgKrNwWeAxa9jT" |
| actorName | string | Careful this is case sensitive.<br>ex : "Isawa Aki" | | actorName | string | Careful this is case-sensitive.<br>ex : "Isawa Aki" |
| difficulty | number | `1` to `9` | | difficulty | number | `1` to `9` |
| difficultyHidden | boolean | If `true`, hide the difficulty and lock the view for the player. | | difficultyHidden | boolean | If `true`, hide the difficulty and lock the view for the player. |
| isInitiativeRoll | boolean | `true` if this is an initiative roll | | isInitiativeRoll | boolean | `true` if this is an initiative roll. |
| itemUuid | string | The `uuid` of technique or weapon used for this roll. Can be anything retrieved by `fromUuid()` or `fromUuidSync()`<br>_Added in v1.9.0_ | | item | Item | The object of technique or weapon used for this roll.<br>_Added in v1.9.0_ |
| ringId | string | If not provided, take the current stance of the actor if any.<br>ex : "fire", "water" | | itemUuid | string | The `uuid` of technique or weapon used for this roll. Can be anything retrieved by `fromUuid()` or `fromUuidSync()`<br>_Added in v1.9.0_ |
| skillId | string | Skill `id`<br>ex : "design", "aesthetics", "courtesy" | | ringId | string | If not provided, take the current stance of the actor if any.<br>ex : "fire", "water" |
| skillCatId | string | Skill category `id`<br>ex : "artisan", "scholar" | | skillId | string | Skill `id`<br>ex : "design", "aesthetics", "courtesy" |
| skillsList | string[] | `skillId`/`skillCatId` list coma separated.<br>Allow the player to select the skill used in a select<br>ex : "artisan,design" | | skillCatId | string | Skill category `id`<br>ex : "artisan", "scholar" |
| skillsList | string[] | `skillId`/`skillCatId` list coma separated.<br>Allow the player to select the skill used in a select<br>ex : "artisan,design" |
| target | TokenDocument | The targeted Token<br>_Added in v1.9.0_ |
All these properties are optional. All these properties are optional.

View File

@@ -12,7 +12,7 @@ difficulty: 2,
difficultyHidden: false, difficultyHidden: false,
history: null, // Stored data of the RnK, can be big history: null, // Stored data of the RnK, can be big
initialFormula: null, // The initial formula use in DP initialFormula: null, // The initial formula use in DP
itemUuid: null, // technique or weapon uuid item: null, // technique or weapon object
isInitiativeRoll: false, isInitiativeRoll: false,
keepLimit: null, // Max number of dice to keep keepLimit: null, // Max number of dice to keep
rnkEnded: false, // false if the player can modify the roll. rnkEnded: false, // false if the player can modify the roll.
@@ -29,6 +29,6 @@ summary: {
opportunity: 0, opportunity: 0,
strife: 0, strife: 0,
}, },
targetInfos: null, // "img" and "name" of the target if any target: null, // Target object (TokenDocument)
voidPointUsed: false, // if a void point as been used for this roll voidPointUsed: false, // if a void point as been used for this roll
``` ```