Compare commits

..

9 Commits

Author SHA1 Message Date
d1b1b2a341 Portrait dans les feuilles simplifiées 2024-10-26 23:10:45 +02:00
e05753fc0b Fix: niveau de compétence non défini
- quand le niveau de compétence n'était pas défini, la feuille de
personnage simplifiée et l'export scriptarium ne marchaient pas
- on pouvait saisitr une compétence avec un niveau non défini
2024-10-26 23:08:13 +02:00
3de6179e9b Move to v12.0.17 2024-10-26 23:08:13 +02:00
a7e7eec261 Utilisation du nom du Nom du token
suite (pour les encaissements)
2024-10-26 01:53:38 +02:00
5c78ecb64e Localisation des blessures en regle optionnelle 2024-10-26 01:33:20 +02:00
c150dee6de Amélioration message encaissement 2024-10-26 01:20:03 +02:00
c8afb6e98a Afficher le nom du token au lieu du nom d'Acteur
Dans les messages d'automatisation de combat, le nom des
tokens est utilisé au lieu d'utiliser le nom de l'acteur.

Ceci permet de ne pas dévoiler un nom générique (Villageois)
si le token a un nom personnalisé.
2024-10-26 00:10:47 +02:00
2429f5b20a Version 12.0.16 2024-10-23 23:51:19 +02:00
4eabb58a89 Fix: Message uniquement MJ
L'utilisation de firstConnectedGM renvoie le GM, pas true si
un GM est connecté.
2024-10-23 23:44:49 +02:00
32 changed files with 330 additions and 9098 deletions

View File

@@ -1,25 +1,6 @@
# 12.0
## 12.0.19 - La témérité d'Astrobazzarh
- Fix
- les défenses des créatures sont correctement filtrées
- le lancer d'initiative pour tous les personnages/PNJs fonctionne correctement
- les lieux et commerces n'ont pas d'initiative
## 12.0.18 - A la barbe d'Astrobazzarh
- Améliorations sur la feuille de PNJ simplifiée
- Ajout du portrait
- Ajout du corps à corps
- Affichage du niveau d'esquive
- Un clic sur l'initiative permet de lancer l'initiative
- les boutons +/- pour la vie, l'endurance et la fatigue changent si on est à la valeur normale
- un clic sur l'endurance effectue un jet d'endurance
- Fix
- les achats des commerces sont de nouveau possibles
- la commande /astro fonctionne de nouveau
- le nombre d'utilisations d'items est réinitialisé à chaque round et fin de combat
- la difficulté de parade pour les armes à distances n'est plus indiquée
- les propositions d'armes de parade sont corrigées
- Ajout d'un indicateur pour les armes de parade nécessitant une significative
- Ajout du portrait sur les feuilles simplifiées
## 12.0.16 - Le secret d'Astrobazzarh
- Fix: les jets envoyés messages uniquement au MJ ne sont plus envoyés à tous les autres joueurs (et dupliqués)

View File

