Merge pull request 'v10.7.19 - les fantômes de Semolosse' (#653) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10

Reviewed-on: https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/pulls/653
This commit was merged in pull request #653.
This commit is contained in:
2023-06-14 08:27:49 +02:00
29 changed files with 455 additions and 264 deletions
+9
View File
@@ -1,5 +1,14 @@
# v10.7 - L'os de Semolosse
## v10.7.19 - les fantômes de Semolosse
- les créatures ont maintenant le droit d'avoir des compétences de tir, lancer, mêlée, armes naturelles, parade.
- les créatures armées utilisent la bonne phase d'initiative
- correction des possessions
- la difficulté de la défense est imposée par l'attaque
- une attaque particulière de possession est en finesse
- le rêve actuel des personnages est bien utilisé
- correction des achats par le MJ sans acteur sélectionné
## v10.7.18 - le repos de Semolosse
- correction des dates de blessures qui ne marchaient plus
+19 -19
View File
@@ -38,13 +38,14 @@ import { RdDItemBlessure } from "./item/blessure.js";
import { AppAstrologie } from "./sommeil/app-astrologie.js";
import { RdDEmpoignade } from "./rdd-empoignade.js";
import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js";
import { TYPES } from "./item.js";
const POSSESSION_SANS_DRACONIC = {
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
name: 'Sans draconic',
system: {
niveau: 0,
defaut_carac: "reve",
defaut_carac: "reve-actuel",
}
};
@@ -109,7 +110,7 @@ export class RdDActor extends RdDBaseActor {
canReceive(item) {
if (this.isCreature()) {
return item.type == 'competencecreature' || item.isInventaire();
return item.type == TYPES.competencecreature || item.isInventaire();
}
if (this.isEntite()) {
return item.type == 'competencecreature';
@@ -270,15 +271,16 @@ export class RdDActor extends RdDBaseActor {
}
getDraconicOuPossession() {
const possessions = this.items.filter(it => it.type == 'competencecreature' && it.system.ispossession)
.sort(Misc.descending(it => it.system.niveau));
if (possessions.length > 0) {
return duplicate(possessions[0]);
const possession = this.items.filter(it => it.type == TYPES.competencecreature && it.system.categorie == 'possession')
.sort(Misc.descending(it => it.system.niveau))
.find(it=>true);
if (possession) {
return possession.clone();
}
const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0),
const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0).map(it =>it.clone()),
POSSESSION_SANS_DRACONIC]
.sort(Misc.descending(it => it.system.niveau));
return duplicate(draconics[0]);
return draconics[0];
}
getPossession(possessionId) {
@@ -778,7 +780,7 @@ export class RdDActor extends RdDBaseActor {
async combattreReveDeDragon(force) {
let rollData = {
actor: this,
competence: duplicate(this.getDraconicOuPossession()),
competence: this.getDraconicOuPossession(),
canClose: false,
rencontre: await game.system.rdd.rencontresTMR.getReveDeDragon(force),
tmr: true,
@@ -959,9 +961,9 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async updateCompetence(idOrName, compValue) {
let competence = this.getCompetence(idOrName);
const competence = this.getCompetence(idOrName);
if (competence) {
let toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie);
const toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie, competence.getCategories());
this.notifyCompetencesTronc(competence, toNiveau);
const fromNiveau = competence.system.niveau;
await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, 'system.niveau': toNiveau }]);
@@ -2299,14 +2301,14 @@ export class RdDActor extends RdDBaseActor {
carac: this.system.carac,
competence: this.getCompetence(idOrName)
}
if (rollData.competence.type == 'competencecreature') {
if (rollData.competence.system.iscombat && options.tryTarget && Targets.hasTargets()) {
if (rollData.competence.type == TYPES.competencecreature) {
const arme = RdDItemCompetenceCreature.armeCreature(rollData.competence)
if (arme && options.tryTarget && Targets.hasTargets()) {
Targets.selectOneToken(target => {
if (rollData.competence.system.ispossession) {
if (arme.action == "possession") {
RdDPossession.onAttaquePossession(target, this, rollData.competence)
}
else {
const arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence)
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme)
}
});
@@ -3053,7 +3055,7 @@ export class RdDActor extends RdDBaseActor {
const competence = this.getCompetence(arme.system.competence)
if (competence.system.ispossession) {
if (competence.isCompetencePossession()) {
return RdDPossession.onAttaquePossession(target, this, competence);
}
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme);
@@ -3133,9 +3135,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
conjurerPossession(possession) {
// TODO: choix de la compétence de draconic ou de possession
let draconic = this.getDraconicOuPossession();
RdDPossession.onConjurerPossession(this, draconic, possession)
RdDPossession.onConjurerPossession(this, possession)
}
/* -------------------------------------------- */
+25 -22
View File
@@ -3,7 +3,8 @@ import { Misc } from "../misc.js";
import { DialogSplitItem } from "../dialog-split-item.js";
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
import { Monnaie } from "../item-monnaie.js";
import { RdDItem } from "../item.js";
import { RdDItem, TYPES } from "../item.js";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
/* -------------------------------------------- */
/**
@@ -53,6 +54,8 @@ export class RdDBaseActorSheet extends ActorSheet {
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
formData.competences.filter(it => it.type == TYPES.competencecreature)
.forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it))
return formData;
}
@@ -125,27 +128,27 @@ export class RdDBaseActorSheet extends ActorSheet {
.map(t => Misc.arrayOrEmpty(itemTypes[t]))
.reduce((a, b) => a.concat(b), [])
.sort(Misc.ascending(it => it.name));
}
/* -------------------------------------------- */ /** @override */
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.html.find('.conteneur-name a').click(async event => {
RdDUtility.toggleAfficheContenu(this.getItemId(event));
this.render(true);
});
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
this.html.find('.recherche')
.each((index, field) => {
this._rechercheSelectArea(field);
})
.keyup(async event => this._rechercherKeyup(event))
.change(async event => this._rechercherKeyup(event));
this.html.find('.recherche').prop( "disabled", false );
}
/* -------------------------------------------- */ /** @override */
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.html.find('.conteneur-name a').click(async event => {
RdDUtility.toggleAfficheContenu(this.getItemId(event));
this.render(true);
});
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
this.html.find('.recherche')
.each((index, field) => {
this._rechercheSelectArea(field);
})
.keyup(async event => this._rechercherKeyup(event))
.change(async event => this._rechercherKeyup(event));
this.html.find('.recherche').prop("disabled", false);
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
+7 -8
View File
@@ -248,13 +248,12 @@ export class RdDBaseActor extends Actor {
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id) ?? achat.vente.item;
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
if (!itemVendu) {
ui.notifications.warn("Erreur sur achat: rien à acheter<br>Si possible, transmettez les logs de la console aux développeurs");
console.log('Erreur sur achat: rien à acheter', achat);
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 (!this.verifierQuantite(vendeur, itemVendu, quantite)) {
if (vendeur && !this.verifierQuantite(itemVendu, quantite)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
return
}
@@ -265,7 +264,7 @@ export class RdDBaseActor extends Actor {
await this.decrementerVente(vendeur, itemVendu, quantite, cout);
if (acheteur) {
await acheteur.depenserSols(cout);
const createdItemId = await acheteur.creerQuantiteItem(achat.vente.item, quantite);
const createdItemId = await acheteur.creerQuantiteItem(itemVendu, quantite);
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
}
if (cout > 0) {
@@ -306,9 +305,9 @@ export class RdDBaseActor extends Actor {
return this.getFortune() >= cout;
}
verifierQuantite(vendeur, item, quantiteTotal) {
const disponible = vendeur?.getQuantiteDisponible(item);
return disponible == undefined || disponible >= quantiteTotal;
verifierQuantite(item, quantiteDemande) {
const disponible = item?.getQuantite();
return disponible == undefined || disponible >= quantiteDemande;
}
async consommerNourritureAchetee(achat, vente, createdItemId) {
+1 -1
View File
@@ -22,7 +22,7 @@ export class RdDCommerce extends RdDBaseActor {
}
getQuantiteDisponible(item) {
return this.system.illimite || item.isService() ? undefined : item.getQuantite();
return (this.system.illimite || item?.isService()) ? undefined : item.getQuantite();
}
verifierFortune(cout) {
+3 -2
View File
@@ -1,4 +1,5 @@
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
import { TYPES } from "./item.js";
import { RdDCombatManager } from "./rdd-combat.js";
const nomCategorieParade = {
@@ -19,7 +20,7 @@ const nomCategorieParade = {
export class RdDItemArme extends Item {
static isArme(item) {
return (item.type == 'competencecreature' && item.system.iscombat) || item.type == 'arme';
return RdDItemCompetenceCreature.getCategorieAttaque(item) || item.type == 'arme';
}
/* -------------------------------------------- */
@@ -27,7 +28,7 @@ export class RdDItemArme extends Item {
switch (arme ? arme.type : '') {
case 'arme': return arme;
case 'competencecreature':
return RdDItemCompetenceCreature.armeNaturelle(arme);
return RdDItemCompetenceCreature.armeCreature(arme);
}
return RdDItemArme.mainsNues();
}
+9 -9
View File
@@ -23,7 +23,7 @@ const limitesArchetypes = [
];
/* -------------------------------------------- */
const categorieCompetences = {
const categoriesCompetences = {
"generale": { base: -4, label: "Générales" },
"particuliere": { base: -8, label: "Particulières" },
"specialisee": { base: -11, label: "Spécialisées" },
@@ -49,16 +49,16 @@ const competence_xp_cumul = _buildCumulXP();
export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static getCategorieCompetences() {
return categorieCompetences;
}
/* -------------------------------------------- */
static getNiveauBase(category) {
return categorieCompetences[category].base;
static getCategories() {
return categoriesCompetences;
}
/* -------------------------------------------- */
static getLabelCategorie(category) {
return categorieCompetences[category].label;
return categoriesCompetences[category].label;
}
/* -------------------------------------------- */
static getNiveauBase(category, categories = categoriesCompetences) {
return categories[category]?.base ?? 0;
}
/* -------------------------------------------- */
@@ -192,7 +192,7 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static isNiveauBase(item) {
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie);
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.getCategories());
}
/* -------------------------------------------- */
+76 -30
View File
@@ -1,51 +1,97 @@
import { RdDItem, TYPES } from "./item.js";
import { RdDCombatManager } from "./rdd-combat.js";
const categories = {
"generale": { base: 0, label: "Générale" },
"naturelle": { base: 0, label: "Arme naturelle" },
"melee": { base: 0, label: "Mêlée" },
"parade": { base: 0, label: "Parade" },
"tir": { base: 0, label: "Tir" },
"lancer": { base: 0, label: "Lancer" },
"possession": { base: 0, label: "Possession" },
}
/* -------------------------------------------- */
export class RdDItemCompetenceCreature extends Item {
/* -------------------------------------------- */
static setRollDataCreature(rollData) {
rollData.competence = rollData.competence
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
rollData.competence.system.defaut_carac = "carac_creature"
rollData.competence.system.categorie = "creature"
rollData.selectedCarac = rollData.carac.carac_creature
if (rollData.competence.system.iscombat) {
rollData.arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence);
}
static getCategories() {
return categories;
}
/* -------------------------------------------- */
static armeNaturelle(competencecreature) {
if (RdDItemCompetenceCreature.isCompetenceAttaque(competencecreature)) {
// si c'est un Item compétence: cloner pour ne pas modifier lma compétence
let arme = (competencecreature instanceof Item) ? competencecreature.clone(): competencecreature;
mergeObject(arme.system,
static setRollDataCreature(rollData) {
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
rollData.competence.system.defaut_carac = "carac_creature"
rollData.selectedCarac = rollData.carac.carac_creature
rollData.arme = RdDItemCompetenceCreature.armeCreature(rollData.competence);
}
/* -------------------------------------------- */
static armeCreature(item) {
const categorieAttaque = RdDItemCompetenceCreature.getCategorieAttaque(item)
if (categorieAttaque != undefined) {
// si c'est un Item compétence: cloner pour ne pas modifier la compétence
let arme = item.clone();
mergeObject(arme,
{
competence: arme.name,
initiative: RdDCombatManager.calculInitiative(competencecreature.system.niveau, competencecreature.system.carac_value),
niveau: competencecreature.system.niveau,
equipe: true,
resistance: 100,
dommagesReels: arme.system.dommages,
penetration: 0,
force: 0,
rapide: true,
cac: competencecreature.system.isnaturelle ? "naturelle" : "",
action: 'attaque'
action: item.isCompetencePossession() ? 'possession' : 'attaque',
system: {
competence: arme.name,
cac: categorieAttaque == "naturelle" ? "naturelle" : "",
niveau: item.system.niveau,
initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value),
equipe: true,
resistance: 100,
dommagesReels: arme.system.dommages,
penetration: 0,
force: 0,
rapide: true,
}
});
return arme;
}
console.error("RdDItemCompetenceCreature.toActionArme(", competencecreature, ") : impossible de transformer l'Item en arme");
return undefined;
}
/* -------------------------------------------- */
static isCompetenceAttaque(item) {
return item.type == 'competencecreature' && item.system.iscombat;
static getCategorieAttaque(item) {
if (item.type == TYPES.competencecreature) {
switch (item.system.categorie) {
case "melee":
case "tir":
case "lancer":
case "naturelle":
case "possession":
return item.system.categorie
}
}
return undefined
}
static isDommages(item) {
if (item.type == TYPES.competencecreature) {
switch (item.system.categorie) {
case "melee":
case "tir":
case "lancer":
case "naturelle":
return true
}
}
return false
}
static isParade(item) {
if (item.type == TYPES.competencecreature) {
switch (item.system.categorie) {
case "melee":
case "naturelle":
case "parade":
return true
}
}
return false
}
/* -------------------------------------------- */
static isCompetenceParade(item) {
return item.type == 'competencecreature' && item.system.categorie_parade !== "";
+9 -2
View File
@@ -11,6 +11,8 @@ import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { Misc } from "./misc.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { TYPES } from "./item.js";
/**
* Extend the basic ItemSheet for RdD specific items
@@ -98,9 +100,13 @@ export class RdDItemSheet extends ItemSheet {
isComestible: this.item.getUtilisationCuisine(),
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable)
}
if (this.item.type == TYPES.competencecreature) {
formData.isparade = RdDItemCompetenceCreature.isParade(this.item)
formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item)
}
const competences = await SystemCompendiums.getCompetences('personnage');
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
formData.categories = this.item.getCategories()
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
@@ -249,7 +255,8 @@ export class RdDItemSheet extends ItemSheet {
event.preventDefault();
if (this.item.isCompetence()) {
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
const categorie = event.currentTarget.value;
const level = RdDItemCompetence.getNiveauBase(categorie, this.item.getCategories());
this.item.system.base = level;
this.html.find('[name="system.base"]').val(level);
}
+11 -1
View File
@@ -6,6 +6,8 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDUtility } from "./rdd-utility.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { RdDRaretes } from "./item/raretes.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
export const TYPES = {
competence: 'competence',
@@ -218,6 +220,7 @@ export class RdDItem extends Item {
isService() { return this.type == TYPES.service; }
isCompetence() { return typesObjetsCompetence.includes(this.type) }
isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" }
isTemporel() { return typesObjetsTemporels.includes(this.type) }
isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
@@ -234,6 +237,13 @@ export class RdDItem extends Item {
isPresentDansMilieux(milieux) {
return this.getEnvironnements(milieux).length > 0
}
getCategories() {
switch (this.type) {
case TYPES.competence: return RdDItemCompetence.getCategories()
case TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories()
}
return {}
}
getEnvironnements(milieux = undefined) {
const environnements = this.isInventaire() ? this.system.environnement : undefined;
@@ -370,7 +380,7 @@ export class RdDItem extends Item {
}
getEncTotal() {
return (this.isService() ? 0 : this.getQuantite()) * this.getEnc();
return (this.getQuantite() ?? 0) * this.getEnc();
}
getEnc() {
+63 -5
View File
@@ -2,7 +2,7 @@ import { RdDBaseActor } from "./actor/base-actor.js";
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
import { Grammar } from "./grammar.js";
import { Monnaie } from "./item-monnaie.js";
import { RdDItem } from "./item.js";
import { RdDItem, TYPES } from "./item.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDRaretes } from "./item/raretes.js";
@@ -13,7 +13,7 @@ class Migration {
async applyItemsUpdates(computeUpdates) {
await game.actors.forEach(async (actor) => {
const actorItemUpdates = computeUpdates(actor.items);
const actorItemUpdates = computeUpdates(actor.items).filter(it => it != undefined);
if (actorItemUpdates.length > 0) {
console.log(
this.code,
@@ -24,7 +24,7 @@ class Migration {
}
});
const itemUpdates = computeUpdates(game.items);
const itemUpdates = computeUpdates(game.items).filter(it => it != undefined);
if (itemUpdates.length > 0) {
console.log(this.code, "Applying updates on items", itemUpdates);
await Item.updateDocuments(itemUpdates);
@@ -65,7 +65,6 @@ class _1_5_34_migrationPngWebp {
}
}
class _10_0_16_MigrationSortsReserve extends Migration {
get code() { return "creation-item-sort-reserve"; }
get version() { return "10.0.16"; }
@@ -370,6 +369,7 @@ class _10_4_6_ServicesEnCommerces extends Migration {
return itemToCreate;
}
}
class _10_5_0_UpdatePeriodicite extends Migration {
get code() { return "migration-periodicite-poisons-maladies"; }
get version() { return "10.5.0"; }
@@ -458,6 +458,62 @@ class _10_7_0_MigrationBlessures extends Migration {
}
}
class _10_7_19_CategorieCompetenceCreature extends Migration {
get code() { return "categorie-competence-creature"; }
get version() { return "10.7.19"; }
async migrate() {
await this.applyItemsUpdates(items => items
.filter(it => TYPES.competencecreature == it.type)
.map(it => this.migrateCompetenceCreature(it))
);
}
migrateCompetenceCreature(it) {
const categorie = this.getCategorie(it)
if (categorie == it.system.categorie) {
return undefined
}
return { _id: it.id, 'system.categorie': categorie }
}
getCategorie(it) {
if (it.system.ispossession) {
return 'possession'
}
switch (it.system.categorie) {
case "melee":
if (it.system.isnaturelle) {
return 'naturelle'
}
return 'melee'
case "particuliere": case "specialisee": case "connaissance":
return "generale"
default:
return it.system.categorie
}
}
}
class _10_7_19_PossessionsEntiteVictime extends Migration {
get code() { return "possessions-entite-victime"; }
get version() { return "10.7.19"; }
async migrate() {
await this.applyItemsUpdates(items => items
.filter(it => TYPES.possession == it.type)
.map(it => this.migratePossession(it))
);
}
migratePossession(it) {
return { _id: it.id,
'system.entite.actorid': it.system.possesseurid,
'system.victime.actorid': it.system.possedeid
}
}
}
export class Migrations {
static getMigrations() {
return [
@@ -474,6 +530,8 @@ export class Migrations {
new _10_4_6_ServicesEnCommerces(),
new _10_5_0_UpdatePeriodicite(),
new _10_7_0_MigrationBlessures(),
new _10_7_19_CategorieCompetenceCreature(),
new _10_7_19_PossessionsEntiteVictime(),
];
}
@@ -490,7 +548,7 @@ export class Migrations {
migrate() {
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion");
if (isNewerVersion(game.system.version, currentVersion)) {
//if (true) { /* comment previous and uncomment here to test before upgrade */
// if (true) { /* comment previous and uncomment here to test before upgrade */
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
if (migrations.length > 0) {
migrations.sort((a, b) => this.compareVersions(a, b));
+5 -1
View File
@@ -1,4 +1,5 @@
import { RdDCarac } from "./rdd-carac.js";
import { RdDPossession } from "./rdd-possession.js";
const conditionsTactiques = [
{ type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true },
@@ -27,6 +28,9 @@ export class RdDBonus {
if (rollData.isEmpoignade && rollData.rolled?.isPart) {
return true
}
if (RdDPossession.isDefensePossession(rollData)) {
return RdDPossession.isPossessionFinesse(rollData)
}
return rollData.attackerRoll?.particuliere == 'finesse';
}
@@ -74,7 +78,7 @@ export class RdDBonus {
/* -------------------------------------------- */
static _dmgArme(rollData) {
if ( rollData.arme) {
if (rollData.arme) {
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0);
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0);
+10 -10
View File
@@ -87,7 +87,7 @@ export class RdDCombatManager extends Combat {
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
if (!formula) {
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
const competence = combatant.actor.items.find(it => it.system.iscombat)
const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.getCategorieAttaque(it))
if (competence) {
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0);
}
@@ -230,15 +230,15 @@ export class RdDCombatManager extends Combat {
}
static listActionsCreature(competences) {
return competences.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
.map(it => RdDItemCompetenceCreature.armeNaturelle(it));
return competences.map(it => RdDItemCompetenceCreature.armeCreature(it))
.filter(it => it != undefined);
}
static listActionsPossessions(actor) {
return RdDCombatManager._indexActions(actor.getPossessions().map(p => {
return {
name: p.name,
action: 'conjurer',
action: 'possession',
system: {
competence: p.name,
possessionid: p.system.possessionid,
@@ -255,7 +255,7 @@ export class RdDCombatManager extends Combat {
return actions;
}
if (actor.isCreatureEntite()) {
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']);
} else if (actor.isPersonnage()) {
// Recupération des items 'arme'
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
@@ -263,7 +263,7 @@ export class RdDCombatManager extends Combat {
.concat(RdDItemArme.mainsNues());
const competences = actor.itemTypes['competence'];
actions = actions.concat(RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac));
actions = RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac);
if (actor.system.attributs.hautrevant.value) {
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
@@ -351,7 +351,7 @@ export class RdDCombatManager extends Combat {
} else if (combatant.actor.getSurprise() == "demi") {
initOffset = 0;
initInfo = "Demi Surprise"
} else if (action.action == 'conjurer') {
} else if (action.action == 'possession') {
initOffset = 10;
caracForInit = combatant.actor.getReveActuel();
initInfo = "Possession"
@@ -790,7 +790,7 @@ export class RdDCombat {
passeArme: randomID(16),
mortalite: arme?.system.mortalite,
coupsNonMortels: false,
competence: competence,
competence: competence.clone(),
surprise: this.attacker.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true),
targetToken: Targets.extractTokenData(this.target),
@@ -1045,7 +1045,7 @@ export class RdDCombat {
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
competence: this.defender.getCompetence(competenceParade),
competence: this.defender.getCompetence(competenceParade).clone(),
arme: armeParade,
surprise: this.defender.getSurprise(true),
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
@@ -1126,7 +1126,7 @@ export class RdDCombat {
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
competence: competence,
competence: competence.clone(),
surprise: this.defender.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true),
carac: this.defender.system.carac,
+1 -1
View File
@@ -70,7 +70,7 @@ export class RdDEmpoignade {
let rollData = {
mode: mode,
isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps"),
competence: attacker.getCompetence("Corps à corps").clone(),
selectedCarac: attacker.system.carac.melee,
empoignade: empoignade,
attackerId: attacker.id,
+96 -47
View File
@@ -1,9 +1,9 @@
/* -------------------------------------------- */
import { RdDCombat } from "./rdd-combat.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRoll } from "./rdd-roll.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { Targets } from "./targets.js";
import { TYPES } from "./item.js";
/* -------------------------------------------- */
/* On part du principe qu'une entité démarre tjs
@@ -20,9 +20,9 @@ export class RdDPossession {
/* -------------------------------------------- */
static searchPossessionFromEntite(attacker, defender) {
let poss = attacker.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
let poss = attacker.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id);
if (!poss) {
poss = defender.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
poss = defender.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id);
}
return poss && duplicate(poss) || undefined;
}
@@ -31,39 +31,40 @@ export class RdDPossession {
static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
const defender = target.actor;
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
const isNouvelle = !suitePossession && ! fromEntite;
const isNouvelle = !suitePossession && !fromEntite;
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
RdDPossession.$updateEtatPossession(possession)
let rollData = {
mode: "possession",
mode: "attaque",
isECNIDefender: false,
competence: competence,
competence: competence.clone(),
possession: possession,
attacker: attacker,
defender: defender,
targetToken: Targets.extractTokenData(target)
};
if (attacker.isCreatureEntite()) {
RdDItemCompetenceCreature.setRollDataCreature(rollData)
}
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
}
/* -------------------------------------------- */
static async onConjurerPossession(attacker, competence, possession) {
static async onConjurerPossession(attacker, possession) {
possession = duplicate(possession);
RdDPossession.$updateEtatPossession(possession)
const defender = game.actors.get(possession.system.entite.actorid);
let rollData = {
mode: "possession",
mode: "attaque",
isECNIDefender: true,
competence: competence,
possession: possession,
attacker: attacker,
defender: game.actors.get(possession.system.possesseurid)
defender: defender,
};
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
await RdDPossession.$rollAttaquePossession(attacker, rollData);
}
@@ -71,7 +72,7 @@ export class RdDPossession {
static async onDefensePossession(attackerId, defenderId, possessionId) {
let attacker = game.actors.get(attackerId)
let possession = attacker?.getPossession(possessionId)
defenderId = defenderId ?? possession?.system.possesseurid ?? undefined
defenderId = defenderId ?? possession?.system.entite.actorid ?? undefined
let defender = game.actors.get(defenderId)
possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
@@ -82,19 +83,29 @@ export class RdDPossession {
possession = duplicate(possession)
// Update for draconic roll
let rollData = {
mode: "conjuration",
mode: "defense",
isECNIDefender: defender.type == "entite",
possession: possession,
attacker: attacker,
defender: defender,
competence: defender.getDraconicOuPossession(),
selectedCarac: defender.system.carac.reve,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
}
rollData.competence.system.defaut_carac = 'reve-actuel'
RdDPossession.selectCompetenceDraconicOuPossession(rollData, defender)
rollData.diffLibre = RdDPossession.getInfoAttaque(rollData).diffLibre
await RdDPossession.$rollDefensePossession(defender, rollData);
}
static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
rollData.competence = rollingActor.getDraconicOuPossession();
if (rollingActor.isCreatureEntite()) {
RdDItemCompetenceCreature.setRollDataCreature(rollData)
}
else {
rollData.selectedCarac = rollingActor.system.carac.reve
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } }
rollData.competence.system.defaut_carac = 'reve-actuel'
}
}
/* -------------------------------------------- */
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
@@ -104,21 +115,22 @@ export class RdDPossession {
name: 'jet-possession',
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
callbacks: [
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDPossession.$onRollPossession(r, true, isNouvelle) },
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDPossession.$onRollPossession(r, false, isNouvelle) },
{ action: async (r) => await RdDPossession.$onRollPossession(r, isNouvelle) },
]
});
dialog.render(true);
dialog.render(true);
}
/* -------------------------------------------- */
static async $onRollPossession(rollData, isSuccess, isNouvelle = false) {
rollData.possession.isSuccess = isSuccess;
RdDPossession.$updateEtatPossession(rollData.possession);
static async $onRollPossession(rollData, isNouvelle = false) {
rollData.possession.isSuccess = rollData.rolled.isSuccess;
RdDPossession.$updateEtatPossession(rollData.possession, rollData);
if (isNouvelle) {
// Creer la possession sur le defenseur
rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
await rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
}
const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid)
RdDPossession.storePossessionAttaque(possession, rollData)
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
}
@@ -127,35 +139,42 @@ export class RdDPossession {
const dialog = await RdDRoll.create(defender, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' },
{
name: 'conjurer',
name: 'possession',
label: 'Conjurer une Possession',
callbacks: [
{ action: async (r) => await RdDPossession.$onRollConjuration(r) }
]
}
);
]
}
);
dialog.render(true);
}
}
/* -------------------------------------------- */
static async $onRollConjuration(rollData) {
let actor = game.actors.get(rollData.possession.system.possedeid)
let victime = game.actors.get(rollData.possession.system.victime.actorid)
let compteur = rollData.possession.system.compteur
if (!rollData.rolled.isSuccess) {
if (rollData.isECNIDefender) {
rollData.possession.system.compteur--
compteur--
} else {
rollData.possession.system.compteur++
compteur++
}
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
await actor.updateEmbeddedDocuments('Item', [update])
}
const possession = victime.getPossession(rollData.possession.system.possessionid)
await possession.update({
system: {
compteur: compteur,
entite: { diffLibre: 0, finesse: false },
victime: { diffLibre: 0, finesse: false }
}
})
rollData.possession = possession
RdDPossession.$updateEtatPossession(rollData.possession)
await RdDResolutionTable.displayRollData(rollData,rollData.defender, 'chat-resultat-possession.html')
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html')
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
// conjuration
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
}
}
@@ -180,13 +199,43 @@ export class RdDPossession {
}
}
/* -------------------------------------------- */
static isPossessionFinesse(rollData) {
return RdDPossession.getInfoAttaque(rollData).finesse
}
/* -------------------------------------------- */
static getInfoAttaque(rollData) {
return rollData.possession.system[rollData.isECNIDefender ? 'victime' : 'entite'];
}
/* -------------------------------------------- */
static isDefensePossession(rollData) {
return rollData.possession && rollData.mode == "defense"
}
/* -------------------------------------------- */
static storePossessionAttaque(possession, rollData = undefined) {
const attaquant = rollData?.isECNIDefender ? 'victime' : 'entite'
possession.update({
[`system.${attaquant}`]: {
diffLibre: rollData?.diffLibre ?? 0,
finesse: rollData?.rolled.isPart ?? false
}
})
}
/* -------------------------------------------- */
static async createPossession(attacker, defender) {
return await Item.create({
name: "Possession en cours de " + attacker.name, type: 'possession',
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
system: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.id, possedeid: defender.id, date: 0, compteur: 0 }
},
name: "Possession en cours de " + attacker.name, type: 'possession',
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
system: {
description: "", typepossession: attacker.name,
possede: false,
possessionid: randomID(16),
entite: { actorid: attacker.id },
victime: { actorid: defender.id },
compteur: 0
}
},
{
temporary: true
})
+2 -2
View File
@@ -75,8 +75,8 @@ export class RdDTokenHud {
(event) => {
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
const action = hudData.actions[actionIndex];
if (action.action == 'conjurer') {
const possession = combatant.actor.getPossession(action.system.possessionid);
const possession = action.action == 'possession' ? combatant.actor.getPossession(action.system.possessionid) : undefined;
if (possession) {
combatant.actor.conjurerPossession(possession);
}
else {
+1 -1
View File
@@ -182,7 +182,7 @@ export class RdDUtility {
'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-categorie-competence.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',
+2 -1
View File
@@ -5,6 +5,7 @@ import { RdDItemSort } from "./item-sort.js";
import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js";
import { RdDCarac } from "./rdd-carac.js";
import { RdDPossession } from "./rdd-possession.js";
import { RdDUtility } from "./rdd-utility.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
@@ -30,7 +31,7 @@ export const referenceAjustements = {
},
diffLibre: {
isUsed: (rollData, actor) => rollData.diffLibre != undefined,
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre',
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ?? RdDPossession.isDefensePossession(rollData) ? 'Imposée' : 'Libre',
getValue: (rollData, actor) => rollData.selectedSort
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
+39 -39
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+5 -5
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -1,8 +1,8 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "10.7.18",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.18.zip",
"version": "10.7.19",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.19.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json",
"compatibility": {
"minimum": "10",
+13 -6
View File
@@ -586,11 +586,11 @@
},
"competencecreature": {
"templates": ["description"],
"categorie_parade": "",
"carac_value": 0,
"niveau": 0,
"default_diffLibre": 0,
"categorie": "",
"carac_value": 0,
"categorie_parade": "",
"iscombat": false,
"isnaturelle": true,
"ispossession": false,
@@ -611,10 +611,17 @@
"typepossession": "",
"possede": false,
"possessionid": "",
"possesseurid": "",
"possedeid": "",
"compteur": 0,
"date": 0
"entite": {
"actorid": "",
"diffLibre": 0,
"finesse": false
},
"victime": {
"actorid": "",
"diffLibre": 0,
"finesse": false
},
"compteur": 0
},
"blessure": {
"templates": ["temporel"],
+18 -12
View File
@@ -9,18 +9,24 @@
<input class="competence-carac creature-carac" type="text" compname="{{comp.name}}" name="{{comp._id}}.carac"
value="{{comp.system.carac_value}}" data-dtype="number"
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
<input class="competence-value creature-niveau" type="text" compname="{{comp.name}}" name="{{comp._id}}.niveau"
value="{{numberFormat comp.system.niveau decimals=0 sign=true}}" data-dtype="number"
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
<input class="competence-damage creature-dommages" type="text" compname="{{comp.name}}" name="{{comp._id}}.dommages"
value="{{numberFormat comp.system.dommages decimals=0 sign=true}}" data-dtype="number"
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
{{#if @root.options.vueDetaillee}}
<div class="item-controls">
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
{{/if}}
<input class="competence-value creature-niveau" type="text" data-dtype="number"
compname="{{comp.name}}" name="{{comp._id}}.niveau"
value="{{numberFormat comp.system.niveau decimals=0 sign=true}}"
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}
/>
<input class="competence-damage creature-dommages" type="text" data-dtype="number"
{{#if comp.isdommages}}
compname="{{comp.name}}" name="{{comp._id}}.dommages"
value="{{numberFormat comp.system.dommages decimals=0 sign=true}}"
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}
{{else}}disabled{{/if}}
/>
{{#if @root.options.vueDetaillee}}
<div class="item-controls">
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
{{/if}}
</li>
{{/each}}
</ol>
+2 -2
View File
@@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" />
<h4>
{{#if (eq mode "possession")}}
{{#if (eq mode "attaque")}}
{{attacker.name}} tente de {{#if isECNIDefender}}conjurer la possession de{{else}}posséder{{/if}} {{defender.name}}
{{else}}
{{defender.name}} tente de {{#if isECNIDefender}}résister à{{else}}conjurer la possession de{{/if}} {{attacker.name}}
@@ -12,7 +12,7 @@
<div>
<span class='chat-card-button-area'>
<br>
{{#if (eq mode "possession")}}
{{#if (eq mode "attaque")}}
{{#if possession.isSuccess}}
<a class='defense-possession chat-card-button'
data-attackerId='{{attacker.id}}'
@@ -0,0 +1,3 @@
{{#each @root.categoriesCompetencesCreature as |categorie key|}}
<option value="{{@key}}">{{categorie.label}}</option>
{{/each}}
@@ -1,3 +1,3 @@
{{#each @root.categorieCompetences as |categorie key|}}
{{#each @root.categories as |categorie key|}}
<option value="{{@key}}">{{categorie.label}}</option>
{{/each}}
+1 -1
View File
@@ -18,7 +18,7 @@
<label for="system.categorie">Catégorie </label>
<select name="system.categorie" class="categorie" data-dtype="String">
{{#select system.categorie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categories.html"}}
{{/select}}
</select>
</div>
+8 -20
View File
@@ -6,50 +6,38 @@
<label for="system.categorie">Catégorie</label>
<select name="system.categorie" class="categorie" data-dtype="String">
{{#select system.categorie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categories.html"}}
{{/select}}
</select>
</div>
<div class="form-group">
<label for="niveau">Valeur de Caractéristique </label>
<label for="niveau">Valeur de Caractéristique</label>
<input class="attribute-value" type="text" name="system.carac_value" value="{{system.carac_value}}" data-dtype="Number"/>
</div>
<div class="form-group">
<label for="niveau">Niveau </label>
<label for="niveau">Niveau</label>
<input class="attribute-value" type="text" name="system.niveau" value="{{system.niveau}}" data-dtype="Number"/>
</div>
<div class="form-group">
<label for="default_diffLibre">Difficulté libre par défaut</label>
<input class="attribute-value" type="text" name="system.default_diffLibre" value="{{system.default_diffLibre}}" data-dtype="Number"/>
</div>
<div class="form-group">
<label for="system.ispossession">Attaque de possession</label>
<input class="attribute-value" type="checkbox" name="system.ispossession" {{#if system.ispossession}}checked{{/if}}/>
</div>
{{#unless system.ispossession}}
<div class="form-group">
<label for="system.iscombat">Compétence d'attaque</label>
<input class="attribute-value" type="checkbox" name="system.iscombat" {{#if system.iscombat}}checked{{/if}}/>
</div>
{{#if system.iscombat}}
<div class="form-group">
<label for="system.isnaturelle">Arme naturelle</label>
<input class="attribute-value" type="checkbox" name="system.isnaturelle" {{#if system.isnaturelle}}checked{{/if}}/>
</div>
{{#if isdommages}}
<div class="form-group">
<label for="niveau">Dommages (+dom)</label>
<input class="attribute-value" type="text" name="system.dommages" value="{{system.dommages}}" data-dtype="Number"/>
</div>
{{/if}}
{{/if}}
{{#if isparade}}
<div class="form-group">
<label>Catégorie parade </label>
<label>Catégorie parade</label>
<select name="system.categorie_parade" id="categorie_parade" data-dtype="String">
{{#select system.categorie_parade}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html"}}
{{/select}}
</select>
</div>
{{/unless}}
{{/if}}
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html"}}
</section>