forked from public/foundryvtt-reve-de-dragon
Compare commits
13 Commits
foundryvtt
...
foundryvtt
Author | SHA1 | Date | |
---|---|---|---|
3821b5bea1 | |||
2739c650d9 | |||
b101d58bee | |||
0e3d721fc7 | |||
e1e45a83be | |||
3b14e54829 | |||
615a3f1315 | |||
ca72d088cc | |||
ac89b948ca | |||
f22c4d2ec8 | |||
ffd80394d3 | |||
0959d1b18e | |||
24e58abfcc |
18
changelog.md
18
changelog.md
@@ -1,5 +1,23 @@
|
||||
# v11.0
|
||||
|
||||
## 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
|
||||
- réorganisation de la fenêtre de sélection des règles optionnelles
|
||||
- correction de l'affichage du type dans les fenêtres d'objets
|
||||
|
||||
## v11.0.8 - la poigne de Sémolosse
|
||||
- lien vers le changelog
|
||||
- organisation des compendiums du système
|
||||
- correction de l'empoignade
|
||||
- les items d'empoignade sont ajoutés par le MJ quand nécessaire
|
||||
- seul le joueur propriétaire du personnage peut effectuer ses choix et actions d'empoignade
|
||||
- les caractéristiques du défenseur sont utilisées pour la défense
|
||||
- la difficulté d'attaque est imposée au défenseur
|
||||
- les attaques particulières sont en finesse (p133)
|
||||
- on peut entraîner au sol dès 2 points d'empoignade
|
||||
- les actions liée à l'immobilisation sont proposées en fin de round
|
||||
|
||||
# v11.0.7
|
||||
|
||||
- les créatures ont maintenant le droit d'avoir des compétences de tir, lancer, mêlée, armes naturelles, parade.
|
||||
|
@@ -7,7 +7,7 @@ import { Misc } from "./misc.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { MAINS_DIRECTRICES } from "./actor.js";
|
||||
@@ -33,7 +33,8 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
|
||||
showCompNiveauBase: false,
|
||||
vueDetaillee: false
|
||||
vueDetaillee: false,
|
||||
vueArchetype: false,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -114,7 +115,7 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
@@ -353,12 +354,19 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value));
|
||||
});
|
||||
this.html.find('.toggle-archetype').click(async event => {
|
||||
this.options.vueArchetype = !this.options.vueArchetype;
|
||||
this.render(true);
|
||||
});
|
||||
// On competence archetype change
|
||||
this.html.find('.competence-archetype').change(async event => {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value));
|
||||
});
|
||||
}
|
||||
this.html.find('.nouvelle-incarnation').click(async event => {
|
||||
this.actor.nouvelleIncarnation();
|
||||
});
|
||||
|
||||
this.html.find('.show-hide-competences').click(async event => {
|
||||
this.options.showCompNiveauBase = !this.options.showCompNiveauBase;
|
||||
|
@@ -18,7 +18,7 @@ import { RdDAlchimie } from "./rdd-alchimie.js";
|
||||
import { STATUSES, StatusEffects } from "./settings/status-effects.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
import { RdDItemSigneDraconique } from "./item/signedraconique.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { Draconique } from "./tmr/draconique.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
@@ -134,7 +134,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
getFatigueActuelle() {
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue") && this.isPersonnage()) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && this.isPersonnage()) {
|
||||
return this.system.sante.fatigue?.value;
|
||||
}
|
||||
return 0;
|
||||
@@ -273,24 +273,24 @@ export class RdDActor extends RdDBaseActor {
|
||||
getDraconicOuPossession() {
|
||||
const possession = this.items.filter(it => it.type == TYPES.competencecreature && it.system.categorie == 'possession')
|
||||
.sort(Misc.descending(it => it.system.niveau))
|
||||
.find(it=>true);
|
||||
.find(it => true);
|
||||
if (possession) {
|
||||
return possession.clone();
|
||||
}
|
||||
const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0).map(it =>it.clone()),
|
||||
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 draconics[0];
|
||||
}
|
||||
|
||||
getPossession(possessionId) {
|
||||
return this.items.find(it => it.type == 'possession' && it.system.possessionid == possessionId);
|
||||
return this.items.find(it => it.type == TYPES.possession && it.system.possessionid == possessionId);
|
||||
}
|
||||
getPossessions() {
|
||||
return this.items.filter(it => it.type == 'possession');
|
||||
return this.items.filter(it => it.type == TYPES.possession);
|
||||
}
|
||||
getEmpoignades() {
|
||||
return this.items.filter(it => it.type == 'empoignade');
|
||||
return this.items.filter(it => it.type == TYPES.empoignade);
|
||||
}
|
||||
getDemiReve() {
|
||||
return this.system.reve.tmrpos.coord;
|
||||
@@ -457,7 +457,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async dormirChateauDormant() {
|
||||
if (!ReglesOptionelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) {
|
||||
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) {
|
||||
const message = {
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
||||
content: ""
|
||||
@@ -712,7 +712,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async recupererFatigue(message) {
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
let fatigue = this.system.sante.fatigue.value;
|
||||
const fatigueMin = this._computeFatigueMin();
|
||||
if (fatigue <= fatigueMin) {
|
||||
@@ -961,7 +961,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async updateCompetence(idOrName, compValue) {
|
||||
const competence = this.getCompetence(idOrName);
|
||||
const competence = this.getCompetence(idOrName);
|
||||
if (competence) {
|
||||
const toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie, competence.getCategories());
|
||||
this.notifyCompetencesTronc(competence, toNiveau);
|
||||
@@ -1178,7 +1178,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
}
|
||||
// Pour les autres
|
||||
let state = Math.min(this.system.sante.vie.value - this.system.sante.vie.max, 0);
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue") && this.system.sante.fatigue) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && this.system.sante.fatigue) {
|
||||
state += RdDUtility.currentFatigueMalus(this.system.sante.fatigue.value, this.system.sante.endurance.max);
|
||||
}
|
||||
// Ajout de l'éthylisme
|
||||
@@ -1362,21 +1362,46 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async finDeRound(options = { terminer: false }) {
|
||||
await this.$finDeRoundSuppressionEffetsTermines(options);
|
||||
await this.$finDeRoundBlessuresGraves();
|
||||
await this.$finDeRoundSupprimerObsoletes();
|
||||
await this.$finDeRoundEmpoignade();
|
||||
}
|
||||
|
||||
async $finDeRoundSuppressionEffetsTermines(options) {
|
||||
for (let effect of this.getEffects()) {
|
||||
if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) {
|
||||
await effect.delete();
|
||||
ChatMessage.create({ content: `${this.name} n'est plus ${Misc.lowerFirst(game.i18n.localize(effect.system.label))} !` });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async $finDeRoundBlessuresGraves() {
|
||||
if (this.isPersonnage() || this.isCreature()) {
|
||||
const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length
|
||||
const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length;
|
||||
if (nbGraves > 0) {
|
||||
// Gestion blessure graves : -1 pt endurance par blessure grave
|
||||
await this.santeIncDec("endurance", - nbGraves);
|
||||
await this.santeIncDec("endurance", -nbGraves);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async $finDeRoundSupprimerObsoletes() {
|
||||
const obsoletes = []
|
||||
.concat(this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp <= 0))
|
||||
.concat(this.itemTypes[TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2))
|
||||
.map(it => it.id);
|
||||
await this.deleteEmbeddedDocuments('Item', obsoletes);
|
||||
}
|
||||
|
||||
async $finDeRoundEmpoignade() {
|
||||
const immobilisations = this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id);
|
||||
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this,
|
||||
game.actors.get(emp.system.empoigneid),
|
||||
emp
|
||||
))
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
async setSonne(sonne = true) {
|
||||
if (this.isEntite()) {
|
||||
@@ -1480,7 +1505,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async santeIncDec(name, inc, isCritique = false) {
|
||||
if (name == 'fatigue' && !ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
return;
|
||||
}
|
||||
const sante = duplicate(this.system.sante)
|
||||
@@ -1522,7 +1547,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
}
|
||||
compteur.value = result.newValue;
|
||||
// If endurance lost, then the same amount of fatigue cannot be recovered
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) {
|
||||
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this._computeFatigueMin());
|
||||
}
|
||||
await this.update({ "system.sante": sante })
|
||||
@@ -2424,7 +2449,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
/* -------------------------------------------- */
|
||||
async _tacheResult(rollData, options) {
|
||||
// Mise à jour de la tache
|
||||
rollData.appliquerFatigue = ReglesOptionelles.isUsing("appliquer-fatigue");
|
||||
rollData.appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue");
|
||||
rollData.tache = duplicate(rollData.tache);
|
||||
rollData.tache.system.points_de_tache_courant += rollData.rolled.ptTache;
|
||||
if (rollData.rolled.isETotal) {
|
||||
@@ -3205,7 +3230,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
return;
|
||||
}
|
||||
const attackerId = attacker?.id;
|
||||
if (ReglesOptionelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
|
||||
if (ReglesOptionnelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
|
||||
RdDBaseActor.remoteActorCall({
|
||||
actorId: this.id,
|
||||
method: 'appliquerEncaissement',
|
||||
@@ -3218,7 +3243,7 @@ export class RdDActor extends RdDBaseActor {
|
||||
|
||||
async appliquerEncaissement(rollData, show, attackerId) {
|
||||
const armure = await this.computeArmure(rollData);
|
||||
if (ReglesOptionelles.isUsing('validation-encaissement-gr')) {
|
||||
if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) {
|
||||
DialogValidationEncaissement.validerEncaissement(this, rollData, armure, show, attackerId, (encaissement, show, attackerId) => this._appliquerEncaissement(encaissement, show, attackerId));
|
||||
}
|
||||
else {
|
||||
@@ -3805,5 +3830,39 @@ export class RdDActor extends RdDBaseActor {
|
||||
content: `${this.name} a reçu un/une ${item.type}: ${item.name}, qui ${manualMessage ? "n'est pas" : "est"} géré(e) automatiquement. ${manualMessage ? manualMessage : ''}`
|
||||
});
|
||||
}
|
||||
|
||||
async nouvelleIncarnation() {
|
||||
let incarnation = this.toObject();
|
||||
|
||||
incarnation.items = Array.from(this.items.filter(it => it.type == TYPES.competence),
|
||||
it => {
|
||||
it = it.toObject();
|
||||
it.id = undefined;
|
||||
it.system.niveau = it.system.base;
|
||||
it.system.niveau_archetype = Math.max(it.system.niveau + (it.system.xp > 0 ? 1 : 0), it.system.niveau_archetype);
|
||||
it.system.xp = 0;
|
||||
it.system.xp_sort = 0;
|
||||
it.system.default_diffLibre = 0;
|
||||
return it;
|
||||
});
|
||||
|
||||
incarnation.name = 'Réincarnation de ' + incarnation.name
|
||||
incarnation.system = {
|
||||
carac: duplicate(this.system.carac),
|
||||
heure: RdDTimestamp.defHeure(await RdDDice.rollTotal("1dh", { rollMode: "selfroll", showDice: SHOW_DICE })).key,
|
||||
age: 18,
|
||||
biographie: '',
|
||||
notes: '',
|
||||
experiencelog: [],
|
||||
'compteurs.experience.value': 3000,
|
||||
'reve.seuil.value': this.system.carac.reve.value,
|
||||
'reve.reve.value': this.system.carac.reve.value,
|
||||
subacteurs: { suivants: [], montures: [], vehicules: [] },
|
||||
}
|
||||
incarnation = await RdDBaseActor.create(incarnation);
|
||||
await incarnation.deleteEmbeddedDocuments('ActiveEffect', incarnation.getEmbeddedCollection("ActiveEffect").map(it => it.id));
|
||||
await incarnation.remiseANeuf();
|
||||
incarnation.sheet.render(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -144,6 +144,18 @@ export class RdDBaseActor extends Actor {
|
||||
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
|
||||
}
|
||||
|
||||
async creerObjetParMJ(object){
|
||||
if (!Misc.isUniqueConnectedGM()) {
|
||||
RdDBaseActor.remoteActorCall({
|
||||
actorId: this.id,
|
||||
method: 'creerObjetParMJ',
|
||||
args: [object]
|
||||
});
|
||||
return;
|
||||
}
|
||||
await this.createEmbeddedDocuments('Item', [object])
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getFortune() {
|
||||
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
||||
|
@@ -78,11 +78,7 @@ export class ChatUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createChatWithRollMode(name, chatOptions) {
|
||||
return await ChatUtility.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createChatMessage(name, rollMode, chatOptions) {
|
||||
let rollMode = game.settings.get("core", "rollMode")
|
||||
switch (rollMode) {
|
||||
case "blindroll": // GM only
|
||||
if (!game.user.isGM) {
|
||||
|
@@ -8,18 +8,18 @@ const xp_par_niveau = [5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20,
|
||||
const niveau_max = xp_par_niveau.length - 10;
|
||||
/* -------------------------------------------- */
|
||||
const limitesArchetypes = [
|
||||
{ "niveau": 0, "nombreMax": 100, "reste": 100 },
|
||||
{ "niveau": 1, "nombreMax": 10, "reste": 10 },
|
||||
{ "niveau": 2, "nombreMax": 9, "reste": 9 },
|
||||
{ "niveau": 3, "nombreMax": 8, "reste": 8 },
|
||||
{ "niveau": 4, "nombreMax": 7, "reste": 7 },
|
||||
{ "niveau": 5, "nombreMax": 6, "reste": 6 },
|
||||
{ "niveau": 6, "nombreMax": 5, "reste": 5 },
|
||||
{ "niveau": 7, "nombreMax": 4, "reste": 4 },
|
||||
{ "niveau": 8, "nombreMax": 3, "reste": 3 },
|
||||
{ "niveau": 9, "nombreMax": 2, "reste": 2 },
|
||||
{ "niveau": 10, "nombreMax": 1, "reste": 1 },
|
||||
{ "niveau": 11, "nombreMax": 1, "reste": 1 }
|
||||
{ niveau: 0, nombreMax: 100 },
|
||||
{ niveau: 1, nombreMax: 10 },
|
||||
{ niveau: 2, nombreMax: 9 },
|
||||
{ niveau: 3, nombreMax: 8 },
|
||||
{ niveau: 4, nombreMax: 7 },
|
||||
{ niveau: 5, nombreMax: 6 },
|
||||
{ niveau: 6, nombreMax: 5 },
|
||||
{ niveau: 7, nombreMax: 4 },
|
||||
{ niveau: 8, nombreMax: 3 },
|
||||
{ niveau: 9, nombreMax: 2 },
|
||||
{ niveau: 10, nombreMax: 1 },
|
||||
{ niveau: 11, nombreMax: 1 },
|
||||
];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -259,13 +259,17 @@ export class RdDItemCompetence extends Item {
|
||||
/* -------------------------------------------- */
|
||||
static computeResumeArchetype(competences) {
|
||||
const computed = duplicate(limitesArchetypes);
|
||||
computed.forEach(it => { it.nombre = 0; it.reste = it.nombreMax; });
|
||||
|
||||
competences.map(it => Math.max(0, it.system.niveau_archetype))
|
||||
.filter(n => n > 0)
|
||||
.forEach(n => {
|
||||
computed[n] = computed[n] ?? { niveau: n, nombreMax: 0, reste: 0 };
|
||||
computed[n].reste = computed[n].reste - 1;
|
||||
computed[n] = computed[n] ?? { niveau: n, nombreMax: 0, reste: 0, nombre: 0 };
|
||||
computed[n].reste--;
|
||||
computed[n].nombre++;
|
||||
|
||||
});
|
||||
return computed.filter(it => it.reste > 0 && it.niveau > 0);
|
||||
return computed.filter(it => it.niveau > 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@@ -5,7 +5,7 @@ import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDHerbes } from "./rdd-herbes.js";
|
||||
import { RdDGemme } from "./rdd-gemme.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||
@@ -157,7 +157,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
super.activateListeners(html);
|
||||
this.html = html;
|
||||
|
||||
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs')
|
||||
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionnelles.isUsing('afficher-prix-joueurs')
|
||||
|| game.user.isGM
|
||||
|| !this.item.isOwned);
|
||||
HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { RdDItem } from "../item.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||
|
||||
export class RdDItemArmure extends RdDItem {
|
||||
|
||||
@@ -9,7 +9,7 @@ export class RdDItemArmure extends RdDItem {
|
||||
}
|
||||
|
||||
deteriorerArmure(dmg) {
|
||||
if (!ReglesOptionelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
|
||||
if (!ReglesOptionnelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
|
||||
return;
|
||||
}
|
||||
let deterioration = (this.system.deterioration ?? 0) + dmg;
|
||||
|
@@ -42,7 +42,7 @@ export class Misc {
|
||||
}
|
||||
|
||||
static typeName(type, subType) {
|
||||
return subType ? game.i18n.localize(`${type.toUpperCase()}.Type${Misc.upperFirst(subType)}`)
|
||||
return subType ? game.i18n.localize(`TYPES.${type}.${Misc.upperFirst(subType)}`)
|
||||
: '';
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,7 @@ import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { Targets } from "./targets.js";
|
||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
@@ -1048,7 +1048,7 @@ export class RdDCombat {
|
||||
competence: this.defender.getCompetence(competenceParade).clone(),
|
||||
arme: armeParade,
|
||||
surprise: this.defender.getSurprise(true),
|
||||
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
||||
needParadeSignificative: ReglesOptionnelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
||||
needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
|
||||
carac: this.defender.system.carac,
|
||||
show: {}
|
||||
@@ -1166,7 +1166,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async computeDeteriorationArme(defenderRoll) {
|
||||
if (!ReglesOptionelles.isUsing('resistanceArmeParade')) {
|
||||
if (!ReglesOptionnelles.isUsing('resistanceArmeParade')) {
|
||||
return;
|
||||
}
|
||||
const attackerRoll = defenderRoll.attackerRoll;
|
||||
@@ -1215,7 +1215,7 @@ export class RdDCombat {
|
||||
}
|
||||
}
|
||||
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
||||
if (ReglesOptionelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(defenderRoll.arme) != 'boucliers') {
|
||||
if (ReglesOptionnelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(defenderRoll.arme) != 'boucliers') {
|
||||
let desarme = await RdDResolutionTable.rollData({
|
||||
caracValue: this.defender.getForce(),
|
||||
finalLevel: Misc.toInt(defenderRoll.competence.system.niveau) - dmg,
|
||||
@@ -1230,7 +1230,7 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
async computeRecul(defenderRoll) { // Calcul du recul (p. 132)
|
||||
const attackerRoll = defenderRoll.attackerRoll;
|
||||
if (ReglesOptionelles.isUsing('recul') && this._isForceOuCharge(attackerRoll)) {
|
||||
if (ReglesOptionnelles.isUsing('recul') && this._isForceOuCharge(attackerRoll)) {
|
||||
const impact = this._computeImpactRecul(attackerRoll);
|
||||
const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact });
|
||||
if (rollRecul.rolled.isSuccess) {
|
||||
|
@@ -1,10 +1,10 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
|
||||
export class RdDConfirm {
|
||||
/* -------------------------------------------- */
|
||||
static confirmer(options, autresActions) {
|
||||
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionelles.isUsing(options.settingConfirmer));
|
||||
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionnelles.isUsing(options.settingConfirmer));
|
||||
if (options.bypass) {
|
||||
options.onAction();
|
||||
}
|
||||
@@ -47,7 +47,7 @@ export class RdDConfirm {
|
||||
icon: '<i class="fas fa-user-check"></i>',
|
||||
label: options.buttonLabel + "<br>et ne plus demander",
|
||||
callback: () => {
|
||||
ReglesOptionelles.set(options.settingConfirmer, false);
|
||||
ReglesOptionnelles.set(options.settingConfirmer, false);
|
||||
options.onAction();
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,8 @@ import { RdDRoll } from "./rdd-roll.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { TYPES } from "./item.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
@@ -14,6 +16,47 @@ export class RdDEmpoignade {
|
||||
static init() {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static registerChatCallbacks(html) {
|
||||
html.on("click", '.defense-empoignade-cac', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
|
||||
});
|
||||
html.on("click", '.defense-empoignade-esquive', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
|
||||
});
|
||||
html.on("click", '.empoignade-poursuivre', event => {
|
||||
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
||||
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
||||
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
|
||||
});
|
||||
html.on("click", '.empoignade-entrainer-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
RdDEmpoignade.entrainerAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
});
|
||||
html.on("click", '.empoignade-projeter-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
RdDEmpoignade.projeterAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
});
|
||||
html.on("change", '.empoignade-perte-endurance', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
||||
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static checkEmpoignadeEnCours(actor) {
|
||||
// TODO: autoriser la perception? la comédie/séduction?
|
||||
@@ -24,74 +67,92 @@ export class RdDEmpoignade {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static $storeRollEmpoignade(msg, rollData) {
|
||||
RdDEmpoignade.$reduceActorToIds(rollData);
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData);
|
||||
}
|
||||
|
||||
static $reduceActorToIds(rollData) {
|
||||
rollData.attacker = { id: rollData.attacker.id };
|
||||
rollData.defender = { id: rollData.defender.id };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static $readRollEmpoignade(msg) {
|
||||
const rollData = ChatUtility.getMessageData(msg, 'empoignade-roll-data');
|
||||
RdDEmpoignade.$replaceIdsWithActors(rollData);
|
||||
return rollData
|
||||
}
|
||||
|
||||
static $replaceIdsWithActors(rollData) {
|
||||
rollData.attacker = game.actors.get(rollData.attacker.id);
|
||||
rollData.defender = game.actors.get(rollData.defender.id);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isEmpoignadeEnCours(actor) {
|
||||
return actor.itemTypes['empoignade'].find(it => it.system.pointsemp > 0)
|
||||
return actor.itemTypes[TYPES.empoignade].find(it => it.system.pointsemp > 0)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getEmpoignadeById(actor, id) {
|
||||
let emp = actor.itemTypes['empoignade'].find(it => it.system.empoignadeid == id)
|
||||
let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id)
|
||||
return emp && duplicate(emp) || undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getEmpoignade(attacker, defender) {
|
||||
let emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id)
|
||||
if (!emp) {
|
||||
emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
|
||||
}
|
||||
let emp = attacker.itemTypes[TYPES.empoignade].find(it =>
|
||||
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
|
||||
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
|
||||
)
|
||||
if (emp) {
|
||||
return duplicate(emp);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getMalusTaille(emp, attacker, defender) {
|
||||
// Si pas empoigné, alors 0
|
||||
if (emp.system.pointsemp == 0) {
|
||||
return 0
|
||||
}
|
||||
// Malus de -1 si différence de taille de 2 ou plus (p 135)
|
||||
if (attacker.system.carac.taille.value < defender.system.carac.taille.value - 1) {
|
||||
return attacker.system.carac.taille.value - (defender.system.carac.taille.value - 1)
|
||||
// p135: Malus de -1 par point de taille de différence de taille au delà de 1 (donc -2 pour une différence de 3, ...)
|
||||
const diffTaille = attacker.system.carac.taille.value - defender.system.carac.taille.value;
|
||||
const diffTailleAbs = Math.abs(diffTaille)
|
||||
const signDiff = diffTaille > 0 ? 1 : -1
|
||||
|
||||
if (diffTailleAbs > 2) {
|
||||
return signDiff * (diffTailleAbs - 1)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignadeValidee(attacker, defender) {
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
const isNouvelle = empoignade == undefined;
|
||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||
static isActionAutorisee(mode, attacker, defender) {
|
||||
const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker;
|
||||
if (acting.getUserLevel(game.user) < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
|
||||
ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`)
|
||||
return false;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
||||
|
||||
let rollData = {
|
||||
mode: mode,
|
||||
isEmpoignade: true,
|
||||
competence: attacker.getCompetence("Corps à corps").clone(),
|
||||
selectedCarac: attacker.system.carac.melee,
|
||||
empoignade: empoignade,
|
||||
attackerId: attacker.id,
|
||||
attackerName: attacker.name,
|
||||
defenderName: defender.name,
|
||||
defenderId: defender.id,
|
||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
||||
}
|
||||
if (attacker.isCreatureEntite()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||
}
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
} else {
|
||||
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
||||
static isActionDefenseur(mode) {
|
||||
switch (mode) {
|
||||
case "liberer":
|
||||
case "contrer-empoigner":
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignade(attacker, defender) {
|
||||
if (!RdDEmpoignade.isActionAutorisee("empoigner", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
const isNouvelle = empoignade == undefined;
|
||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||
@@ -105,6 +166,38 @@ export class RdDEmpoignade {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignadeValidee(attacker, defender) {
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
const isNouvelle = empoignade == undefined;
|
||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||
|
||||
let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
||||
|
||||
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
|
||||
return
|
||||
}
|
||||
|
||||
let rollData = {
|
||||
mode, empoignade, attacker, defender,
|
||||
isEmpoignade: true,
|
||||
competence: attacker.getCompetence("Corps à corps").clone(),
|
||||
selectedCarac: attacker.system.carac.melee,
|
||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
||||
}
|
||||
if (attacker.isCreatureEntite()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||
}
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
if (!empoignade.system.ausol) {
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.html');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
} else {
|
||||
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignadeFromItem(empoignade) {
|
||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
@@ -112,6 +205,20 @@ export class RdDEmpoignade {
|
||||
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||
}
|
||||
|
||||
static async onImmobilisation(attacker, defender, empoignade) {
|
||||
const rollData = {
|
||||
mode: "immobilise",
|
||||
empoignade, attacker, defender,
|
||||
isEmpoignade: true,
|
||||
competence: attacker.getCompetence("Corps à corps").clone()
|
||||
}
|
||||
const msg = await ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name),
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.html`, rollData)
|
||||
})
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
|
||||
const dialog = await RdDRoll.create(attacker, rollData,
|
||||
@@ -119,35 +226,40 @@ export class RdDEmpoignade {
|
||||
{
|
||||
name: 'jet-empoignade',
|
||||
label: 'Empoigner',
|
||||
callbacks: [
|
||||
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, true, isNouvelle) },
|
||||
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, false, isNouvelle) },
|
||||
]
|
||||
callbacks: [{ action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, isNouvelle) },]
|
||||
});
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $onRollEmpoignade(rollData, isSuccess, isNouvelle = false) {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
static async $onRollEmpoignade(rollData, isNouvelle = false) {
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
|
||||
let empoignade = rollData.empoignade
|
||||
empoignade.isSuccess = isSuccess;
|
||||
|
||||
if (isSuccess && isNouvelle) {
|
||||
if (rollData.rolled.isSuccess && isNouvelle) {
|
||||
const objectEmpoignade = rollData.empoignade.toObject();
|
||||
// Creer l'empoignade sur attaquant/defenseur
|
||||
await attacker.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
||||
await defender.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
||||
attacker.creerObjetParMJ(objectEmpoignade);
|
||||
defender.creerObjetParMJ(objectEmpoignade);
|
||||
}
|
||||
|
||||
rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
|
||||
if (rollData.rolled.isPart) {
|
||||
rollData.particuliere = "finesse";
|
||||
}
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onDefenseEmpoignade(rollData, defenseMode, competenceName = "Corps à corps", carac = "melee") {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
static async onDefenseEmpoignade(attackerRoll, mode, competenceName = "Corps à corps", carac = "melee") {
|
||||
let attacker = game.actors.get(attackerRoll.attacker.id)
|
||||
let defender = game.actors.get(attackerRoll.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
|
||||
return
|
||||
}
|
||||
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
if (!empoignade) {
|
||||
@@ -156,18 +268,23 @@ export class RdDEmpoignade {
|
||||
}
|
||||
|
||||
empoignade = duplicate(empoignade)
|
||||
rollData.mode = defenseMode
|
||||
rollData.empoignade = empoignade
|
||||
rollData.competence = defender.getCompetence(competenceName),
|
||||
rollData.selectedCarac = defender.system.carac[carac],
|
||||
rollData.malusTaille = RdDEmpoignade.getMalusTaille(empoignade, defender, attacker)
|
||||
|
||||
await RdDEmpoignade.$rollDefenseEmpoignade(defender, rollData);
|
||||
let defenderRoll = {
|
||||
mode, attacker, defender, empoignade, attackerRoll,
|
||||
diffLibre: attackerRoll.diffLibre,
|
||||
attaqueParticuliere: attackerRoll.particuliere,
|
||||
competence: defender.getCompetence(competenceName).clone(),
|
||||
surprise: defender.getSurprise(true),
|
||||
carac: defender.system.carac,
|
||||
selectedCarac: defender.system.carac[carac],
|
||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, defender, attacker),
|
||||
show: {}
|
||||
};
|
||||
await RdDEmpoignade.$rollDefenseEmpoignade(defender, defenderRoll);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $rollDefenseEmpoignade(defender, rollData) {
|
||||
const dialog = await RdDRoll.create(defender, rollData,
|
||||
static async $rollDefenseEmpoignade(defender, defenderRoll) {
|
||||
const dialog = await RdDRoll.create(defender, defenderRoll,
|
||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' },
|
||||
{
|
||||
name: 'empoignade',
|
||||
@@ -183,7 +300,7 @@ export class RdDEmpoignade {
|
||||
/* -------------------------------------------- */
|
||||
static async $onRollContrerLiberer(rollData) {
|
||||
let empoignade = rollData.empoignade
|
||||
|
||||
|
||||
if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) {
|
||||
empoignade.system.pointsemp++
|
||||
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
||||
@@ -192,13 +309,12 @@ export class RdDEmpoignade {
|
||||
empoignade.system.pointsemp--
|
||||
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
||||
}
|
||||
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
}
|
||||
|
||||
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html')
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-empoignade-entrainer.html');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -223,16 +339,15 @@ export class RdDEmpoignade {
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||
await defender.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
|
||||
//let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
//emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
||||
//await attacker.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async entrainerAuSol(rollData) {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
empoignade.system.ausol = true
|
||||
@@ -242,25 +357,32 @@ export class RdDEmpoignade {
|
||||
await defender.setEffect(STATUSES.StatusProne, true);
|
||||
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async projeterAuSol(rollData) {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
await defender.setEffect(STATUSES.StatusProne, true);
|
||||
await this.$deleteEmpoignade(empoignade)
|
||||
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async perteEndurance(rollData, perteMode) {
|
||||
let attacker = game.actors.get(rollData.attackerId)
|
||||
let defender = game.actors.get(rollData.defenderId)
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
//console.log("Perte d'endurance :!!!", perteMode)
|
||||
@@ -278,7 +400,7 @@ export class RdDEmpoignade {
|
||||
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
|
||||
}
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html');
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@@ -15,7 +15,7 @@ import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { StatusEffects } from "./settings/status-effects.js";
|
||||
import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { RdDHotbar } from "./rdd-hotbar-drop.js"
|
||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { RdDHerbes } from "./rdd-herbes.js";
|
||||
@@ -186,7 +186,7 @@ export class SystemReveDeDragon {
|
||||
RdDCalendrier.init();
|
||||
SystemCompendiums.init();
|
||||
DialogChronologie.init();
|
||||
ReglesOptionelles.init();
|
||||
ReglesOptionnelles.init();
|
||||
RdDUtility.init();
|
||||
RdDDice.init();
|
||||
RdDCommands.init();
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
|
||||
/**
|
||||
* difficultés au delà de -10
|
||||
@@ -91,13 +91,17 @@ export class RdDResolutionTable {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') {
|
||||
return await ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, {
|
||||
content: await RdDResolutionTable.buildRollDataHtml(rollData, actor, template)
|
||||
return await ChatUtility.createChatWithRollMode(RdDResolutionTable.actorChatName(actor), {
|
||||
content: await RdDResolutionTable.buildRollDataHtml(rollData, template)
|
||||
});
|
||||
}
|
||||
|
||||
static actorChatName(actor) {
|
||||
return actor?.userName ?? game.user.name;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async buildRollDataHtml(rollData, actor, template = 'chat-resultat-general.html') {
|
||||
static async buildRollDataHtml(rollData, template = 'chat-resultat-general.html') {
|
||||
rollData.show = rollData.show || {};
|
||||
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData);
|
||||
}
|
||||
@@ -122,7 +126,7 @@ export class RdDResolutionTable {
|
||||
rolled.bonus = rollData.bonus;
|
||||
rolled.factorHtml = Misc.getFractionHtml(rollData.diviseurSignificative);
|
||||
|
||||
if (ReglesOptionelles.isUsing("afficher-colonnes-reussite")) {
|
||||
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
|
||||
rolled.niveauNecessaire = this.findNiveauNecessaire(caracValue, rolled.roll);
|
||||
rolled.ajustementNecessaire = rolled.niveauNecessaire - finalLevel;
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
|
||||
/**
|
||||
* Extend the base Dialog entity to select roll parameters
|
||||
@@ -85,7 +85,7 @@ export class RdDRoll extends Dialog {
|
||||
if (RdDBonus.isDefenseAttaqueFinesse(rollData)) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (!ReglesOptionelles.isUsing('tripleSignificative')) {
|
||||
if (!ReglesOptionnelles.isUsing('tripleSignificative')) {
|
||||
facteurSign = Math.min(facteurSign, 4);
|
||||
}
|
||||
return facteurSign;
|
||||
|
@@ -12,7 +12,7 @@ import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
||||
import { Draconique } from "./tmr/draconique.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { RdDRencontre } from "./item/rencontre.js";
|
||||
@@ -55,7 +55,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.actor = actor;
|
||||
this.actor.tmrApp = this; // reference this app in the actor structure
|
||||
this.viewOnly = tmrData.mode == "visu"
|
||||
this.fatigueParCase = this.viewOnly || !ReglesOptionelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
||||
this.fatigueParCase = this.viewOnly || !ReglesOptionnelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
||||
this.cumulFatigue = 0;
|
||||
this.loadRencontres();
|
||||
this.loadCasesSpeciales();
|
||||
@@ -207,7 +207,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return;
|
||||
}
|
||||
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
|
||||
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
|
||||
|
||||
// Roll Sort
|
||||
@@ -227,7 +227,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
// Gestion du cout de montée en points de rêve
|
||||
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
await this.actor.reveActuelIncDec(reveCout);
|
||||
@@ -263,7 +263,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||
refoulement.innerHTML = this.actor.system.reve.refoulement.value;
|
||||
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
||||
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.system.sante.fatigue.value, this.actor.system.sante.endurance.max).html() + "</table>";
|
||||
}
|
||||
@@ -367,7 +367,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return true;
|
||||
}
|
||||
const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.cumulFatigue;
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue") && resteAvantInconscience <= 0) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && resteAvantInconscience <= 0) {
|
||||
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
|
||||
this.quitterLesTMRInconscient();
|
||||
return true;
|
||||
@@ -451,7 +451,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
setTimeout(() => {
|
||||
// TODO: remplacer par une boucle while(this.currentRencontre) ?
|
||||
rencData.nbRounds++;
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
this._tentativeMaitrise(rencData);
|
||||
@@ -1004,7 +1004,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this.actor.updateCoordTMR(tmr.coord);
|
||||
|
||||
this.forceDemiRevePositionView();
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
this.updateValuesDisplay();
|
||||
|
@@ -5,7 +5,7 @@ import { Misc } from "./misc.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
import { DialogItemAchat } from "./dialog-item-achat.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { RdDPossession } from "./rdd-possession.js";
|
||||
@@ -121,6 +121,7 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-hautreve.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/archetype.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html',
|
||||
@@ -278,7 +279,7 @@ export class RdDUtility {
|
||||
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
|
||||
|
||||
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
||||
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
||||
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionnelles.isUsing(option));
|
||||
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
|
||||
Handlebars.registerHelper('filtreTriCompetences', competences => RdDItemCompetence.triVisible(competences));
|
||||
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
||||
@@ -478,7 +479,7 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculFatigueHtml(fatigue, endurance) {
|
||||
return ReglesOptionelles.isUsing("appliquer-fatigue") ? {
|
||||
return ReglesOptionnelles.isUsing("appliquer-fatigue") ? {
|
||||
malus: RdDUtility.calculMalusFatigue(fatigue, endurance),
|
||||
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(fatigue, endurance).html() + "</table>"
|
||||
} : { malus: 0, html: '' };
|
||||
@@ -554,14 +555,14 @@ export class RdDUtility {
|
||||
let formula = "2d10";
|
||||
|
||||
// Chaque dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre')) {
|
||||
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
formula += "min" + valeurMin;
|
||||
}
|
||||
}
|
||||
// Chaque dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-ajout-malus-libre')) {
|
||||
if (ReglesOptionnelles.isUsing('degat-ajout-malus-libre')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
formula += "+" + valeurMin;
|
||||
@@ -571,7 +572,7 @@ export class RdDUtility {
|
||||
let roll = await RdDDice.roll(formula, options);
|
||||
|
||||
// 1 dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre-simple')) {
|
||||
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
if (roll.terms[0].results[0].result < valeurMin) {
|
||||
@@ -624,7 +625,7 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static currentFatigueMalus(value, max) {
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
max = Math.max(1, Math.min(max, 60));
|
||||
value = Math.min(max * 2, Math.max(0, value));
|
||||
|
||||
@@ -668,6 +669,7 @@ export class RdDUtility {
|
||||
/* -------------------------------------------- */
|
||||
static async chatListeners(html) {
|
||||
RdDCombat.registerChatCallbacks(html);
|
||||
RdDEmpoignade.registerChatCallbacks(html);
|
||||
|
||||
// Gestion spécifique message passeurs
|
||||
html.on("click", '.tmr-passeur-coord a', event => {
|
||||
@@ -694,44 +696,6 @@ export class RdDUtility {
|
||||
RdDPossession.onDefensePossession(attackerId, defenderId, possessionId)
|
||||
});
|
||||
|
||||
html.on("click", '.defense-empoignade-cac', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
|
||||
});
|
||||
html.on("click", '.defense-empoignade-esquive', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
|
||||
});
|
||||
html.on("click", '.empoignade-poursuivre', event => {
|
||||
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
||||
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
||||
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
|
||||
});
|
||||
html.on("click", '.empoignade-entrainer-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
RdDEmpoignade.entrainerAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
});
|
||||
html.on("click", '.empoignade-projeter-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
RdDEmpoignade.projeterAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
});
|
||||
html.on("change", '.empoignade-perte-endurance', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
||||
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
||||
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
}
|
||||
});
|
||||
|
||||
// gestion bouton tchat Acheter
|
||||
html.on("click", '.button-acheter', event => {
|
||||
const venteData = DialogItemAchat.preparerAchat(event.currentTarget);
|
||||
|
@@ -7,7 +7,7 @@ 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";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
|
||||
/**
|
||||
* tous les ajustements pouvant s'appliquer.
|
||||
@@ -86,7 +86,7 @@ export const referenceAjustements = {
|
||||
getValue: (rollData, actor) => actor.getMoralTotal()
|
||||
},
|
||||
astrologique: {
|
||||
isUsed: (rollData, actor) => ReglesOptionelles.isUsing("astrologie") && RdDBonus.isAjustementAstrologique(rollData),
|
||||
isUsed: (rollData, actor) => ReglesOptionnelles.isUsing("astrologie") && RdDBonus.isAjustementAstrologique(rollData),
|
||||
getLabel: (rollData, actor) => 'Astrologique',
|
||||
getValue: (rollData, actor) => actor.ajustementAstrologique()
|
||||
},
|
||||
|
@@ -1,119 +0,0 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
import { Misc } from "../misc.js";
|
||||
|
||||
const listeReglesOptionelles = [
|
||||
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
||||
{ group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
||||
{ group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" },
|
||||
{ group: 'Règles de combat', name: 'defenseurDesarme', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" },
|
||||
{ group: 'Règles de combat', name: 'categorieParade', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" },
|
||||
{ group: 'Règles de combat', name: 'tripleSignificative', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" },
|
||||
{ group: 'Règles de combat', name: 'degat-minimum-malus-libre-simple', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si le plus petit dé est inférieur à 4, alors il devient 4.", default: false },
|
||||
{ group: 'Règles de combat', name: 'degat-minimum-malus-libre', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false },
|
||||
{ group: 'Règles de combat', name: 'degat-ajout-malus-libre', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false },
|
||||
{ group: 'Règles de combat', name: 'validation-encaissement-gr', descr: "Le Gardien des Rêves doit valider les jets d'encaissement et peut les changer.", default: false },
|
||||
|
||||
{ group: 'Règles générales', name: 'astrologie', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"},
|
||||
{ group: 'Règles générales', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true},
|
||||
{ group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
|
||||
{ group: 'Règles générales', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
||||
{ group: 'Règles générales', name: 'chateau-dormant-gardien', descr: "Saisie des heures de sommeil/jets de moral par le gardien des rêves", default: true },
|
||||
|
||||
{ group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-equipement', descr: "Confirmer la suppression des équipements", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-oeuvre', descr: "Confirmer la suppression des oeuvres", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-connaissance', descr: "Confirmer la suppression des connaissances", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-draconique', descr: "Confirmer la suppression des queues, souffles, têtes", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-effet', descr: "Confirmer la suppression des effets", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-competence', descr: "Confirmer la suppression des compétences", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-autres', descr: "Confirmer la suppression des autres types d'Objets", scope: "client"},
|
||||
];
|
||||
|
||||
const uniquementJoueur = listeReglesOptionelles.filter(it => it.uniquementJoueur).map(it=>it.name);
|
||||
|
||||
export class ReglesOptionelles extends FormApplication {
|
||||
static init() {
|
||||
for (const regle of listeReglesOptionelles) {
|
||||
const name = regle.name;
|
||||
const id = ReglesOptionelles._getIdRegle(name);
|
||||
game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
||||
}
|
||||
|
||||
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
||||
name: "Choisir les règles optionelles",
|
||||
label: "Règles optionelles",
|
||||
hint: "Ouvre la fenêtre de sélection des règles optionelles",
|
||||
icon: "fas fa-bars",
|
||||
type: ReglesOptionelles
|
||||
});
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
static _getIdRegle(name) {
|
||||
return `rdd-option-${name}`;
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
const options = super.defaultOptions;
|
||||
mergeObject(options, {
|
||||
id: "regles-optionelles",
|
||||
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionelles.html",
|
||||
height: 600,
|
||||
width: 450,
|
||||
minimizable: false,
|
||||
closeOnSubmit: true,
|
||||
title: "Règles optionnelles"
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
getData() {
|
||||
let formData = super.getData();
|
||||
const regles = listeReglesOptionelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
|
||||
it = duplicate(it);
|
||||
it.id = ReglesOptionelles._getIdRegle(it.name);
|
||||
it.active = ReglesOptionelles.isSet(it.name);
|
||||
return it;
|
||||
});
|
||||
formData.regles = regles;
|
||||
formData.groups = Misc.classify(regles, it => it.group);
|
||||
return formData;
|
||||
}
|
||||
|
||||
static isUsing(name) {
|
||||
if (game.user.isGM && uniquementJoueur.includes(name)) {
|
||||
return true;
|
||||
}
|
||||
return ReglesOptionelles.isSet(name);
|
||||
}
|
||||
|
||||
static isSet(name) {
|
||||
return game.settings.get(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name));
|
||||
}
|
||||
|
||||
static set(name, value) {
|
||||
return game.settings.set(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name), value ? true: false);
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
html.find(".select-option").click((event) => {
|
||||
if (event.currentTarget.attributes.name) {
|
||||
let id = event.currentTarget.attributes.name.value;
|
||||
let isChecked = event.currentTarget.checked;
|
||||
game.settings.set(SYSTEM_RDD, id, isChecked);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async _updateObject(event, formData) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
122
module/settings/regles-optionnelles.js
Normal file
122
module/settings/regles-optionnelles.js
Normal file
@@ -0,0 +1,122 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
import { Misc } from "../misc.js";
|
||||
|
||||
const listeReglesOptionnelles = [
|
||||
{ group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
|
||||
{ group: 'Règles générales', name: 'astrologie', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"},
|
||||
|
||||
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
||||
{ group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
||||
{ group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" },
|
||||
{ group: 'Règles de combat', name: 'defenseurDesarme', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" },
|
||||
{ group: 'Règles de combat', name: 'categorieParade', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" },
|
||||
{ group: 'Règles de combat', name: 'tripleSignificative', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" },
|
||||
{ group: 'Règles de combat', name: 'validation-encaissement-gr', descr: "Le Gardien des Rêves doit valider les jets d'encaissement et peut les changer.", default: false },
|
||||
|
||||
{ group: 'Automatisation', name: 'chateau-dormant-gardien', descr: "Saisie des heures de sommeil/jets de moral par le gardien des rêves", default: true },
|
||||
|
||||
{ group: 'Affichage', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
||||
{ group: 'Affichage', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true},
|
||||
|
||||
{ group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-equipement', descr: "Confirmer la suppression des équipements", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-oeuvre', descr: "Confirmer la suppression des oeuvres", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-connaissance', descr: "Confirmer la suppression des connaissances", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-draconique', descr: "Confirmer la suppression des queues, souffles, têtes", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-effet', descr: "Confirmer la suppression des effets", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-competence', descr: "Confirmer la suppression des compétences", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-autres', descr: "Confirmer la suppression des autres types d'Objets", scope: "client"},
|
||||
|
||||
{ group: 'Options alternatives', name: 'degat-minimum-malus-libre-simple', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si le plus petit dé est inférieur à 4, alors il devient 4.", default: false },
|
||||
{ group: 'Options alternatives', name: 'degat-minimum-malus-libre', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false },
|
||||
{ group: 'Options alternatives', name: 'degat-ajout-malus-libre', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false },
|
||||
];
|
||||
|
||||
const uniquementJoueur = listeReglesOptionnelles.filter(it => it.uniquementJoueur).map(it=>it.name);
|
||||
|
||||
export class ReglesOptionnelles extends FormApplication {
|
||||
static init() {
|
||||
for (const regle of listeReglesOptionnelles) {
|
||||
const name = regle.name;
|
||||
const id = ReglesOptionnelles._getIdRegle(name);
|
||||
game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
||||
}
|
||||
|
||||
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
||||
name: "Choisir les règles optionnelles",
|
||||
label: "Règles optionnelles",
|
||||
hint: "Ouvre la fenêtre de sélection des règles optionnelles",
|
||||
icon: "fas fa-bars",
|
||||
type: ReglesOptionnelles
|
||||
});
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
static _getIdRegle(name) {
|
||||
return `rdd-option-${name}`;
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
const options = super.defaultOptions;
|
||||
mergeObject(options, {
|
||||
id: "regles-optionnelles",
|
||||
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html",
|
||||
height: 600,
|
||||
width: 450,
|
||||
minimizable: false,
|
||||
closeOnSubmit: true,
|
||||
title: "Règles optionnelles"
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
getData() {
|
||||
let formData = super.getData();
|
||||
const regles = listeReglesOptionnelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
|
||||
it = duplicate(it);
|
||||
it.id = ReglesOptionnelles._getIdRegle(it.name);
|
||||
it.active = ReglesOptionnelles.isSet(it.name);
|
||||
return it;
|
||||
});
|
||||
formData.regles = regles;
|
||||
formData.groups = Misc.classify(regles, it => it.group);
|
||||
return formData;
|
||||
}
|
||||
|
||||
static isUsing(name) {
|
||||
if (game.user.isGM && uniquementJoueur.includes(name)) {
|
||||
return true;
|
||||
}
|
||||
return ReglesOptionnelles.isSet(name);
|
||||
}
|
||||
|
||||
static isSet(name) {
|
||||
return game.settings.get(SYSTEM_RDD, ReglesOptionnelles._getIdRegle(name));
|
||||
}
|
||||
|
||||
static set(name, value) {
|
||||
return game.settings.set(SYSTEM_RDD, ReglesOptionnelles._getIdRegle(name), value ? true: false);
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
html.find(".select-option").click((event) => {
|
||||
if (event.currentTarget.attributes.name) {
|
||||
let id = event.currentTarget.attributes.name.value;
|
||||
let isChecked = event.currentTarget.checked;
|
||||
game.settings.set(SYSTEM_RDD, id, isChecked);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async _updateObject(event, formData) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||
import { EffetsDraconiques } from "../tmr/effets-draconiques.js";
|
||||
|
||||
export class DialogRepos extends Dialog {
|
||||
@@ -7,7 +7,7 @@ export class DialogRepos extends Dialog {
|
||||
if (!actor.isPersonnage()) {
|
||||
return
|
||||
}
|
||||
if (!ReglesOptionelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) {
|
||||
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) {
|
||||
actor.system.sommeil = {
|
||||
"nouveaujour": true,
|
||||
"insomnie": EffetsDraconiques.isSujetInsomnie(actor),
|
||||
|
@@ -6,7 +6,7 @@ import { RdDDice } from "../rdd-dice.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { DialogChronologie } from "../dialog-chronologie.js";
|
||||
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
|
||||
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||
import { DialogChateauDormant } from "../sommeil/dialog-chateau-dormant.js";
|
||||
import { APP_ASTROLOGIE_REFRESH, AppAstrologie } from "../sommeil/app-astrologie.js";
|
||||
|
||||
@@ -305,7 +305,7 @@ export class RdDCalendrier extends Application {
|
||||
const oldTimestamp = this.timestamp;
|
||||
await Promise.all(game.actors.map(async actor => await actor.onTimeChanging(oldTimestamp, newTimestamp)));
|
||||
RdDTimestamp.setWorldTime(newTimestamp);
|
||||
if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionelles.isUsing("chateau-dormant-gardien")) {
|
||||
if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionnelles.isUsing("chateau-dormant-gardien")) {
|
||||
await DialogChateauDormant.create();
|
||||
}
|
||||
this.timestamp = newTimestamp;
|
||||
|
@@ -156,7 +156,9 @@ export class RdDTimestamp {
|
||||
fields.minute.change(async (event) => await onChangeTimestamp(fields, path));
|
||||
}
|
||||
|
||||
|
||||
static defHeure(heure) {
|
||||
return DEFINITION_HEURES.find(it => (it.heure) == heure % RDD_HEURES_PAR_JOUR);
|
||||
}
|
||||
static findHeure(heure) {
|
||||
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
|
||||
let parHeureOuLabel = DEFINITION_HEURES.filter(it => (it.heure) == parseInt(heure) % RDD_HEURES_PAR_JOUR || Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure);
|
||||
|
@@ -287,6 +287,16 @@ table {border: 1px solid #7a7971;}
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
.grid-competence-archetype {
|
||||
display: grid;
|
||||
grid-column: span 3 / span 3;
|
||||
grid-template-columns: 2fr 2fr 1fr;
|
||||
gap: 0.5rem;
|
||||
margin: 0.5rem 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.grid-3col {
|
||||
grid-column: span 3 / span 3;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
@@ -1898,34 +1908,51 @@ div.calendar-timestamp-edit select.calendar-signe-heure {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chat-card-button {
|
||||
box-shadow: inset 0px 1px 0px 0px #a6827e;
|
||||
background: var(--background-custom-button);
|
||||
background-color: #7d5d3b00;
|
||||
border-radius: 3px;
|
||||
border: 2px ridge #846109;
|
||||
display: inline-block;
|
||||
.chat-card-button, .chat-card-button-pushed {
|
||||
border-radius: 0.2rem;
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
font-family: CaslonPro;
|
||||
font-size: 0.9rem;
|
||||
padding: 4px 12px 0px 12px;
|
||||
padding: 0.2rem 0.4rem 0rem 0.4rem;
|
||||
text-decoration: none;
|
||||
text-shadow: 0px 1px 0px #4d3534;
|
||||
position: relative;
|
||||
margin:5px;
|
||||
margin: 0.3rem;
|
||||
|
||||
border: 2px ridge #846109;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.chat-card-button{
|
||||
text-shadow: 1px 1px #4d3534;
|
||||
box-shadow: inset 1x 1px #a6827e;
|
||||
color: var(--major-button-color);
|
||||
background: var(--background-custom-button);
|
||||
background-color: #7d5d3b00;
|
||||
}
|
||||
|
||||
.chat-card-button-pushed {
|
||||
text-shadow: 1px 1px hsla(202, 30%, 70%, 0.5);
|
||||
box-shadow: inset -1px -1px #a6827e;
|
||||
color: hsla(202, 42%, 14%, 0.7);
|
||||
background: var(--major-button-color);
|
||||
background-color: #7d5d3b00;
|
||||
}
|
||||
|
||||
.chat-card-button:hover {
|
||||
background: var(--background-custom-button-hover);
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.chat-card-button:active {
|
||||
.chat-card-button-pushed:hover {
|
||||
background: var(--background-custom-button-hover);
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.chat-card-button:active, .chat-card-button-pushed:active {
|
||||
position:relative;
|
||||
top:1px;
|
||||
}
|
||||
|
||||
/* Dropdown Content (Hidden by Default) */
|
||||
.button-dropdown-content {
|
||||
display: none;
|
||||
|
101
system.json
101
system.json
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"id": "foundryvtt-reve-de-dragon",
|
||||
"title": "Rêve de Dragon",
|
||||
"version": "11.0.7",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.7.zip",
|
||||
"version": "11.0.9",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.9.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",
|
||||
@@ -82,7 +83,8 @@
|
||||
"path": "packs/arts-et-divertissements.db",
|
||||
"type": "Item",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -117,7 +119,8 @@
|
||||
"path": "packs/sorts-oniros.db",
|
||||
"type": "Item",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -128,7 +131,8 @@
|
||||
"path": "packs/sorts-hypnos.db",
|
||||
"type": "Item",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -139,7 +143,8 @@
|
||||
"path": "packs/sorts-narcos.db",
|
||||
"type": "Item",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -150,7 +155,8 @@
|
||||
"path": "packs/sorts-thanatos.db",
|
||||
"type": "Item",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -161,7 +167,8 @@
|
||||
"path": "packs/equipement.db",
|
||||
"type": "Item",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -184,7 +191,8 @@
|
||||
"path": "packs/rappel-des-regles.db",
|
||||
"type": "JournalEntry",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OBSERVER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -195,7 +203,8 @@
|
||||
"path": "packs/macros.db",
|
||||
"type": "Macro",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -242,7 +251,8 @@
|
||||
"path": "packs/tarot-draconique.db",
|
||||
"type": "Item",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -253,7 +263,8 @@
|
||||
"path": "packs/extrait-poetique.db",
|
||||
"type": "Item",
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER"
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
@@ -438,6 +449,72 @@
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"packFolders": [
|
||||
{
|
||||
"name": "Rêve de Dragon",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"rappel-des-regles"
|
||||
],
|
||||
"folders": [
|
||||
{
|
||||
"name": "Personnages",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"voyageurs",
|
||||
"archetypes",
|
||||
"humanoides",
|
||||
"equipement",
|
||||
"competences",
|
||||
"arts-et-divertissements",
|
||||
"meditations-et-ecrits",
|
||||
"recettes-alchimiques"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Le Haut-rêve",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"tetes-de-dragon-pour-tous-personnages",
|
||||
"sorts-oniros",
|
||||
"sorts-hypnos",
|
||||
"sorts-narcos",
|
||||
"sorts-thanatos",
|
||||
"invocations",
|
||||
"rencontres",
|
||||
"queues-de-dragon",
|
||||
"ombres-de-thanatos",
|
||||
"souffles-de-dragon",
|
||||
"tetes-de-dragon-pour-haut-revants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Découverte du monde",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"animaux",
|
||||
"vehicules",
|
||||
"entites",
|
||||
"faune-flore-mineraux",
|
||||
"competences-creatures",
|
||||
"competences-entites",
|
||||
"maladies-et-poisons"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Outils du Gardien",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"scenes-rdd",
|
||||
"tables-diverses",
|
||||
"macros",
|
||||
"tarot-draconique",
|
||||
"extrait-poetique"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"socket": true,
|
||||
"gridDistance": 1,
|
||||
"gridUnits": "m",
|
||||
|
@@ -53,7 +53,9 @@
|
||||
{{#if options.isObserver}}{{!-- Compétences Tab --}}
|
||||
<div class="tab competences" data-group="primary" data-tab="competences">
|
||||
<div class="flexrow">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}}
|
||||
<span>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}}
|
||||
</span>
|
||||
<span class="flexrow"><a class="show-hide-competences">
|
||||
{{#if options.showCompNiveauBase}}
|
||||
<i class="fa-regular fa-filter-slash"></i> Montrer tout
|
||||
@@ -65,9 +67,17 @@
|
||||
<input class="recherche flex-grow" type="text" value="{{options.recherche.text}}" name="recherche" size="8" data-dtype="String" placeholder=""/>
|
||||
</span>
|
||||
<span>
|
||||
{{#if options.vueDetaillee}}
|
||||
|
||||
{{#if @root.options.vueArchetype}}
|
||||
<a class="competence-archetype toggle-archetype chat-card-button-pushed"><i class="fa-solid fa-up-right-from-square"></i>Incarnation</a>
|
||||
{{else}}
|
||||
<a class="competence-archetype toggle-archetype chat-card-button"><i class="fa-solid fa-people-line"></i>Archétype</a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="grid grid-2col">
|
||||
<div class="grid {{#if (and options.vueDetaillee options.vueArchetype)}}grid-competence-archetype{{else}}grid-2col{{/if}}">
|
||||
<div class="competence-column">
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.generale) categorie="Compétences générales"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.particuliere) categorie="Compétences Particulières"}}
|
||||
@@ -83,6 +93,11 @@
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.draconic) categorie="Draconic"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if (and options.vueDetaillee options.vueArchetype)}}
|
||||
<div>
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/archetype.hbs"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
21
templates/actor/archetype.hbs
Normal file
21
templates/actor/archetype.hbs
Normal file
@@ -0,0 +1,21 @@
|
||||
<div>
|
||||
<ul class="item-list">
|
||||
{{#if @root.options.isGM}}
|
||||
<li>
|
||||
<a class="nouvelle-incarnation chat-card-button"><i class="fa-solid fa-person-circle-plus"></i> Nouvelle incarnation</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li><hr></li>
|
||||
<li>Niveaux d'archétype</li>
|
||||
{{#if calc.comptageArchetype}}
|
||||
{{#each calc.comptageArchetype as |archetype|}}
|
||||
|
||||
<li class="item flexrow">
|
||||
<label class="generic-label">
|
||||
Niveaux {{numberFormat archetype.niveau decimals=0 sign=true}} : {{archetype.nombre}} / {{archetype.nombreMax}}
|
||||
</label>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</div>
|
@@ -14,12 +14,13 @@
|
||||
|
||||
<input class="competence-value" type="text" compname="{{name}}" name="comp-value-{{name}}"
|
||||
value="{{numberFormat system.niveau decimals=0 sign=true}}" data-dtype="number"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}} />
|
||||
{{#if (or (not @root.options.vueDetaillee) @root.options.vueArchetype)}}disabled{{/if}} />
|
||||
|
||||
{{#if @root.options.vueDetaillee}}
|
||||
<span class="competence-xp {{#unless system.isLevelUp}}tooltip{{/unless}}">
|
||||
<input class="competence-xp " type="text" compname="{{name}}" name="comp-xp-{{name}}"
|
||||
value="{{numberFormat system.xp decimals=0 sign=false}}" data-dtype="number"/>
|
||||
value="{{numberFormat system.xp decimals=0 sign=false}}" data-dtype="number"
|
||||
{{#if (or (not @root.options.vueDetaillee) @root.options.vueArchetype)}}disabled{{/if}} />
|
||||
{{#unless system.isLevelUp}}
|
||||
<span class="tooltiptext left-competence ttt-xp">Vous devez acquérir {{system.xpNext}} points d'Experience pour augmenter de 1 votre compétence {{name}}</span>
|
||||
{{/unless}}
|
||||
@@ -28,7 +29,7 @@
|
||||
{{#if (eq system.categorie 'draconic')}}
|
||||
<input class="competence-xp-sort" type="text" compname="{{name}}" name="comp-xp-sort-{{name}}"
|
||||
value="{{numberFormat system.xp_sort decimals=0 sign=false}}" data-dtype="number"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
|
||||
{{#if (or (not @root.options.vueDetaillee) @root.options.vueArchetype)}}disabled{{/if}} />
|
||||
{{/if}}
|
||||
{{#if @root.options.vueDetaillee}}
|
||||
<div class="item-controls">
|
||||
@@ -41,7 +42,8 @@
|
||||
<i class="far fa-circle"></i>
|
||||
{{/if}}
|
||||
<input class="competence-archetype niveau-archetype" type="text" compname="{{name}}" name="comp-archetype-{{name}}"
|
||||
value="{{numberFormat system.niveau_archetype decimals=0 sign=true}}" data-dtype="number"/>
|
||||
value="{{numberFormat system.niveau_archetype decimals=0 sign=true}}" data-dtype="number"
|
||||
{{#if (not @root.options.vueArchetype)}}disabled{{/if}} />
|
||||
<a class="item-edit" title="Modifier"><i class="fas fa-edit"></i></a>
|
||||
{{#if @root.options.isGM}}
|
||||
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
|
||||
|
@@ -13,18 +13,7 @@
|
||||
<span class="generic-label">Total XP compétences</span>
|
||||
<span class="competence-value">{{calc.competenceXPTotal}}</span>
|
||||
</li>
|
||||
{{#if calc.comptageArchetype}}
|
||||
<li><hr></li>
|
||||
<li>Niveaux d'archétype à répartir</li>
|
||||
{{#each calc.comptageArchetype as |archetype key|}}
|
||||
{{#if (gt archetype.reste 0)}}
|
||||
<li class="item flexrow">
|
||||
<label class="generic-label">Reste {{archetype.reste}} niveaux {{numberFormat archetype.niveau decimals=0 sign=true}} sur {{archetype.nombreMax}}</label>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<li> </li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@@ -1,39 +0,0 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} a empoigné {{defenderName}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
|
||||
<span class='chat-card-button-area'>
|
||||
Au round suivant l'acquisition des 2 points d'Emp, {{attackerName}} peut faire perdre autant de points d'Endurance qu'il souhaite à {{defenderName}}
|
||||
<br>
|
||||
<a class='empoignade-perte-endurance chat-card-button'>
|
||||
<select class='empoignade-perte-endurance'>
|
||||
<option value="none">Faire perdre de l'endurance (selectionnez)</option>
|
||||
<option value="end0">Endurance à 0</option>
|
||||
<option value="end1">Endurance à 1</option>
|
||||
<option value="endmoitie">La moitié de l'endurance</option>
|
||||
<option value="endquart">Le quart de l'endurance</option>
|
||||
</select>
|
||||
</a>
|
||||
|
||||
{{#if empoignade.system.ausol}}
|
||||
|
||||
{{else}}
|
||||
<br>
|
||||
Dès l'acquisition des 2 points d'Emp, {{attackerName}} peut entraîner {{defenderName}} au sol. Les deux protagonistes restent empoignés.
|
||||
<br>
|
||||
<a class='empoignade-entrainer-sol chat-card-button'>
|
||||
Entraîner au sol
|
||||
</a>
|
||||
<br>
|
||||
A la fin du round ou les 2 points d'Emp sont acquis, {{attackerName}} peut projeter {{defenderName}} au sol. Les deux protagonistes ne sont plus empoignés.
|
||||
<br>
|
||||
<a class='empoignade-projeter-sol chat-card-button'>
|
||||
Projeter au sol
|
||||
</a>
|
||||
{{/if}}
|
||||
|
||||
|
||||
</div>
|
@@ -1,7 +1,8 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} a entraîné {{defenderName}} au sol. L'empoignade peut continuer.
|
||||
{{attacker.name}} a entraîné {{defender.name}} au sol
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
L'empoignade peut continuer.
|
||||
</div>
|
||||
|
16
templates/chat-empoignade-entrainer.html
Normal file
16
templates/chat-empoignade-entrainer.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attacker.name}} a empoigné {{defender.name}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
<span class='chat-card-button-area'>
|
||||
{{attacker.name}} vient d'obtenir 2 points d'Emp, et peut
|
||||
entraîner {{defender.name}} au sol. Les deux protagonistes
|
||||
restent empoignés.
|
||||
<br>
|
||||
<a class='empoignade-entrainer-sol chat-card-button'>
|
||||
Entraîner au sol
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
35
templates/chat-empoignade-immobilise.html
Normal file
35
templates/chat-empoignade-immobilise.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attacker.name}} a empoigné {{defender.name}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
<span class='chat-card-button-area'>
|
||||
<p>
|
||||
{{attacker.name}} a obtenu 2 points d'Emp à la fin du round précédent, et peut:
|
||||
|
||||
<ul><li>
|
||||
faire perdre des points d'Endurance à {{defender.name}}
|
||||
<br>
|
||||
<a class='empoignade-perte-endurance chat-card-button'>
|
||||
<select class='empoignade-perte-endurance'>
|
||||
<option value="none">Faire perdre de l'endurance (selectionnez)</option>
|
||||
<option value="end0">Endurance à 0</option>
|
||||
<option value="end1">Endurance à 1</option>
|
||||
<option value="endmoitie">La moitié de l'endurance</option>
|
||||
<option value="endquart">Le quart de l'endurance</option>
|
||||
</select>
|
||||
</a>
|
||||
{{#if empoignade.system.ausol}}
|
||||
{{else}}
|
||||
</li><li>
|
||||
projeter {{defender.name}} au sol. Les deux protagonistes ne sont plus empoignés.
|
||||
<br>
|
||||
<a class='empoignade-projeter-sol chat-card-button'>
|
||||
Projeter au sol
|
||||
</a>
|
||||
{{/if}}
|
||||
</li></ul>
|
||||
</p>
|
||||
</span>
|
||||
</div>
|
@@ -1,7 +1,8 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} a fait perdre de l'endurance à {{defenderName}}, qui reste immobilisé. L'empoignade peut continuer.
|
||||
{{attacker.name}} a fait perdre de l'endurance à {{defender.name}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
{{defender.name}} reste immobilisé. L'empoignade peut continuer.
|
||||
</div>
|
||||
|
@@ -1,7 +1,8 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} a projeté {{defenderName}} au sol. L'empoignade est terminée et a été supprimée.
|
||||
{{attacker.name}} a projeté {{defender.name}} au sol
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
L'empoignade est terminée et a été supprimée.
|
||||
</div>
|
||||
|
@@ -1,16 +1,17 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{log 'rollData' this}}
|
||||
{{#if (eq mode "empoigner")}}
|
||||
{{attackerName}} tente d'empoigner {{defenderName}}
|
||||
{{attacker.name}} tente d'empoigner {{defender.name}}
|
||||
{{/if}}
|
||||
{{#if (eq mode "contrer-empoigner")}}
|
||||
{{defenderName}} tente de contrer l'empoignade de {{attackerName}}
|
||||
{{defender.name}} tente de contrer l'empoignade de {{attacker.name}}
|
||||
{{/if}}
|
||||
{{#if (eq mode "liberer")}}
|
||||
{{attackerName}} tente de se libérer de l'empoignade de {{defenderName}}
|
||||
{{attacker.name}} tente de se libérer de l'empoignade de {{defender.name}}
|
||||
{{/if}}
|
||||
{{#if (eq mode "contrer-liberer")}}
|
||||
{{defenderName}} tente de contrer la libération de {{attackerName}}
|
||||
{{defender.name}} tente de contrer la libération de {{attacker.name}}
|
||||
{{/if}}
|
||||
</h4>
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
|
||||
@@ -20,7 +21,7 @@
|
||||
|
||||
{{#if (gte empoignade.system.pointsemp 2)}}
|
||||
|
||||
<br><strong>{{defenderName}} est empoigné et immobilisé par {{attackerName}} !</strong>
|
||||
<br><strong>{{defender.name}} est empoigné et immobilisé par {{attacker.name}} !</strong>
|
||||
|
||||
{{else}}
|
||||
<span class='chat-card-button-area'>
|
||||
@@ -29,16 +30,12 @@
|
||||
{{#if (eq mode "empoigner")}}
|
||||
{{#if empoignade.isSuccess}}
|
||||
<a class='defense-empoignade-cac chat-card-button'
|
||||
data-attackerId='{{attacker.id}}'
|
||||
data-defenderId='{{defender.id}}'
|
||||
data-diff-libre='{{diffLibre}}'
|
||||
data-defense-mode="contrer-empoigner">
|
||||
Contrer l'empoignade (Corps à Corps)
|
||||
</a>
|
||||
{{#if (eq empoignade.system.pointsemp 0)}}
|
||||
<a class='defense-empoignade-esquive chat-card-button'
|
||||
data-attackerId='{{attacker.id}}'
|
||||
data-defenderId='{{defender.id}}'
|
||||
data-diff-libre='{{diffLibre}}'
|
||||
data-defense-mode="contrer-empoigner">
|
||||
Contrer l'empoignade (Esquive)
|
||||
@@ -52,8 +49,6 @@
|
||||
{{#if (eq mode "liberer")}}
|
||||
{{#if empoignade.isSuccess}}
|
||||
<a class='defense-empoignade-cac chat-card-button'
|
||||
data-attackerId='{{attacker.id}}'
|
||||
data-defenderId='{{defender.id}}'
|
||||
data-diff-libre='{{diffLibre}}'
|
||||
data-defense-mode="contrer-liberer">
|
||||
Contrer la libération (Corps à Corps)
|
||||
@@ -78,8 +73,7 @@
|
||||
La tentative de contrer la libération est un échec!
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
<br>Points d'Emp: {{empoignade.system.pointsemp}}
|
||||
|
||||
</span>
|
||||
<br>Points d'Emp: {{empoignade.system.pointsemp}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
@@ -1,10 +1,9 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attackerName}} tente d'empoigner {{defenderName}}
|
||||
{{attacker.name}} tente d'empoigner {{defender.name}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
|
||||
<span class='chat-card-button-area'>
|
||||
<br>
|
||||
<strong>{{attacker.name}} tente d'empoigner {{defender.name}}, qui est équipé d'une arme de mêlée. {{defender.name}}
|
||||
@@ -16,5 +15,5 @@
|
||||
data-defenderId='{{defender.id}}'>
|
||||
Poursuivre l'empoignade
|
||||
</a>
|
||||
|
||||
</span>
|
||||
</div>
|
@@ -1,6 +1,6 @@
|
||||
<form class="skill-roll-dialog">
|
||||
<h2>
|
||||
{{defenderName}} tente de contrer l'empoignade de {{attackerName}}
|
||||
{{defender.name}} tente de contrer l'empoignade de {{attacker.name}}
|
||||
</h2>
|
||||
<div class="grid grid-2col">
|
||||
<div class="flex-group-left">
|
||||
|
Reference in New Issue
Block a user