@@ -224,7 +224,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
this.html.find('.roll-arme').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)), 'competence'))
// Initiative pour l'arme
this.html.find('.roll-init-arme').click(async event => {
this.html.find('.arme-initiative a').click(async event => {
let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id)
if (combatant) {
RdDCombatManager.rollInitiativeAction(combatant._id, this._getEventArmeCombat(event));

View File

@@ -36,8 +36,6 @@ import { ITEM_TYPES } from "./item.js";
import { RdDBaseActorSang } from "./actor/base-actor-sang.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js";
import { RdDItemArme } from "./item-arme.js";
import { RdDCombatManager } from "./rdd-combat.js";
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
@@ -132,23 +130,6 @@ export class RdDActor extends RdDBaseActorSang {
.reduce(Misc.sum(), 0);
}
listActionsCombat() {
// Recupération des armes
const actions = RdDCombatManager.listActionsArmes(
this.itemTypes[ITEM_TYPES.arme]
.filter(it => RdDItemArme.isAttaque(it))
.concat(RdDItemArme.empoignade(this))
.concat(RdDItemArme.mainsNues(this))
,
this.itemTypes[ITEM_TYPES.competence],
this.system.carac)
if (this.system.attributs.hautrevant.value) {
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
}
return actions
}
/* -------------------------------------------- */
getTache(id) { return this.findItemLike(id, 'tache') }
getMeditation(id) { return this.findItemLike(id, 'meditation') }
@@ -1567,7 +1548,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') {
if (!Misc.isFirstConnectedGM()) {
if (!Misc.isFirstConnectedGM()){
return
}
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
@@ -2634,7 +2615,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async resetItemUse() {
await this.unsetFlag(SYSTEM_RDD, 'itemUse');
await this.setFlag(SYSTEM_RDD, 'itemUse', {});
}
/* -------------------------------------------- */
@@ -3086,7 +3067,7 @@ export class RdDActor extends RdDBaseActorSang {
incarnation.name = 'Réincarnation de ' + incarnation.name
incarnation.system = {
carac: foundry.utils.duplicate(this.system.carac),
heure: RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key,
heure: RdDTimestamp.defHeure(await RdDDice.rollHeure( { rollMode: "selfroll", showDice: SHOW_DICE })).key,
age: 18,
biographie: '',
notes: '',

View File

@@ -15,7 +15,7 @@ import { StatusEffects } from "../settings/status-effects.js";
import { ITEM_TYPES } from "../item.js";
import { Targets } from "../targets.js";
import { RdDPossession } from "../rdd-possession.js";
import { RdDCombat, RdDCombatManager } from "../rdd-combat.js";
import { RdDCombat } from "../rdd-combat.js";
import { RdDConfirm } from "../rdd-confirm.js";
import { ENTITE_INCARNE, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
import { RdDItemArme } from "../item-arme.js";
@@ -78,27 +78,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
async jetEndurance(resteEndurance = undefined) { return { jetEndurance: 0, sonne: false } }
isDead() { return false }
isSonne() { return false }
blessuresASoigner() { return [] }
getEtatGeneral(options = { ethylisme: false }) { return 0 }
isActorCombat() { return true }
getCaracInit(competence) {
if (!competence){
return 0
}
if (competence.type == ITEM_TYPES.competencecreature) {
return competence.system.carac_value
}
return this.system.carac[competence.system.defaut_carac].value;
}
listActionsCombat() {
return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => RdDItemCompetenceCreature.isAttaque(it))
.map(it => RdDItemCompetenceCreature.armeCreature(it))
.filter(it => it != undefined);
}
async computeArmure(attackerRoll) { return this.getProtectionNaturelle() }
async remiseANeuf() { }
@@ -172,6 +153,9 @@ export class RdDBaseActorReve extends RdDBaseActor {
getPossession(possessionId) {
return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
}
getPossessions() {
return this.itemTypes[ITEM_TYPES.possession];
}
getEmpoignades() {
return this.itemTypes[ITEM_TYPES.empoignade];
}
@@ -384,7 +368,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
rollArme(arme, categorieArme, token) {
token = token ?? RdDUtility.getSelectedToken(this)
const compToUse = this.$getCompetenceArme(arme, categorieArme)
if (!RdDItemArme.isUtilisable(arme)) {
if (!RdDItemArme.isArmeUtilisable(arme)) {
ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`)
return
}
@@ -421,7 +405,12 @@ export class RdDBaseActorReve extends RdDBaseActor {
return RdDItemArme.getCompetenceArme(arme, competenceName)
}
verifierForceMin(item) { }
verifierForceMin(item) {
}
/* -------------------------------------------- */
async resetItemUse() { }
async incDecItemUse(itemId, inc = 1) { }
getItemUse(itemId) { return 0; }
/* -------------------------------------------- */
async encaisser() { await RdDEncaisser.encaisser(this) }
@@ -466,7 +455,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
alias: defenderToken?.name ?? this.name,
hasPlayerOwner: this.hasPlayerOwner,
show: show ?? {}
}, { overwrite: false });
}, {overwrite: false});
await ChatUtility.createChatWithRollMode(
{

View File

@@ -276,11 +276,11 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
ui.notifications.info(`${this.name} est hors combat, il ne reste donc pas sonné`);
return;
}
await this.setEffect(STATUSES.StatusStunned, sonne)
await this.setEffect(STATUSES.StatusStunned, sonne);
}
isSonne() {
return this.getEffect(STATUSES.StatusStunned)
getSonne() {
return this.getEffect(STATUSES.StatusStunned);
}
isEffectAllowed(effectId) { return true }

View File

@@ -205,8 +205,11 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) { }
async onCreateItem(item, options, id) { }
async onDeleteItem(item, options, id) { }
async onUpdateActor(update, options, actorId) { }
async onTimeChanging(oldTimestamp, newTimestamp) {
@@ -314,7 +317,7 @@ export class RdDBaseActor extends Actor {
RdDAudio.PlayContextAudio("argent"); // Petit son
ChatMessage.create({
whisper: ChatUtility.getOwners(this),
whisper: ChatUtility.getOwners(this.name),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
});
}
@@ -705,24 +708,5 @@ export class RdDBaseActor extends Actor {
}
return undefined
}
async resetItemUse() { }
async incDecItemUse(itemId, inc = 1) { }
getItemUse(itemId) { return 0; }
async finDeRound(options = { terminer: false }) { }
isActorCombat() { return false }
getCaracInit(competence) { return 0 }
listActionsCombat() { return [] }
listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession]
.map(p => {
return {
name: p.name,
action: 'possession',
system: {
competence: p.name,
possessionid: p.system.possessionid,
}
}
})
}
}

View File

@@ -84,7 +84,7 @@ const MAPPING_BASE = [
{ column: "malus_armure", getter: (actor, context) => Mapping.getMalusArmure(actor, context) },
{ column: "reve_actuel", rollClass: 'roll-reve-actuel', colName: 'Rêve actuel', getter: (actor, context) => actor.system.reve.reve.value },
{ column: "vie_actuel", rollClass: 'jet-vie', getter: (actor, context) => actor.system.sante.vie.value },
{ column: "endurance_actuel", rollClass: 'jet-endurance', getter: (actor, context) => actor.system.sante.endurance.value },
{ column: "endurance_actuel", rollClass: 'jet-vie', getter: (actor, context) => actor.system.sante.endurance.value },
{ column: "esquive", getter: (actor, context) => Mapping.getEsquive(context) },
{ column: "esquive_armure", getter: (actor, context) => Mapping.getEsquiveArmure(context) },
{ column: "competences", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_COMPETENCES) },
@@ -140,52 +140,45 @@ export class Mapping {
static prepareArmes(actor) {
const armes = actor.items.filter(it => it.type == ITEM_TYPES.arme)
RdDItemArme.ajoutCorpsACorps(armes, actor)
return armes.map(arme => [
arme.system.unemain ? Mapping.prepareArme(actor, arme, 'unemain') : undefined,
arme.system.deuxmains ? Mapping.prepareArme(actor, arme, 'deuxmains') : undefined,
!(arme.system.unemain || arme.system.deuxmains) ? Mapping.prepareArme(actor, arme, 'competence') : undefined,
arme.system.lancer != "" ? Mapping.prepareArme(actor, arme, 'lancer') : undefined,
arme.system.tir != "" ? Mapping.prepareArme(actor, arme, 'tir') : undefined]
.filter(it => it != undefined))
.reduce((a, b) => a.concat(b), [])
return armes.map(arme =>
[
arme.system.unemain ? Mapping.prepareArme(actor, arme, 'unemain') : undefined,
arme.system.deuxmains ? Mapping.prepareArme(actor, arme, 'deuxmains') : undefined,
!(arme.system.unemain || arme.system.deuxmains) ? Mapping.prepareArme(actor, arme, 'competence') : undefined,
arme.system.lancer != "" ? Mapping.prepareArme(actor, arme, 'lancer') : undefined,
arme.system.tir != "" ? Mapping.prepareArme(actor, arme, 'tir') : undefined
]
.filter(it => it != undefined)
).reduce((a, b) => a.concat(b), [])
}
static prepareArme(actor, arme, maniement) {
const nameCompetenceArme = RdDItemArme.getCompetenceArme(arme, maniement)
const competence = actor.getCompetence(nameCompetenceArme)
const nameCompArme = RdDItemArme.getCompetenceArme(arme, maniement)
const competence = actor.getCompetence(nameCompArme)
if (RdDItemCompetence.isNiveauBase(competence)) {
return undefined
}
const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
const dommages = dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme)
const categorie = Mapping.complementCategorie(arme, maniement)
const dommages = Mapping.dommagesArme(actor, arme, maniement)
return {
name: arme.name + categorie,
niveau: Misc.toSignedString(competence.system.niveau),
init: Mapping.calculBaseInit(actor, competence.system.categorie) + competence.system.niveau,
dommages: dommages,
dommages: Misc.toSignedString(dommages),
competence: competence,
arme: arme
}
}
static dommagesArme(actor, arme, maniement){
const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme))
switch(arme.system.mortalite) {
case 'non-mortel': return `(${dommages})`
case 'empoignade': return '-'
}
return dommages
}
static complementCategorie(arme, maniement) {
switch (maniement) {
case 'unemain': return (arme.system.deuxmains) ? ' 1 main' : (arme.system.lancer || arme.system.tir) ? ' mêlée' : ''
case 'deuxmains': return (arme.system.unemain) ? ' 2 mains' : (arme.system.lancer || arme.system.tir) ? ' mêlée' : ''
case 'unemain': return (arme.system.deuxmains) ? ' 1 main' : (arme.system.lancer||arme.system.tir) ? ' mêlée': ''
case 'deuxmains': return (arme.system.unemain) ? ' 2 mains' : (arme.system.lancer||arme.system.tir) ? ' mêlée': ''
case 'lancer': return (arme.system.unemain || arme.system.deuxmains || arme.system.tir) ? ' jet' : ''
case 'tir': return (arme.system.unemain || arme.system.deuxmains || arme.system.lancer) ? ' tir' : ''
}
return ''
return ''
}
static calculBaseInit(actor, categorie) {

View File

@@ -1,433 +0,0 @@
/************************************************************************************/
import "./xregexp-all.js";
import { SystemCompendiums } from "../settings/system-compendiums.js";
import { RdDBaseActorReve } from "../actor/base-actor-reve.js";
/************************************************************************************/
// Some internal test strings
let statBlock01 = `+$16(/, baron de Sylvedire, né à lheure du
Roseau, 40 ans, 1m78, 65 kg, Beauté 13.
TAILLE
10
Mêlée
14
APPARENCE
13
Tir
11
CONSTITUTION
12
Lancer
11
FORCE
12
Dérobée
13
AGILITÉ
16
Vie
11
DEXTÉRITÉ
13
Endurance
25
VUE
10
+dom
0
OUÏE
11
Protection
2 ou 4
ODO-GOÛT
9
cuir souple
VOLONTÉ
14
ou cuir / métal
INTELLECT
9
EMPATHIE
11
RÊVE
13
CHANCE
10
niv
init
+dom
Épée dragonne
+5
12
+3
Hache de bataille
+6
13
+3
Bouclier moyen
+5
Dague mêlée
+4
11
+1
Corps à corps
+4
11
(0)
Esquive
+8
Escalade +4 / Saut +5 / Commerce +3 / Équitation
+6 / Chirurgie 0 / Survie en extérieur +4 / Survie fo-
rêt +6 / Acrobatie -2 / Métallurgie +2 / Natation +3 /
Légendes -1 / Écriture -4
`;
let statBlock02 = `/HVJDUGHV
TAILLE
11
Mêlée
12
CONSTITUTION
11
Tir
11
FORCE
12
Lancer
11
AGILITÉ
12
Dérobée
11
DEXTERITÉ
11
Vie
11
VUE
11
Endurance
22
OUÏE
11
Vitesse
12
VOLONTÉ
10
+dom
0
Protection
4
cuir / métal
niv
init
+dom
Hache de bataille
+4
10
+3
Bouclier moyen
+4
Dague mêlée
+3
9
+1
Arc
+5
10
+2
Corps à corps
+3
9
(0)
Esquive avec armure
+2
Course +1/ Vigilance +4
`;
let statBlock03 = `rencontres sont laissées à /HVFKLHQVORXSVGXEDURQ
chaque gardien des rêves.
TAILLE
8
Vie
10
CONSTITUTION FORCE
12
11
Endurance
Vitesse
12/38
21
/HVFKLHQV]RPELV
PERCEPTION 13
+dom
0
VOLONTÉ
10
Protection
0
Les « monstres » apparaîtront un soir, durant
RÊVE
10
lheure du Serpent, et attaqueront les voya-
niv
init
+dom
geurs à leur campement. Si ces derniers ne
Morsure
13
+4
10
+1
campent pas, ils apparaîtront tout de même à
Esquive
11
+3
lheure du Serpent. Le feu ne les effraie pas. Ils
Course, Saut
12
+3
ne sont pas très rapides, mais en revanche, très
Discrétion
12
+3
silencieux : ils naboient pas. Les voyageurs
Vigilance
13
+3
`
// Skill parser depending on the type of actor
const compParser = { personnage: "\\s+(?<value>[\\+\\-]?\\d+)", creature: "\\s+(?<carac>\\d+)\\s+(?<value>[\\+\\-]?\\d+)\\s?(?<init>\\d+)?\\s+?(?<dommages>\\+\\d+)?" };
// Main class for parsing a stat block
export class RdDStatBlockParser {
static openInputDialog() {
let dialog = new Dialog({
title: "Import de stats de PNJ/Créatures",
content: `
<div>
<p>Coller le texte de la stat ici</p>
<textarea id="statBlock" style="width: 100%; height: 200px;"></textarea>
</div>
`,
buttons: {
ok: {
label: "OK",
callback: async (html) => {
let statBlock = html.find("#statBlock")[0].value;
await RdDStatBlockParser.parseStatBlock(statBlock);
dialog.close();
}
},
cancel: {
label: "Cancel"
}
}
});
dialog.render(true);
}
static fixWeirdPDF(statString) {
// Split the statString into lines
let lines = statString.split("\n");
let newLines = [];
let index = 0;
let nextType = "string";
// Loop through each line
for (let i = 0; i < lines.length; i++) {
// remove trailing spaces
lines[i] = lines[i].trim();
// Is it text ?
if (lines[i].match(/^[a-zA-Zéêè\s]+/)) {
if ( nextType == "string" ) {
newLines[index] = lines[i];
nextType = "number";
} else {
console.log("Wrong sequence string detected...", lines[i], nextType);
}
}
// Is it a number ?
if (lines[i].match(/^[\d\s]+/)) {
if ( nextType == "number" ) {
newLines[index] = newLines[index] + lines[i];
nextType = "string";
index++;
} else {
console.log("Wrong sequence number detected...", lines[i], nextType);
}
}
}
}
static async parseStatBlock(statString, type = "npc") {
//statString = statBlock03;
if (!statString) {
return;
}
// Special function to fix strange/weird copy/paste from PDF readers
// Unused up to now : this.fixWeirdPDF(statString);
// Replace all endline by space in the statString
statString = statString.replace(/\n/g, " ");
// Remove all multiple spaces
statString = statString.replace(/\s{2,}/g, " ");
// Remove all leading and trailing spaces
statString = statString.trim();
let actorType = "personnage";
let perception = XRegExp.exec(statString.toLowerCase(), XRegExp("perception\\s+(?<value>\\d+)", 'gi'));
if (perception?.value ) {
actorType = "creature";
}
// Now start carac
let actorData = foundry.utils.deepClone(game.model.Actor[actorType]);
for (let key in game.model.Actor.personnage.carac) {
let caracDef = game.model.Actor.personnage.carac[key];
// Parse the stat string for each caracteristic
let carac = XRegExp.exec(statString.toLowerCase(), XRegExp(caracDef.label.toLowerCase()+"\\s+(?<value>\\d+)", 'gi'));
if (carac?.value) {
actorData.carac[key].value = Number(carac.value);
}
}
// If creature we need to setup additionnal fields
if (actorType == "creature") {
let plusDom = XRegExp.exec(statString.toLowerCase(), XRegExp("\\+dom\\s+(?<value>\\+\\d+)", 'gi'));
if (plusDom?.values) {
actorData.attributs.plusdom.value = Number(plusDom.value);
}
let protection = XRegExp.exec(statString.toLowerCase(), XRegExp("protection\\s+(?<value>\\d+)", 'gi'));
if (protection?.value) {
actorData.attributs.protection.value = Number(protection.value);
}
let endurance = XRegExp.exec(statString.toLowerCase(), XRegExp("endurance\\s+(?<value>\\d+)", 'gi'));
if (endurance?.value) {
actorData.sante.endurance.value = Number(endurance.value);
actorData.sante.endurance.max = Number(endurance.value);
}
let vie = XRegExp.exec(statString.toLowerCase(), XRegExp("vie\\s+(?<value>\\d+)", 'gi'));
if (vie.value) {
actorData.sante.vie.value = Number(vie.value);
actorData.sante.vie.max = Number(vie.value);
}
let vitesse = XRegExp.exec(statString.toLowerCase(), XRegExp("vitesse\\s+(?<value>[\\d\\/]+)", 'gi'));
if (vitesse?.value) {
actorData.attributs.vitesse.value = vitesse.value;
}
}
let items = [];
// Get skills from compendium
const competences = await SystemCompendiums.getCompetences(actorType);
//console.log("Competences : ", competences);
let allComp = competences.map(i => i.toObject())
for (let comp of allComp) {
let skill = XRegExp.exec(statString.toLowerCase(), XRegExp(comp.name.toLowerCase()+compParser[actorType], 'gi'));
if (skill) {
comp.system.niveau = Number(skill.value);
if (actorType == "creature") {
comp.system.carac_value = Number(skill.carac);
if (skill.init) {
comp.system.dommages = Number(skill.dommages);
comp.system.iscombat = true;
}
items.push(comp); // Only selective push
}
}
if (actorType == "personnage") {
items.push(comp); // Always push
}
}
// Now process weapons
const weapons = await SystemCompendiums.getWorldOrCompendiumItems("arme", "equipement")
//console.log("Equipement : ", equipment);
for (let w of weapons) {
let weapon = XRegExp.exec(statString.toLowerCase(), XRegExp(w.name.toLowerCase()+"\\s+(?<value>\\+\\d+)", 'gi'));
if (weapon) {
w.system.equipe = true
items.push(w.toObject());
// now process the skill
if ( w.system?.competence != "") {
let wComp = items.find(i => i.name.toLowerCase() == w.system.competence.toLowerCase());
if (wComp) {
wComp.system.niveau = Number(weapon.value);
}
}
if ( w.system?.tir != "") {
let wComp = items.find(i => i.name.toLowerCase() == w.system.tir.toLowerCase());
if (wComp) {
wComp.system.niveau = Number(weapon.value);
}
}
if ( w.system?.lancer != "") {
let wComp = items.find(i => i.name.toLowerCase() == w.system.lancer.toLowerCase());
if (wComp) {
wComp.system.niveau = Number(weapon.value);
}
}
}
}
// Now process armors
const armors = await SystemCompendiums.getWorldOrCompendiumItems("armure", "equipement")
for (let a of armors) {
let armor = XRegExp.exec(statString.toLowerCase(), XRegExp(a.name.toLowerCase(), 'gi'));
if (armor) {
a.system.equipe = true
items.push(a.toObject());
}
}
// Get hour name : heure du XXXXX
let heure = XRegExp.exec(statString.toLowerCase(), XRegExp("heure du\\s+(?<value>\\w+)", 'gi'));
if (heure?.value) {
actorData.heure = heure.value;
}
// Get age
let age = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>\\d+) ans", 'gi'));
if (age?.value) {
actorData.age = Number(age.value);
}
// Get height
let taille = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>\\d+)m\\d+", 'gi'));
if (taille?.value) {
actorData.taille = taille.value;
}
// Get weight
let poids = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>\\d+) kg", 'gi'));
if (poids?.value) {
actorData.poids = poids.value;
}
// Get beauty
let beaute = XRegExp.exec(statString.toLowerCase(), XRegExp("beauté\\s+(?<value>\\d+)", 'gi'));
if (beaute?.value) {
actorData.beaute = Number(beaute.value);
}
// Name is all string before ', né'
let name
if (actorType == "personnage") {
name = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>[\\w\\s\\d]+),", 'gi'));
if (!name?.value) {
name = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>.+)\\s+taille", 'gi'));
}
name = name?.value || "Importé";
}
if (actorType == "creature") {
name = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>.+)\\s+taille", 'gi'));
name = name?.value || "Importé";
}
let newActor = RdDBaseActorReve.create({name: name || "Importé", type:actorType, system: actorData, items: items});
// DUmp....
console.log(actorData);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -81,59 +81,37 @@ export class RdDItemArme extends Item {
/* -------------------------------------------- */
static getCategorieParade(armeData) {
if (armeData.system.categorie_parade) {
return armeData.system.categorie_parade
return armeData.system.categorie_parade;
}
// pour compatibilité avec des personnages existants
if (armeData.type == ITEM_TYPES.competencecreature || armeData.system.categorie == 'creature') {
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '')
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
}
if (!armeData.type.match(/arme|competencecreature/)) {
return ''
return '';
}
if (armeData.system.competence == undefined) {
return ITEM_TYPES.competencecreature;
}
let compname = armeData.system.competence.toLowerCase();
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) {
return ''
}
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
if (compname.match('hache')) return 'haches'
if (compname.match('hast')) return 'hast'
if (compname.match('lance')) return 'lances'
if (compname.match('bouclier')) return 'boucliers'
if (compname.match('masse')) return 'masses'
if (compname.match('hache')) return 'haches';
if (compname.match('hast')) return 'hast';
if (compname.match('lance')) return 'lances';
if (compname.match('bouclier')) return 'boucliers';
if (compname.match('masse')) return 'masses';
if (compname.match('epée') || compname.match('épée')) {
if (armeData.name.toLowerCase().match(/(gnome)/))
return 'epees-courtes'
return 'epees-courtes';
if (armeData.name.toLowerCase().match(/((e|é)pée dragone|esparlongue|demi-dragonne)/))
return 'epees-longues'
return 'epees-lourdes'
return 'epees-longues';
return 'epees-lourdes';
}
if (compname.match('dague')) {
return 'dagues'
}
return 'sans-armes'
}
static defenseArmeParade(armeAttaque, armeParade) {
const defCategory = RdDItemArme.getCategorieParade(armeParade)
if (defCategory == 'bouclier') {
return 'norm'
}
if (armeAttaque.system.competence.toLowerCase().match(/(fléau)/)) {
return ''
}
if (armeParade.system.tir) {
return ''
}
const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
switch (attCategory) {
case 'armes-naturelles': case 'sans-armes':
return defCategory == 'sans-armes' ? 'norm' : ''
default:
return RdDItemArme.needParadeSignificative(armeAttaque, armeParade) ? 'sign' : 'norm'
return 'dagues';
}
return 'sans-armes';
}
/* -------------------------------------------- */
@@ -142,8 +120,8 @@ export class RdDItemArme extends Item {
return false;
}
// categories d'armes à la parade (cf. page 115 )
const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
const defCategory = RdDItemArme.getCategorieParade(armeParade)
let attCategory = RdDItemArme.getCategorieParade(armeAttaque);
let defCategory = RdDItemArme.getCategorieParade(armeParade);
// bouclier et mêmes catégorie: peuvent se parer sans difficulté
if (defCategory == 'boucliers') {
return false;
@@ -206,7 +184,7 @@ export class RdDItemArme extends Item {
return arme.system.competence.replace(" 1 main", " 2 mains");
}
static isUtilisable(arme) {
static isArmeUtilisable(arme) {
switch (arme.type) {
case ITEM_TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
case ITEM_TYPES.competencecreature: return true
@@ -214,26 +192,6 @@ export class RdDItemArme extends Item {
return false
}
static isAttaque(arme) {
switch (arme.type) {
case ITEM_TYPES.arme:
return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
case ITEM_TYPES.competencecreature:
return arme.system.iscombat && RdDItemCompetenceCreature.isAttaque(item)
}
return false
}
static isParade(arme) {
switch (arme.type) {
case ITEM_TYPES.arme:
return arme.system.equipe && arme.system.resistance > 0 && true/* TODO: regarder la categorie d'arme?*/
case ITEM_TYPES.competencecreature:
return arme.system.iscombat && RdDItemCompetenceCreature.isParade(arme)
}
return false
}
static ajoutCorpsACorps(armes, actor) {
armes.push(RdDItemArme.mainsNues(actor));
armes.push(RdDItemArme.empoignade(actor));

View File

@@ -27,28 +27,29 @@ export class RdDItemCompetenceCreature extends Item {
static armeCreature(item) {
const categorieAttaque = RdDItemCompetenceCreature.getCategorieAttaque(item)
if (categorieAttaque != undefined) {
// cloner pour ne pas modifier la compétence
return foundry.utils.mergeObject(item, {
// si c'est un Item compétence: cloner pour ne pas modifier la compétence
let arme = item.clone();
return foundry.utils.mergeObject(arme, {
action: item.isCompetencePossession() ? 'possession' : 'attaque',
system: {
competence: item.name,
competence: arme.name,
cac: categorieAttaque == "naturelle" ? "naturelle" : "",
niveau: item.system.niveau,
initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value),
equipe: true,
resistance: 100,
dommagesReels: item.system.dommages,
dommagesReels: arme.system.dommages,
penetration: 0,
force: 0,
rapide: true,
}
}, { inplace: false, });
}, { inplace: false });
}
return undefined;
}
/* -------------------------------------------- */
static isAttaque(item) {
static isCompetenceAttaque(item) {
if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) {
case "melee":
@@ -59,7 +60,7 @@ export class RdDItemCompetenceCreature extends Item {
return true
}
}
return false
return undefined
}
static getCategorieAttaque(item) {
@@ -76,7 +77,6 @@ export class RdDItemCompetenceCreature extends Item {
}
return undefined
}
static isDommages(item) {
if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) {
@@ -89,7 +89,6 @@ export class RdDItemCompetenceCreature extends Item {
}
return false
}
static isParade(item) {
if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) {
@@ -102,4 +101,8 @@ export class RdDItemCompetenceCreature extends Item {
return false
}
}
/* -------------------------------------------- */
static isCompetenceParade(item) {
return item.type == 'competencecreature' && item.system.categorie_parade !== "";
}
}

View File

@@ -67,7 +67,7 @@ export class RdDItemBlessure extends RdDItem {
}
static async createBlessure(actor, gravite, localisation = '', attackerToken) {
static async createBlessure(actor, gravite, localisation = '', attacker) {
const definition = RdDItemBlessure.getDefinition(gravite)
const blessure = {
name: definition.label,
@@ -77,7 +77,7 @@ export class RdDItemBlessure extends RdDItem {
gravite: gravite,
difficulte: - gravite,
localisation: localisation,
origine: attackerToken?.name ?? ""
origine: attacker?.name ?? ""
}
}
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])

View File

@@ -139,7 +139,7 @@ export class Misc {
}
static join(params, separator = '') {
return (!params || params.length == 0) ? '' : params.reduce(Misc.joining(separator))
return params?.reduce(Misc.joining(separator)) ?? '';
}
static joining(separator = '') {

View File

@@ -42,8 +42,7 @@ export class RdDCombatManager extends Combat {
/* -------------------------------------------- */
Hooks.on("getCombatTrackerEntryContext", (html, options) => { RdDCombatManager.pushInitiativeOptions(html, options); });
Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) });
Hooks.on("preDeleteCombat", (combat, html, id) => { combat.onPreDeleteCombat() })
Hooks.on("deleteCombat", (combat, html, id) => { combat.onDeleteCombat() })
Hooks.on("preDeleteCombat", (combat, html, id) => { combat.onPreDeleteCombat() });
}
/* -------------------------------------------- */
@@ -62,40 +61,20 @@ export class RdDCombatManager extends Combat {
RdDEmpoignade.deleteAllEmpoignades()
}
}
async onDeleteCombat() {
if (Misc.isFirstConnectedGM()) {
if (game.combats.size <= 1) {
game.actors.forEach(actor => actor.resetItemUse())
}
}
}
/* -------------------------------------------- */
async finDeRound(options = { terminer: false }) {
this.combatants.map(it => RdDCombatManager.getActorCombatant(it, { warning: false }))
.filter(it => it != undefined)
.forEach(async actor => {
await actor.finDeRound(options)
await actor.resetItemUse()
})
}
this.turns.forEach(turn => turn.actor.resetItemUse());
static getActorCombatant(combatant, options = { warning: true }) {
if (!combatant.actor) {
if (options.warning) {
for (let combatant of this.combatants) {
if (combatant.actor) {
await combatant.actor.finDeRound(options);
}
else {
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur!`)
}
return undefined
}
else if (!combatant.actor.isActorCombat()) {
if (options.warning) {
ui.notifications.warn(`${combatant.name} ne peut pas combattre!`)
}
return undefined
}
return combatant.actor
}
static calculAjustementInit(actor, arme) {
const efficacite = (arme?.system.magique) ? arme.system.ecaille_efficacite : 0
const etatGeneral = actor.getEtatGeneral() ?? 0
@@ -104,27 +83,57 @@ export class RdDCombatManager extends Combat {
}
/************************************************************************************/
async rollInitiative(ids, messageOptions = {}) {
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, messageOptions)
ids = typeof ids === "string" ? [ids] : ids
ids.forEach(async id =>
await this.rollInitRdD(id, undefined, messageOptions)
)
return this
}
async rollInitiative(ids, formula = undefined, messageOptions = {}) {
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
async rollInitRdD(id, formula, messageOptions = {}) {
const combatant = this.combatants.get(id);
const actor = RdDCombatManager.getActorCombatant(combatant)
if (actor) {
const rollFormula = formula ?? RdDCombatManager.getFirstInitRollFormula(actor)
ids = typeof ids === "string" ? [ids] : ids;
// calculate initiative
for (let cId = 0; cId < ids.length; cId++) {
const combatant = this.combatants.get(ids[cId]);
const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, undefined);
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, ajustement);
if (!formula) {
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
if (competence) {
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, etatGeneral);
}
} else {
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
let compName = "Corps à corps"
if (armeCombat) {
if (armeCombat.system.competence != "") {
compName = armeCombat.system.competence
}
if (armeCombat.system.lancer != "") {
compName = armeCombat.system.lancer
}
if (armeCombat.system.tir != "") {
compName = armeCombat.system.tir
}
}
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
if (competence && competence.system.defaut_carac) {
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
const niveau = competence.system.niveau;
const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, armeCombat)
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, ajustement);
} else {
ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`);
}
}
}
//console.log("Combatat", c);
const roll = combatant.getInitiativeRoll(rollFormula);
if (!roll.total) {
await roll.evaluate();
}
const total = Math.max(roll.total, 0.00);
console.log("Compute init for", rollFormula, roll, total, combatant);
await this.updateEmbeddedDocuments("Combatant", [{ _id: combatant._id || combatant.id, initiative: total }]);
let id = combatant._id || combatant.id;
await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: total }]);
// Send a chat message
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
@@ -136,7 +145,7 @@ export class RdDCombatManager extends Combat {
alias: combatant.token.name,
sound: CONFIG.sounds.dice,
},
flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.info})<br>`
flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})<br>`,
},
messageOptions);
roll.toMessage(messageData, { rollMode, create: true });
@@ -144,20 +153,7 @@ export class RdDCombatManager extends Combat {
RdDCombatManager.processPremierRoundInit();
}
return this;
}
static getFirstInitRollFormula(actor) {
const actions = actor.listActionsCombat()
if (actions.length > 0) {
const action = actions[0]
const init = RdDCombatManager.getInitData(actor, action)
const ajustement = RdDCombatManager.calculAjustementInit(actor, action)
return RdDCombatManager.formuleInitiative(init.offset, init.carac, init.niveau, ajustement);
}
let ajustement = RdDCombatManager.calculAjustementInit(actor, undefined);
return RdDCombatManager.formuleInitiative(2, 10, 0, ajustement);
}
};
static formuleInitiative(rang, carac, niveau, bonusMalus) {
return `${rang} +( (${RdDCombatManager.calculInitiative(niveau, carac, bonusMalus)} )/100)`;
@@ -240,6 +236,58 @@ export class RdDCombatManager extends Combat {
return attaque;
}
static listActionsCreature(competences) {
return competences
.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
.map(it => RdDItemCompetenceCreature.armeCreature(it))
.filter(it => it != undefined);
}
static listActionsPossessions(actor) {
return RdDCombatManager._indexActions(actor.getPossessions().map(p => {
return {
name: p.name,
action: 'possession',
system: {
competence: p.name,
possessionid: p.system.possessionid,
}
}
}));
}
/* -------------------------------------------- */
static listActionsCombat(combatant) {
const actor = combatant.actor;
let actions = RdDCombatManager.listActionsPossessions(actor);
if (actions.length > 0) {
return actions;
}
if (actor.isCreatureEntite()) {
actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']);
} else if (actor.isPersonnage()) {
// Recupération des items 'arme'
const competences = actor.itemTypes['competence'];
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
.concat(RdDItemArme.empoignade(actor))
.concat(RdDItemArme.mainsNues(actor));
actions = RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac);
if (actor.system.attributs.hautrevant.value) {
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
}
}
return RdDCombatManager._indexActions(actions);
}
static _indexActions(actions) {
for (let index = 0; index < actions.length; index++) {
actions[index].index = index;
}
return actions;
}
/* -------------------------------------------- */
static processPremierRoundInit() {
// Check if we have the whole init !
@@ -277,13 +325,13 @@ export class RdDCombatManager extends Combat {
/* -------------------------------------------- */
static pushInitiativeOptions(html, options) {
for (let i = 0; i < options.length; i++) {
let option = options[i]
let option = options[i];
if (option.name == 'COMBAT.CombatantReroll') { // Replace !
option.name = "Sélectionner l'initiative..."
option.condition = true
option.icon = '<i class="far fa-question-circle"></i>'
option.name = "Sélectionner l'initiative...";
option.condition = true;
option.icon = '<i class="far fa-question-circle"></i>';
option.callback = target => {
RdDCombatManager.displayInitiativeMenu(html, target.data('combatant-id'))
RdDCombatManager.displayInitiativeMenu(html, target.data('combatant-id'));
}
}
}
@@ -294,83 +342,96 @@ export class RdDCombatManager extends Combat {
}
/* -------------------------------------------- */
static rollInitiativeAction(combatantId, action) {
const combatant = game.combat.combatants.get(combatantId)
const actor = RdDCombatManager.getActorCombatant(combatant)
if (actor == undefined) { return [] }
const combatant = game.combat.combatants.get(combatantId);
if (combatant.actor == undefined) {
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
return [];
}
let initInfo = "";
let initOffset = 0;
let caracForInit = 0;
let compNiveau = 0;
let compData = { name: "Aucune" };
if (combatant.actor.getSurprise() == "totale") {
initOffset = -1; // To force 0
initInfo = "Surprise Totale"
} else if (combatant.actor.getSurprise() == "demi") {
initOffset = 0;
initInfo = "Demi Surprise"
} else if (action.action == 'possession') {
initOffset = 10;
caracForInit = combatant.actor.getReveActuel();
initInfo = "Possession"
} else if (action.action == 'autre') {
initOffset = 2;
initInfo = "Autre Action"
} else if (action.action == 'haut-reve') {
initOffset = 9;
initInfo = "Draconic"
} else {
compData = RdDItemCompetence.findCompetence(combatant.actor.items, action.system.competence);
compNiveau = compData.system.niveau;
initInfo = action.name + " / " + action.system.competence;
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
caracForInit = compData.system.carac_value;
} else {
caracForInit = combatant.actor.system.carac[compData.system.defaut_carac].value;
}
initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action);
}
// Cas des créatures et entités vs personnages
const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, action)
let rollFormula = RdDCombatManager.formuleInitiative(initOffset, caracForInit, compNiveau, ajustement);
// Garder la trace de l'arme/compétence utilisée pour l'iniative
combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0
const init = RdDCombatManager.getInitData(actor, action)
const ajustement = RdDCombatManager.calculAjustementInit(actor, action)
const rollFormula = RdDCombatManager.formuleInitiative(init.offset, init.carac, init.niveau, ajustement);
game.combat.rollInitRdD(combatantId, rollFormula, init);
game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo });
}
static getInitData(actor, action) {
if (actor.getSurprise() == "totale") { return { offset: -1, info: "Surprise Totale", carac: 0, niveau: 0 } }
if (actor.getSurprise() == "demi") { return { offset: 0, info: "Demi Surprise", carac: 0, niveau: 0 } }
if (action.action == 'autre') { return { offset: 2, info: "Autre Action", carac: 0, niveau: 0 } }
if (action.action == 'possession') { return { offset: 10, info: "Possession", carac: actor.getReveActuel(), niveau: 0 } }
if (action.action == 'haut-reve') { return { offset: 9, info: "Draconic", carac: actor.getReveActuel(), niveau: 0 } }
const comp = RdDItemCompetence.findCompetence(actor.items, action.system.competence);
return {
offset: RdDCombatManager.initOffset(comp?.system.categorie, action),
info: action.name + " / " + action.system.competence,
carac: actor.getCaracInit(comp),
niveau: comp?.system.niveau ?? -8
/* -------------------------------------------- */
static _baseInitOffset(categorie, arme) {
if (categorie == "tir") { // Offset de principe pour les armes de jet
return 8;
}
}
static initOffset(categorie, arme) {
switch (categorie) {
case "tir": return 8
case "lancer": return 7
default:
switch (arme.system.cac) {
case "empoignade": return 3
case "pugilat": return 4
case "naturelle": return 4
default: return 5
}
if (categorie == "lancer") { // Offset de principe pour les armes de jet
return 7;
}
switch (arme.system.cac) {
case "empoignade":
return 3;
case "pugilat":
case "naturelle":
return 4;
}
return 5;
}
/* -------------------------------------------- */
static displayInitiativeMenu(html, combatantId) {
const combatant = game.combat.combatants.get(combatantId)
const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false })
if (actor) {
const actions = RdDCombatManager.listActionsActorCombatant(actor)
// Build the relevant submenu
const menuItems = actions.map(action => {
return {
console.log("Combatant ; ", combatantId);
const combatant = game.combat.combatants.get(combatantId);
if (!(combatant?.actor)) {
ui.notifications.warn(`Le combatant ${combatant.name ?? combatantId} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
return;
}
let actions = RdDCombatManager.listActionsCombat(combatant);
// Build the relevant submenu
if (actions) {
let menuItems = [];
for (let action of actions) {
menuItems.push({
name: action.system.competence,
icon: "<i class='fas fa-dice-d6'></i>",
callback: target => { RdDCombatManager.rollInitiativeAction(combatantId, action) }
}
})
if (menuItems.length > 0) {
new ContextMenu(html, ".directory-list", menuItems).render();
});
}
new ContextMenu(html, ".directory-list", menuItems).render();
}
}
/* -------------------------------------------- */
static listActionsActorCombatant( actor) {
const possessions = actor.listActionsPossessions()
const actions = possessions.length > 0
? possessions
: actor.listActionsCombat()
for (let index = 0; index < actions.length; index++) {
actions[index].index = index
}
return actions
}
}
/* -------------------------------------------- */
@@ -396,8 +457,8 @@ export class RdDCombat {
if (Misc.isFirstConnectedGM()) {
let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId);
if (turn?.actor) {
// TODO Playaudio for player??
RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token);
// TODO Playaudio for player??
}
}
}
@@ -513,15 +574,15 @@ export class RdDCombat {
static $extractAttackerTokenData(attacker, attackerTokenId) {
const token = canvas.tokens.get(attackerTokenId);
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(attackerTokenId, attacker)
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(attackerTokenId, attacker)
}
static $extractDefenderTokenData(defender, defenderTokenId, target) {
if (target) {
return Targets.extractTokenData(target)
}
const token = canvas.tokens.get(defenderTokenId);
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender)
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender)
}
@@ -750,7 +811,7 @@ export class RdDCombat {
dialog.render(true);
}
/* -------------------------------------------- */
_prepareAttaque(competence, arme) {
let rollData = {
@@ -764,7 +825,7 @@ export class RdDCombat {
targetToken: this.defenderToken,
essais: {}
};
if (this.attacker.isCreatureEntite()) {
RdDItemCompetenceCreature.setRollDataCreature(rollData);
}
@@ -857,7 +918,7 @@ export class RdDCombat {
// # utilisation esquive
const corpsACorps = this.defender.getCompetenceCorpsACorps({ onMessage: it => console.info(it, this.defender) });
const esquives = foundry.utils.duplicate(this.defender.getCompetencesEsquive())
esquives.forEach(e => e.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
const paramChatDefense = {
passeArme: attackerRoll.passeArme,
@@ -917,21 +978,20 @@ export class RdDCombat {
}
/* -------------------------------------------- */
_filterArmesParade(defender, competence, armeAttaque) {
let defenses = defender.items.filter(it => RdDItemArme.isParade(it))
defenses = foundry.utils.duplicate(defenses)
defenses.forEach(armeDefense => {
// Ajout du # d'utilisation ce round
armeDefense.nbUsage = defender.getItemUse(armeDefense.id)
armeDefense.typeParade = RdDItemArme.defenseArmeParade(armeAttaque, armeDefense)
})
_filterArmesParade(defender, competence) {
let items = defender.items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it))
items.forEach(item => item.system.nbUsage = defender.getItemUse(item.id)); // Ajout du # d'utilisation ce round
switch (competence.system.categorie) {
case 'tir':
case 'lancer':
return defenses.filter(armeDefense => RdDItemArme.getCategorieParade(armeDefense) == 'boucliers')
return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers')
default:
return defenses.filter(armeDefense => armeDefense.typeParade != '')
// Le fléau ne peut être paré quau bouclier p115
if (competence.name == "Fléau") {
return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers')
}
return items.filter(item => RdDItemArme.getCategorieParade(item));
}
}
@@ -1275,14 +1335,11 @@ export class RdDCombat {
/* -------------------------------------------- */
static async displayActorCombatStatus(combat, actor, token) {
if (!actor?.isActorCombat()) {
return
}
const formData = {
let formData = {
combatId: combat._id,
alias: token.name ?? actor.name,
etatGeneral: actor.getEtatGeneral(),
isSonne: actor.isSonne(),
isSonne: actor.getSonne(),
blessuresStatus: actor.computeResumeBlessure(),
SConst: actor.getSConst(),
actorId: actor.id,
@@ -1299,6 +1356,6 @@ export class RdDCombat {
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData),
whisper: ChatUtility.getOwners(actor),
alias: token.name ?? actor.name
})
});
}
}

View File

@@ -68,7 +68,6 @@ import { OptionsAvancees } from "./settings/options-avancees.js"
import { ExportScriptarium } from "./actor/export-scriptarium/export-scriptarium.js"
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js"
import { RdDActorExportSheet } from "./actor/export-scriptarium/actor-encart-sheet.js"
import { RdDStatBlockParser } from "./apps/rdd-import-stats.js"
/**
* RdD system
@@ -88,7 +87,6 @@ export class SystemReveDeDragon {
this.config = RDD_CONFIG
this.RdDUtility = RdDUtility
this.RdDHotbar = RdDHotbar
this.RdDStatBlockParser = RdDStatBlockParser
this.itemClasses = {
armure: RdDItemArmure,
blessure: RdDItemBlessure,
@@ -274,16 +272,6 @@ export class SystemReveDeDragon {
})
}
static async setupAccueil() {
let exists = game.scenes.find(j => j.name == "Accueil RdD");
if (!exists) {
const scenes = await SystemCompendiums.loadCompendium("foundryvtt-reve-de-dragon.scenes-rdd")
let newDocuments = scenes.filter(i => i.name == "Accueil RdD");
await game.scenes.documentClass.create(newDocuments);
game.scenes.find(i => i.name == "Accueil RdD").activate();
}
}
async onReady() {
/* -------------------------------------------- */
@@ -304,8 +292,6 @@ export class SystemReveDeDragon {
StatusEffects.onReady()
RdDHerbes.onReady()
RdDDice.onReady()
RdDStatBlockParser.parseStatBlock()
/* -------------------------------------------- */
/* Affiche/Init le calendrier */
game.system.rdd.calendrier.display()
@@ -317,8 +303,6 @@ export class SystemReveDeDragon {
user: game.user.id
})
}
SystemReveDeDragon.setupAccueil()
}
/* -------------------------------------------- */

