Roll : Added target info in Roll

This commit is contained in:
Vlyan
2022-02-17 15:24:50 +01:00
parent 448fadeca7
commit efe1e088ed
18 changed files with 148 additions and 68 deletions

View File

@@ -125,7 +125,7 @@ export class ActorL5r5e extends Actor {
prepareData() {
super.prepareData();
if (["character", "npc"].includes(this.data.type)) {
if (this.isCharacter) {
const data = this.data.data;
// No automation for npc as they cheat in stats
@@ -232,6 +232,14 @@ export class ActorL5r5e extends Actor {
return tpl;
}
/**
* Return true if this actor is a PC or NPC
* @return {boolean}
*/
get isCharacter() {
return ["character", "npc"].includes(this.data.type);
}
/**
* Return true if a weapon is equipped
* @return {boolean}
@@ -261,7 +269,7 @@ export class ActorL5r5e extends Actor {
* @return {boolean}
*/
get isPrepared() {
if (!["character", "npc"].includes(this.data.type)) {
if (!this.isCharacter) {
return false;
}
@@ -285,7 +293,7 @@ export class ActorL5r5e extends Actor {
* @return {number|null}
*/
get statusRank() {
if (!["character", "npc"].includes(this.data.type)) {
if (!this.isCharacter) {
return null;
}
return Math.floor(this.data.data.social.status / 10);
@@ -296,7 +304,7 @@ export class ActorL5r5e extends Actor {
* @return {number|null}
*/
get intrigueRank() {
if (!["character", "npc"].includes(this.data.type)) {
if (!this.isCharacter) {
return null;
}
return this.data.type === "npc" ? this.data.data.conflict_rank.social : this.data.data.identity.school_rank;
@@ -307,7 +315,7 @@ export class ActorL5r5e extends Actor {
* @return {number|null}
*/
get martialRank() {
if (!["character", "npc"].includes(this.data.type)) {
if (!this.isCharacter) {
return null;
}
return this.data.type === "npc" ? this.data.data.conflict_rank.martial : this.data.data.identity.school_rank;

View File

@@ -225,7 +225,7 @@ export class ArmySheetL5r5e extends BaseSheetL5r5e {
* @private
*/
async _updateLinkedActorData(type, actor) {
if (!actor || actor.documentName !== "Actor" || !["character", "npc"].includes(actor.data?.type)) {
if (!actor || actor.documentName !== "Actor" || !actor.isCharacter) {
console.warn("L5R5E | Wrong actor type", actor?.data?.type, actor);
return;
}

View File

@@ -91,6 +91,12 @@ export class CharacterSheetL5r5e extends BaseCharacterSheetL5r5e {
)?.[0]
)
);
game.l5r5e.HelpersL5r5e.autocomplete(
html,
"data.identity.school",
game.l5r5e.HelpersL5r5e.getSchoolsList(),
","
);
game.l5r5e.HelpersL5r5e.autocomplete(
html,
"data.identity.roles",

View File

@@ -233,6 +233,7 @@ export class TwentyQuestionsDialog extends FormApplication {
)?.[0]
)
);
game.l5r5e.HelpersL5r5e.autocomplete(html, "step3.school", game.l5r5e.HelpersL5r5e.getSchoolsList(), ",");
game.l5r5e.HelpersL5r5e.autocomplete(html, "step3.roles", game.l5r5e.HelpersL5r5e.getLocalizedRolesList(), ",");
}

View File

@@ -40,7 +40,7 @@ export class CombatL5r5e extends Combat {
const combatant = game.combat.combatants.find((c) => c.id === combatantId);
// Skip non character types (army)
if (!["character", "npc"].includes(combatant.actor.data.type)) {
if (!combatant.actor.isCharacter) {
updatedCombatants.push({
_id: combatant.id,
initiative: 0,

View File

@@ -139,6 +139,12 @@ export class DicePickerDialog extends FormApplication {
this.skillCatId = options.skillCatId;
}
// Target Infos : get the 1st selected target
const targetToken = Array.from(game.user.targets).values().next()?.value?.document;
if (targetToken) {
this.targetInfos = targetToken;
}
// Difficulty
if (!options.difficulty || !this.parseDifficulty(options.difficulty)) {
this.difficulty = game.settings.get("l5r5e", "initiative-difficulty-value");
@@ -167,7 +173,7 @@ export class DicePickerDialog extends FormApplication {
/**
* Set actor
* @param actor
* @param {ActorL5r5e} actor
*/
set actor(actor) {
if (!actor || !(actor instanceof Actor) || !actor.isOwner) {
@@ -177,13 +183,26 @@ export class DicePickerDialog extends FormApplication {
this.ringId = this._actor.data.data.stance;
}
/**
* Set Target Infos (Name, Img)
* @param {TokenDocument} targetToken
*/
set targetInfos(targetToken) {
this.object.targetInfos = targetToken
? {
img: targetToken.data.img,
name: targetToken.data.name,
}
: null;
}
/**
* Set ring preset
* @param ringId
*/
set ringId(ringId) {
this.object.ring.id = CONFIG.l5r5e.stances.includes(ringId) ? ringId : "void";
this.object.ring.value = this._actor.data.data.rings[this.object.ring.id];
this.object.ring.value = this._actor.data.data.rings?.[this.object.ring.id] || 1;
}
/**
@@ -322,7 +341,9 @@ export class DicePickerDialog extends FormApplication {
actor: this._actor,
useCategory: this.useCategory,
canUseVoidPoint:
this.object.difficulty.addVoidPoint || !this._actor || this._actor.data.data.void_points.value > 0,
this.object.difficulty.addVoidPoint ||
!this._actor ||
(this._actor.isCharacter && this._actor.data.data.void_points.value > 0),
disableSubmit: this.object.skill.value < 1 && this.object.ring.value < 1,
difficultyHiddenIsLock: this._difficultyHiddenIsLock.gm || this._difficultyHiddenIsLock.option,
};
@@ -632,13 +653,13 @@ export class DicePickerDialog extends FormApplication {
let targetToken;
if (isMin === null) {
// only one target, get the first element
targetToken = Array.from(game.user.targets).values().next()?.value.document;
targetToken = Array.from(game.user.targets).values().next()?.value?.document;
} else {
// Group (Min/Max)
const targetGrp = Array.from(game.user.targets).reduce(
(acc, tgt) => {
const targetActor = tgt.document.actor;
if (!["character", "npc"].includes(targetActor.type)) {
if (!targetActor.isCharacter) {
return acc;
}
@@ -727,10 +748,7 @@ export class DicePickerDialog extends FormApplication {
if (infos[1] === "T") {
this.difficultyHidden = true;
this._difficultyHiddenIsLock.option = true;
this.object.targetInfos = {
img: targetToken.data.img,
name: targetToken.data.name,
};
this.targetInfos = targetToken;
}
return true;
}

View File

@@ -235,7 +235,7 @@ export class RollnKeepDialog extends FormApplication {
return {
...super.getData(options),
isGM: game.user.isGM,
showStrifeBt: rollData.summary.strife > 0 && rollData.actor,
showStrifeBt: rollData.summary.strife > 0 && rollData.actor?.isCharacter,
cssClass: this.options.classes.join(" "),
data: this.object,
l5r5e: rollData,
@@ -706,7 +706,7 @@ export class RollnKeepDialog extends FormApplication {
// Apply strife to actor
const strifeApplied = Math.min(this.roll.l5r5e.summary.strife, Math.max(0, formData.strifeApplied));
const actorMod = strifeApplied - this.roll.l5r5e.strifeApplied;
if (actorMod !== 0 && this.roll.l5r5e.actor) {
if (actorMod !== 0 && this.roll.l5r5e.actor?.isCharacter) {
await this.roll.l5r5e.actor.update({
data: {
strife: {

View File

@@ -5,39 +5,42 @@ export class RollL5r5e extends Roll {
static CHAT_TEMPLATE = "dice/chat-roll.html";
static TOOLTIP_TEMPLATE = "dice/tooltip.html";
/**
* Specific data for L5R
*/
l5r5e = {
actor: null,
dicesTypes: {
std: false,
l5r: false,
},
difficulty: 2,
difficultyHidden: false,
history: null,
initialFormula: null,
isInitiativeRoll: false,
keepLimit: null,
rnkEnded: false,
skillAssistance: 0,
skillCatId: "",
skillId: "",
stance: "",
strifeApplied: 0,
summary: {
totalSuccess: 0,
totalBonus: 0,
success: 0,
explosive: 0,
opportunity: 0,
strife: 0,
},
targetInfos: null,
voidPointUsed: false,
};
constructor(formula, data = {}, options = {}) {
super(formula, data, options);
this.l5r5e = {
actor: null,
dicesTypes: {
std: false,
l5r: false,
},
difficulty: 2,
difficultyHidden: false,
history: null,
initialFormula: null,
isInitiativeRoll: false,
keepLimit: null,
rnkEnded: false,
skillAssistance: 0,
skillCatId: "",
skillId: "",
stance: "",
strifeApplied: 0,
summary: {
totalSuccess: 0,
totalBonus: 0,
success: 0,
explosive: 0,
opportunity: 0,
strife: 0,
},
targetInfos: null,
voidPointUsed: false,
};
// Parse flavor for stance and skillId
const flavors = Array.from(formula.matchAll(/\d+d([sr])\[([^\]]+)\]/gmu));
flavors.forEach((res) => {
@@ -48,12 +51,35 @@ export class RollL5r5e extends Roll {
this.l5r5e.skillId = res[2];
}
});
// Target Infos : get the 1st selected target
const targetToken = Array.from(game.user.targets).values().next()?.value?.document;
if (targetToken) {
this.targetInfos = targetToken;
}
}
/**
* Set actor
* @param {ActorL5r5e} actor
*/
set actor(actor) {
this.l5r5e.actor = actor instanceof Actor && actor.isOwner ? actor : null;
}
/**
* Set Target Infos (Name, Img)
* @param {TokenDocument} targetToken
*/
set targetInfos(targetToken) {
this.l5r5e.targetInfos = targetToken
? {
img: targetToken.data.img,
name: targetToken.data.name,
}
: null;
}
/**
* Execute the Roll, replacing dice and evaluating the total result
* @override

View File

@@ -196,7 +196,7 @@ export class GmToolbox extends FormApplication {
for await (const actor of game.actors.contents) {
// Only characters types
if (!["character", "npc"].includes(actor.data.type)) {
if (!actor.isCharacter) {
continue;
}

View File

@@ -89,6 +89,18 @@ export class HelpersL5r5e {
.map(([k, v]) => v);
}
/**
* Return the list of Schools (from compendium)
* @return {string[]}
*/
static getSchoolsList() {
const comp = game.packs.get("l5r5e.core-journal-school-curriculum");
if (!comp) {
return [];
}
return Array.from(comp.index).map((v) => v.name);
}
/**
* Return the list of Roles
* @return {string[]}
@@ -725,12 +737,16 @@ export class HelpersL5r5e {
}
/**
* Return the string without accents
* Return the string simplified for comparaison
* @param {string} str
* @return {string}
*/
static noAccents(str) {
return str.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
static normalize(str) {
return str
.normalize("NFKD")
.replace(/[\u0300-\u036f]/g, "") // remove accents
.replace(/[\W]/g, " ") // remove non word things
.toLowerCase();
}
/**
@@ -741,14 +757,17 @@ export class HelpersL5r5e {
* @param {string} sep (optional) Separator
*/
static autocomplete(html, name, list = [], sep = "") {
return; // TODO tmp disabled
/*
/* // TODO tmp disabled
const inp = document.getElementsByName(name)?.[0];
if (list.length < 1) {
return;
}
let currentFocus;
// Add wrapper class to the parent node of the input
inp.classList.add("autocomplete");
inp.parentNode.classList.add("autocomplete-wrapper");
const closeAllLists = (elmnt = null) => {
const collection = document.getElementsByClassName("autocomplete-items");
for (let item of collection) {
@@ -788,8 +807,8 @@ export class HelpersL5r5e {
list.forEach((value, index) => {
if (
HelpersL5r5e.noAccents(value.substring(0, val.length).toLowerCase()) ===
HelpersL5r5e.noAccents(val.toLowerCase())
HelpersL5r5e.normalize(value.substring(0, val.length)) ===
HelpersL5r5e.normalize(val)
) {
const choiceDiv = document.createElement("DIV");
choiceDiv.setAttribute("data-id", index);
@@ -853,6 +872,6 @@ export class HelpersL5r5e {
html.on("focusout", (e) => {
closeAllLists(e.target);
});
*/
//*/
}
}

View File

@@ -112,7 +112,7 @@ export class ArmyCohortSheetL5r5e extends ItemSheetL5r5e {
* @private
*/
async _updateLinkedActorData(actor) {
if (!actor || actor.documentName !== "Actor" || !["character", "npc"].includes(actor.data?.type)) {
if (!actor || actor.documentName !== "Actor" || !actor.isCharacter) {
console.warn("L5R5E | Wrong actor type", actor?.data?.type, actor);
return;
}