diff --git a/COFantasy/3.15/COFantasy.js b/COFantasy/3.15/COFantasy.js
index 26b5d93c3..40b3a8722 100644
--- a/COFantasy/3.15/COFantasy.js
+++ b/COFantasy/3.15/COFantasy.js
@@ -1,4 +1,4 @@
-//Derni\xE8re modification : sam. 18 mai 2024, 03:02
+//Derni\xE8re modification : ven. 24 mai 2024, 02:53
// ------------------ generateRowID code from the Aaron ---------------------
const generateUUID = (function() {
"use strict";
@@ -1968,8 +1968,7 @@ var COFantasy = COFantasy || function() {
//Renvoie 1dk + bonus, avec le texte
//champs val et roll
//de peut \xEAtre un nombre > 0 ou bien le r\xE9sultat de parseDice
- function rollDePlus(de, options) {
- options = options || {};
+ function rollDePlus(de, options = {}) {
let nbDes = options.nbDes || 1;
let bonus = options.bonus || 0;
if (de.dice !== undefined) {
@@ -2066,12 +2065,11 @@ var COFantasy = COFantasy || function() {
attribute: attr,
current: attr.get('current'),
max: attr.get('max'),
+ withWorker: true,
});
}
- token.set(fieldv, val); //On le fait aussi pour forcer la mise \xE0 jour de la barre
let aset = {
current: val,
- withWorker: true
};
if (maxVal) aset.max = maxVal;
attr.setWithWorker(aset);
@@ -4064,6 +4062,7 @@ var COFantasy = COFantasy || function() {
break;
case 'paralyseTemp':
case 'paralyseGoule':
+ case 'poisonParalysant':
iterTokensOfAttribute(charId, options.pageId, effet, attrName,
function(token) {
setState({
@@ -7097,7 +7096,7 @@ var COFantasy = COFantasy || function() {
let dice = 20;
if ((estAffaibli(personnage) && !predicateAsBool(personnage, 'insensibleAffaibli')) ||
getState(personnage, 'immobilise') ||
- (carac == 'DEX' && getState(personnage, 'encombre')) ||
+ (carac == 'DEX' && getState(personnage, 'encombre')) ||
attributeAsBool(personnage, 'mortMaisNAbandonnePas'))
dice = 12;
else {
@@ -10535,10 +10534,19 @@ var COFantasy = COFantasy || function() {
// seulement pour l'attaque avec l'arme principale
// suppose qu'on a calcul\xE9 les armes en main
function malusAttaqueDeuxArmes(perso, weaponStats) {
- if (!perso.armeGauche) return;
+ if (!perso.armeGauche || !perso.arme) return;
if (persoEstPNJ(perso)) return; //On ne rentre pas dans ces d\xE9tails pour les PNJs
if (predicateAsBool(perso, 'ambidextrie') || predicateAsBool(perso, 'combatADeuxArmesAmeliore')) return;
if (predicateAsBool(perso, 'coupDeBouclier') && perso.armeGauche.label == predicateAsBool(perso, 'attaqueAuBouclier')) return;
+ if (predicateAsBool(perso, 'tirDouble') && perso.armeGauche.poudre && perso.arme.poudre) return;
+ //L'attaque doit se faire au d12
+ weaponStats.modificateurs += ' avecd12crit';
+ }
+
+ //weaponStats est la stat de l'arme en main gauche
+ function malusAttaqueMainGauche(perso, weaponStats) {
+ if (predicateAsBool(perso, 'ambidextrie')) return;
+ if (predicateAsBool(perso, 'tirDouble') && weaponStats.poudre && (!perso.arme || perso.arme.poudre)) return;
//L'attaque doit se faire au d12
weaponStats.modificateurs += ' avecd12crit';
}
@@ -10641,10 +10649,7 @@ var COFantasy = COFantasy || function() {
} else if (attackLabel == -2) { //attaque avec l'arme en main gauche
if (attaquant.armesEnMain === undefined) armesEnMain(attaquant);
weaponStats = attaquant.armeGauche;
- if (!predicateAsBool(attaquant, 'ambidextrie')) {
- //L'attaque doit se faire au d12
- weaponStats.modificateurs += ' avecd12crit';
- }
+ malusAttaqueMainGauche(attaquant, weaponStats);
}
if (weaponStats === undefined) {
let arme = armesEnMain(attaquant);
@@ -10653,10 +10658,7 @@ var COFantasy = COFantasy || function() {
malusAttaqueDeuxArmes(attaquant, weaponStats);
} else if (attaquant.armeGauche && attaquant.armeGauche.label == attackLabel) {
weaponStats = attaquant.armeGauche;
- if (!predicateAsBool(attaquant, 'ambidextrie')) {
- //L'attaque doit se faire au d12
- weaponStats.modificateurs += ' avecd12crit';
- }
+ malusAttaqueMainGauche(attaquant, weaponStats);
} else weaponStats = getWeaponStats(attaquant, attackLabel);
}
}
@@ -13071,8 +13073,10 @@ var COFantasy = COFantasy || function() {
unlockToken(attaquant, evt);
} else {
attBonus -= 5;
- options.diviseDmg = options.diviseDmg || 1;
- options.diviseDmg *= 2;
+ if (!options.redo) {
+ options.diviseDmg = options.diviseDmg || 1;
+ options.diviseDmg *= 2;
+ }
messageAttaqueDM("Attaquant dans le ventre de " + nomPerso(gobant), explications, options, -5, 'moiti\xE9');
}
}
@@ -16556,54 +16560,81 @@ var COFantasy = COFantasy || function() {
typePoison = defPoison.substring(0, index);
value = defPoison.substring(index + 1);
}
- if (typePoison == 'rapide') {
- attaquant.additionalDmg.push({
- type: 'poison',
- value,
- partialSave: {
- carac: 'CON',
- seuil
+ switch (typePoison) {
+ case 'rapide':
+ {
+ attaquant.additionalDmg.push({
+ type: 'poison',
+ value,
+ partialSave: {
+ carac: 'CON',
+ seuil
+ }
+ });
+ break;
}
- });
- } else if (typePoison == 'affaiblissant') {
- options.effets = options.effets || [];
- if (value == 0) {
- options.effets.push({
- effet: 'poisonAffaiblissant',
- typeDmg: 'poison',
- message: messageEffetCombat.poisonAffaiblissant,
- save: {
- carac: 'CON',
- seuil
- },
- });
- } else {
- let exprDuree = parseDice(value, 'dur\xE9e');
- let duree = randomInteger(6);
- if (exprDuree) {
- if (exprDuree.nbDe <= 0) {
- if (exprDuree.bonus > 0) duree = exprDuree.bonus;
+ case 'affaiblissant':
+ {
+ options.effets = options.effets || [];
+ if (value == 0) {
+ options.effets.push({
+ effet: 'poisonAffaiblissant',
+ typeDmg: 'poison',
+ message: messageEffetCombat.poisonAffaiblissant,
+ save: {
+ carac: 'CON',
+ seuil
+ },
+ });
} else {
- duree = rollDePlus(exprDuree.dice, {
- nbDes: exprDuree.nbDes,
- bonus: exprDuree.bonus
- }).val;
+ let exprDuree = parseDice(value, 'dur\xE9e');
+ let duree = randomInteger(6);
+ if (exprDuree) {
+ if (exprDuree.nbDe <= 0) {
+ if (exprDuree.bonus > 0) duree = exprDuree.bonus;
+ } else {
+ duree = rollDePlus(exprDuree).val;
+ }
+ }
+ options.effets.push({
+ effet: 'poisonAffaiblissantLatent',
+ typeDmg: 'poison',
+ duree,
+ message: messageOfEffetTemp('poisonAffaiblissantLatent'),
+ save: {
+ carac: 'CON',
+ seuil
+ },
+ });
}
+ break;
}
-
- options.effets.push({
- effet: 'poisonAffaiblissantLatent',
- typeDmg: 'poison',
- duree,
- message: messageOfEffetTemp('poisonAffaiblissantLatent'),
- save: {
- carac: 'CON',
- seuil
- },
- });
- }
- } else {
- error("Type de poison " + typePoison + " non reconnu.", poisonAttr);
+ case 'paralysant':
+ {
+ options.effets = options.effets || [];
+ let exprDuree = parseDice(value, 'dur\xE9e');
+ let duree = 1;
+ if (exprDuree) {
+ duree = rollDePlus(exprDuree);
+ if (duree && duree.val > 0) duree = duree.val;
+ else duree = 0;
+ }
+ if (duree) {
+ options.effets.push({
+ effet: 'poisonParalysant',
+ typeDmg: 'poison',
+ duree,
+ message: messageOfEffetTemp('poisonParalysant'),
+ save: {
+ carac: 'CON',
+ seuil
+ },
+ });
+ }
+ break;
+ }
+ default:
+ error("Type de poison " + typePoison + " non reconnu.", poisonAttr);
}
explications.push("L'arme est empoisonn\xE9e");
return defPoison;
@@ -16654,8 +16685,10 @@ var COFantasy = COFantasy || function() {
if (!options.pasDeDmg && options.contact) {
if (!options.auto) msgDrain += " et ";
msgDrain += "DM/2";
- options.diviseDmg = options.diviseDmg || 1;
- options.diviseDmg *= 2;
+ if (!options.redo) {
+ options.diviseDmg = options.diviseDmg || 1;
+ options.diviseDmg *= 2;
+ }
}
expliquer(msgDrain);
}
@@ -18072,6 +18105,11 @@ var COFantasy = COFantasy || function() {
return oldSide;
}
+ function immuniseAuxSaignements(perso) {
+ return predicateAsBool(perso, 'immuniteSaignement') ||
+ predicateAsBool(perso, 'controleSanguin');
+ }
+
//Met un effet temporaire sur target. L'effet temporaire est sp\xE9cifi\xE9 dans ef
// - effet : le nom de l'effet
// - whisper : true si on doit chuchoter l'effet, undefined si on n'affiche pas (mais dans ce cas, target.messages doit \xEAtre d\xE9fini)
@@ -18141,7 +18179,7 @@ var COFantasy = COFantasy || function() {
}
return;
}
- if (ef.effet == 'saignementsSang' && predicateAsBool(target, 'immuniteSaignement')) {
+ if (ef.effet == 'saignementsSang' && immuniseAuxSaignements(target)) {
if (ef.whisper !== undefined) {
if (ef.whisper === true) {
whisperChar(target.charId, "ne peut pas saigner");
@@ -18230,6 +18268,7 @@ var COFantasy = COFantasy || function() {
break;
case 'paralyseTemp':
case 'paralyseGoule':
+ case 'poisonParalysant':
setState(target, 'paralyse', true, evt);
break;
case 'immobiliseTemp':
@@ -19642,6 +19681,20 @@ var COFantasy = COFantasy || function() {
if (effets) effets = effets.concat(target.effets);
else effets = target.effets;
}
+ if (predicateAsBool(attaquant, 'hemorragiePestrilax') && !immuniseAuxSaignements(target)) {
+ if (attributeAsBool(target, 'blessureQuiSaigne')) {
+ let niveauBlessure = getIntValeurOfEffet(target, 'blessureQuiSaigne', 0);
+ target.messages.push("La blessure devient plus importante");
+ setTokenAttr(target, 'blessureQuiSaigneValeur', niveauBlessure + 1, evt);
+ } else {
+ effets = effets || [];
+ effets.push({
+ effet: 'blessureQuiSaigne',
+ attaquant,
+ message: messageEffetCombat.blessureQuiSaigne,
+ });
+ }
+ }
if (effets) {
effets.forEach(function(ef) {
if (((options.sortilege || options.mana !== undefined) &&
@@ -29479,6 +29532,7 @@ var COFantasy = COFantasy || function() {
(effet == 'immobiliseTemp' ||
effet == 'paralyseTemp' ||
effet == 'paralyseGoule' ||
+ effet == 'poisonParalysant' ||
effet == 'ralentiTemp' ||
effet == 'toiles')) ||
(mEffet.entrave && effet != 'paralyseTemp' && effet != 'paralyseGoule' && predicateAsInt(perso, 'voieDeLArchange', 1) > 1 && attributeAsBool(perso, 'formeDAnge'))
@@ -29923,7 +29977,7 @@ var COFantasy = COFantasy || function() {
if (activer) {
initiative(selected, evt);
iterSelected(selected, function(perso) {
- if (effet == 'blessureQuiSaigne' && predicateAsBool(perso, 'immuniteSaignement')) {
+ if (effet == 'blessureQuiSaigne' && immuniseAuxSaignements(perso)) {
sendPerso(perso, "ne saigne pas");
return;
}
@@ -34916,8 +34970,14 @@ var COFantasy = COFantasy || function() {
}
let label = cmd[1];
let typePoison = cmd[2];
- if (typePoison != 'rapide' && typePoison != 'affaiblissant') {
- error("Les seuls type de poison g\xE9r\xE9s sont rapide et affaiblissant, mais pas encore " + typePoison, cmd);
+ switch (typePoison) {
+ case 'rapide':
+ case 'affaiblissant':
+ case 'paralysant':
+ break;
+ default:
+ error("Les seuls type de poison g\xE9r\xE9s sont rapide, affaiblissant et paralysant, mais pas encore " + typePoison, cmd);
+ return;
}
let nomMunition;
let estMunition = label.startsWith('munition_');
@@ -46429,6 +46489,25 @@ var COFantasy = COFantasy || function() {
prejudiciable: true,
visible: true
},
+ poisonAffaiblissantLatent: {
+ activation: "sent qu'un poison commence \xE0 se r\xE9pandre dans ses veines",
+ actif: "est empoisonn\xE9, mais l'effet du poison ne se fait pas encore sentir",
+ actifF: "est empoisonn\xE9e, mais l'effet du poison ne se fait pas encore sentir",
+ fin: "se sent faible",
+ msgSave: "r\xE9sister au poison",
+ prejudiciable: true,
+ seulementVivant: true,
+ },
+ poisonParalysant: {
+ activation: "sent le poison ralentir ses mouvements. Il ne peut plus bouger !",
+ activationf: "sent le poison ralentir ses mouvements. Elle ne peut plus bouger !",
+ actif: "est empoisonn\xE9 et ne peut plus bouger",
+ actifF: "est empoisonn\xE9e et ne peut plus bouger",
+ fin: "peut \xE0 nouveau bouger",
+ msgSave: "r\xE9sister au poison",
+ prejudiciable: true,
+ seulementVivant: true,
+ },
protectionContreLesProjectiles: {
activation: "gagne une protection contre les projectiles",
actif: "est prot\xE9g\xE9 contre les projectiles",
@@ -47196,15 +47275,6 @@ var COFantasy = COFantasy || function() {
msgSave: "r\xE9sister \xE0 la provocation",
prejudiciable: true,
},
- poisonAffaiblissantLatent: {
- activation: "sent qu'un poison commence \xE0 se r\xE9pandre dans ses veines",
- actif: "est empoisonn\xE9, mais l'effet du poison ne se fait pas encore sentir",
- actifF: "est empoisonn\xE9e, mais l'effet du poison ne se fait pas encore sentir",
- fin: "se sent faible",
- msgSave: "r\xE9sister au poison",
- prejudiciable: true,
- seulementVivant: true,
- },
};
function buildPatternEffets(listeEffets, postfix) {
@@ -47312,11 +47382,24 @@ var COFantasy = COFantasy || function() {
actif: "attaque \xE0 outrance",
fin: "attaque normalement",
},
+ blessureQuiSaigne: {
+ activation: "re\xE7oit une blessure qui saigne",
+ actif: "saigne \xE0 cause d'une blessure",
+ fin: "saigne beaucoup moins",
+ msgSave: "ne plus saigner",
+ prejudiciable: true,
+ dm: true
+ },
bonusInitEmbuscade: { //Effet interne pour la capacit\xE9 Surveillance
activation: "a un temps d'avance en cas d'embuscade",
actif: "a un temps d'avance",
fin: ""
},
+ bonusInitVariable: {
+ activation: "entre en combat",
+ actif: "est en combat",
+ fin: ''
+ },
criDeGuerre: {
activation: "pousse son cri de guerre",
actif: "a effray\xE9 ses adversaires",
@@ -47385,11 +47468,6 @@ var COFantasy = COFantasy || function() {
fin: "retrouve son calme",
msgSave: "retrouver son calme",
},
- bonusInitVariable: {
- activation: "entre en combat",
- actif: "est en combat",
- fin: ''
- },
defiDuelliste: {
activation: "lance un d\xE9fi",
actif: "a lanc\xE9 un d\xE9fi",
@@ -47472,14 +47550,6 @@ var COFantasy = COFantasy || function() {
dm: true,
visible: true
},
- blessureQuiSaigne: {
- activation: "re\xE7oit une blessure qui saigne",
- actif: "saigne \xE0 cause d'une blessure",
- fin: "saigne beaucoup moins",
- msgSave: "ne plus saigner",
- prejudiciable: true,
- dm: true
- },
poisonAffaiblissant: {
activation: "sent le poison ralentir ses mouvements",
actif: "est empoisonn\xE9",
@@ -47720,6 +47790,16 @@ var COFantasy = COFantasy || function() {
return effet;
}
+ function getEffectOptions(perso, effet, options) {
+ options = options || {};
+ let optionsAttr = tokenAttribute(perso, effet + 'Options');
+ optionsAttr.forEach(function(oAttr) {
+ parseDmgOptions(oAttr.get('current'), options);
+ });
+ copyDmgOptionsToTarget(perso, options);
+ return options;
+ }
+
function rollAndDealDmg(perso, dmg, type, effet, attrName, msg, count, evt, options, callback, display) {
if (options.valeur) {
let attrsVal = tokenAttribute(perso, options.valeur);
@@ -47895,16 +47975,6 @@ var COFantasy = COFantasy || function() {
}); //fin iterTokensOfAttribute
}
- function getEffectOptions(perso, effet, options) {
- options = options || {};
- let optionsAttr = tokenAttribute(perso, effet + 'Options');
- optionsAttr.forEach(function(oAttr) {
- parseDmgOptions(oAttr.get('current'), options);
- });
- copyDmgOptionsToTarget(perso, options);
- return options;
- }
-
// gestion des effets qui se d\xE9clenchent \xE0 la fin de chaque tour
// N'ajoute pas evt \xE0 l'historique
// Asynchrone (\xE0 cause des saves par tour)
@@ -48124,16 +48194,18 @@ var COFantasy = COFantasy || function() {
});
}
if (attributeAsBool(perso, 'blessureQuiSaigne') &&
- !getState(perso, 'mort') &&
- !predicateAsBool(perso, 'immuniteSaignement') &&
- !predicateAsBool(perso, 'controleSanguin')) {
- let jetSaignement = rollDePlus(6);
+ !getState(perso, 'mort') && !immuniseAuxSaignements(perso)) {
+ let bonus = getIntValeurOfEffet(perso, 'blessureQuiSaigne', 0);
+ let jetSaignement = rollDePlus(6, {
+ bonus
+ });
let dmgSaignement = {
type: 'normal',
total: jetSaignement.val,
display: jetSaignement.roll
};
let optDMSaignements = getEffectOptions(perso, 'blessureQuiSaigne');
+ perso.ignoreTouteRD = true;
dealDamage(perso, dmgSaignement, [], evt, false, optDMSaignements, undefined,
function(dmgDisplay, dmgFinal) {
sendPerso(perso, "saigne. " + onGenre(perso, 'Il', 'Elle') + " perd " + dmgDisplay + " PVs");
@@ -49834,7 +49906,7 @@ var COFantasy = COFantasy || function() {
else arme = l;
}
}
- if (arme !== undefined && arme !== true) {
+ if (arme && arme !== true) {
degainerArme(perso, arme, {}, {
secret: true
});
diff --git a/COFantasy/3.15/doc.html b/COFantasy/3.15/doc.html
index bdae6b0a4..9c647289b 100644
--- a/COFantasy/3.15/doc.html
+++ b/COFantasy/3.15/doc.html
@@ -1035,7 +1035,7 @@
Voie du Pistolero
Plus vite que son ombre : ajouter un prédicat plusViteQueSonOmbre
. On peut associer un nombre à ce prédicat pour modifier le bonus à l'initiative, ou bien lui donner la valeur arbalete
pour activer le bonus sur les arbalètes au lieu des armes à poudre.
Cadence de tir : pas de support
- Tir double : utiliser l'option --tirDouble
si deux tirs sur une même cible. Si les deux armes sont différentes, rajouter le label de la deuxième arme après l'option (si le label est l2, cela donne --tirDouble l2
). Si vous avez une pétoire dans la main droite et l'autre dans la main gauche, vous pouvez par exemple utiliser l'action #Attaque -1 --tirDouble -2
. Attention, il faut faire 2 undo pour annuler une attaque de tir double réussie.
+ Tir double : ajouter un prédicat tirDouble
pour ne pas avoir le malus à l'attaque avec une arme à poudre dans chaque main. Si le personnage veut faire 2 tirs sur la même cible, il peut utiliser l'option --tirDouble
. Si les deux armes sont différentes, rajouter le label de la deuxième arme après l'option (si le label est l2, cela donne --tirDouble l2
). Si vous avez une pétoire dans la main droite et l'autre dans la main gauche, vous pouvez par exemple utiliser l'action #Attaque -1 --tirDouble -2
. Attention, il faut faire 2 undo pour annuler une attaque de tir double réussie.
As de la gâchette : ajouter un prédicat asDeLaGachette
sur la fiche.
Dextérité héroïque : reporter le bonus sur la fiche
@@ -2471,6 +2471,7 @@ 4.5 Capacités diverses
Foudres du temps : !cof-effet-chaque-d20 foudresDuTemps
permet d'activer les foudres du temps. On peut donner un argument pour remplacer la valeur par défaut (13) par un autre jet de dés. Un deuxième argument permet de faire sortir la foudre pour tout jet entre les deux valeurs. Par exemple !cof-effet-chaque-d20 foudresDuTemps 13 14
fait venir la foudre pour tout jet de 13 ou 14. Si votre jeu contient un son (ou playlist) nommé Foudre
(avec la majuscule), le son sera joué à chaque fois que la foudre frappera. Finalement, !cof-effet-chaque-d20 foudresDuTemps fin
met fin aux foudres du temps.
Frénésie : Ajouter un prédicat frenesie
avec comme valeur le nombre de PV en-dessous duquel la créature devient frénétique (+2 aus jets d'attaque).
Général (pour la campagne Vengeance) : Ajouter au général un prédicat generalVengeance
, et aux gardes d'élite un prédicat gardeEliteVengeance
.
+ Hémorragie (Invincible) : ajouter un prédicat hemorragiePestrilax
.
Hors de portée : ajouter un prédicat horsDePortee
Huile de fort assaut : !cof-effet-temp dmgArme(L) 10 --valeur 1d6
où L est le label de l'arme qu'on veut enduire d'huile de fort assaut.
Hurlement : Pour les chiens infernaux, !cof-peur [[10+?{Nombre de chiens?}]] 2d4 --titre Hurlement --immuniseSiResiste hurlement --disque 50 --saufAllies
, et pour les fantômes, !cof-peur 12 1d6 --titre Hurlement terrible --immuniseSiResiste hurlement --disque 10 --saufAllies
.
@@ -2495,7 +2496,7 @@ 4.5 Capacités diverses
Phylactère de canalisation : ajouter un prédicat phylacterePositif
pour un phylactère de canalisation positive, ou phylactereNegatif
pour un phylactère de canalisation négative. Associez à ce prédicat la valeur ajoutée pour chaque PM dépensé (nécessite l'utilisation du prédicat deCanalisation
). Une valeur de 1d4
semble adaptée pour le phylactère de canalisation de Pathfinder 1.
Piqûres d'insectes : Rajouter un prédicat piquresDInsectes
avec comme valeur la résistance aux dégâts à distance appropriée
- Poison : pour enduire une arme de label L de poison, utiliser !cof-enduire-poison L type force save
. Pour l'instant, type ne peut être que rapide
ou affaiblissant
. Pour un poison rapide, force est une expression pour les dégâts (typiquement, 2d6
), pour un poison affaiblissant c'est une expression indiquant au bout de combien de tours le poison fait effet (si c'est 0, alors l'affaiblissement ne dure que pendant un combat, sinon c'est une durée en heures, à gérer par le MJ). save est la difficulté du jet de CON pour résister au poison. On peut rajouter deux arguments optionnels :
+ Poison : pour enduire une arme de label L de poison, utiliser !cof-enduire-poison L type force save
. Pour l'instant, type ne peut être que rapide
, affaiblissant
ou paralysant
. Pour un poison rapide, force est une expression pour les dégâts (typiquement, 2d6
), pour un poison affaiblissant c'est une expression indiquant au bout de combien de tours le poison fait effet (si c'est 0, alors l'affaiblissement ne dure que pendant un combat, sinon c'est une durée en heures, à gérer par le MJ), et pour un poison paralysant, c'est la durée de la paralysie en tours. save est la difficulté du jet de CON pour résister au poison. On peut rajouter deux arguments optionnels :
--testINT
n: fixe la difficulté du jet d'INT pour réussir à poser le poison. La difficulté par défaut est 14.
--dose
nom: indique une ressource dans laquelle on puise pour enduire de poison. Il faudra que le personnage ait un attribut de nom dose_nom
avec comme valeur le nombre de doses possédées.
@@ -2506,6 +2507,7 @@ 4.5 Capacités diverses
- poisonAffaiblissant est un effet qui rend affaibli pendant tout un combat.
- poisonAffaiblissantLong, le même effet mais sans limite de durée (à gérer par le MJ).
- poisonAffaiblissantLatent est un effet à durée en tours. Quand l'effet prend fin, le personnage devient empoisonné et affaibli.
+ - poisonParalysant est un effet à durée en tours, qui paralyse.
Potion de sang de l'Arbre-Coeur : !cof-effet sangDeLArbreCoeur true
, à enlever quand les 24h sont passées.
@@ -3127,6 +3129,7 @@ 9. Index des prédicats
briseurDOs : booléen, augmente les chances de critique des attaques au contact, et applique un effet d'os brisés a la cible en cas de critique.
bucheron : booléen, augmente les DM des armes à 2 mains de 1d6 contre les créatures grandes, et 2d6 contre les créatures énormes.
cavalierEmerite : entier, s'ajoute à l'attaque au contact quand le personnage est sur une monture.
+ champion : booléen, touche automatiquement et ajoute 1d6 aux DM sur un résultat de 15 ou plus au dé d'attaque.
charge : entier (défaut 1), indique que l'arme doit être rechargée (ainsi que le nombre de charge, si on associe un nombre).
chasseurDeSorciere : booléen, ajoute 2 aux DM et à la DEF contre les nécromanciens.
chasseurEmerite : booléen, rajoute +2 à l'attaque et aux DM contre les animaux.
@@ -3183,6 +3186,8 @@ 9. Index des prédicats
grosseTete : booléen, remplace le mod. de FOR par le mod. d'INT pour les tests.
guetteur : nom de personnage, nom du personnage représentant le compagnon qui donne un bonus en perception.
hachesEtMarteaux : booléen, ajoute un bonus de 1 en attaque est DM pour les haches et les marteaux.
+ hausserLeTon : booléen, capacité Hausser le ton de la Voie du champion.
+ hemorragiePestrilax : booléen, les attaques qui font des dégâts font saigner la cible.
humanoide : booléen, le personnage est humanoïde.
ignorerLaDouleur : booléen, permet de reporter les DM d'une attaque à la fin du combat.
immunite_x : booléen, empêche de mettre le personnage dans l'état ou effet temporaire nommé x. On peut aussi immuniser aux effets de pétrification avec x=petrification, ou contre la desctruction des mort-vivants avec x=destruction.
@@ -3255,12 +3260,14 @@ 9. Index des prédicats
resistanceA_nonMagique : booléen, divise par 2 les DM non magiques.
resistanceA_type : booléen, divise par 2 les DM du type.
resistanceALaMagieBarbare : booléen, propose un jet pour résister à la magie.
+ riposte : booléen, capacité Riposte de la Voie du champion.
riposteGuerrier : booléen, propose un jet de riposte au personnage.
sangFroid : booléen, réduit les DM quand l'ogre prend sur lui pour éviter une réaction violente.
sansPeur : booléen, immunise aux effets de peur et donne un bonus de 2+CHA aux alliés en vue pour résister aux effets de peur.
scienceDuCritique : booléen, augmente de 1 les chances de critique.
secondSouffle : booléen ou entier, propose un jet de récupération de PV une fois par combat, appliqué automatiquement à la fin du combat si pas utilisé. Si on met un entier, on soigne avec cette valeur à la place de CON + niveau.
sensAffutes : booléen, ajoute la sagesse aux dégâts des arcs et à l'initiative.
+ sergent : booléen, une fois par combat, ignore une attaque qui aurait dû le mettre à 0 PV.
sournoisesParTour : entier (1 par défaut), nombre maximum d'effets d'attaques sournoises par tour pour le personnage.
specialisationGuerrier : booléen ou entier (2 par défaut), donne un bonus aux DM pour l'arme de prédilection.
siphonDesAmes : booléen ou entier, fait récupérer 1d6 PV quand une créature meurt dans les 20 mètres. Si une valeur est précisée, elle est ajoutée à ce dé.
@@ -3269,6 +3276,7 @@ 9. Index des prédicats
techniqueDuSabre : entier, bonus aux DM pour le combat au sabre, katana ou vivelame. Ce bonus ne se cumule qu'à moitié avec le mod. de FOR.
tenacite : booléen, donne un bonus de +2 puis +5 contre un adversaire que le personnage n'a pas réussi à toucher.
tirDeSemonce : booléan, propose un tir de semonce au tour suivant un tir raté.
+ tirDouble : booléan, quand le personnage attaque avec une arme à poudre dans chaque main, il utilise un d20 par défaut.
tirFatal : booléen ou nom de type d'arme (par défaut, arc), augmente les chance de coup critique du mod. de SAG pour les armes de ce type. De plus les DM des coups critiques pour ces attaques sont augmentées de 1 ou 2 d6 (selon la valeur du prédicat voieDeLArcEtDuCheval
).
tirParabolique : booléen, augmente la portée des armes à distance (comme la capacité tir parabolique).
tirPrecis : entier, ajouté aux DM quand la cible est à moins de 5xDEX mètres.
@@ -3283,6 +3291,7 @@ 9. Index des prédicats
vieArtificielle : booléan, divise les soins par 2.
violenceCiblee : booléen, permet d'emmagasiner et d'utliser des points de violence.
visionDansLeNoir : entier, le personnage voit dans le noir jusqu'à la distance indiquée par le prédicat, en mètres.
+ vitaliteEpique : booléan, multiplie par 2 les soins reçus.
vitesseDuFelin : entier, bonus à l'initiative et aux jets de course, d'escalade, et de saut.
voieDeLaConjuration : entier, rang dans la Voie de la conjuration. Contrôle les conjurations de prédateurs et la conjuration d'armées.
voieDeLaMagieElementaire : entier, on utilise 2 fois cette valeur pour la valeur de la protection des éléments.
diff --git a/COFantasy/COFantasy.js b/COFantasy/COFantasy.js
index 26b5d93c3..40b3a8722 100644
--- a/COFantasy/COFantasy.js
+++ b/COFantasy/COFantasy.js
@@ -1,4 +1,4 @@
-//Derni\xE8re modification : sam. 18 mai 2024, 03:02
+//Derni\xE8re modification : ven. 24 mai 2024, 02:53
// ------------------ generateRowID code from the Aaron ---------------------
const generateUUID = (function() {
"use strict";
@@ -1968,8 +1968,7 @@ var COFantasy = COFantasy || function() {
//Renvoie 1dk + bonus, avec le texte
//champs val et roll
//de peut \xEAtre un nombre > 0 ou bien le r\xE9sultat de parseDice
- function rollDePlus(de, options) {
- options = options || {};
+ function rollDePlus(de, options = {}) {
let nbDes = options.nbDes || 1;
let bonus = options.bonus || 0;
if (de.dice !== undefined) {
@@ -2066,12 +2065,11 @@ var COFantasy = COFantasy || function() {
attribute: attr,
current: attr.get('current'),
max: attr.get('max'),
+ withWorker: true,
});
}
- token.set(fieldv, val); //On le fait aussi pour forcer la mise \xE0 jour de la barre
let aset = {
current: val,
- withWorker: true
};
if (maxVal) aset.max = maxVal;
attr.setWithWorker(aset);
@@ -4064,6 +4062,7 @@ var COFantasy = COFantasy || function() {
break;
case 'paralyseTemp':
case 'paralyseGoule':
+ case 'poisonParalysant':
iterTokensOfAttribute(charId, options.pageId, effet, attrName,
function(token) {
setState({
@@ -7097,7 +7096,7 @@ var COFantasy = COFantasy || function() {
let dice = 20;
if ((estAffaibli(personnage) && !predicateAsBool(personnage, 'insensibleAffaibli')) ||
getState(personnage, 'immobilise') ||
- (carac == 'DEX' && getState(personnage, 'encombre')) ||
+ (carac == 'DEX' && getState(personnage, 'encombre')) ||
attributeAsBool(personnage, 'mortMaisNAbandonnePas'))
dice = 12;
else {
@@ -10535,10 +10534,19 @@ var COFantasy = COFantasy || function() {
// seulement pour l'attaque avec l'arme principale
// suppose qu'on a calcul\xE9 les armes en main
function malusAttaqueDeuxArmes(perso, weaponStats) {
- if (!perso.armeGauche) return;
+ if (!perso.armeGauche || !perso.arme) return;
if (persoEstPNJ(perso)) return; //On ne rentre pas dans ces d\xE9tails pour les PNJs
if (predicateAsBool(perso, 'ambidextrie') || predicateAsBool(perso, 'combatADeuxArmesAmeliore')) return;
if (predicateAsBool(perso, 'coupDeBouclier') && perso.armeGauche.label == predicateAsBool(perso, 'attaqueAuBouclier')) return;
+ if (predicateAsBool(perso, 'tirDouble') && perso.armeGauche.poudre && perso.arme.poudre) return;
+ //L'attaque doit se faire au d12
+ weaponStats.modificateurs += ' avecd12crit';
+ }
+
+ //weaponStats est la stat de l'arme en main gauche
+ function malusAttaqueMainGauche(perso, weaponStats) {
+ if (predicateAsBool(perso, 'ambidextrie')) return;
+ if (predicateAsBool(perso, 'tirDouble') && weaponStats.poudre && (!perso.arme || perso.arme.poudre)) return;
//L'attaque doit se faire au d12
weaponStats.modificateurs += ' avecd12crit';
}
@@ -10641,10 +10649,7 @@ var COFantasy = COFantasy || function() {
} else if (attackLabel == -2) { //attaque avec l'arme en main gauche
if (attaquant.armesEnMain === undefined) armesEnMain(attaquant);
weaponStats = attaquant.armeGauche;
- if (!predicateAsBool(attaquant, 'ambidextrie')) {
- //L'attaque doit se faire au d12
- weaponStats.modificateurs += ' avecd12crit';
- }
+ malusAttaqueMainGauche(attaquant, weaponStats);
}
if (weaponStats === undefined) {
let arme = armesEnMain(attaquant);
@@ -10653,10 +10658,7 @@ var COFantasy = COFantasy || function() {
malusAttaqueDeuxArmes(attaquant, weaponStats);
} else if (attaquant.armeGauche && attaquant.armeGauche.label == attackLabel) {
weaponStats = attaquant.armeGauche;
- if (!predicateAsBool(attaquant, 'ambidextrie')) {
- //L'attaque doit se faire au d12
- weaponStats.modificateurs += ' avecd12crit';
- }
+ malusAttaqueMainGauche(attaquant, weaponStats);
} else weaponStats = getWeaponStats(attaquant, attackLabel);
}
}
@@ -13071,8 +13073,10 @@ var COFantasy = COFantasy || function() {
unlockToken(attaquant, evt);
} else {
attBonus -= 5;
- options.diviseDmg = options.diviseDmg || 1;
- options.diviseDmg *= 2;
+ if (!options.redo) {
+ options.diviseDmg = options.diviseDmg || 1;
+ options.diviseDmg *= 2;
+ }
messageAttaqueDM("Attaquant dans le ventre de " + nomPerso(gobant), explications, options, -5, 'moiti\xE9');
}
}
@@ -16556,54 +16560,81 @@ var COFantasy = COFantasy || function() {
typePoison = defPoison.substring(0, index);
value = defPoison.substring(index + 1);
}
- if (typePoison == 'rapide') {
- attaquant.additionalDmg.push({
- type: 'poison',
- value,
- partialSave: {
- carac: 'CON',
- seuil
+ switch (typePoison) {
+ case 'rapide':
+ {
+ attaquant.additionalDmg.push({
+ type: 'poison',
+ value,
+ partialSave: {
+ carac: 'CON',
+ seuil
+ }
+ });
+ break;
}
- });
- } else if (typePoison == 'affaiblissant') {
- options.effets = options.effets || [];
- if (value == 0) {
- options.effets.push({
- effet: 'poisonAffaiblissant',
- typeDmg: 'poison',
- message: messageEffetCombat.poisonAffaiblissant,
- save: {
- carac: 'CON',
- seuil
- },
- });
- } else {
- let exprDuree = parseDice(value, 'dur\xE9e');
- let duree = randomInteger(6);
- if (exprDuree) {
- if (exprDuree.nbDe <= 0) {
- if (exprDuree.bonus > 0) duree = exprDuree.bonus;
+ case 'affaiblissant':
+ {
+ options.effets = options.effets || [];
+ if (value == 0) {
+ options.effets.push({
+ effet: 'poisonAffaiblissant',
+ typeDmg: 'poison',
+ message: messageEffetCombat.poisonAffaiblissant,
+ save: {
+ carac: 'CON',
+ seuil
+ },
+ });
} else {
- duree = rollDePlus(exprDuree.dice, {
- nbDes: exprDuree.nbDes,
- bonus: exprDuree.bonus
- }).val;
+ let exprDuree = parseDice(value, 'dur\xE9e');
+ let duree = randomInteger(6);
+ if (exprDuree) {
+ if (exprDuree.nbDe <= 0) {
+ if (exprDuree.bonus > 0) duree = exprDuree.bonus;
+ } else {
+ duree = rollDePlus(exprDuree).val;
+ }
+ }
+ options.effets.push({
+ effet: 'poisonAffaiblissantLatent',
+ typeDmg: 'poison',
+ duree,
+ message: messageOfEffetTemp('poisonAffaiblissantLatent'),
+ save: {
+ carac: 'CON',
+ seuil
+ },
+ });
}
+ break;
}
-
- options.effets.push({
- effet: 'poisonAffaiblissantLatent',
- typeDmg: 'poison',
- duree,
- message: messageOfEffetTemp('poisonAffaiblissantLatent'),
- save: {
- carac: 'CON',
- seuil
- },
- });
- }
- } else {
- error("Type de poison " + typePoison + " non reconnu.", poisonAttr);
+ case 'paralysant':
+ {
+ options.effets = options.effets || [];
+ let exprDuree = parseDice(value, 'dur\xE9e');
+ let duree = 1;
+ if (exprDuree) {
+ duree = rollDePlus(exprDuree);
+ if (duree && duree.val > 0) duree = duree.val;
+ else duree = 0;
+ }
+ if (duree) {
+ options.effets.push({
+ effet: 'poisonParalysant',
+ typeDmg: 'poison',
+ duree,
+ message: messageOfEffetTemp('poisonParalysant'),
+ save: {
+ carac: 'CON',
+ seuil
+ },
+ });
+ }
+ break;
+ }
+ default:
+ error("Type de poison " + typePoison + " non reconnu.", poisonAttr);
}
explications.push("L'arme est empoisonn\xE9e");
return defPoison;
@@ -16654,8 +16685,10 @@ var COFantasy = COFantasy || function() {
if (!options.pasDeDmg && options.contact) {
if (!options.auto) msgDrain += " et ";
msgDrain += "DM/2";
- options.diviseDmg = options.diviseDmg || 1;
- options.diviseDmg *= 2;
+ if (!options.redo) {
+ options.diviseDmg = options.diviseDmg || 1;
+ options.diviseDmg *= 2;
+ }
}
expliquer(msgDrain);
}
@@ -18072,6 +18105,11 @@ var COFantasy = COFantasy || function() {
return oldSide;
}
+ function immuniseAuxSaignements(perso) {
+ return predicateAsBool(perso, 'immuniteSaignement') ||
+ predicateAsBool(perso, 'controleSanguin');
+ }
+
//Met un effet temporaire sur target. L'effet temporaire est sp\xE9cifi\xE9 dans ef
// - effet : le nom de l'effet
// - whisper : true si on doit chuchoter l'effet, undefined si on n'affiche pas (mais dans ce cas, target.messages doit \xEAtre d\xE9fini)
@@ -18141,7 +18179,7 @@ var COFantasy = COFantasy || function() {
}
return;
}
- if (ef.effet == 'saignementsSang' && predicateAsBool(target, 'immuniteSaignement')) {
+ if (ef.effet == 'saignementsSang' && immuniseAuxSaignements(target)) {
if (ef.whisper !== undefined) {
if (ef.whisper === true) {
whisperChar(target.charId, "ne peut pas saigner");
@@ -18230,6 +18268,7 @@ var COFantasy = COFantasy || function() {
break;
case 'paralyseTemp':
case 'paralyseGoule':
+ case 'poisonParalysant':
setState(target, 'paralyse', true, evt);
break;
case 'immobiliseTemp':
@@ -19642,6 +19681,20 @@ var COFantasy = COFantasy || function() {
if (effets) effets = effets.concat(target.effets);
else effets = target.effets;
}
+ if (predicateAsBool(attaquant, 'hemorragiePestrilax') && !immuniseAuxSaignements(target)) {
+ if (attributeAsBool(target, 'blessureQuiSaigne')) {
+ let niveauBlessure = getIntValeurOfEffet(target, 'blessureQuiSaigne', 0);
+ target.messages.push("La blessure devient plus importante");
+ setTokenAttr(target, 'blessureQuiSaigneValeur', niveauBlessure + 1, evt);
+ } else {
+ effets = effets || [];
+ effets.push({
+ effet: 'blessureQuiSaigne',
+ attaquant,
+ message: messageEffetCombat.blessureQuiSaigne,
+ });
+ }
+ }
if (effets) {
effets.forEach(function(ef) {
if (((options.sortilege || options.mana !== undefined) &&
@@ -29479,6 +29532,7 @@ var COFantasy = COFantasy || function() {
(effet == 'immobiliseTemp' ||
effet == 'paralyseTemp' ||
effet == 'paralyseGoule' ||
+ effet == 'poisonParalysant' ||
effet == 'ralentiTemp' ||
effet == 'toiles')) ||
(mEffet.entrave && effet != 'paralyseTemp' && effet != 'paralyseGoule' && predicateAsInt(perso, 'voieDeLArchange', 1) > 1 && attributeAsBool(perso, 'formeDAnge'))
@@ -29923,7 +29977,7 @@ var COFantasy = COFantasy || function() {
if (activer) {
initiative(selected, evt);
iterSelected(selected, function(perso) {
- if (effet == 'blessureQuiSaigne' && predicateAsBool(perso, 'immuniteSaignement')) {
+ if (effet == 'blessureQuiSaigne' && immuniseAuxSaignements(perso)) {
sendPerso(perso, "ne saigne pas");
return;
}
@@ -34916,8 +34970,14 @@ var COFantasy = COFantasy || function() {
}
let label = cmd[1];
let typePoison = cmd[2];
- if (typePoison != 'rapide' && typePoison != 'affaiblissant') {
- error("Les seuls type de poison g\xE9r\xE9s sont rapide et affaiblissant, mais pas encore " + typePoison, cmd);
+ switch (typePoison) {
+ case 'rapide':
+ case 'affaiblissant':
+ case 'paralysant':
+ break;
+ default:
+ error("Les seuls type de poison g\xE9r\xE9s sont rapide, affaiblissant et paralysant, mais pas encore " + typePoison, cmd);
+ return;
}
let nomMunition;
let estMunition = label.startsWith('munition_');
@@ -46429,6 +46489,25 @@ var COFantasy = COFantasy || function() {
prejudiciable: true,
visible: true
},
+ poisonAffaiblissantLatent: {
+ activation: "sent qu'un poison commence \xE0 se r\xE9pandre dans ses veines",
+ actif: "est empoisonn\xE9, mais l'effet du poison ne se fait pas encore sentir",
+ actifF: "est empoisonn\xE9e, mais l'effet du poison ne se fait pas encore sentir",
+ fin: "se sent faible",
+ msgSave: "r\xE9sister au poison",
+ prejudiciable: true,
+ seulementVivant: true,
+ },
+ poisonParalysant: {
+ activation: "sent le poison ralentir ses mouvements. Il ne peut plus bouger !",
+ activationf: "sent le poison ralentir ses mouvements. Elle ne peut plus bouger !",
+ actif: "est empoisonn\xE9 et ne peut plus bouger",
+ actifF: "est empoisonn\xE9e et ne peut plus bouger",
+ fin: "peut \xE0 nouveau bouger",
+ msgSave: "r\xE9sister au poison",
+ prejudiciable: true,
+ seulementVivant: true,
+ },
protectionContreLesProjectiles: {
activation: "gagne une protection contre les projectiles",
actif: "est prot\xE9g\xE9 contre les projectiles",
@@ -47196,15 +47275,6 @@ var COFantasy = COFantasy || function() {
msgSave: "r\xE9sister \xE0 la provocation",
prejudiciable: true,
},
- poisonAffaiblissantLatent: {
- activation: "sent qu'un poison commence \xE0 se r\xE9pandre dans ses veines",
- actif: "est empoisonn\xE9, mais l'effet du poison ne se fait pas encore sentir",
- actifF: "est empoisonn\xE9e, mais l'effet du poison ne se fait pas encore sentir",
- fin: "se sent faible",
- msgSave: "r\xE9sister au poison",
- prejudiciable: true,
- seulementVivant: true,
- },
};
function buildPatternEffets(listeEffets, postfix) {
@@ -47312,11 +47382,24 @@ var COFantasy = COFantasy || function() {
actif: "attaque \xE0 outrance",
fin: "attaque normalement",
},
+ blessureQuiSaigne: {
+ activation: "re\xE7oit une blessure qui saigne",
+ actif: "saigne \xE0 cause d'une blessure",
+ fin: "saigne beaucoup moins",
+ msgSave: "ne plus saigner",
+ prejudiciable: true,
+ dm: true
+ },
bonusInitEmbuscade: { //Effet interne pour la capacit\xE9 Surveillance
activation: "a un temps d'avance en cas d'embuscade",
actif: "a un temps d'avance",
fin: ""
},
+ bonusInitVariable: {
+ activation: "entre en combat",
+ actif: "est en combat",
+ fin: ''
+ },
criDeGuerre: {
activation: "pousse son cri de guerre",
actif: "a effray\xE9 ses adversaires",
@@ -47385,11 +47468,6 @@ var COFantasy = COFantasy || function() {
fin: "retrouve son calme",
msgSave: "retrouver son calme",
},
- bonusInitVariable: {
- activation: "entre en combat",
- actif: "est en combat",
- fin: ''
- },
defiDuelliste: {
activation: "lance un d\xE9fi",
actif: "a lanc\xE9 un d\xE9fi",
@@ -47472,14 +47550,6 @@ var COFantasy = COFantasy || function() {
dm: true,
visible: true
},
- blessureQuiSaigne: {
- activation: "re\xE7oit une blessure qui saigne",
- actif: "saigne \xE0 cause d'une blessure",
- fin: "saigne beaucoup moins",
- msgSave: "ne plus saigner",
- prejudiciable: true,
- dm: true
- },
poisonAffaiblissant: {
activation: "sent le poison ralentir ses mouvements",
actif: "est empoisonn\xE9",
@@ -47720,6 +47790,16 @@ var COFantasy = COFantasy || function() {
return effet;
}
+ function getEffectOptions(perso, effet, options) {
+ options = options || {};
+ let optionsAttr = tokenAttribute(perso, effet + 'Options');
+ optionsAttr.forEach(function(oAttr) {
+ parseDmgOptions(oAttr.get('current'), options);
+ });
+ copyDmgOptionsToTarget(perso, options);
+ return options;
+ }
+
function rollAndDealDmg(perso, dmg, type, effet, attrName, msg, count, evt, options, callback, display) {
if (options.valeur) {
let attrsVal = tokenAttribute(perso, options.valeur);
@@ -47895,16 +47975,6 @@ var COFantasy = COFantasy || function() {
}); //fin iterTokensOfAttribute
}
- function getEffectOptions(perso, effet, options) {
- options = options || {};
- let optionsAttr = tokenAttribute(perso, effet + 'Options');
- optionsAttr.forEach(function(oAttr) {
- parseDmgOptions(oAttr.get('current'), options);
- });
- copyDmgOptionsToTarget(perso, options);
- return options;
- }
-
// gestion des effets qui se d\xE9clenchent \xE0 la fin de chaque tour
// N'ajoute pas evt \xE0 l'historique
// Asynchrone (\xE0 cause des saves par tour)
@@ -48124,16 +48194,18 @@ var COFantasy = COFantasy || function() {
});
}
if (attributeAsBool(perso, 'blessureQuiSaigne') &&
- !getState(perso, 'mort') &&
- !predicateAsBool(perso, 'immuniteSaignement') &&
- !predicateAsBool(perso, 'controleSanguin')) {
- let jetSaignement = rollDePlus(6);
+ !getState(perso, 'mort') && !immuniseAuxSaignements(perso)) {
+ let bonus = getIntValeurOfEffet(perso, 'blessureQuiSaigne', 0);
+ let jetSaignement = rollDePlus(6, {
+ bonus
+ });
let dmgSaignement = {
type: 'normal',
total: jetSaignement.val,
display: jetSaignement.roll
};
let optDMSaignements = getEffectOptions(perso, 'blessureQuiSaigne');
+ perso.ignoreTouteRD = true;
dealDamage(perso, dmgSaignement, [], evt, false, optDMSaignements, undefined,
function(dmgDisplay, dmgFinal) {
sendPerso(perso, "saigne. " + onGenre(perso, 'Il', 'Elle') + " perd " + dmgDisplay + " PVs");
@@ -49834,7 +49906,7 @@ var COFantasy = COFantasy || function() {
else arme = l;
}
}
- if (arme !== undefined && arme !== true) {
+ if (arme && arme !== true) {
degainerArme(perso, arme, {}, {
secret: true
});
diff --git a/COFantasy/ChangeLog.md b/COFantasy/ChangeLog.md
index b0f0e56f2..14b64bf07 100644
--- a/COFantasy/ChangeLog.md
+++ b/COFantasy/ChangeLog.md
@@ -1,11 +1,14 @@
# COFantasy: Historique des changements (depuis la version 1.0)
## 3.15
### Capacités
+* Hémorragie de Pestrilax.
+* Prise en compte de la capacité Tir double pour les attaques à 2 mains.
* Défi de la Voie du Duelliste
* Meilleure prise en charge de la spécialisation du guerrier.
* Implémentation de la version avancée du drain de force de Dominia.
### Autres améliorations
+* Ajout du poison paralysant
* Ajout d'une option --depensePR pour les actions autres que les attaques
* Ajout d'une commande !cof-recupere-mana.
* Règle optionnelle pour faire récupérer des points de mana quand on dépense un point de récupération.
diff --git a/COFantasy/doc.html b/COFantasy/doc.html
index bdae6b0a4..9c647289b 100644
--- a/COFantasy/doc.html
+++ b/COFantasy/doc.html
@@ -1035,7 +1035,7 @@ Voie du Pistolero
Plus vite que son ombre : ajouter un prédicat plusViteQueSonOmbre
. On peut associer un nombre à ce prédicat pour modifier le bonus à l'initiative, ou bien lui donner la valeur arbalete
pour activer le bonus sur les arbalètes au lieu des armes à poudre.
Cadence de tir : pas de support
- Tir double : utiliser l'option --tirDouble
si deux tirs sur une même cible. Si les deux armes sont différentes, rajouter le label de la deuxième arme après l'option (si le label est l2, cela donne --tirDouble l2
). Si vous avez une pétoire dans la main droite et l'autre dans la main gauche, vous pouvez par exemple utiliser l'action #Attaque -1 --tirDouble -2
. Attention, il faut faire 2 undo pour annuler une attaque de tir double réussie.
+ Tir double : ajouter un prédicat tirDouble
pour ne pas avoir le malus à l'attaque avec une arme à poudre dans chaque main. Si le personnage veut faire 2 tirs sur la même cible, il peut utiliser l'option --tirDouble
. Si les deux armes sont différentes, rajouter le label de la deuxième arme après l'option (si le label est l2, cela donne --tirDouble l2
). Si vous avez une pétoire dans la main droite et l'autre dans la main gauche, vous pouvez par exemple utiliser l'action #Attaque -1 --tirDouble -2
. Attention, il faut faire 2 undo pour annuler une attaque de tir double réussie.
As de la gâchette : ajouter un prédicat asDeLaGachette
sur la fiche.
Dextérité héroïque : reporter le bonus sur la fiche
@@ -2471,6 +2471,7 @@ 4.5 Capacités diverses
Foudres du temps : !cof-effet-chaque-d20 foudresDuTemps
permet d'activer les foudres du temps. On peut donner un argument pour remplacer la valeur par défaut (13) par un autre jet de dés. Un deuxième argument permet de faire sortir la foudre pour tout jet entre les deux valeurs. Par exemple !cof-effet-chaque-d20 foudresDuTemps 13 14
fait venir la foudre pour tout jet de 13 ou 14. Si votre jeu contient un son (ou playlist) nommé Foudre
(avec la majuscule), le son sera joué à chaque fois que la foudre frappera. Finalement, !cof-effet-chaque-d20 foudresDuTemps fin
met fin aux foudres du temps.
Frénésie : Ajouter un prédicat frenesie
avec comme valeur le nombre de PV en-dessous duquel la créature devient frénétique (+2 aus jets d'attaque).
Général (pour la campagne Vengeance) : Ajouter au général un prédicat generalVengeance
, et aux gardes d'élite un prédicat gardeEliteVengeance
.
+ Hémorragie (Invincible) : ajouter un prédicat hemorragiePestrilax
.
Hors de portée : ajouter un prédicat horsDePortee
Huile de fort assaut : !cof-effet-temp dmgArme(L) 10 --valeur 1d6
où L est le label de l'arme qu'on veut enduire d'huile de fort assaut.
Hurlement : Pour les chiens infernaux, !cof-peur [[10+?{Nombre de chiens?}]] 2d4 --titre Hurlement --immuniseSiResiste hurlement --disque 50 --saufAllies
, et pour les fantômes, !cof-peur 12 1d6 --titre Hurlement terrible --immuniseSiResiste hurlement --disque 10 --saufAllies
.
@@ -2495,7 +2496,7 @@ 4.5 Capacités diverses
Phylactère de canalisation : ajouter un prédicat phylacterePositif
pour un phylactère de canalisation positive, ou phylactereNegatif
pour un phylactère de canalisation négative. Associez à ce prédicat la valeur ajoutée pour chaque PM dépensé (nécessite l'utilisation du prédicat deCanalisation
). Une valeur de 1d4
semble adaptée pour le phylactère de canalisation de Pathfinder 1.
Piqûres d'insectes : Rajouter un prédicat piquresDInsectes
avec comme valeur la résistance aux dégâts à distance appropriée
- Poison : pour enduire une arme de label L de poison, utiliser !cof-enduire-poison L type force save
. Pour l'instant, type ne peut être que rapide
ou affaiblissant
. Pour un poison rapide, force est une expression pour les dégâts (typiquement, 2d6
), pour un poison affaiblissant c'est une expression indiquant au bout de combien de tours le poison fait effet (si c'est 0, alors l'affaiblissement ne dure que pendant un combat, sinon c'est une durée en heures, à gérer par le MJ). save est la difficulté du jet de CON pour résister au poison. On peut rajouter deux arguments optionnels :
+ Poison : pour enduire une arme de label L de poison, utiliser !cof-enduire-poison L type force save
. Pour l'instant, type ne peut être que rapide
, affaiblissant
ou paralysant
. Pour un poison rapide, force est une expression pour les dégâts (typiquement, 2d6
), pour un poison affaiblissant c'est une expression indiquant au bout de combien de tours le poison fait effet (si c'est 0, alors l'affaiblissement ne dure que pendant un combat, sinon c'est une durée en heures, à gérer par le MJ), et pour un poison paralysant, c'est la durée de la paralysie en tours. save est la difficulté du jet de CON pour résister au poison. On peut rajouter deux arguments optionnels :
--testINT
n: fixe la difficulté du jet d'INT pour réussir à poser le poison. La difficulté par défaut est 14.
--dose
nom: indique une ressource dans laquelle on puise pour enduire de poison. Il faudra que le personnage ait un attribut de nom dose_nom
avec comme valeur le nombre de doses possédées.
@@ -2506,6 +2507,7 @@ 4.5 Capacités diverses
- poisonAffaiblissant est un effet qui rend affaibli pendant tout un combat.
- poisonAffaiblissantLong, le même effet mais sans limite de durée (à gérer par le MJ).
- poisonAffaiblissantLatent est un effet à durée en tours. Quand l'effet prend fin, le personnage devient empoisonné et affaibli.
+ - poisonParalysant est un effet à durée en tours, qui paralyse.
Potion de sang de l'Arbre-Coeur : !cof-effet sangDeLArbreCoeur true
, à enlever quand les 24h sont passées.
@@ -3127,6 +3129,7 @@ 9. Index des prédicats
briseurDOs : booléen, augmente les chances de critique des attaques au contact, et applique un effet d'os brisés a la cible en cas de critique.
bucheron : booléen, augmente les DM des armes à 2 mains de 1d6 contre les créatures grandes, et 2d6 contre les créatures énormes.
cavalierEmerite : entier, s'ajoute à l'attaque au contact quand le personnage est sur une monture.
+ champion : booléen, touche automatiquement et ajoute 1d6 aux DM sur un résultat de 15 ou plus au dé d'attaque.
charge : entier (défaut 1), indique que l'arme doit être rechargée (ainsi que le nombre de charge, si on associe un nombre).
chasseurDeSorciere : booléen, ajoute 2 aux DM et à la DEF contre les nécromanciens.
chasseurEmerite : booléen, rajoute +2 à l'attaque et aux DM contre les animaux.
@@ -3183,6 +3186,8 @@ 9. Index des prédicats
grosseTete : booléen, remplace le mod. de FOR par le mod. d'INT pour les tests.
guetteur : nom de personnage, nom du personnage représentant le compagnon qui donne un bonus en perception.
hachesEtMarteaux : booléen, ajoute un bonus de 1 en attaque est DM pour les haches et les marteaux.
+ hausserLeTon : booléen, capacité Hausser le ton de la Voie du champion.
+ hemorragiePestrilax : booléen, les attaques qui font des dégâts font saigner la cible.
humanoide : booléen, le personnage est humanoïde.
ignorerLaDouleur : booléen, permet de reporter les DM d'une attaque à la fin du combat.
immunite_x : booléen, empêche de mettre le personnage dans l'état ou effet temporaire nommé x. On peut aussi immuniser aux effets de pétrification avec x=petrification, ou contre la desctruction des mort-vivants avec x=destruction.
@@ -3255,12 +3260,14 @@ 9. Index des prédicats
resistanceA_nonMagique : booléen, divise par 2 les DM non magiques.
resistanceA_type : booléen, divise par 2 les DM du type.
resistanceALaMagieBarbare : booléen, propose un jet pour résister à la magie.
+ riposte : booléen, capacité Riposte de la Voie du champion.
riposteGuerrier : booléen, propose un jet de riposte au personnage.
sangFroid : booléen, réduit les DM quand l'ogre prend sur lui pour éviter une réaction violente.
sansPeur : booléen, immunise aux effets de peur et donne un bonus de 2+CHA aux alliés en vue pour résister aux effets de peur.
scienceDuCritique : booléen, augmente de 1 les chances de critique.
secondSouffle : booléen ou entier, propose un jet de récupération de PV une fois par combat, appliqué automatiquement à la fin du combat si pas utilisé. Si on met un entier, on soigne avec cette valeur à la place de CON + niveau.
sensAffutes : booléen, ajoute la sagesse aux dégâts des arcs et à l'initiative.
+ sergent : booléen, une fois par combat, ignore une attaque qui aurait dû le mettre à 0 PV.
sournoisesParTour : entier (1 par défaut), nombre maximum d'effets d'attaques sournoises par tour pour le personnage.
specialisationGuerrier : booléen ou entier (2 par défaut), donne un bonus aux DM pour l'arme de prédilection.
siphonDesAmes : booléen ou entier, fait récupérer 1d6 PV quand une créature meurt dans les 20 mètres. Si une valeur est précisée, elle est ajoutée à ce dé.
@@ -3269,6 +3276,7 @@ 9. Index des prédicats
techniqueDuSabre : entier, bonus aux DM pour le combat au sabre, katana ou vivelame. Ce bonus ne se cumule qu'à moitié avec le mod. de FOR.
tenacite : booléen, donne un bonus de +2 puis +5 contre un adversaire que le personnage n'a pas réussi à toucher.
tirDeSemonce : booléan, propose un tir de semonce au tour suivant un tir raté.
+ tirDouble : booléan, quand le personnage attaque avec une arme à poudre dans chaque main, il utilise un d20 par défaut.
tirFatal : booléen ou nom de type d'arme (par défaut, arc), augmente les chance de coup critique du mod. de SAG pour les armes de ce type. De plus les DM des coups critiques pour ces attaques sont augmentées de 1 ou 2 d6 (selon la valeur du prédicat voieDeLArcEtDuCheval
).
tirParabolique : booléen, augmente la portée des armes à distance (comme la capacité tir parabolique).
tirPrecis : entier, ajouté aux DM quand la cible est à moins de 5xDEX mètres.
@@ -3283,6 +3291,7 @@ 9. Index des prédicats
vieArtificielle : booléan, divise les soins par 2.
violenceCiblee : booléen, permet d'emmagasiner et d'utliser des points de violence.
visionDansLeNoir : entier, le personnage voit dans le noir jusqu'à la distance indiquée par le prédicat, en mètres.
+ vitaliteEpique : booléan, multiplie par 2 les soins reçus.
vitesseDuFelin : entier, bonus à l'initiative et aux jets de course, d'escalade, et de saut.
voieDeLaConjuration : entier, rang dans la Voie de la conjuration. Contrôle les conjurations de prédateurs et la conjuration d'armées.
voieDeLaMagieElementaire : entier, on utilise 2 fois cette valeur pour la valeur de la protection des éléments.