View File

@@ -28,15 +28,16 @@ export class RdDTokenHud {
await RdDTokenHud.addExtensionHudSoins(html, actor);
if (isCombat) {
const combatant = game.combat.combatants.find(c => c.tokenId == tokenId)
const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false })
if (actor) {
let actions = RdDCombatManager.listActionsActorCombatant(actor)
// initiative
await RdDTokenHud.addExtensionHudInit(html, combatant, actions)
// combat
await RdDTokenHud.addExtensionHudCombat(html, combatant, token, actions)
let combatant = game.combat.combatants.find(c => c.tokenId == tokenId);
if (!(combatant?.actor)) {
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
return;
}
let actions = RdDCombatManager.listActionsCombat(combatant);
// initiative
await RdDTokenHud.addExtensionHudInit(html, combatant, actions);
// combat
await RdDTokenHud.addExtensionHudCombat(html, combatant, token, actions);
}

View File

@@ -609,12 +609,12 @@ export class RdDUtility {
const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite);
const over20 = Math.max(jetTotal - 20, 0);
encaissement.dmg = rollData.dmg
if (ReglesOptionnelles.isUsing('localisation-aleatoire')) {
if (ReglesOptionnelles.isUsing('localisation-aleatoire')){
encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(actor.type)
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'
}
else {
encaissement.dmg.loc = { label: '' }
else{
encaissement.dmg.loc = {label:''}
}
encaissement.dmg.bonusDegatsDiffLibre = bonusDegatsDiffLibre
encaissement.roll = roll;
@@ -749,7 +749,7 @@ export class RdDUtility {
static getSelectedToken(actor) {
if (canvas.tokens.controlled.length > 0) {
const tokens = canvas.tokens.controlled
.filter(it => it.actor.id == actor.id)
.filter(it => it.actor.id == actor.id)
return tokens[0]
}
return undefined
@@ -881,10 +881,10 @@ export class RdDUtility {
/* -------------------------------------------- */
static afficherHeuresChanceMalchance(heureNaissance) {
if (game.user.isGM) {
const heure = RdDTimestamp.findHeure(heureNaissance)
const heure = RdDTimestamp.findHeure(heureNaissance - 1);
if (heureNaissance && heure) {
const ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance)
const current = game.system.rdd.calendrier.heureCourante()
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
const current = game.system.rdd.calendrier.heureCourante();
ChatMessage.create({
content: `A l'heure de <strong>${current.label}</strong>, le modificateur de Chance/Malchance est de <strong>${Misc.toSignedString(ajustement)}</strong> pour l'heure de naissance <strong>${heure.label}</strong>.`,
whisper: ChatUtility.getGMs()

View File

@@ -112,19 +112,6 @@ export class SystemCompendiums extends FormApplication {
return elements;
}
/* -------------------------------------------- */
static async loadCompendiumData(compendium) {
const pack = game.packs.get(compendium);
return await pack?.getDocuments() ?? [];
}
/* -------------------------------------------- */
static async loadCompendium(compendium, filter = item => true) {
let compendiumData = await SystemCompendiums.loadCompendiumData(compendium);
return compendiumData.filter(filter);
}
static async getDefaultItems(compendium) {
const pack = game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
if (pack.metadata.type == 'Item') {

View File

@@ -15,7 +15,7 @@ export class AutoAdjustDarkness {
}
static async adjust(darkness) {
if (game.user.isGM && AutoAdjustDarkness.isAuto()) {
if (AutoAdjustDarkness.isAuto()) {
const scene = game.scenes.viewed;
if (scene?.environment?.globalLight?.enabled && scene?.tokenVision) {
await scene.update({ darkness });

View File

@@ -160,21 +160,15 @@ export class RdDTimestamp {
}
static findHeure(heure) {
let filtered
if (Number.isInteger(Number(heure))) {
filtered = DEFINITION_HEURES.filter(it => it.heure == Misc.modulo(Number(heure) - 1, RDD_HEURES_PAR_JOUR))
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
let parHeureOuLabel = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure || it.heure == Misc.modulo(parseInt(heure), RDD_HEURES_PAR_JOUR));
if (parHeureOuLabel.length == 1) {
return parHeureOuLabel[0];
}
else {
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
filtered = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure || it.heure == Misc.modulo(parseInt(heure), RDD_HEURES_PAR_JOUR));
}
if (filtered.length == 1) {
return filtered[0]
}
filtered = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure));
if (filtered.length > 0) {
filtered.sort(Misc.ascending(h => h.label.length));
return filtered[0]
let parLabelPartiel = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure));
if (parLabelPartiel.length > 0) {
parLabelPartiel.sort(Misc.ascending(h => h.label.length));
return parLabelPartiel[0];
}
return undefined;
}

View File

@@ -64,7 +64,6 @@
{"_id":"MGvyXFQJpv6nNynl","name":"Masse lourde","type":"arme","img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/masse_lourde.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.MGvyXFQJpv6nNynl"}},"system":{"description":"","descriptionmj":"","equipe":false,"encombrement":3,"quantite":1,"qualite":0,"cout":4,"milieu":"","environnement":[{"milieu":"Villages","rarete":"Rare","frequence":6},{"milieu":"Villes","rarete":"Frequente","frequence":18}],"resistance":10,"categorie_parade":"","dommages":"3/4","penetration":0,"force":"12/11","competence":"Masse à 1 main","lancer":"","tir":"","portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"rapide":false,"deuxmains":true,"unemain":true,"initpremierround":"masse"},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.15","coreVersion":"10.291","createdTime":1668808206023,"modifiedTime":1676074487966,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"MQxgfYTEQEUhG116","name":"Épée bâtarde","type":"arme","img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_batarde.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.MQxgfYTEQEUhG116"}},"system":{"description":"<p>Comme son nom l&rsquo;indique, c&rsquo;est une <em>b&acirc;tarde </em>de l'&eacute;p&eacute;e longue et de l'&eacute;p&eacute;e sorde, &agrave; la fois longue et large, pouvant s&rsquo;utiliser &agrave; une ou deux mains.</p>","descriptionmj":"","equipe":false,"encombrement":3,"quantite":1,"qualite":0,"cout":30,"milieu":"","environnement":[{"milieu":"Villages","rarete":"Rarissime","frequence":2},{"milieu":"Villes","rarete":"Rare","frequence":6}],"resistance":14,"categorie_parade":"epees-lourdes","dommages":"4/5","penetration":0,"force":"13/12","competence":"Epée à 1 main","lancer":"","tir":"","portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"rapide":false,"deuxmains":true,"unemain":true,"initpremierround":"epeebatarde"},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.15","coreVersion":"10.291","createdTime":1668808206023,"modifiedTime":1676074487966,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"Mbh2M8JS1Rf0vxEX","name":"Harpe","type":"objet","img":"systems/foundryvtt-reve-de-dragon/icons/objets/harpe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.Mbh2M8JS1Rf0vxEX"}},"system":{"description":"","descriptionmj":"","encombrement":1,"quantite":1,"qualite":0,"cout":5,"milieu":"","environnement":[{"milieu":"Villages","rarete":"Rarissime","frequence":2},{"milieu":"Villes","rarete":"Rare","frequence":6}],"equipe":false,"resistance":1},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.15","coreVersion":"10.291","createdTime":1668808206023,"modifiedTime":1676074487966,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"NCp2kdTKmJVdFuit","name":"Dague mêlée","type":"arme","img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/dague.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sheetClass":"","sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.NCp2kdTKmQGyAh1U"}},"system":{"description":"","descriptionmj":"","equipe":false,"encombrement":0.5,"quantite":1,"qualite":0,"cout":3,"milieu":"","environnement":[{"milieu":"Villages","rarete":"Frequente","frequence":18},{"milieu":"Villes","rarete":"Frequente","frequence":18}],"resistance":8,"categorie_parade":"dagues","dommages":"1","penetration":0,"force":"7","competence":"Dague","lancer":"Dague de jet","tir":"","portee_courte":3,"portee_moyenne":8,"portee_extreme":15,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"dague"},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.15","coreVersion":"10.291","createdTime":1668808206023,"modifiedTime":1676074487966,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"NCp2kdTKmQGyAh1U","name":"Dague","type":"arme","img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/dague.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sheetClass":"","sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.NCp2kdTKmQGyAh1U"}},"system":{"description":"","descriptionmj":"","equipe":false,"encombrement":0.5,"quantite":1,"qualite":0,"cout":3,"milieu":"","environnement":[{"milieu":"Villages","rarete":"Frequente","frequence":18},{"milieu":"Villes","rarete":"Frequente","frequence":18}],"resistance":8,"categorie_parade":"dagues","dommages":"1","penetration":0,"force":"7","competence":"Dague","lancer":"Dague de jet","tir":"","portee_courte":3,"portee_moyenne":8,"portee_extreme":15,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"dague"},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.15","coreVersion":"10.291","createdTime":1668808206023,"modifiedTime":1676074487966,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"NNLhxjFsoJVdFuit","name":"Bouteille de verre (1 litre)","type":"conteneur","img":"systems/foundryvtt-reve-de-dragon/icons/objets/bouteille_verre.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.NNLhxjFsoJVdFuit"}},"system":{"description":"","descriptionmj":"","encombrement":0.2,"quantite":1,"qualite":0,"cout":0.7,"milieu":"","environnement":[{"milieu":"Villages","rarete":"Rare","frequence":6},{"milieu":"Villes","rarete":"Frequente","frequence":18}],"contenu":[],"capacite":0.5,"equipe":false},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.15","coreVersion":"10.291","createdTime":1668808206023,"modifiedTime":1676074487966,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"OXFFRZOqlhZDJas3","name":"Béret de velours","type":"objet","img":"systems/foundryvtt-reve-de-dragon/icons/objets/beret_velours.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.OXFFRZOqlhZDJas3"}},"system":{"description":"","descriptionmj":"","encombrement":0.05,"quantite":1,"qualite":0,"cout":3,"milieu":"","environnement":[{"milieu":"Villages","rarete":"Rare","frequence":6},{"milieu":"Villes","rarete":"Frequente","frequence":18}],"equipe":false,"resistance":1},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.15","coreVersion":"10.291","createdTime":1668808206023,"modifiedTime":1676074487966,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}

View File

@@ -11,3 +11,4 @@
{"name":"Thème astral","type":"script","scope":"global","author":"Hp9ImM4o9YRTSdfu","img":"icons/magic/nature/symbol-moon-stars-white.webp","command":"game.system.rdd.AppAstrologie.create()","ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"flags":{"core":{"sourceId":"Macro.oA0HPFeFK6YMspAX"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.6.19","coreVersion":"10.291","createdTime":1678127868791,"modifiedTime":1678237392810,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"koqhiDJSGP4gQ4vf"}
{"name":"Jet d'éthylisme","type":"script","scope":"global","author":"Hp9ImM4o9YRTSdfu","img":"icons/consumables/drinks/alcohol-beer-stein-wooden-metal-brown.webp","command":"const selected = game.system.rdd.RdDUtility.getSelectedActor();\nif (selected) {\n selected.jetEthylisme();\n}\nelse {\n ui.notifications.info('Pas de personnage sélectionné');\n}","ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"flags":{"core":{"sourceId":"Macro.XHNbjnGKXaCiCadq"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"11.1.0","coreVersion":"10.291","createdTime":1671220038331,"modifiedTime":1671233646086,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"mvub1dRHNFmWjRr7"}
{"name":"Tirer le tarot","type":"chat","scope":"global","author":"Hp9ImM4o9YRTSdfu","img":"systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp","command":"/tirer tarot","ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"flags":{"core":{"sourceId":"Macro.HBZSKR9OHCQbLcTC"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"11.1.0","coreVersion":"10.291","createdTime":1669469547231,"modifiedTime":1671237401618,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"vTfJTFYYiRu8X5LM"}
{"name": "Mon personnage","type": "script","author": "Hp9ImM4o9YRTSdfu","img": "systems/foundryvtt-reve-de-dragon/icons/voyageurs/token_hr_dilettante.webp","scope": "global","command": "if (game.user.isGM) {\n ui.notifications.warn(\"En tant que gardien, vous n'avez pas de personnage attitré\")\n return\n}\nconst actor = game.users.get(game.userId)?.character\nif (!actor) {\n ui.notifications.warn(\"Vous n'avez pas de personnage attitré\")\n return\n}\nactor.sheet.render(true)","folder": null,"flags": {"core": {},"exportSource": {"world": "graine","system": "foundryvtt-reve-de-dragon","coreVersion": "11.313","systemVersion": "11.1.1"}},"_stats": {"systemId": "foundryvtt-reve-de-dragon","systemVersion": "11.1.1","coreVersion": "11.313","createdTime": 1699477824379,"modifiedTime": 1699485023429,"lastModifiedBy": "Hp9ImM4o9YRTSdfu"}}

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 613 KiB

View File

@@ -1,8 +1,8 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "12.0.20",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.20.zip",
"version": "12.0.17",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.17.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": {

View File

@@ -25,7 +25,7 @@
<span class="competence-value">{{plusMoins arme.system.niveau}}</span>
<span class="competence-value">{{plusMoins arme.system.dommagesReels}}</span>
<span class="competence-value"></span>
<span class="initiative-value"><a class="roll-init-arme" data-tooltip="{{arme.name}}: initiative {{arme.system.initiative}}">{{arme.system.initiative}}</a></span>
<span class="initiative-value arme-initiative"><a data-tooltip="{{arme.name}}: initiative {{arme.system.initiative}}">{{arme.system.initiative}}</a></span>
</li>
{{/each}}
{{#each esquives as |esq key|}}

View File

@@ -10,11 +10,7 @@
<div class="flexrow">
<div>{{niveau}}</div>
{{#if init}}
{{#if name}}
<div><a class="roll-init-arme">{{init}}</a></div>
{{else}}
<div>{{init}}</div>
{{/if}}
<div>{{init}}</div>
<div>{{dommages}}</div>
{{else}}
<div></div>

View File

@@ -11,6 +11,8 @@
<a class="{{button-name}}-plus"><i class="fa-regular fa-square-plus"></i></a>
</div>
<div class="flex-group-right">
{{log carac.colName carac.value (eq carac.value actuel.value) actuel.value}}
{{log carac.colName carac.value (eq 1 1) actuel.value}}
<a class="{{actuel.rollClass}}" data-carac-name="{{actuel.column}}">{{carac.value}} {{#unless (eq carac.value actuel.value)}}(Actuel : {{actuel.value}}){{/unless}}</a>
</div>
</div>

View File

@@ -2,11 +2,7 @@
<div>
{{upperFirst carac.colName}}
<a class="{{carac.column}}-moins"><i class="fa-regular fa-square-minus"></i></a>
{{#if (eq carac.value actuel.value)}}
<i class="fa-regular fa-square"></i>
{{else}}
<a class="{{carac.column}}-plus"><i class="fa-regular fa-square-plus"></i></a>
{{/if}}
</div>
<div class="flex-group-right">
<a class="{{actuel.rollClass}}" data-carac-name="{{actuel.column}}">{{carac.value}} {{#unless (eq carac.value actuel.value)}}(Actuel : {{actuel.value}}){{/unless}}</a>

View File

@@ -2,7 +2,7 @@
<div class="flexrow item" data-item-id="{{competence._id}}">
<a class="roll-competence" name="Esquive">{{upperFirst name}}</a>
<div class="flexrow">
<div>{{numberFormat competence.system.niveau decimals=0 sign=true}}</div>
<div>{{niveau}}</div>
<div></div>
<div></div>
</div>

View File

@@ -3,11 +3,7 @@
{{#if etat.fatigue.malus}}
({{etat.fatigue.malus}})
{{/if}}
{{#if (eq etat.fatigue.value 0)}}
<i class="fa-regular fa-square"></i>
{{else}}
<a class="fatigue-moins"><i class="fa-regular fa-square-minus"></i></a>
{{/if}}
<a class="fatigue-plus"><i class="fa-regular fa-square-plus"></i></a>
</div>
<div class="flex-group-right">

View File

@@ -20,56 +20,45 @@
{{#if essais.defense}}
{{#unless essais.defenseChance}}
{{#if (eq defender.type 'personnage')}}
<a class='chat-card-button' id='appel-chance-defense'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
Faire appel à la chance</a>
</a>
<br>
<a class='chat-card-button' id='appel-chance-defense'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
Faire appel à la chance</a>
</a>
<br>
{{/if}}
{{#if (and (eq defender.type 'personnage') (gt defender.system.compteurs.destinee.value 0))}}
{{#if (eq defender.type 'personnage')}}
{{#if (gt defender.system.compteurs.destinee.value 0)}}
<a class='chat-card-button' id='appel-destinee-defense'
data-attackerId='{{attackerId}}' data-attackerTokenId='{{attackerToken.id}}' data-defenderTokenId='{{defenderToken.id}}'>
Utiliser la destinée</a>
</a>
<br>
{{/if}}
{{/if}}
{{/unless}}
{{else}}
{{#each armes as |arme key|}}
<a class='chat-card-button' id='parer-button'
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
data-armeid='{{arme._id}}'>
Parer avec {{arme.name}}
{{#if (or (eq ../attaqueCategorie 'tir') (eq ../attaqueCategorie 'lancer'))}}
(difficulté à déterminer)
{{else}}à {{../diffLibre }}
{{/if}}
{{#if (eq arme.typeParade 'sign')}}
<span class="rdd-diviseur">&times;&frac12;</span>
{{/if}}
{{#if arme.nbUsage}}(Utilisations : {{arme.nbUsage}}){{/if}}
Parer avec {{arme.name}} à {{../diffLibre }}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}}
</a>
<br>
{{/each}}
{{#if mainsNues}}
{{/each}}
{{#if mainsNues}}
<a class='chat-card-button' id='parer-button'
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'
data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'>
Parer à mains nues à {{diffLibre}}{{#if arme.nbUsage}} (Utilisations : {{arme.nbUsage}}){{/if}}
</a>
<br>
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'
data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'>
Parer à mains nues à {{diffLibre}}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}}
</a>
<br>
{{/if}}
{{#if (ne attaqueCategorie 'tir')}}
{{#each esquives as |esquive key|}}
{{#each esquives as |esquive key|}}
<a class='chat-card-button' id='esquiver-button'
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
data-compid='{{esquive._id}}' data-competence='{{esquive.name}}'>
{{esquive.name}}
{{#if (or (eq ../attaqueCategorie 'tir') (eq ../attaqueCategorie 'lancer'))}}
(difficulté à déterminer)
{{else}}à {{../diffLibre }}
{{/if}}
{{#if esquive.nbUsage}}(Utilisations : {{esquive.nbUsage}}){{/if}}
{{esquive.name}} à {{../diffLibre}} {{#if esquive.system.nbUsage}} (Utilisations : {{esquive.system.nbUsage}}){{/if}}
</a>
<br>
{{/each}}