Draft: Gestion des signes draconiques #452

Closed
vincent.vandeme wants to merge 9 commits from v1.4-signes-draconiques into v1.4
12 changed files with 182 additions and 133 deletions
Showing only changes of commit 7c4d7987ac - Show all commits

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
.idea
todo.txt
todo.md
/.vscode

BIN
icons/heures/de-heures.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@ -2,59 +2,43 @@ import { ChatUtility } from "./chat-utility.js";
import { HtmlUtility } from "./html-utility.js";
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
import { Misc } from "./misc.js";
import { RdDRollTables } from "./rdd-rolltables.js";
import { TMRType, TMRUtility } from "./tmr-utility.js";
export class DialogCreateSigneDraconiqueForActors extends Dialog {
export class DialogCreateSigneDraconique extends Dialog {
static async createSigneForActors() {
let dialogData = {
signe: {
name: 'Un signe draconique',
type: "signedraconique",
img: 'systems/foundryvtt-reve-de-dragon/icons/tmr/gift.webp',
data: {
typesTMR: DialogCreateSigneDraconiqueForActors.selectRandomTmrs(),
ephemere: true,
duree: "1 round",
difficulte: -5,
valeur: { norm: 10, sign: 10, part: 15 },
}
},
signe: await RdDItemSigneDraconique.randomSigneDraconique(),
actors: game.actors.filter(actor => actor.isHautRevant()).map(it => duplicate(Misc.data(it)))
};
dialogData.tmrs = TMRUtility.listSelectedTMR(dialogData.signe.data.typesTMR ?? []);
dialogData.actors.forEach(it => it.selected = false);
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique-actors.html", dialogData);
new DialogCreateSigneDraconiqueForActors(dialogData, html)
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique.html", dialogData);
new DialogCreateSigneDraconique(dialogData, html)
.render(true);
}
static selectRandomTmrs() {
let tmrs = Object.values(TMRType).map(value => Misc.upperFirst(value.name));
const nbTmr = tmrs.length;
let remove = Math.floor(Math.random() * (nbTmr - 1));
for (let i = nbTmr; i > remove; i--) {
tmrs.splice(Math.floor(Math.random() * i), 1);
}
return tmrs;
}
constructor(dialogData, html, callback) {
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 650, 'z-index': 99999 };
let conf = {
title: "Créer un signe pour les personnages",
title: "Créer un signe",
content: html,
default: "Créer le signe",
buttons: { "Créer le signe": { label: "Créer le signe", callback: it => { this._onCreerSigne(); } } }
default: "Ajouter aux haut-rêvants",
buttons: {
"Ajouter aux haut-rêvants": { label: "Ajouter aux haut-rêvants", callback: it => { this._onCreerSigneActeurs(); } }
}
};
super(conf, options);
this.dialogData = dialogData;
}
async _onCreerSigne() {
async _onCreerSigneActeurs() {
this.validerSigne();
this.dialogData.actors.filter(it => it.selected).map(it => game.actors.get(it._id))
.forEach(actor => this._createSigneForActor(actor, this.dialogData.signe));
}
@ -71,29 +55,53 @@ export class DialogCreateSigneDraconiqueForActors extends Dialog {
}
validerSigne() {
this.dialogData.signe.name = $("[name='signe.name']").val();
this.dialogData.signe.data.valeur.norm = $("[name='signe.data.valeur.norm']").val();
this.dialogData.signe.data.valeur.sign = $("[name='signe.data.valeur.sign']").val();
this.dialogData.signe.data.valeur.part = $("[name='signe.data.valeur.part']").val();
this.dialogData.signe.data.difficulte = $("[name='signe.data.difficulte']").val();
this.dialogData.signe.data.ephemere = $("[name='signe.data.ephemere']").prop("checked");
this.dialogData.signe.data.duree = $("[name='signe.data.duree']").val();
this.dialogData.signe.data.typesTMR = $(".select-tmr").val();
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
this.setEphemere(this.dialogData.signe.data.ephemere);
html.find(".signe-name").change((event) => this.dialogData.signe.name = event.currentTarget.value);
html.find(".signe-data-ephemere").change((event) => this.setEphemere(event.currentTarget.checked));
html.find(".select-tmr").change((event) => this.onSelectTmr(event));
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
html.find("[name='signe.data.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked));
// html.find(".select-tmr").change((event) => this.onSelectTmr(event));
html.find(".select-actor").change((event) => this.onSelectActor(event));
html.find(".valeur-xp-sort").change((event) => this.onValeurXpSort(event));
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event));
}
async setEphemere(ephemere){
async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique();
$("[name='signe.name']").val(newSigne.name);
$("[name='signe.data.valeur.norm']").val(newSigne.data.valeur.norm);
$("[name='signe.data.valeur.sign']").val(newSigne.data.valeur.sign);
$("[name='signe.data.valeur.part']").val(newSigne.data.valeur.part);
$("[name='signe.data.difficulte']").val(newSigne.data.difficulte);
$("[name='signe.data.duree']").val(newSigne.data.duree);
$("[name='signe.data.ephemere']").prop("checked", newSigne.data.ephemere);
$(".select-tmr").val(newSigne.data.typesTMR);
this.setEphemere(newSigne.data.ephemere);
}
async setEphemere(ephemere) {
this.dialogData.signe.data.ephemere = ephemere;
HtmlUtility._showControlWhen($(".signe-data-duree"), ephemere);
}
async onSelectTmr(event) {
event.preventDefault();
this.dialogData.signe.data.typesTMR = $(".select-tmr").val();
}
// async onSelectTmr(event) {
// event.preventDefault();
// this.dialogData.signe.data.typesTMR = $(".select-tmr").val();
// }
async onSelectActor(event) {
event.preventDefault();
let selectActor = $(".select-actor");
const options = event.currentTarget.options;
for (var i = 0; i < options.length; i++) { // looping over the options
const actorId = options[i].attributes["data-actor-id"].value;

View File

@ -60,8 +60,23 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
if (!this.options.editable) return;
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
html.find(".select-tmr").change((event) => this.onSelectTmr(event));
html.find(".valeur-xp-sort").change((event) => this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value)));
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value)));
}
async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique();
// $("[name='signe.name']").val(newSigne.name);
// $("[name='signe.data.valeur.norm']").val(newSigne.data.valeur.norm);
// $("[name='signe.data.valeur.sign']").val(newSigne.data.valeur.sign);
// $("[name='signe.data.valeur.part']").val(newSigne.data.valeur.part);
// $("[name='signe.data.difficulte']").val(newSigne.data.difficulte);
// $("[name='signe.data.duree']").val(newSigne.data.duree);
// $("[name='signe.data.ephemere']").prop("checked", newSigne.data.ephemere);
// $(".select-tmr").val(newSigne.data.typesTMR);
// this.setEphemere(newSigne.data.ephemere);
this.object.update(newSigne);
}
async onSelectTmr(event) {

View File

@ -1,5 +1,15 @@
import { Misc } from "./misc.js";
import { RdDRollTables } from "./rdd-rolltables.js";
import { TMRType } from "./tmr-utility.js";
const tableSignesIndicatifs = [
{ rarete: "Très facile", difficulte: 0, xp: 6, nbCases: 14 },
{ rarete: "Facile", difficulte: -2, xp: 10, nbCases: 10 },
{ rarete: "Moyen", difficulte: -3, xp: 15, nbCases: 7 },
{ rarete: "Difficile", difficulte: -5, xp: 20, nbCases: 4 },
{ rarete: "Ardu", difficulte: -8, xp: 30, nbCases: 1 }
]
export class RdDItemSigneDraconique {
static prepareSigneDraconiqueMeditation(meditation, rolled) {
@ -57,4 +67,33 @@ export class RdDItemSigneDraconique {
}
}
static async randomSigneDraconique() {
let modele = await Misc.rollOneOf(tableSignesIndicatifs);
return {
name: await RdDItemSigneDraconique.randomSigneDescription(),
type: "signedraconique",
img: 'systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp',
data: {
typesTMR: await RdDItemSigneDraconique.randomTmrs(modele.nbCases),
ephemere: true,
duree: "1 round",
difficulte: modele.difficulte,
valeur: { norm: modele.xp, sign: modele.xp, part: Math.floor(modele.xp * 1.5) },
}
};
}
static async randomTmrs(nbTmr = undefined) {
let tmrs = Object.values(TMRType).map(value => Misc.upperFirst(value.name));
let keep = nbTmr ?? (await new Roll("1d" + TMRType.length).evaluate().total + 1);
for (let i = tmrs.length; i > keep; i--) {
tmrs.splice(await new Roll("1d" + i).evaluate().total, 1);
}
return tmrs;
}
static async randomSigneDescription() {
return await RdDRollTables.drawTextFromRollTable("Signes draconiques", false);
}
}

View File

@ -1,6 +1,6 @@
/* -------------------------------------------- */
import { DialogCreateSigneDraconiqueForActors } from "./dialog-create-signedraconique-actors.js";
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
import { RdDItemCompetence } from "./item-competence.js";
import { Misc } from "./misc.js";
import { RdDCarac } from "./rdd-carac.js";
@ -325,7 +325,7 @@ export class RdDCommands {
}
async creerSignesDraconiques() {
DialogCreateSigneDraconiqueForActors.createSigneForActors();
DialogCreateSigneDraconique.createSigneForActors();
return true;
}

View File

@ -8,31 +8,20 @@ export class RdDRollTables {
const table = await pack.getDocument(entry._id);
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"});
console.log("RdDRollTables", tableName, toChat, ":", draw);
return draw;
return draw.results.length > 0 ? draw.results[0] : undefined;
}
/* -------------------------------------------- */
static async drawItemFromRollTable(tableName, toChat) {
const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined;
if (drawnItemRef.data.collection) {
console.log(drawnItemRef);
const pack = game.packs.get(drawnItemRef.data.collection);
return await pack.getDocument(drawnItemRef.data.resultId);
}
ui.notifications.warn("le tirage ne correspond pas à une entrée d'un Compendium")
return drawnItemRef.text;
static async drawItemFromRollTable(tableName, toChat = false) {
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
const pack = game.packs.get(drawResult.data.collection);
return await pack.getDocument(drawResult.data.resultId);
}
/* -------------------------------------------- */
static async drawTextFromRollTable(tableName, toChat) {
const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined;
if (drawnItemRef.collection) {
ui.notifications.warn("le tirage correspond à une entrée d'un Compendium, on attendait un texte")
return await pack.getDocument(drawnItemRef.resultId);
}
return drawnItemRef.text;
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
return drawResult.data.text;
}
/* -------------------------------------------- */

File diff suppressed because one or more lines are too long

View File

@ -1,57 +0,0 @@
<form class="skill-roll-dialog">
<div>
<h4>Un signe draconique éphémère se manifeste:
<br><input class="signe-name" type="text" name="signe.name" value="{{signe.name}}" data-dtype="String" />
</h4>
</div>
<div class="form-group">
<label for="actors">Personnages concernés</label>
<select class="select-actor attribute-value" name="actors" id="actors" size="7" multiple>
{{#each actors as |actor key|}}
<option value="{{actor.name}}" data-actor-id="{{actor._id}}" {{#if actor.selected}}selected{{/if}}>
<img class="chat-icon" src="{{actor.img}}" title="{{actor.name}}" alt="{{actor.name}}" />
{{actor.name}}
</option>
{{/each}}
</select>
</div>
<div class="form-group">
<label for="signe.data.difficulte">Difficulte</label>
<input class="attribute-value" type="number" name="signe.data.difficulte" value="{{signe.data.difficulte}}" data-dtype="Number" />
</div>
<div class="form-group">
<label for="signe.data.valeur.norm">Expérience en sorts</label>
<div class="flexrow">
<input class="valeur-xp-sort" type="number" name="signe.data.valeur.norm" data-typereussite="norm"
value="{{signe.data.valeur.norm}}" min="1" max="100" data-dtype="Number" />
<span>Sign.</span>
<input class="valeur-xp-sort" type="number" name="signe.data.valeur.sign" data-typereussite="sign"
value="{{signe.data.valeur.sign}}" min="1" max="100" data-dtype="Number" />
<span>Part.</span>
<input class="valeur-xp-sort" type="number" name="signe.data.valeur.part" data-typereussite="part"
value="{{signe.data.valeur.part}}" min="1" max="100" data-dtype="Number" />
</div>
</div>
<div class="form-group">
<span>
<label for="signe.data.ephemere">Ephémère</label>
<input class="attribute-value signe-data-ephemere" type="checkbox" name="signe.data.ephemere" {{#if signe.data.ephemere}}checked{{/if}} />
</span>
<span>
<input class="signe-data-duree attribute-value" type="text" name="signe.data.duree" value="{{signe.data.duree}}" data-dtype="String" />
</span>
</div>
<div class="form-group">
<label for="tmrs">Terres médianes</label>
<select class="select-tmr attribute-value" name="tmrs" id="tmrs" size="{{tmrs.length}}" multiple>
{{#each tmrs as |tmr key|}}
<option value="{{tmr.name}}" {{#if tmr.selected}}selected{{/if}}>{{tmr.name}}</option>
{{/each}}
</select>
</div>
</form>

View File

@ -0,0 +1,52 @@
<form class="skill-roll-dialog">
<div>
<h4>Paramétrer le signe draconique
<span class="chat-card-button-area">
<a class="signe-aleatoire chat-card-button">Signe aléatoire</a>
</span>
<br><input type="text" name="signe.name" value="{{signe.name}}" data-dtype="String" />
</h4>
</div>
<div class="form-group">
<label for="signe.data.difficulte">Difficulte</label>
<input type="number" name="signe.data.difficulte" value="{{signe.data.difficulte}}" data-dtype="Number" />
</div>
<div class="form-group">
<label for="signe.data.valeur.norm">Expérience en sorts</label>
<div class="flexrow">
<input class="signe-xp-sort" type="number" name="signe.data.valeur.norm" data-typereussite="norm"
value="{{signe.data.valeur.norm}}" min="1" max="100" data-dtype="Number" />
<span>Sign.</span>
<input class="signe-xp-sort" type="number" name="signe.data.valeur.sign" data-typereussite="sign"
value="{{signe.data.valeur.sign}}" min="1" max="100" data-dtype="Number" />
<span>Part.</span>
<input class="signe-xp-sort" type="number" name="signe.data.valeur.part" data-typereussite="part"
value="{{signe.data.valeur.part}}" min="1" max="100" data-dtype="Number" />
</div>
</div>
<div class="form-group flexrow">
<label for="signe.data.ephemere">Ephémère</label>
<input class="flex-shrink" type="checkbox" name="signe.data.ephemere" {{#if signe.data.ephemere}}checked{{/if}} />
<span>
<input type="text" name="signe.data.duree" value="{{signe.data.duree}}" data-dtype="String" />
</span>
</div>
<div class="form-group">
<label for="tmrs">Terres médianes</label>
<select class="select-tmr" name="tmrs" id="tmrs" size="{{tmrs.length}}" multiple>
{{#each tmrs as |tmr key|}}
<option value="{{tmr.name}}" {{#if tmr.selected}}selected{{/if}}>{{tmr.name}}</option>
{{/each}}
</select>
</div>
<div class="form-group">
<label for="actors">Haut-rêvants concernés</label>
<select class="select-actor" id="actors" size="7" multiple>
{{#each actors as |actor key|}}
<option value="{{actor.name}}" data-actor-id="{{actor._id}}" {{#if actor.selected}}selected{{/if}}>{{actor.name}}</option>
{{/each}}
</select>
</div>
</form>

View File

@ -3,9 +3,10 @@
<img class="profile-img" src="{{img}}" data-edit="img" title="{{name}}" />
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{name}}" placeholder="Name" /></h1>
<a class="signe-aleatoire chat-card-button">Signe aléatoire</a>
</div>
</header>
{{!-- Sheet Body --}}
<section class="sheet-body">
<div class="form-group">
@ -16,13 +17,13 @@
<div class="form-group">
<label for="data.valeur.norm">Expérience en sorts</label>
<div class="flexrow">
<input class="valeur-xp-sort" type="number" name="data.valeur.norm" data-typereussite="norm"
<input class="signe-xp-sort" type="number" name="data.valeur.norm" data-typereussite="norm"
value="{{data.valeur.norm}}" min="1" max="100" data-dtype="Number" />
<span>Sign.</span>
<input class="valeur-xp-sort" type="number" name="data.valeur.sign" data-typereussite="sign"
<input class="signe-xp-sort" type="number" name="data.valeur.sign" data-typereussite="sign"
value="{{data.valeur.sign}}" min="1" max="100" data-dtype="Number" />
<span>Part.</span>
<input class="valeur-xp-sort" type="number" name="data.valeur.part" data-typereussite="part"
<input class="signe-xp-sort" type="number" name="data.valeur.part" data-typereussite="part"
value="{{data.valeur.part}}" min="1" max="100" data-dtype="Number" />
</div>
</div>