Compare commits

...

41 Commits

Author SHA1 Message Date
1c475348d5 Gestion des armes dans hotbar 2023-10-04 21:24:51 +02:00
de5d32f88f Gestion des armes dans hotbar 2023-10-04 09:33:24 +02:00
76a02d60ca Gestion des armes dans hotbar 2023-10-04 09:07:49 +02:00
724c556b9e Merge pull request 'v11' (#667) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #667
2023-10-04 09:07:10 +02:00
7dfba94a11 Nettoyage de date
Pas de "T" entre date et heure
2023-10-03 21:03:19 +02:00
928c7bbcfe Désespoir 2023-08-28 01:46:43 +02:00
222a06a978 Fix remoteCall 2023-08-15 17:24:01 +02:00
b4edaf8584 Fix remoteActorCall 2023-08-13 20:43:32 +02:00
3c062afd56 Fix remoteActorCall 2023-08-13 20:42:54 +02:00
6de4fff403 Merge pull request 'v11.0.15 - L'apprentissage de Khrachtchoum' (#666) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #666
2023-08-03 09:10:32 +02:00
3543f081b2 Version 11.0.15 2023-08-03 00:41:16 +02:00
56f14e12a2 Fix: regression sur les particulières
L'utilisation de la méthode clone() pôur cloner la compétence
supprime l'id de la compétence, du coup l'update pour y
ajouter de l'expérience ne marchait plus et bloquait la suite de la
résolution (pas de messages dans le tchat, ...)
2023-08-03 00:41:16 +02:00
e226af5ac5 Merge pull request 'v11.0.14' (#665) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #665
2023-07-30 09:25:10 +02:00
d8be37a2ec v11.0.14 2023-07-29 23:47:08 +02:00
ba2d9de7b6 Version 11.0.13
Les pincettes de Khrachtchoum le Problémeux
- Correction du calcul de la place restante lors de l'ajout dans un conteneur
2023-07-29 23:44:56 +02:00
6b8fb3267a Fix: calcul de la place dans un conteneur
Correction de l'ajout dans un conteneur, en faisant un calcul arrondi
pour éviter les problèmes de virgule flotante
2023-07-29 23:42:22 +02:00
05d6f64a31 Merge pull request 'v11.0.13 - La multiplication de l'eau de Khrachtchoum le Problémeux' (#664) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #664
2023-07-28 10:11:26 +02:00
c0570e58b4 Version 11.0.13 2023-07-27 19:21:48 +02:00
8389d578bc Fix: achat d'objet illimités
Lors de l'achat à un commerce avec une quantité illimité, on était
tout de même limité à la quantité de l'objet, même si elle n'était
pas diminuée
2023-07-27 19:17:57 +02:00
f05ef79b97 Merge pull request 'v11.0.12 - Les poids de la mesure de Khrachtchoum le Problémeux' (#663) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #663
2023-07-14 00:36:37 +02:00
d2a8bfae4f v11.0.12 - Les poids de la mesure
- Correction des malus de surencombrement
- Le malus armure est correctement affiché dans l'onglet des
  caractéristiques
2023-07-13 01:02:03 +02:00
d54834fa71 Amélioration des messages d'art 2023-07-13 01:02:03 +02:00
c898bf5212 Merge pull request 'Encombrement et malus armure' (#661) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #661
2023-07-11 14:46:14 +02:00
a118dc7334 Correction sur-Encombrement v2
Le malus appliqué est maintenant correct.

Avant, le malus pouvait avoir une virgule, et donc être arrondi
dans le malus vraiment appliqué même si affiché correctement.
2023-07-11 02:53:34 +02:00
46401e5d63 Cleanup: simplification _computeFinalLevel
méthode supprimée dasn RdDRoll (car basée sur les ajustements),
pas utile ici non plus.
2023-07-11 02:36:39 +02:00
7eb1d9f838 Fix affichage Malus Armure
Le malus armure est correctement affiché dans l'onglet caractéristiques.

Il n'est plus stocké dans l'acteur mais calculé.
2023-07-11 02:36:39 +02:00
1d8f4ebb88 Merge pull request 'Fix: sélection de compendiums que pour le MJ' (#660) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #660
2023-07-09 11:09:28 +02:00
145a92f462 Fix: sélection de compendiums que pour le MJ 2023-07-07 00:47:05 +02:00
5148d02314 Correction sur arrondi sur-encombrement 2023-07-01 21:28:18 +02:00
000c89b11a Merge pull request 'V11.0.11 - Les bleus de Khrachtchoum le Problémeux' (#659) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #659
2023-06-25 09:48:17 +02:00
5d4a18aac5 Version 11.0.11 2023-06-24 23:59:25 +02:00
34b5df637f Notifier le joueur qu'il peut passer sa nuit
Lorsque le MJ configure la nuit des personnages, une notification est
envoyée aux joueurs pour leur dire de gérer leur nuit.
2023-06-24 23:50:05 +02:00
22572ca98c Support des armes non mortelles 2023-06-24 23:40:07 +02:00
a6a1c1009e Merge pull request 'v11.0.10 - Les Songes de Khrachtchoum le Problémeux' (#658) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #658
2023-06-24 09:22:24 +02:00
288cf9162c Version v11.0.10 2023-06-24 01:48:34 +02:00
4b1381e535 Decompte des heure en cas de réveil
Si le gardien gère la durée des nuits, en cas de rêve de dragon,
les heures restant à dormir sont mises à jour.
2023-06-24 01:41:12 +02:00
78336a3f45 Fix: affichage sommeil avec RdD première heure
Le message ne s'affichait pas en cas de rêve de dragon dès la
première récupération
2023-06-24 01:19:54 +02:00
3001ae44de Endurance limitée en cas d'insomnie 2023-06-24 01:19:54 +02:00
a43ceb3188 Fix: lire depuis un livre 2023-06-24 01:19:54 +02:00
9e95a44efd Fix: click pour se déplacer dans les TMR 2023-06-24 01:19:54 +02:00
179ea0c85b Fix: selection de TMR des signes draconiques 2023-06-24 01:19:53 +02:00
32 changed files with 226 additions and 169 deletions

View File

@ -1,5 +1,33 @@
# v11.0
## v11.0.15 - L'apprentissage de Khrachtchoum
- Fix: l'expérience ne s'appliquait plus sur certaines réussites particulières (régression depuis la 11.0.7)
## v11.0.14 - Les pincettes de Khrachtchoum le Problémeux
- Correction du calcul de la place restante lors de l'ajout dans un conteneur
## v11.0.13 - La multiplication de l'eau de Khrachtchoum le Problémeux
- Correction de la vente depuis un commerce ayant des quantités illimitées
## v11.0.12 - Les poids de la mesure de Khrachtchoum le Problémeux
- Correction des malus de surencombrement
- Le malus armure est correctement affiché dans l'onglet des caractéristiques
- Correction d'orthographe et amélioration des messages des oeuvres d'art
## v11.0.11 - Les bleus de Khrachtchoum le Problémeux
- si le gardien configure le sommeil, les joueurs sont notifiés que chateau dormant vient de passer
- possibilité de créer des armes et des compétences de créatures non-mortelles.
## v11.0.10 - Les Songes de Khrachtchoum le Problémeux
- on peut de nouveau se déplacer dans les TMRs d'un clic sur la case à atteindre
- Lire un livre depuis l'inventaire permet de nouveau de faire un jet de la tâche
créée au lieu de créer toujours une nouvelle tâche
- La sélection des TMR pour la création de signes draconiques ne cause plus d'erreurs
- la récupération d'endurance en cas d'insomnie est limitée à la moitié
- le résultat du sommeil lors d'un rêve de dragon à la première heure s'affiche normalement
- lorsque le gardien gère la durée des nuits, en cas de rêve de dragon,
les heures dormies sont déduites des heures restant à dormir
## v11.0.9 - Les Souvenirs de Khrachtchoum le Problémeux
- mode de saisie de l'archétype en vue détaillée
- création une nouvelle incarnation depuis l'archétype

View File

@ -57,6 +57,7 @@ export class RdDActorSheet extends RdDBaseActorSheet {
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
malusArmure: this.actor.getMalusArmure()
})
this.timerRecherche = undefined;

View File

@ -95,7 +95,6 @@ export class RdDActor extends RdDBaseActor {
this.computeIsHautRevant();
await this.cleanupConteneurs();
await this.computeEncTotal();
await this.computeMalusArmure();
}
/* -------------------------------------------- */
@ -218,7 +217,12 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
getMalusArmure() {
return Misc.toInt(this.system.attributs?.malusarmure?.value)
if (this.isPersonnage()) {
return this.itemTypes[TYPES.armure].filter(it => it.system.equipe)
.map(it => it.system.malus)
.reduce(Misc.sum(), 0);
}
return 0;
}
/* -------------------------------------------- */
@ -261,7 +265,7 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
getDraconicList() {
return this.items.filter(it => it.isCompetencePersonnage() && it.system.categorie == 'draconic')
return this.itemTypes[TYPES.competence].filter(it => it.system.categorie == 'draconic')
}
/* -------------------------------------------- */
getBestDraconic() {
@ -271,13 +275,13 @@ export class RdDActor extends RdDBaseActor {
}
getDraconicOuPossession() {
const possession = this.items.filter(it => it.type == TYPES.competencecreature && it.system.categorie == 'possession')
const possession = this.itemTypes[TYPES.competencecreature].filter(it => it.system.categorie == 'possession')
.sort(Misc.descending(it => it.system.niveau))
.find(it => true);
if (possession) {
return possession.clone();
return possession;
}
const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0).map(it => it.clone()),
const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0),
POSSESSION_SANS_DRACONIC]
.sort(Misc.descending(it => it.system.niveau));
return draconics[0];
@ -387,6 +391,14 @@ export class RdDActor extends RdDBaseActor {
await this.distribuerStress('stress', consigne.stress.valeur, consigne.stress.motif);
}
await this.update({ 'system.sommeil': consigne.sommeil })
const player = this.findPlayer();
if (player) {
ChatUtility.notifyUser(player.id, 'info', `Vous pouvez gérer la nuit de ${this.name}`);
}
}
findPlayer() {
return game.users.players.find(player => player.active && player.character?.id == this.id);
}
async onTimeChanging(oldTimestamp, newTimestamp) {
@ -621,21 +633,22 @@ export class RdDActor extends RdDBaseActor {
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
content: this.name + ': '
};
await this.recupereEndurance(message);
if (this.system.sommeil?.insomnie || heures == 0) {
const insomnie = this.system.sommeil?.insomnie || heures == 0;
await this.recupereEndurance({ message: message, demi: insomnie });
if (insomnie) {
message.content += 'Vous ne trouvez pas le sommeil';
}
else {
let jetsReve = [];
let dormi = await this.dormirDesHeures(jetsReve, message, heures, options);
message.content += `Vous dormez ${dormi.heures <= 1 ? 'une heure' : (dormi.heures + ' heures')}. `;
if (jetsReve.length > 0) {
message.content += `Vous récupérez ${jetsReve.filter(it => it >= 0).reduce(Misc.joining("+"))} Points de rêve. `;
message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '(dragon)' : it).reduce(Misc.joining("+"))} Points de rêve. `;
}
if (dormi.etat == 'eveil') {
message.content += 'Vous êtes réveillé par un Rêve de Dragon.'
await this.reveilReveDeDragon(message, dormi.heures);
}
options.chateauDormant = options.chateauDormant && dormi.heures >= heures;
message.content += `Vous avez dormi ${dormi.heures <= 1 ? 'une heure' : (dormi.heures + ' heures')}. `;
}
if (!options.grisReve) {
@ -649,6 +662,14 @@ export class RdDActor extends RdDBaseActor {
}
}
async reveilReveDeDragon(message, heures) {
message.content += 'Vous êtes réveillé par un Rêve de Dragon.';
const restant = Math.max(this.system.sommeil?.heures - heures, 0)
if (restant > 0) {
await this.update({ 'system.sommeil': { heures: restant } });
}
}
async dormirDesHeures(jetsReve, message, heures, options) {
const dormi = { heures: 0, etat: 'dort' };
for (; dormi.heures < heures && dormi.etat == 'dort'; dormi.heures++) {
@ -702,8 +723,13 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
async recupereEndurance(message) {
const manquant = this._computeEnduranceMax() - this.system.sante.endurance.value;
async recupereEndurance({ message, demi }) {
let max = this._computeEnduranceMax();
if (demi) {
max = Math.floor(max / 2);
}
const manquant = max - this.system.sante.endurance.value;
if (manquant > 0) {
await this.santeIncDec("endurance", manquant);
message.content += `Vous récuperez ${manquant} points d'endurance. `;
@ -1092,7 +1118,7 @@ export class RdDActor extends RdDBaseActor {
case 'entite': case 'vehicule':
return 0;
}
return Math.min(0, this.getEncombrementMax() - Math.ceil(Number(this.getEncTotal())));
return Math.min(0, Math.floor(this.getEncombrementMax() - this.encTotal));
}
getMessageSurEncombrement() {
@ -1120,20 +1146,6 @@ export class RdDActor extends RdDBaseActor {
}
}
/* -------------------------------------------- */
async computeMalusArmure() {
if (this.isPersonnage()) {
const malusArmure = this.filterItems(it => it.type == 'armure' && it.system.equipe)
.map(it => it.system.malus ?? 0)
.reduce(Misc.sum(), 0);
// Mise à jour éventuelle du malus armure
if (this.system.attributs?.malusarmure?.value != malusArmure) {
await this.updateAttributeValue("malusarmure", malusArmure);
}
}
}
/* -------------------------------------------- */
computeResumeBlessure() {
const blessures = this.filterItems(it => it.system.gravite > 0, 'blessure')
@ -1706,6 +1718,7 @@ export class RdDActor extends RdDBaseActor {
await this.rollTache(tache.id);
}
}
async actionHerbe(item, onActionItem = async () => { }) {
if (item.isHerbeAPotion()) {
return DialogFabriquerPotion.create(this, item, onActionItem);
@ -1728,6 +1741,7 @@ export class RdDActor extends RdDBaseActor {
async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }, userId = undefined) {
if (userId != undefined && userId != game.user.id) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'consommerNourritureboisson',
args: [itemId, choix, userId]
@ -3057,29 +3071,43 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
rollArme(arme) {
getArmeCompetence(arme, competenceName) {
let comp = arme.system[competenceName]
if (!comp || comp.name == "") {
comp = arme.system[competenceName]
}
if ( !comp || comp.name == "") {
comp = arme.system[competenceName]
}
return comp
}
/* -------------------------------------------- */
rollArme(arme, competenceName = "competence") {
let compToUse = this.getArmeCompetence(arme, competenceName)
if (!Targets.hasTargets()) {
RdDConfirm.confirmer({
settingConfirmer: "confirmer-combat-sans-cible",
content: `<p>Voulez vous faire un jet de compétence ${arme.system.competence} sans choisir de cible valide?
content: `<p>Voulez vous faire un jet de compétence ${competenceName} sans choisir de cible valide?
<br>Tous les jets de combats devront être gérés à la main
</p>`,
title: 'Ne pas utiliser les automatisation de combat',
buttonLabel: "Pas d'automatisation",
onAction: async () => {
this.rollCompetence(arme.system.competence, { tryTarget: false })
this.rollCompetence(compToUse, { tryTarget: false })
}
});
return;
}
Targets.selectOneToken(target => {
if (Targets.isTargetEntite(target)) {
ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`);
return;
}
const competence = this.getCompetence(arme.system.competence)
const competence = this.getCompetence(compToUse)
//console.log("RollArme", competence, arme)
if (competence.isCompetencePossession()) {
return RdDPossession.onAttaquePossession(target, this, competence);
}
@ -3108,7 +3136,7 @@ export class RdDActor extends RdDBaseActor {
async onRollTachePremiersSoins(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({ actorId: this.id, method: 'onRollTachePremiersSoins', args: [blessureId, rollData] });
return RdDBaseActor.remoteActorCall({ tokenId: this.token?.id, actorId: this.id, method: 'onRollTachePremiersSoins', args: [blessureId, rollData] });
}
const blessure = this.getItem(blessureId, 'blessure')
console.log('TODO update blessure', this, blessureId, rollData, rollData.tache);
@ -3138,7 +3166,7 @@ export class RdDActor extends RdDBaseActor {
async onRollSoinsComplets(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({ actorId: this.id, method: 'onRollSoinsComplets', args: [blessureId, rollData] });
return RdDBaseActor.remoteActorCall({ tokenId: this.token?.id, actorId: this.id, method: 'onRollSoinsComplets', args: [blessureId, rollData] });
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
@ -3232,6 +3260,7 @@ export class RdDActor extends RdDBaseActor {
const attackerId = attacker?.id;
if (ReglesOptionnelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'appliquerEncaissement',
args: [rollData, show, attackerId]

View File

@ -50,7 +50,13 @@ export class RdDBaseActor extends Actor {
static onRemoteActorCall(callData, userId) {
if (userId == game.user.id) {
const actor = game.actors.get(callData?.actorId);
let actor = game.actors.get(callData?.actorId);
if ( callData.tokenId) {
let token = canvas.tokens.placeables.find(t => t.id == callData.tokenId)
if (token) {
actor = token.actor
}
}
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
const args = callData.args;
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
@ -119,7 +125,7 @@ export class RdDBaseActor extends Actor {
}
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
filterItems(filter, type = undefined) { return type ? this.itemTypes[type]?.filter(filter) ?? [] : []; }
filterItems(filter, type = undefined) { return (type ? this.itemTypes[type] : this.items)?.filter(filter) ?? []; }
findItemLike(idOrName, type) {
return this.getItem(idOrName, type)
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
@ -144,9 +150,10 @@ export class RdDBaseActor extends Actor {
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
}
async creerObjetParMJ(object){
async creerObjetParMJ(object) {
if (!Misc.isUniqueConnectedGM()) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'creerObjetParMJ',
args: [object]
@ -220,6 +227,7 @@ export class RdDBaseActor extends Actor {
if (fromActorId && !game.user.isGM) {
RdDBaseActor.remoteActorCall({
userId: Misc.connectedGMOrUser(),
tokenId: this.token?.id,
actorId: this.id,
method: 'ajouterSols', args: [sols, fromActorId]
});
@ -262,10 +270,10 @@ export class RdDBaseActor extends Actor {
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
if (!itemVendu) {
ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !`: `Impossible de retrouver: ${achat.vente.item.name} !`);
ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !` : `Impossible de retrouver: ${achat.vente.item.name} !`);
return;
}
if (vendeur && !this.verifierQuantite(itemVendu, quantite)) {
if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
return
}
@ -318,7 +326,7 @@ export class RdDBaseActor extends Actor {
}
verifierQuantite(item, quantiteDemande) {
const disponible = item?.getQuantite();
const disponible = this.getQuantiteDisponible(item);
return disponible == undefined || disponible >= quantiteDemande;
}
@ -447,62 +455,33 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */
conteneurPeutContenir(dest, item) {
conteneurPeutContenir(dest, moved) {
if (!dest) {
return true;
}
if (!dest.isConteneur()) {
return false;
}
const destData = dest
if (this._isConteneurContenu(item, dest)) {
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`);
return false; // Loop detected !
if (moved.isConteneurContenu(dest)) {
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${moved.name}) dans un de ses contenus ${dest.name} !`);
return false;
}
// Calculer le total actuel des contenus
let encContenu = this.getRecursiveEnc(dest) - Number(destData.system.encombrement);
let newEnc = this.getRecursiveEnc(item); // Calculer le total actuel du nouvel objet
const encContenu = dest.getEncContenu();
const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
const placeDisponible = Math.roundDecimals(dest.system.capacite - encContenu - newEnc, 4)
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
if (Number(destData.system.capacite) < encContenu + newEnc) {
if (placeDisponible < 0) {
ui.notifications.warn(
`Le conteneur ${dest.name} a une capacité de ${destData.system.capacite}, et contient déjà ${encContenu}.
Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`);
`Le conteneur ${dest.name} a une capacité de ${dest.system.capacite}, et contient déjà ${encContenu}.
Impossible d'y ranger: ${moved.name} d'encombrement ${newEnc}!`);
return false;
}
return true;
}
/* -------------------------------------------- */
_isConteneurContenu(item, conteneur) {
if (item?.isConteneur()) { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant
for (let id of item.system.contenu) {
let subObjet = this.getItem(id);
if (subObjet?.id == conteneur.id) {
return true; // Loop detected !
}
if (subObjet?.isConteneur()) {
return this._isConteneurContenu(subObjet, conteneur);
}
}
}
return false;
}
/* -------------------------------------------- */
getRecursiveEnc(objet) {
if (!objet) {
return 0;
}
const tplData = objet.system;
if (objet.type != 'conteneur') {
return Number(tplData.encombrement) * Number(tplData.quantite);
}
const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getItem(idContenu)));
return encContenus.reduce(Misc.sum(), 0)
+ Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/
}
/* -------------------------------------------- */
/** Ajoute un item dans un conteneur, sur la base
* de leurs ID */

View File

@ -28,6 +28,7 @@ export class RdDCommerce extends RdDBaseActor {
verifierFortune(cout) {
return this.system.illimite || super.verifierFortune(cout);
}
async depenserSols(cout) {
if (this.system.illimite) {
return

View File

@ -114,7 +114,7 @@ export class DialogChronologie extends Dialog {
heure: RdDTimestamp.definition(this.html.find("form.rdddialogchrono :input[name='chronologie.heure']").val()),
minute: this.html.find("form.rdddialogchrono :input[name='chronologie.minute']").val(),
},
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val()
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ')
}
}

View File

@ -111,7 +111,7 @@ export class DialogCreateSigneDraconique extends Dialog {
onSelectTmr(event) {
const tmrName = this.html.find(event.currentTarget)?.data("tmr-name");
const onTmr = this.tmrs.find(it => it.name == tmrName);
const onTmr = this.dialogData.tmrs.find(it => it.name == tmrName);
if (onTmr){
onTmr.selected = event.currentTarget.checked;
}

View File

@ -395,6 +395,16 @@ export class RdDItem extends Item {
return Math.max(this.system.encombrement ?? 0, 0);
}
getEncContenu() {
return this.getContenu()
.map(it => it.getRecursiveEnc())
.reduce(Misc.sum(), 0);
}
getRecursiveEnc() {
return this.getEncTotal() + this.getEncContenu()
}
getEncHerbe() {
switch (this.system.categorie) {
case 'Repos': case 'Soin': case 'Alchimie':
@ -404,6 +414,18 @@ export class RdDItem extends Item {
}
getContenu() {
if (this.isConteneur()) {
return this.system.contenu.map(idContenu => this.actor.getItem(idContenu));
}
return []
}
isConteneurContenu(conteneur) {
return this.getContenu()
.find(it => it.id == conteneur.id || it.isConteneurContenu(conteneur))
}
valeurTotale() {
return (this.isService() ? 1 : this.getQuantite()) * this.valeur()
}
@ -675,7 +697,7 @@ export class RdDItem extends Item {
_armeChatData() {
return [
`<b>Compétence</b>: ${this.system.competence}`,
`<b>Dommages</b>: ${this.system.dommages}`,
`<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == 'non-mortel' ? '(Non mortel)' : ''}`,
`<b>Force minimum</b>: ${this.system.force}`,
`<b>Resistance</b>: ${this.system.resistance}`,
...this._inventaireTemplateChatData()

View File

@ -789,8 +789,7 @@ export class RdDCombat {
let rollData = {
passeArme: randomID(16),
mortalite: arme?.system.mortalite,
coupsNonMortels: false,
competence: competence.clone(),
competence: competence,
surprise: this.attacker.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true),
targetToken: Targets.extractTokenData(this.target),
@ -1045,7 +1044,7 @@ export class RdDCombat {
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
competence: this.defender.getCompetence(competenceParade).clone(),
competence: this.defender.getCompetence(competenceParade),
arme: armeParade,
surprise: this.defender.getSurprise(true),
needParadeSignificative: ReglesOptionnelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
@ -1126,7 +1125,7 @@ export class RdDCombat {
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
competence: competence.clone(),
competence: competence,
surprise: this.defender.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true),
carac: this.defender.system.carac,

View File

@ -181,7 +181,7 @@ export class RdDEmpoignade {
let rollData = {
mode, empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps").clone(),
competence: attacker.getCompetence("Corps à corps"),
selectedCarac: attacker.system.carac.melee,
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
}
@ -210,7 +210,7 @@ export class RdDEmpoignade {
mode: "immobilise",
empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps").clone()
competence: attacker.getCompetence("Corps à corps")
}
const msg = await ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name),
@ -272,7 +272,7 @@ export class RdDEmpoignade {
mode, attacker, defender, empoignade, attackerRoll,
diffLibre: attackerRoll.diffLibre,
attaqueParticuliere: attackerRoll.particuliere,
competence: defender.getCompetence(competenceName).clone(),
competence: defender.getCompetence(competenceName),
surprise: defender.getSurprise(true),
carac: defender.system.carac,
selectedCarac: defender.system.carac[carac],

View File

@ -1,8 +1,8 @@
export class RdDHotbar {
static async addToHotbar(item, slot) {
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`;
static async createItemMacro(item, slot, armeCompetence = undefined) {
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}"` + ((armeCompetence) ? `, "${armeCompetence}");` : `);`);
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command));
if (!macro) {
macro = await Macro.create({
@ -15,6 +15,25 @@ export class RdDHotbar {
await game.user.assignHotbarMacro(macro, slot);
}
static async addToHotbar(item, slot) {
if (item?.type == "arme") { // Used to manage weapons with multiple skills
if (item.system.competence != "") {
await this.createItemMacro(item, slot, "competence")
slot++
}
if (item.system.lancer != "") {
await this.createItemMacro(item, slot, "lancer")
slot++
}
if (item.system.tir != "") {
await this.createItemMacro(item, slot, "lancer")
slot++
}
} else {
await this.createItemMacro(item, slot)
}
}
/**
* Create a macro when dropping an entity on the hotbar
* Item - open roll dialog for item
@ -44,7 +63,7 @@ export class RdDHotbar {
}
/** Roll macro */
static rollMacro(itemName, itemType, bypassData) {
static rollMacro(itemName, itemType, competenceName) {
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
@ -58,7 +77,7 @@ export class RdDHotbar {
// Trigger the item roll
switch (item.type) {
case "arme":
return actor.rollArme(item);
return actor.rollArme(item, competenceName);
case "competence":
return actor.rollCompetence(itemName);
}

View File

@ -39,7 +39,7 @@ export class RdDPossession {
let rollData = {
mode: "attaque",
isECNIDefender: false,
competence: competence.clone(),
competence: competence,
possession: possession,
attacker: attacker,
defender: defender,

View File

@ -112,7 +112,7 @@ export class RdDRollResolutionTable extends Dialog {
async updateRollResult() {
let rollData = this.rollData;
rollData.caracValue = parseInt(rollData.selectedCarac.value)
rollData.finalLevel = this._computeFinalLevel(rollData);
rollData.finalLevel = Misc.toInt(rollData.diffConditions) + Misc.toInt(rollData.diffLibre);
const htmlTable = await RdDResolutionTable.buildHTMLTable({
carac: rollData.caracValue,
@ -129,12 +129,6 @@ export class RdDRollResolutionTable extends Dialog {
}
/* -------------------------------------------- */
_computeFinalLevel(rollData) {
const diffConditions = Misc.toInt(rollData.diffConditions);
const diffLibre = Misc.toInt(rollData.diffLibre);
return diffLibre + diffConditions;
}
async close() {
await super.close();

View File

@ -187,7 +187,7 @@ export class RdDRoll extends Dialog {
console.log("RdDRollSelectDialog - Cout reve", ptreve);
this.updateRollResult(html);
});
this.html.find("[name='coupsNonMortels']").change((event) => {
this.html.find("[name='mortalite']").change((event) => {
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
this.updateRollResult(html);
});
@ -295,8 +295,7 @@ export class RdDRoll extends Dialog {
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat())
rollData.caracValue = parseInt(rollData.selectedCarac.value)
rollData.mortalite = rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite ?? 'mortel';
rollData.coupsNonMortels = (rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite) == 'non-mortel';
rollData.mortalite = rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite ?? rollData.mortalite ?? 'mortel';
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
let dmgText = Misc.toSignedString(rollData.dmg.total);
@ -306,7 +305,6 @@ export class RdDRoll extends Dialog {
}
RollDataAjustements.calcul(rollData, this.actor);
rollData.finalLevel = this._computeFinalLevel(rollData);
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
const adjustements = await this.buildAjustements(rollData);
@ -319,7 +317,7 @@ export class RdDRoll extends Dialog {
// Mise à jour valeurs
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
this.html.find("[name='coupsNonMortels']").prop('checked', rollData.mortalite == 'non-mortel');
this.html.find("[name='mortalite']").prop('checked', rollData.mortalite == 'non-mortel');
this.html.find(".dmg-arme-actor").text(dmgText);
this.html.find("div.placeholder-ajustements").empty().append(adjustements);
this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
@ -331,30 +329,6 @@ export class RdDRoll extends Dialog {
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html`, rollData);
}
/* -------------------------------------------- */
_computeFinalLevel(rollData) {
return RollDataAjustements.sum(rollData.ajustements);
}
/* -------------------------------------------- */
_computeDiffCompetence(rollData) {
if (rollData.competence) {
return Misc.toInt(rollData.competence.system.niveau);
}
if (rollData.draconicList) {
return Misc.toInt(rollData.competence.system.niveau);
}
return 0;
}
/* -------------------------------------------- */
_computeMalusArmure(rollData) {
let malusArmureValue = 0;
if (rollData.malusArmureValue && (rollData.selectedCarac.label == "Agilité" || rollData.selectedCarac.label == "Dérobée")) {
malusArmureValue = rollData.malusArmureValue;
}
return malusArmureValue;
}
/* -------------------------------------------- */
_getTitle(rollData) {
const carac = rollData.selectedCarac.label;

View File

@ -906,7 +906,7 @@ export class RdDTMRDialog extends Dialog {
if (this.viewOnly) {
return;
}
let clickOddq = RdDTMRDialog._computeEventOddq(event.data.originalEvent);
let clickOddq = RdDTMRDialog._computeEventOddq(event.nativeEvent);
await this._onClickTMRPos(clickOddq); // Vérifier l'état des compteurs reve/fatigue/vie
}

View File

@ -180,24 +180,25 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
// partial enums
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categories.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-periode.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
// Partials
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs',

View File

@ -164,7 +164,7 @@ export class RollDataAjustements {
descr: reference.getDescr && reference.getDescr(rollData, actor)
}
}
rollData.finalLevel = RollDataAjustements.sum(rollData.ajustements);
rollData.finalLevel = RollDataAjustements.sum(rollData.ajustements)
}
/* -------------------------------------------- */

View File

@ -47,6 +47,7 @@ export class SystemCompendiums extends FormApplication {
label: "Compendiums système",
hint: "Ouvre la fenêtre de sélection des compendiums système",
icon: "fas fa-bars",
restricted: true,
type: SystemCompendiums
})
}

View File

@ -106,11 +106,6 @@ export class RdDCalendrier extends Application {
return buttons
}
/*async maximize() {
await super.maximize()
this.render(true)
}*/
async close() { }
async onUpdateSetting(setting, update, options, id) {

View File

@ -1,14 +1,13 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "11.0.9",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.9.zip",
"version": "11.0.19",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.19.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": {
"minimum": "11",
"verified": "11",
"maximum": "11"
"verified": "11"
},
"description": "Rêve de Dragon RPG for FoundryVTT",
"authors": [

View File

@ -393,12 +393,6 @@
"label": "Encombrement",
"derivee": true
},
"malusarmure": {
"type": "number",
"value": 0,
"label": "Malus Armure",
"derivee": true
},
"protection": {
"type": "number",
"value": 0,
@ -594,7 +588,8 @@
"iscombat": false,
"isnaturelle": true,
"ispossession": false,
"dommages": 0
"dommages": 0,
"mortalite": "mortel"
},
"empoignade": {
"templates": ["description"],
@ -671,6 +666,7 @@
"resistance": 0,
"categorie_parade": "",
"dommages": "0",
"mortalite": "mortel",
"penetration": 0,
"force": "0",
"competence": "",

View File

@ -72,7 +72,7 @@
</li>
<li class="caracteristique flexrow list-item" >
<label class="carac-label">Malus armure</label>
<input class="derivee-value" type="number" disabled value="{{system.attributs.malusarmure.value}}" data-dtype="number"/>
<input class="derivee-value" type="number" disabled value="{{calc.malusArmure}}" data-dtype="number"/>
</li>
<li class="caracteristique flexrow list-item">
<label class="carac-label" for="system.attributs.protection.value" >Protection naturelle</label>

View File

@ -1,6 +1,6 @@
{{#if use.moral}}
<span>
Vous avez fait appel {{#if (gt moral 0)}}au moral{{else}}à l'énergie du déspoir{{/if}}
Vous avez fait appel {{#if (gt moral 0)}}au moral{{else}}à l'énergie du désespoir{{/if}}
{{#if (eq perteMoralEchec 'dissolution')}}et échoué, cous marquez un point de dissolution!.
{{else if (eq perteMoralEchec 'perte')}}et échoué, votre moral baisse à {{moral}}.
{{else}}et réussi, votre moral reste de {{moral}}.

View File

@ -1,14 +1,14 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4>
{{alias}} tente de chanter : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} {{#if rolled.isSuccess}}chante{{else}}tente de chanter{{/if}} {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
<div>
{{#if rolled.isSuccess}}
{{alias}} réussi son interprétation avec une qualité de {{qualiteFinale}} .
{{alias}} réussit son interprétation avec une qualité de {{qualiteFinale}} .
{{else}}
{{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}.
{{alias}} manque d'inspiration, son interprétation a une qualité de {{qualiteFinale}}.
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -1,14 +1,14 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4>
{{alias}} tente de danser : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} {{#if rolled.isSuccess}}danse{{else}}tente de danser{{/if}} {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
<div>
{{#if rolled.isSuccess}}
{{alias}} réussi son interprétation avec une qualité de {{qualiteFinale}} .
{{alias}} réussit son interprétation avec une qualité de {{qualiteFinale}} .
{{else}}
{{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}.
{{alias}} manque d'inspiration, son interprétation a une qualité de {{qualiteFinale}}.
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4>
{{alias}} tente de jouer le morceau : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} {{#if rolled.isSuccess}}interprete{{else}}tente de jouer{{/if}} le morceau : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
@ -8,7 +8,7 @@
{{#if rolled.isSuccess}}
{{alias}} réussit son interprétation avec une qualité de {{qualiteFinale}} .
{{else}}
{{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}.
{{alias}} manque d'inspiration, son interprétation a une qualité de {{qualiteFinale}}.
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -7,9 +7,9 @@
<hr>
<div>
{{#if rolled.isSuccess}}
{{alias}} réussi son interprétation avec une qualité de {{qualiteFinale}} .
{{alias}} réussit son interprétation avec une qualité de {{qualiteFinale}} .
{{else}}
{{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}.
{{alias}} manque d'inspiration, son interprétation a une qualité de {{qualiteFinale}}.
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4>
{{alias}} tente de cuisiner la recette : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} {{#if rolled.isSuccess}}réalise{{else}}tente de cuisiner{{/if}} la recette : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>

View File

@ -54,7 +54,7 @@
<label>Empoignade</label>
{{else}}
<span>
<input class="attribute-value" type="checkbox" name="coupsNonMortels" {{#unless (eq mortalite 'mortel')}}checked{{/unless}} />
<input class="attribute-value" type="checkbox" name="motalite" {{#unless (eq mortalite 'mortel')}}checked{{/unless}} />
<label class="dmg-arme-actor"></label>
</span>
{{/if}}

View File

@ -0,0 +1,3 @@
<option value="mortel">Mortel</option>
<option value="non-mortel">Non mortel</option>
<option value="empoignade">Empoignade</option>

View File

@ -37,6 +37,14 @@
<label for="system.dommages">Dommages </label>
<input class="attribute-value" type="text" name="system.dommages" value="{{system.dommages}}" data-dtype="String"/>
</div>
<div class="form-group">
<label for="system.mortalite">Mortalité</label>
<select name="system.mortalite" data-dtype="String">
{{#select system.mortalite}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.html"}}
{{/select}}
</select>
</div>
<div class="form-group">
<label for="system.resistance">Résistance </label>
<input class="attribute-value" type="text" name="system.resistance" value="{{system.resistance}}" data-dtype="Number"/>

View File

@ -27,6 +27,14 @@
<label for="niveau">Dommages (+dom)</label>
<input class="attribute-value" type="text" name="system.dommages" value="{{system.dommages}}" data-dtype="Number"/>
</div>
<div class="form-group">
<label for="system.mortalite">Mortalité</label>
<select name="system.mortalite" data-dtype="String">
{{#select system.mortalite}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.html"}}
{{/select}}
</select>
</div>
{{/if}}
{{#if isparade}}
<div class="form-group">