Amélioration des entités

- l'attaquant ne sait plus que c'est une entité de cauchemar (surprise!)
- l'encaissement indique une blessure dans le tchat... même si ce
  n'est que de l'endurance
- les blurettes suivent les règles des entités de cauchemar (p322)
This commit is contained in:
2025-10-21 00:36:54 +02:00
parent 8f4df1af56
commit 7f4f942d50
19 changed files with 184 additions and 172 deletions

View File

@@ -1,6 +1,10 @@
# 13.0
## 13.0.14 - Le familier d'Illysis
- Amélioration des entités:
- l'attaquant ne sait plus que c'est une entité de cauchemar (surprise!)
- l'encaissement indique une blessure dans le tchat... même si ce n'est que de l'endurance
- les blurettes suivent les règles des entités de cauchemar (p322)
- Nouvelle fenêtre de jets de dés
- Attaque/défense des créatures

View File

@@ -1,4 +1,4 @@
import { ENTITE_INCARNE, renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
import { renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js";
import { RdDResolutionTable } from "../rdd-resolution-table.js";
@@ -670,7 +670,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
async accorder(entite, when = 'avant-encaissement') {
if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
|| entite == undefined
|| !entite.isEntite([ENTITE_INCARNE])
|| !entite.isEntiteIncarnee()
|| entite.isEntiteAccordee(this)) {
return true
}

View File

@@ -215,9 +215,11 @@ export class RdDBaseActor extends Actor {
return game.users.players.find(player => player.active && player.character?.id == this.id);
}
isCreatureEntite() { return this.isCreature() || this.isEntite() }
isCreatureOuEntite() { return this.isCreature() || this.isEntite() }
isCreature() { return false }
isEntite(typeentite = []) { return false }
isEntite() { return false }
isEntiteIncarnee() { return false }
isEntiteNonIncarnee() { return false }
isHautRevant() { return false }
isVehicule() { return false }
isPersonnage() { return false }

View File

@@ -43,7 +43,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
this.html.find('.resonance-add').click(async event =>
await DialogSelect.select({
label: "Choisir un acteur à accorder",
list: game.actors.filter(it => it.isPersonnage() && it.prototypeToken.actorLink)
list: game.actors.filter(it => true)
},
it => this.resonanceAdd(it.id))
)

View File

@@ -1,5 +1,6 @@
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
import { ITEM_TYPES } from "../constants.js";
import { RdDItemBlessure } from "../item/blessure.js";
import { Misc } from "../misc.js";
import { RdDCarac } from "../rdd-carac.js";
import { RdDEncaisser } from "../rdd-roll-encaisser.js";
@@ -16,11 +17,10 @@ export class RdDEntite extends RdDBaseActorReve {
return item.type == ITEM_TYPES.competencecreature
}
isEntite(typeentite = []) {
return (typeentite.length == 0 || typeentite.includes(this.system.definition.typeentite));
}
isNonIncarnee() { return this.isEntite([ENTITE_NONINCARNE]) }
isEntite() { return true }
isEntiteNonIncarnee() { return this.system.definition.typeentite == ENTITE_NONINCARNE }
isEntiteIncarnee() { return [ENTITE_INCARNE, ENTITE_BLURETTE].includes(this.system.definition.typeentite) }
isEntiteBlurette() { return this.system.definition.typeentite !== ENTITE_BLURETTE }
getReveActuel() {
return Misc.toInt(this.system.carac.reve?.value)
@@ -49,20 +49,20 @@ export class RdDEntite extends RdDBaseActorReve {
}
async remiseANeuf() {
await this.removeEffects(e => true);
if (!this.isNonIncarnee()) {
if (!this.isEntiteNonIncarnee()) {
await this.update({
'system.sante.endurance.value': this.system.sante.endurance.max
});
}
await this.removeEffects(e => true)
}
isDead() {
return this.isNonIncarnee() ? false : this.system.sante.endurance.value <= 0
return this.isEntiteNonIncarnee() ? false : this.system.sante.endurance.value <= 0
}
async santeIncDec(name, inc, isCritique = false) {
if (name == 'endurance' && !this.isNonIncarnee()) {
if (name == 'endurance' && !this.isEntiteNonIncarnee()) {
const oldValue = this.system.sante.endurance.value;
const endurance = Math.max(0,
Math.min(oldValue + inc,
@@ -78,7 +78,7 @@ export class RdDEntite extends RdDBaseActorReve {
}
async encaisser() {
if (this.isNonIncarnee()) {
if (this.isEntiteNonIncarnee()) {
return
}
await RdDEncaisser.encaisser(this)
@@ -89,15 +89,19 @@ export class RdDEntite extends RdDBaseActorReve {
}
async onAppliquerJetEncaissement(encaissement, attackerToken) {
if (this.isEntiteNonIncarnee()) {
return
}
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
foundry.utils.mergeObject(encaissement, {
resteEndurance: perteEndurance.newValue,
endurance: perteEndurance.perte
});
endurance: perteEndurance.perte,
blessure: RdDItemBlessure.prepareBlessure(encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken)
})
}
isEntiteAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) {
if (this.isEntiteIncarnee()) {
let resonnance = this.system.sante.resonnance
return (resonnance.actors.find(it => it == attacker.id))
}
@@ -106,7 +110,7 @@ export class RdDEntite extends RdDBaseActorReve {
/* -------------------------------------------- */
async setEntiteReveAccordee(actor) {
if (this.isEntite([ENTITE_INCARNE])) {
if (this.isEntiteIncarnee()) {
if (this.system.sante.resonnance.actors.find(it => it == actor.id)) {
// déjà accordé
return

View File

@@ -2,7 +2,7 @@ import { Grammar } from "../../grammar.js"
import { EMPOIGNADE, RdDItemArme } from "../../item/arme.js"
import { RdDItemCompetence } from "../../item-competence.js"
import { RdDItemSort } from "../../item-sort.js"
import { ITEM_TYPES } from "../../constants.js"
import { ITEM_TYPES, RDD_CONFIG } from "../../constants.js"
import { Misc } from "../../misc.js"
import { RdDTimestamp } from "../../time/rdd-timestamp.js"
import { RdDBonus } from "../../rdd-bonus.js"
@@ -175,8 +175,8 @@ export class Mapping {
const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme))
switch (arme.system.mortalite) {
case 'non-mortel': return `(${dommages})`
case EMPOIGNADE: return '-'
case RDD_CONFIG.encaissement.nonmortel: return `(${dommages})`
case RDD_CONFIG.encaissement.empoignade: return '-'
}
return dommages
}

View File

@@ -13,44 +13,44 @@ export const renderTemplate = foundry.applications.handlebars.renderTemplate
export const RDD_CONFIG = {
niveauEthylisme: [
{ value: "1", label: "Aucun" },
{ value: "0", label: "Eméché (0)" },
{ value: "-1", label: "Gris (-1)" },
{ value: "-2", label: "Pinté (-2)" },
{ value: "-3", label: "Pas Frais (-3)" },
{ value: "-4", label: "Ivre (-4)" },
{ value: "-5", label: "Bu (-5)" },
{ value: "-6", label: "Complètement fait (-6)" },
{ value: "-7", label: "Ivre mort (-7)" }
{ value: '1', label: 'Aucun' },
{ value: '0', label: 'Eméché (0)' },
{ value: '-1', label: 'Gris (-1)' },
{ value: '-2', label: 'Pinté (-2)' },
{ value: '-3', label: 'Pas Frais (-3)' },
{ value: '-4', label: 'Ivre (-4)' },
{ value: '-5', label: 'Bu (-5)' },
{ value: '-6', label: 'Complètement fait (-6)' },
{ value: '-7', label: 'Ivre mort (-7)' }
],
categorieEntite: {
"cauchemar": "Cauchemar",
"reve": "Rêve"
'cauchemar': 'Cauchemar',
'reve': 'Rêve'
},
typeEntite: {
"incarne": "Incarnée",
"nonincarne": "Non Incarnée",
"blurette": "Blurette"
[ENTITE_INCARNE]: 'Incarnée',
[ENTITE_NONINCARNE]: 'Non Incarnée',
[ENTITE_BLURETTE]: 'Blurette'
},
heuresRdD: [
{ value: "vaisseau", label: "Vaisseau", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd01.webp" },
{ value: "sirene", label: "Sirène", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd02.webp" },
{ value: "faucon", label: "Faucon", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd03.webp" },
{ value: "couronne", label: "Couronne", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd04.webp" },
{ value: "dragon", label: "Dragon", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd05.webp" },
{ value: "epees", label: "Epées", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp" },
{ value: "lyre", label: "Lyre", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd07.webp" },
{ value: "serpent", label: "Serpent", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd08.webp" },
{ value: "poissonacrobate", label: "Poisson Acrobate", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd09.webp" },
{ value: "araignee", label: "Araignée", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd10.webp" },
{ value: "roseau", label: "Roseau", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd11.webp" },
{ value: "chateaudormant", label: "Chateau Dormant", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd12.webp" }
{ value: 'vaisseau', label: 'Vaisseau', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd01.webp' },
{ value: 'sirene', label: 'Sirène', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd02.webp' },
{ value: 'faucon', label: 'Faucon', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd03.webp' },
{ value: 'couronne', label: 'Couronne', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd04.webp' },
{ value: 'dragon', label: 'Dragon', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd05.webp' },
{ value: 'epees', label: 'Epées', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp' },
{ value: 'lyre', label: 'Lyre', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd07.webp' },
{ value: 'serpent', label: 'Serpent', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd08.webp' },
{ value: 'poissonacrobate', label: 'Poisson Acrobate', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd09.webp' },
{ value: 'araignee', label: 'Araignée', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd10.webp' },
{ value: 'roseau', label: 'Roseau', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd11.webp' },
{ value: 'chateaudormant', label: 'Chateau Dormant', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.webp' }
],
raretes: [
{ value: "Commune", label: "Commune" },
{ value: "Frequente", label: "Fréquente" },
{ value: "Rare", label: "Rare" },
{ value: "Rarissime", label: "Rarissime" }
{ value: 'Commune', label: 'Commune' },
{ value: 'Frequente', label: 'Fréquente' },
{ value: 'Rare', label: 'Rare' },
{ value: 'Rarissime', label: 'Rarissime' }
],
particuliere: {
force: { key: 'force', descr: 'en force', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-force.svg' },
@@ -62,10 +62,15 @@ export const RDD_CONFIG = {
demiReve: 'systems/foundryvtt-reve-de-dragon/assets/actions/sort.svg',
empoignade: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp',
forceWeak: 'systems/foundryvtt-reve-de-dragon/assets/actions/weak.svg',
},
encaissement: {
mortel: 'mortel',
nonmortel: 'non-mortel',
entiteincarnee: 'entiteincarnee',
empoignade: 'empoignade'
}
}
export const ACTOR_TYPES = {
personnage: 'personnage',
creature: 'creature',

View File

@@ -1,4 +1,4 @@
import { ITEM_TYPES, renderTemplate } from "./constants.js";
import { ITEM_TYPES, RDD_CONFIG, renderTemplate } from "./constants.js";
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES, CATEGORIES_COMPETENCES_CREATURES } from "./item/base-items.js";
import { ITEM_ACTIONS, DEFAULT_ACTIONS, COMMON_ACTIONS } from "./item/item-actions.js";
@@ -629,7 +629,7 @@ export class RdDItem extends Item {
_armeChatData() {
return [
`<b>Compétence</b>: ${this.system.competence}`,
`<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == 'non-mortel' ? '(Non mortel)' : ''}`,
`<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == RDD_CONFIG.encaissement.nonmortel ? '(Non mortel)' : ''}`,
`<b>Force minimum</b>: ${this.system.force}`,
`<b>Resistance</b>: ${this.system.resistance}`,
...this._inventaireTemplateChatData()

View File

@@ -1,4 +1,4 @@
import { ITEM_TYPES } from "../constants.js";
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
import { RdDItem } from "../item.js";
import { BASE_CORPS_A_CORPS } from "./base-items.js";
import { Grammar } from "../grammar.js";
@@ -30,7 +30,7 @@ export const ATTAQUE_TYPE = {
export const CORPS_A_CORPS = 'Corps à corps'
export const PUGILAT = 'pugilat'
export const EMPOIGNADE = 'empoignade'
export const EMPOIGNADE = RDD_CONFIG.encaissement.empoignade
/* -------------------------------------------- */
export class RdDItemArme extends RdDItem {
@@ -259,10 +259,10 @@ export class RdDItemArme extends RdDItem {
}
static empoignade(actor) {
return RdDItemArme.$corpsACorps(actor, 'Empoignade', EMPOIGNADE)
return RdDItemArme.$corpsACorps(actor, 'Empoignade', RDD_CONFIG.encaissement.empoignade)
}
static $corpsACorps(actor, name, cac, system) {
static $corpsACorps(actor, name, cac) {
const competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS
const melee = actor ? actor.system.carac['melee'].value : 0
return new RdDItemArme({
@@ -277,10 +277,10 @@ export class RdDItemArme extends RdDItem {
force: 0,
dommages: "0",
dommagesReels: 0,
mortalite: cac == EMPOIGNADE ? EMPOIGNADE : 'non-mortel',
mortalite: cac == RDD_CONFIG.encaissement.empoignade ? RDD_CONFIG.encaissement.empoignade : RDD_CONFIG.encaissement.nonmortel,
competence: CORPS_A_CORPS,
resistance: 1,
baseInit: cac == EMPOIGNADE ? 3 : 4,
baseInit: cac == RDD_CONFIG.encaissement.empoignade ? 3 : 4,
cac: cac,
deuxmains: true,
categorie_parade: 'sans-armes'

View File

@@ -71,21 +71,25 @@ export class RdDItemBlessure extends RdDItem {
return 0
}
static async createBlessure(actor, gravite, localisation = '', attackerToken) {
const definition = RdDItemBlessure.getDefinition(gravite)
const blessure = {
static async createBlessure(actor, gravite, localisation = '', attackerToken = undefined) {
const blessure = RdDItemBlessure.prepareBlessure(gravite, localisation, attackerToken);
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
return blessures[0]
}
static prepareBlessure(gravite, localisation, attackerToken) {
const definition = RdDItemBlessure.getDefinition(gravite);
return {
name: definition.label,
type: 'blessure',
img: definition.icon,
system: {
gravite: gravite,
difficulte: - gravite,
difficulte: -gravite,
localisation: localisation,
origine: attackerToken?.name ?? ""
}
}
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
return blessures[0]
}
static async createTacheSoinBlessure(actor, gravite) {

View File

@@ -1,3 +1,4 @@
import { RDD_CONFIG } from "./constants.js";
import { RdDItemArme } from "./item/arme.js";
import { RdDPossession } from "./rdd-possession.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
@@ -35,7 +36,7 @@ export class RdDBonus {
}
/* -------------------------------------------- */
static dmg(rollData, actor, isEntiteIncarnee = false) {
static dmg(rollData, actor) {
const diff = rollData.diffLibre;
const dmgArme = RdDBonus.dmgArme(rollData.arme, rollData.arme?.system.dommagesReels)
const forceRequise = rollData.arme ? RdDItemArme.valeurMain(rollData.arme.system.force ?? 0, RdDItemArme.getMainAttaque(rollData.competence)) : 0
@@ -48,12 +49,12 @@ export class RdDBonus {
dmgTactique: RdDBonus.dmgBonus(rollData.tactique),
dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris?.used),
mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee),
mortalite: RdDBonus.mortalite(rollData.dmg?.mortalite, rollData.arme?.system.mortalite),
dmgActor: RdDBonus.bonusDmg(actor, rollData.selectedCarac?.label.toLowerCase(), dmgArme),
dmgForceInsuffisante: Math.min(0, actor.getForce() - forceRequise)
}
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante
return dmg;
return dmg
}
static dmgRollV2(rollData, attaque) {
@@ -68,7 +69,7 @@ export class RdDBonus {
dmgTactique: attaque.tactique?.dmg ?? 0,
dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0,
mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme?.system.mortalite, rollData.opponent?.actor?.isEntite()),
mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme?.system.mortalite),
dmgActor: RdDBonus.bonusDmg(actor, attaque.carac.key, dmgArme, attaque.forceRequise),
dmgForceInsuffisante: Math.min(0, actor.getForce() - (attaque.forceRequise ?? 0)),
dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0
@@ -93,15 +94,8 @@ export class RdDBonus {
}
/* -------------------------------------------- */
static _calculMortalite(rollData, isEntiteIncarnee) {
return RdDBonus.mortalite(rollData.dmg?.mortalite, rollData.arme?.system.mortalite, isEntiteIncarnee)
}
static mortalite(mortaliteSelect, mortaliteArme, isEntiteIncarnee) {
return isEntiteIncarnee ? "entiteincarnee"
: mortaliteSelect
?? mortaliteArme
?? "mortel";
static mortalite(mortaliteSelect, mortaliteArme) {
return mortaliteSelect ?? mortaliteArme ?? RDD_CONFIG.encaissement.mortel
}
/* -------------------------------------------- */

View File

@@ -1,5 +1,5 @@
import { ChatUtility } from "./chat-utility.js";
import { ENTITE_BLURETTE, HIDE_DICE, renderTemplate, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { HIDE_DICE, renderTemplate, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js";
@@ -15,7 +15,7 @@ import { RdDItemCompetence } from "./item-competence.js";
import { MAP_PHASE, RdDInitiative } from "./initiative.mjs";
import RollDialog from "./roll/roll-dialog.mjs";
import { PART_DEFENSE } from "./roll/roll-part-defense.mjs";
import { DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
@@ -601,7 +601,7 @@ export class RdDCombat {
/* -------------------------------------------- */
async proposerAjustementTirLancer(rollData) {
if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) {
if (this.defender.isEntite([ENTITE_BLURETTE])) {
if (this.defender.isEntiteBlurette()) {
ChatMessage.create({
content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`,
whisper: ChatUtility.getGMs()
@@ -797,7 +797,7 @@ export class RdDCombat {
essais: {}
};
if (this.attacker.isCreatureEntite()) {
if (this.attacker.isCreatureOuEntite()) {
MappingCreatureArme.setRollDataCreature(rollData);
}
else if (arme) {
@@ -866,7 +866,7 @@ export class RdDCombat {
async _onAttaqueNormale(attackerRoll) {
console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll);
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite());
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker);
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
attackerRoll.show = {
cible: this.defender?.getAlias() ?? 'la cible',
@@ -1104,7 +1104,7 @@ export class RdDCombat {
show: {}
};
if (this.defender.isCreatureEntite()) {
if (this.defender.isCreatureOuEntite()) {
MappingCreatureArme.setRollDataCreature(defenderRoll);
}
@@ -1231,7 +1231,7 @@ export class RdDCombat {
show: {}
};
if (this.defender.isCreatureEntite()) {
if (this.defender.isCreatureOuEntite()) {
MappingCreatureArme.setRollDataCreature(rollData);
}
return rollData;

View File

@@ -184,7 +184,7 @@ export class RdDEmpoignade {
selectedCarac: attacker.system.carac.melee,
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
}
if (attacker.isCreatureEntite()) {
if (attacker.isCreatureOuEntite()) {
MappingCreatureArme.setRollDataCreature(rollData)
}
if (empoignade.system.pointsemp >= 2) {

View File

@@ -95,7 +95,7 @@ export class RdDPossession {
static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
rollData.competence = rollingActor.getDraconicOuPossession();
if (rollingActor.isCreatureEntite()) {
if (rollingActor.isCreatureOuEntite()) {
const carac = rollingActor.system.carac
rollData.carac = carac
rollData.competence.system.defaut_carac = 'reve'

View File

@@ -1,4 +1,4 @@
import { ENTITE_BLURETTE, ENTITE_INCARNE, renderTemplate } from "./constants.js";
import { ENTITE_NONINCARNE, RDD_CONFIG, renderTemplate } from "./constants.js";
import { RdDUtility } from "./rdd-utility.js";
/**
@@ -16,34 +16,29 @@ export class RdDEncaisser extends Dialog {
/* -------------------------------------------- */
constructor(html, actor) {
let dialogConf = {
if (actor.isEntiteNonIncarnee([ENTITE_NONINCARNE])) {
throw `${actor.name} est une entité non incarnée et ne peut pas subnir de dommages`
}
const dialogConf = {
title: "Jet d'Encaissement",
content: html,
}
if (!actor.isEntite()) {
dialogConf.default = "mortel";
dialogConf.buttons = {
"mortel": { label: "Mortel", callback: html => this.performEncaisser("mortel") },
"non-mortel": { label: "Non-mortel", callback: html => this.performEncaisser("non-mortel") },
"sonne": { label: "Sonné", callback: html => this.actor.setSonne() },
};
}
else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])) {
dialogConf.default = "entiteincarnee"
dialogConf.buttons = {
"entiteincarnee": { label: "Entité incarnée", callback: html => this.performEncaisser("entiteincarnee") }
default: RDD_CONFIG.encaissement.mortel,
buttons: {
[RDD_CONFIG.encaissement.mortel]: { label: "Mortel", callback: html => this.performEncaisser(RDD_CONFIG.encaissement.mortel) },
}
}
let dialogOptions = {
classes: ["rdd-roll-dialog"],
width: 320,
height: 'fit-content'
if (!actor.isEntite()) {
dialogConf.buttons[RDD_CONFIG.encaissement.nonmortel] = { label: "Non-mortel", callback: html => this.performEncaisser(RDD_CONFIG.encaissement.nonmortel) }
dialogConf.buttons["sonne"] = { label: "Sonné", callback: html => this.actor.setSonne() }
}
// Select proper roll dialog template and stuff
super(dialogConf, dialogOptions);
super(dialogConf, {
classes: ["rdd-roll-dialog"],
width: 320,
height: 'fit-content'
});
this.actor = actor;
this.modifier = 0;

View File

@@ -8,7 +8,7 @@ import { RdDCarac } from "./rdd-carac.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { Grammar } from "./grammar.js";
import { ACTOR_TYPES, renderTemplate } from "./constants.js";
import { ACTOR_TYPES, RDD_CONFIG, renderTemplate } from "./constants.js";
import { EMPOIGNADE } from "./item/arme.js";
/**
@@ -206,7 +206,7 @@ export class RdDRoll extends Dialog {
this.updateRollResult(html);
});
this.html.find("input.check-mortalite").change((event) => {
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
this.rollData.dmg.mortalite = event.currentTarget.checked ? RDD_CONFIG.encaissement.nonmortel : RDD_CONFIG.encaissement.mortel;
this.updateRollResult(html);
});
this.html.find('.cuisine-proportions').change((event) => {
@@ -333,7 +333,7 @@ export class RdDRoll extends Dialog {
// Mise à jour valeurs
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == 'non-mortel');
this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == RDD_CONFIG.encaissement.nonmortel);
this.html.find("label.dmg-arme-actor").text(rollData.dmg.mortalite == EMPOIGNADE ? EMPOIGNADE : Misc.toSignedString(rollData.dmg.total));
this.html.find("label.arme-mortalite").text(rollData.dmg.mortalite);
this.html.find("div.placeholder-ajustements").empty().append(adjustements);

View File

@@ -75,30 +75,27 @@ const fatigueLineMalus = [0, -1, -2, -3, -4, -5, -6, -7];
/* -------------------------------------------- */
const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"];
/* -------------------------------------------- */
const definitionsEncaissement = {
"mortel": [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4 },
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6 },
],
"non-mortel": [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
],
"entiteincarnee": [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 },
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 },
]
};
const TABLE_ENCAISSEMENT_MORTEL = [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4 },
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6 },
]
const TABLE_ENCAISSEMENT_NONMORTEL = [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
]
const TABLE_ENCAISSEMENT_ENTITE = [
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 4 },
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 6 },
]
/* -------------------------------------------- */
export class RdDUtility {
@@ -278,7 +275,7 @@ export class RdDUtility {
Handlebars.registerHelper('plusMoins', diff => parseInt(diff) ? (diff > 0 ? '+' : '') + Math.round(diff) : diff)
Handlebars.registerHelper('fractionOneN', n => new Handlebars.SafeString(Misc.getFractionOneN(n)))
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
@@ -286,7 +283,7 @@ export class RdDUtility {
const html = options.fn(this);
return html.replace(rgx, "$& selected");
})
// logic
Handlebars.registerHelper('either', (a, b) => a ?? b);
// string manipulation
@@ -299,7 +296,7 @@ export class RdDUtility {
Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str));
Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args));
Handlebars.registerHelper('json-stringify', object => JSON.stringify(object))
// math
Handlebars.registerHelper('math-sum', (...values) => values.slice(0, -1).reduce(Misc.sum(), 0))
Handlebars.registerHelper('math-abs', diff => Math.abs(parseInt(diff)))
@@ -613,20 +610,20 @@ export class RdDUtility {
/* -------------------------------------------- */
static async getLocalisation(type = 'personnage') {
const loc = { result: await RdDDice.rollTotal("1d20")};
const loc = { result: await RdDDice.rollTotal("1d20") };
if (type == 'personnage') {
if (loc.result <= 3) loc.txt = "Jambe, genou, pied, jarret";
else if (loc.result <= 7) loc.txt = "Hanche, cuisse, fesse";
else if (loc.result <= 9) loc.txt = "Ventre, reins";
else if (loc.result <= 12) loc.txt = "Poitrine, dos";
else if (loc.result <= 14) loc.txt = "Avant-bras, main, coude";
else if (loc.result <= 18) loc.txt = "Epaule, bras, omoplate";
else if (loc.result == 19) loc.txt = "Tête";
else if (loc.result == 20) loc.txt = "Tête (visage)";
if (loc.result <= 3) loc.txt = "Jambe, genou, pied, jarret";
else if (loc.result <= 7) loc.txt = "Hanche, cuisse, fesse";
else if (loc.result <= 9) loc.txt = "Ventre, reins";
else if (loc.result <= 12) loc.txt = "Poitrine, dos";
else if (loc.result <= 14) loc.txt = "Avant-bras, main, coude";
else if (loc.result <= 18) loc.txt = "Epaule, bras, omoplate";
else if (loc.result == 19) loc.txt = "Tête";
else if (loc.result == 20) loc.txt = "Tête (visage)";
} else {
if (loc.result <= 7) loc.txt = "Jambes/Pattes";
else if (loc.result <= 18) loc.txt = "Corps";
else if (loc.result <= 20) loc.txt = "Tête";
if (loc.result <= 7) loc.txt = "Jambes/Pattes";
else if (loc.result <= 18) loc.txt = "Corps";
else if (loc.result <= 20) loc.txt = "Tête";
}
return loc
}
@@ -671,13 +668,13 @@ export class RdDUtility {
}
/* -------------------------------------------- */
static async prepareEncaissement(actor, dmg, roll, armure) {
static async prepareEncaissement(targetActor, dmg, roll, armure) {
const jetTotal = roll.total + dmg.total - armure
const encaissement = RdDUtility._selectEncaissement(jetTotal, dmg.mortalite);
const over20 = Math.max(jetTotal - 20, 0);
const encaissement = RdDUtility.$selectEncaissement(targetActor, jetTotal, dmg.mortalite)
const over20 = Math.max(jetTotal - 20, 0)
encaissement.dmg = dmg
if (ReglesOptionnelles.isUsing('localisation-aleatoire')) {
encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(actor.type)
encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(targetActor.type)
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'
}
else {
@@ -693,15 +690,21 @@ export class RdDUtility {
}
/* -------------------------------------------- */
static _selectEncaissement(degats, mortalite) {
const table = definitionsEncaissement[mortalite] === undefined ? definitionsEncaissement["mortel"] : definitionsEncaissement[mortalite];
for (let encaissement of table) {
if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
&& (encaissement.maximum === undefined || degats <= encaissement.maximum)) {
return foundry.utils.duplicate(encaissement);
}
static $selectEncaissement(targetActor, degats, mortalite) {
const table = RdDUtility.$getTableEncaissement(targetActor, mortalite)
const encaissement = table.find(it => ((it.minimum ?? degats) <= degats && degats <= (it.maximum ?? degats)))
return foundry.utils.duplicate(encaissement ?? table[0])
}
static $getTableEncaissement(targetActor, mortalite) {
if (targetActor.isEntite()) {
return TABLE_ENCAISSEMENT_ENTITE
}
return foundry.utils.duplicate(table[0]);
switch (mortalite) {
case RDD_CONFIG.encaissement.nonmortel: return TABLE_ENCAISSEMENT_NONMORTEL
case RDD_CONFIG.encaissement.entiteincarnee: return TABLE_ENCAISSEMENT_ENTITE
}
return TABLE_ENCAISSEMENT_MORTEL
}
/* -------------------------------------------- */

View File

@@ -1,3 +1,4 @@
import { RDD_CONFIG } from "../constants.js"
import { RdDBonus } from "../rdd-bonus.js"
import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
@@ -94,7 +95,7 @@ export class RollPartAttaque extends RollPartSelect {
})
checkMortalite?.addEventListener("change", e => {
current.dmg.mortalite = (e.currentTarget.checked ? 'mortel' : 'non-mortel')
current.dmg.mortalite = (e.currentTarget.checked ? RDD_CONFIG.encaissement.mortel : RDD_CONFIG.encaissement.nonmortel)
rollDialog.render()
})
}

View File

@@ -21,12 +21,12 @@
{{~#unless (eq penetration 0)}} (pénétration de {{penetration}}){{/unless}}
{{~/unless~}}, total: <span class="rdd-roll-echec">{{total}}</span>
<br>
{{alias}}
{{#if (eq dmg.mortalite 'entiteincarnee')}}subit le coup
{{else if mort}}vient de mourir
{{alias}}
{{log 'encaissement' this}}
{{#if mort}}vient de mourir
{{else if blessure}}
{{#if (gt blessure.system.gravite 0)}}subit une blessure {{blessure.system.label}}
{{~else~}}subit une contusion
{{#if (gt blessure.system.gravite 0)}}subit une blessure {{blessure.name}}
{{~else~}}subit une éraflure
{{~/if~}}
{{~else~}}s'en sort sans une égratignure
{{~/if~}}